Skip to main content
Needs an MCP OAuth 2.1 authorization server. The upstream never sees a client token.
1

Set the signing secret

Must match your authorization server’s signingSecret. Pass it by environment variable, not on the command line.
2

Start the gateway

--mcp-resource is the token audience: your authorization server must set it as aud. Terminate TLS in front and route the public URL to port 3000.
3

Check the challenge

Clients then follow the challenge on their own.

What MCP mode does

Per route scopes and agent policy

requiredPermissions checks the agent in the agent_id claim, against the gateway’s TheAuth database. No agent_id means 403. Use requiredScopes for tokens not tied to an agent.

Embedded mode

For a same-process authorization server or a revocation list, pass the real module.
Only requireMcpAuth and getProtectedResourceMetadata are used, so a shared-key validation module is enough. The CLI does this.

Limits

  • Path level only. Tool names sit in the unparsed JSON-RPC body. Enforce per tool rules upstream or split routes.
  • The CLI cannot see revocations. Tokens stay valid until exp. Use short lifetimes, or embedded mode with a shared jtiDenylist.
  • HS256 shared secret. Anyone holding it can mint tokens. The CLI does not fetch JWKS.
  • Not an authorization server. Registration, login, consent and issuing stay upstream.
  • Well-known paths are shadowed. Upstream /.well-known/oauth-protected-resource routes never run.
  • Sessions are not bound to tokens. Mcp-Session-Id passes through, and a second authenticated client that learns an ID could use it. Treat IDs as secrets.
  • Audit only with agent_id. Other OAuth tokens are enforced but not logged.
  • Rate limits are in memory, per process.
  • HTTP only. No TLS or WebSocket. The legacy stdio transport is out of scope.
  • Not tested with a real MCP client. Unit and local socket tests only. Add headers missing from the default list to cors.headers.
Last modified on October 17, 2026