Token Vault
Reference

MCP Proxy Endpoint

Reference for POST /api/proxy/mcp — proxy key auth forms, webhook credential injection, and the tv_session upstream auth type.

POST /api/proxy/mcp

The MCP proxy endpoint. An agent's MCP client points at a proxy URL; Token Vault authenticates the proxy key, evaluates ABAC policies, and forwards the request to your webhook's /v1/proxy with a signed ticket. Your webhook injects the real credential (substituting ${TOKEN} in your header templates) and calls the upstream service; Token Vault streams the response back but never sees the credential.

.cursor/mcp.json
{
  "mcpServers": {
    "github": {
      "url": "https://api.tokenvault.uk/api/proxy/mcp",
      "headers": { "Authorization": "Bearer mcp_…" }
    }
  }
}

Authentication

The proxy's mcp_… key, one of two ways (checked in this order):

MethodExampleNotes
Authorization headerAuthorization: Bearer mcp_…Preferred
x-mcp-key headerx-mcp-key: mcp_…For clients that reserve Authorization

A ?key= query parameter is not accepted. A long-lived key in a URL is recorded by every hop that logs a request line and cannot be scrubbed afterwards.

Keys are issued when you create a proxy in the dashboard, shown once, and revocable in one click.

Upstream auth types

TypeCredential sourcePath
Token (default)A credential stored on your webhookTV → webhook /v1/proxy → webhook injects and calls upstream
tv_sessionToken Vault's own session token (tvsess_…), auto-refreshed and bound to an agentTV injects Authorization: Bearer tvsess_… and dials the upstream directly — no webhook hop, because the injected token is TV's own, not a stored credential

tv_session is for gating your own MCP servers with Token Vault identities: your server validates the session via the introspection endpoint.

Behaviour notes

  • Upstream 3xx responses are not followed (the bearer must never leak to a redirect target).
  • Expired stored credentials are refreshed by your webhook before the upstream call — the agent never sees a 401.
  • Policy denials: on GET/DELETE/OPTIONS (no JSON-RPC body), the standard POLICY_DENIED body — 403 for most rule types, 429 for an ABAC rate_limit rule. On POST, a rate_limit rule denial is the -32029 JSON-RPC shape (429) described below; any other rule denies with the plain 403 body above (this endpoint has no tool result to attach a non-rate-limit denial to — unlike /api/agents/mcp, it's a transparent proxy with no tools of its own).
  • Webhook offline → 502 with code WEBHOOK_UNAVAILABLE: a harder form of the kill switch.

Rate limiting and JSON-RPC error shape

This endpoint shares the same penalty box → floor → account-aggregate pipeline as the MCP credentials endpoint — its own proxy_mcp floor scope (300/minute per proxy) in place of the agent's agent_credentials scope. initialize, tools/list, and notifications/* are exempt from the floor and never strike, but still count against the account-wide aggregate ceiling; the SSE GET transport probe always counts against the full floor.

A POST denial (limiter, penalty box, or a policy rate_limit rule) comes back as a JSON-RPC error carrying your request's id, HTTP 429, and Retry-After — the same {"code":-32029,...} shape documented on the MCP credentials endpoint. GET/DELETE/OPTIONS denials, which carry no JSON-RPC body, keep the plain-JSON shape shown above instead.

A JSON-RPC batch body is passed through to your webhook/upstream as-is (this endpoint is a transparent proxy, not a tool server) — it's still rate-limited as a single unit the same way the credentials endpoint's batches are.

Ready to try it?

Sign up free with Google — your credentials stay on your own webhook, and the quickstart gets an agent fetching its first credential in about ten minutes.

On this page