# Attest MCP server

> Provides a policy-driven verification layer that gates AI agent actions, verifies them via system read-back, and records evidence in a hash-chained ledger.

- Repository: https://github.com/dev-prathap/ATTEST
- Page: https://hostedmcp.org/servers/dev-prathap/attest
- Transport: stdio
- Stars: 1
- License: MIT
- Latest version: 0.1.0

## Install

### Claude Code

```sh
claude mcp add --env GMAIL_TOKEN=<YOUR_GMAIL_TOKEN> --env GOOGLE_TOKEN=<YOUR_GOOGLE_TOKEN> --env GRAPH_TOKEN=<YOUR_GRAPH_TOKEN> --env HUBSPOT_TOKEN=<YOUR_HUBSPOT_TOKEN> --env LINEAR_API_KEY=<YOUR_LINEAR_API_KEY> --env NOTION_TOKEN=<YOUR_NOTION_TOKEN> --env SLACK_BOT_TOKEN=<YOUR_SLACK_BOT_TOKEN> attest -- uvx attestlayer
```

### Cursor (`~/.cursor/mcp.json`)

```json
{
  "mcpServers": {
    "attest": {
      "command": "uvx",
      "args": [
        "attestlayer"
      ],
      "env": {
        "GMAIL_TOKEN": "<YOUR_GMAIL_TOKEN>",
        "GOOGLE_TOKEN": "<YOUR_GOOGLE_TOKEN>",
        "GRAPH_TOKEN": "<YOUR_GRAPH_TOKEN>",
        "HUBSPOT_TOKEN": "<YOUR_HUBSPOT_TOKEN>",
        "LINEAR_API_KEY": "<YOUR_LINEAR_API_KEY>",
        "NOTION_TOKEN": "<YOUR_NOTION_TOKEN>",
        "SLACK_BOT_TOKEN": "<YOUR_SLACK_BOT_TOKEN>"
      }
    }
  }
}
```

### VS Code (`.vscode/mcp.json`)

```json
{
  "servers": {
    "attest": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "attestlayer"
      ],
      "env": {
        "GMAIL_TOKEN": "<YOUR_GMAIL_TOKEN>",
        "GOOGLE_TOKEN": "<YOUR_GOOGLE_TOKEN>",
        "GRAPH_TOKEN": "<YOUR_GRAPH_TOKEN>",
        "HUBSPOT_TOKEN": "<YOUR_HUBSPOT_TOKEN>",
        "LINEAR_API_KEY": "<YOUR_LINEAR_API_KEY>",
        "NOTION_TOKEN": "<YOUR_NOTION_TOKEN>",
        "SLACK_BOT_TOKEN": "<YOUR_SLACK_BOT_TOKEN>"
      }
    }
  }
}
```

### Claude Desktop (`claude_desktop_config.json`)

```json
{
  "mcpServers": {
    "attest": {
      "command": "uvx",
      "args": [
        "attestlayer"
      ],
      "env": {
        "GMAIL_TOKEN": "<YOUR_GMAIL_TOKEN>",
        "GOOGLE_TOKEN": "<YOUR_GOOGLE_TOKEN>",
        "GRAPH_TOKEN": "<YOUR_GRAPH_TOKEN>",
        "HUBSPOT_TOKEN": "<YOUR_HUBSPOT_TOKEN>",
        "LINEAR_API_KEY": "<YOUR_LINEAR_API_KEY>",
        "NOTION_TOKEN": "<YOUR_NOTION_TOKEN>",
        "SLACK_BOT_TOKEN": "<YOUR_SLACK_BOT_TOKEN>"
      }
    }
  }
}
```

### Codex (`~/.codex/config.toml`)

```toml
[mcp_servers.attest]
command = "uvx"
args = ["attestlayer"]

[mcp_servers.attest.env]
GMAIL_TOKEN = "<YOUR_GMAIL_TOKEN>"
GOOGLE_TOKEN = "<YOUR_GOOGLE_TOKEN>"
GRAPH_TOKEN = "<YOUR_GRAPH_TOKEN>"
HUBSPOT_TOKEN = "<YOUR_HUBSPOT_TOKEN>"
LINEAR_API_KEY = "<YOUR_LINEAR_API_KEY>"
NOTION_TOKEN = "<YOUR_NOTION_TOKEN>"
SLACK_BOT_TOKEN = "<YOUR_SLACK_BOT_TOKEN>"
```

### Gemini CLI (`~/.gemini/settings.json`)

```json
{
  "mcpServers": {
    "attest": {
      "command": "uvx",
      "args": [
        "attestlayer"
      ],
      "env": {
        "GMAIL_TOKEN": "<YOUR_GMAIL_TOKEN>",
        "GOOGLE_TOKEN": "<YOUR_GOOGLE_TOKEN>",
        "GRAPH_TOKEN": "<YOUR_GRAPH_TOKEN>",
        "HUBSPOT_TOKEN": "<YOUR_HUBSPOT_TOKEN>",
        "LINEAR_API_KEY": "<YOUR_LINEAR_API_KEY>",
        "NOTION_TOKEN": "<YOUR_NOTION_TOKEN>",
        "SLACK_BOT_TOKEN": "<YOUR_SLACK_BOT_TOKEN>"
      }
    }
  }
}
```

## Environment variables

| Name | Required | Secret | Description |
|---|---|---|---|
| `GMAIL_TOKEN` | no | yes | Google OAuth access token with gmail.readonly — enables Gmail read-back |
| `GOOGLE_TOKEN` | no | yes | Google OAuth access token — enables Calendar / Drive / Docs / Sheets read-back |
| `GRAPH_TOKEN` | no | yes | Microsoft Graph token — enables Outlook / Teams read-back |
| `HUBSPOT_TOKEN` | no | yes | HubSpot private-app token — enables HubSpot read-back |
| `LINEAR_API_KEY` | no | yes | Linear API key — enables Linear read-back |
| `NOTION_TOKEN` | no | yes | Notion integration token — enables Notion read-back |
| `SLACK_BOT_TOKEN` | no | yes | Slack bot token (xoxb-…) with channels:history, channels:read — enables Slack read-back |
| `ATTEST_AUTO_APPROVE` | no | no | Set to 1 to approve every confirm request (development only) |
| `ATTEST_CONFIRM_TIMEOUT` | no | no | Seconds attest_confirm waits for a human (default 900) |
| `ATTEST_LEDGER` | no | no | Ledger SQLite path (default .attest/ledger.sqlite) |
| `ATTEST_POLICY` | no | no | Path to a policy YAML (defaults to ./attest.yaml or the built-in default) |

## FAQ

### Does Attest execute my agent's actions?

No, Attest never executes your action; your tool does, allowing it to work with any app and framework.

### How does Attest verify that an action actually happened?

It uses read-back from the system of record to check the results against the agent's claim.

### What are the different verification levels?

Levels include verified (read back and matched), verified-custom (custom check passed), acknowledged (accepted but no read-back possible), attested-only (recorded without verifier), and unverified (check contradicted the claim).
