API Key and MCP Route Boundary
How personal API keys and OAuth 2.1 access tokens are restricted to cataloged tool routes via HMAC provenance signatures, what routes external tokens cannot reach, and how the tool catalog enforces this boundary across the CLI, stdio MCP server, and hosted MCP endpoint.
MarkDocket exposes its tool surface through two external token types — personal API keys (used by the CLI and direct integrations) and OAuth 2.1 access tokens (used by the hosted MCP endpoint and browser-authenticated CLI sessions). Neither token type can call arbitrary API routes. Instead, all external-token requests must pass through a catalog-derived provenance gate enforced by an HMAC signature before any internal route is reached.
The Two External Token Types
| Token type | Issued by | Primary entry point | Execution transport |
|---|---|---|---|
| Personal API key | MarkDocket dashboard or CLI markdocket login --password | /v1/tools REST gateway | Direct bearer auth to cataloged routes |
| OAuth 2.1 access token | Browser OAuth flow (markdocket login) or third-party MCP client | /mcp hosted Streamable HTTP endpoint | Resource-bound; cannot call /api/* directly |
Both token types ultimately execute the same cataloged tools. The difference is in the execution path and the resource binding applied at issuance.
The Catalog HMAC Provenance Gate
When either token type triggers a tool call, the platform adds an HMAC provenance signature before dispatching to any internal route. This signature encodes:
- The exact HTTP method and path being requested
- The caller's bearer token
- The semantic scope of the operation
- A timestamp
The API server verifies this signature on every inbound request that arrives bearing a personal API key or OAuth access token. A request that lacks a valid signature — or that presents a signature for a different method, path, or token — is rejected before any handler runs.
The HMAC proof is generated by the catalog execution layer, not by the caller. External clients cannot construct or forge it; the signature is created server-side as part of dispatching through the tool catalog.
This means:
- Only cataloged tools can be reached. A route that shares the
/api/prefix with cataloged routes but has no catalog entry is permanently unreachable from external tokens, regardless of URL guessing. - Adding a new tool to the catalog automatically grants access. No additional gateway configuration is needed; the catalog registration is the authorization step.
- Replay and path-swapping attacks are not possible. The signature binds the exact method and path, so a captured proof for one tool cannot be reused against a different route.
OAuth Access Tokens Are Resource-Bound
OAuth 2.1 access tokens issued through the hosted MCP flow carry a resource binding to the /mcp endpoint. They cannot be used directly against /api/* routes — the API server rejects them at the auth layer before any route handler is reached.
This is by design: browser-authenticated CLI sessions and third-party MCP clients use executeRemoteMcpTool(), which opens a per-invocation MCP StreamableHTTPClientTransport connection to /mcp. The hosted endpoint handles the HMAC signing internally before any internal dispatch occurs.
Password-mode CLI sessions (markdocket login --password) produce a session token rather than an OAuth access token. These sessions call /api/ routes directly via bearer auth and are not resource-bound to the MCP endpoint. The CLI automatically dispatches through the correct execution path based on the session type.
Personal API Keys and the /v1/tools Gateway
Personal API keys authenticate at /v1/tools, the REST gateway for catalog tool calls. The executeCatalogToolWithTrace() path used by API-key sessions adds the HMAC catalog proof header before any internal /api/ call is made. The API server then verifies the signature against the catalog entry for that tool.
The gateway enforces one additional requirement for write-mutating calls: an Idempotency-Key header must be present. The server persists idempotency keys to deduplicate retried requests.
What External Tokens Cannot Reach
The following surfaces are explicitly outside the route boundary for both personal API keys and OAuth access tokens:
- Billing management routes — subscription changes, payment methods, invoice access
- Device pairing routes — the
/api/devicesone-time pairing code flow used by the Desktop companion - Credential management routes — password changes, two-factor enrollment, session management
- Raw internal API routes — any
/api/*path that does not have a corresponding catalog entry - Agent-only tools — tools such as
web_search,classify_goods, andattachment_listthat exist in the agent's internal registry but are excluded from the external catalog viaEXTERNAL_TOOL_EXCLUSIONS
The OAuth consent page presented during the browser login flow explicitly discloses these exclusions to the user before they grant access.
The Tool Catalog as the Boundary Definition
The canonical tool catalog lives in the @markdocket/cli package and is the single source of truth for every external-facing tool surface: the CLI, the stdio MCP server, the /v1/tools REST gateway, and the hosted /mcp endpoint all derive their tool registries from the same catalog with no duplication.
The agent's internal registry is a superset of the catalog. Agent-only tools that depend on AI Gateway credentials or durable chat session state are excluded from the external catalog and are therefore unreachable from any external token, regardless of the provenance mechanism.
Agent internal registry (superset)
└── External catalog (EXTERNAL_TOOL_EXCLUSIONS applied)
├── CLI commands (markdocket call <name>)
├── stdio MCP server tools
├── /v1/tools REST gateway ← personal API keys
└── /mcp hosted endpoint ← OAuth 2.1 access tokensMCP behavioral hints (readOnlyHint, idempotentHint, destructiveHint) are derived automatically from the HTTP method and read/write metadata already present on each tool definition — there is no separate annotation registry to maintain.
MCP Tool Response Size Management
Before returning a tool result over the MCP transport, the platform applies domain-aware compaction. Polling tools have intermediate data stripped from their responses, while final result tools pass through in full. If the compacted result still exceeds the size limit, the first 150,000 characters are returned as a preview with a truncated: true indicator rather than an error, so MCP clients always receive a usable response.
Summary of Protections
| Protection | Personal API key | OAuth access token |
|---|---|---|
| HMAC catalog provenance required | Yes | Yes (applied internally by /mcp) |
| Resource binding to entry point | No (uses /v1/tools) | Yes (bound to /mcp) |
Direct /api/* access | Blocked without valid HMAC proof | Blocked entirely |
| Agent-only tools accessible | No | No |
| Billing / device / credential routes | No | No |
| Idempotency-Key required for writes | Yes | Yes (enforced by catalog layer) |
The combination of catalog-derived routing, HMAC provenance signing, and OAuth resource binding means that the external tool surface is closed by default: only explicitly cataloged tools at explicitly registered entry points can be reached with external credentials.
CLI OAuth and Dynamic Client Registration
How the MarkDocket CLI performs browser-based OAuth 2.1 login using RFC 7591 dynamic client registration and PKCE, with no embedded client_id in the distributed package.
BYOK Key Storage and Encryption
Explains how MarkDocket encrypts and stores user-supplied AI provider keys (BYOK), the identity-bound encryption scope that ties each key to a specific user, and the execution boundary that restricts BYOK keys exclusively to automation agent nodes.