> ## Documentation Index
> Fetch the complete documentation index at: https://docs.amdital.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Authentication

> Learn how to authenticate with the AmDital MCP server using API keys or workspace tokens.

The AmDital MCP server (`POST /api/v1/mcp`) accepts **two** authentication methods on the same endpoint. Send either as a `Bearer` token in the `Authorization` header — the server detects which one you're using automatically.

| | Path 1 — API key | Path 2 — Workspace bearer token |
| - | - | - |
| Format | `sk_` followed by 64 hex characters | Three dot-separated JWT segments |
| Lifetime | Long-lived — no expiry by default, or a fixed expiry you choose at creation | 15 minutes (refreshable via a 30-day refresh token) |
| Best for | Static config (`.mcp.json`), cron jobs, CLI tools, long-running agents | Interactive clients that already hold an active AmDital session |
| Permissions | Scoped to the workspace it was issued for and to the scopes chosen at creation (`read:projects`, `write:projects`, `read:hr`, `write:hr`, `read:finance`, `admin`) | Scoped to the workspace encoded in the token — every tool is available to any authenticated workspace member |
| Revocation | Immediate — revoke from the workspace's Developer settings | Automatic at expiry; refresh tokens can be revoked from account settings |

<Warning>
  Never share an API key or bearer token in public repositories, client-side code, or screenshots.
  An API key does not expire on its own unless you set an expiry — treat it with the same care as a
  database password.
</Warning>

## Path 1 — API keys (recommended for `.mcp.json` and other long-lived clients)

Create a key from **Settings → Developer** in any workspace (admin/owner role required): click **Create API Key**, choose one or more scopes, optionally set an expiry, and copy the key immediately — like most API-key systems, the full value is shown once and only its hash is stored, so it cannot be retrieved again later. Revoke a key from the same page at any time; revocation takes effect on the next request.

```json theme={null}
// .mcp.json — a static, long-lived entry (mirrors this repo's own
// `sentry`/`posthog` MCP entries)
{
  "mcpServers": {
    "amdital": {
      "command": "bash",
      "args": [
        "-c",
        "set -a; [ -f .env.local ] && . ./.env.local; set +a; exec npx -y mcp-remote@latest https://api.amdital.com/api/v1/mcp --header \"Authorization:Bearer ${AMDITAL_MCP_API_KEY}\""
      ]
    }
  }
}
```

```bash theme={null}
# .env.local
AMDITAL_MCP_API_KEY=sk_your_key_here
```

```python theme={null}
# Custom MCP client (Python SDK example)
from mcp import Client

async with Client("https://api.amdital.com/api/v1/mcp",
  headers={"Authorization": f"Bearer {api_key}"}
) as client:
  result = await client.call_tool("crm.leads.list", {})
```

An API key can never reach a workspace other than the one it was issued for, regardless of tool arguments — the server resolves the workspace from the key itself, never from anything the caller sends.

## Path 2 — Workspace bearer token (short-lived, for interactive sessions)

```ts theme={null}
// apps/app — server component or API route, or your own backend that has
// a logged-in AmDital session
import { getAuthNextSession } from '@amdital/auth-next'

const session = await getAuthNextSession()
const workspaceToken = session && 'accessToken' in session ? session.accessToken : null
```

```python theme={null}
# Custom MCP client (Python SDK example) — obtain workspaceToken via your
# own AmDital login flow, then connect:
from mcp import Client

async with Client("https://api.amdital.com/api/v1/mcp",
  headers={"Authorization": f"Bearer {workspace_token}"}
) as client:
  result = await client.call_tool("crm.leads.list", {})
```

Access tokens are short-lived (15 minutes). A 30-day refresh token backs the session — your client must refresh and reconnect when the access token expires; long-running agents should refresh proactively rather than waiting for a 401. This is the same session token AmDital's own web app uses.

## Error responses

| Condition | Response |
| - | - |
| Missing/malformed `Authorization` header, unknown/revoked/expired API key, or invalid/expired bearer token | `401 Unauthorized` — the message is intentionally identical across all of these so a caller can never determine *why* a credential was rejected |
| Unknown tool name in `tools/call` | JSON-RPC error, `404`, code `-32602` |
| Unknown top-level method | JSON-RPC error, `404`, code `-32601` |
| Tool executes but the underlying operation fails | `200` with `result.isError: true` and a text explanation — not a transport error |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.