Get started

Authentication

Every request to /mcp must carry a Bearer token. Today that's a shared static token stored in AWS Secrets Manager. Per-user OAuth via Auth0 is the MVP target.

Header shape

Every HTTP request to the MCP endpoint (GET, POST, DELETE on /mcp) must include:

http
Authorization: Bearer <YOUR_TOKEN>
Content-Type: application/json
MCP-Protocol-Version: 2025-03-26

For a stateful session, the client also echoes the mcp-session-id header on every follow-up request after initialize. See Transport & endpoints for the full session-lifecycle contract.

Where the token lives

The expected token is read from AWS Secrets Manager at server start. The server expects a JSON secret at the ARN in CONFIG_SECRET_ARN with a mcpBearerToken field:

jsonSecrets Manager value
{
  "mcpBearerToken": "GENERATED_RANDOM_TOKEN"
}

The token is cached in-process; rotating it requires either an SDK push (production) or a server restart (dev). There is no live reload yet.

Token rotation

Rotate by writing a new value to the same secret ARN and restarting the MCP service. ECS deployments restart on every push, so in production the cycle is:

  1. Write the new value to Secrets Manager (new version).
  2. Update all clients with the new token.
  3. Trigger a no-op deploy of the cortex-mcp-server service to pick up the new value.
  4. Old token continues to work until step 3 completes (no overlap window today).

Failure modes

SymptomCauseFix
HTTP 401{"error":"Unauthorized"}Missing, malformed, or mismatched Authorization header.Verify the header literal matches Bearer <TOKEN> exactly (case-sensitive scheme, single space).
HTTP 401 on a working tokenSecrets Manager value rotated; server cache stale.Restart the MCP service or roll the ECS task.
Client never connects, no 401Request body has no Authorization header at all.Some MCP client libraries scope per-server headers separately — confirm they ride POST/GET/DELETE alike.

OAuth (planned, MVP)

Before public MVP, the bearer model is replaced by per-user OAuth via Auth0. The transport contract stays identical — only the token issuance flow changes:

  • User authenticates via the operator dashboard (Auth0) and approves the MCP scopes their client needs.
  • Operator dashboard mints a per-(user × client) token. Token carries the user's sub claim; the server resolves it to a tenant + row-level-security context.
  • Client config is identical — same Authorization: Bearer <token> header, just a different token per client.

Quotas and inference budgets become per-(user × client) at the same time. The current per-token rate-limit code already partitions by token, so the wiring is plumbing rather than a protocol break.