docs(mcp): document the remote transport, deprecate stdio - #85
Merged
Conversation
Rewrites docs/core/mcp.md for the HTTP surface shipped in authorizerdev/authorizer#757. The page led with `authorizer mcp` (stdio) and described it as stdio-only by design. Both statements are now wrong: the deployable transport is `--mcp-enabled` at POST <url>/mcp, and stdio is deprecated for removal in 2.5.0. It now opens with the difference that actually matters — per-request identity and shared providers, versus one process-wide bearer and a second copy of the whole server — then walks the discovery chain end to end so an operator can follow it with curl. The client-support table is deliberately blunt. Authorizer has no RFC 7591 dynamic client registration, so clients that self-register are not supported and a pre-registered client ID is the path. Claude Code needs both loopback redirect URIs registered because it binds an ephemeral port. Saying so in a table beats someone discovering it from a 401. The "protecting your own MCP server" half is kept — it is still valid and is what someone with their own resource server needs — but demoted, since it is no longer the only way to use MCP with Authorizer. Also adds the two specs behind the work: the transport design and the SDK and examples rollout plan.
✅ Deploy Preview for authorizerdev-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Tested against Claude Code 2.1.226. The OAuth path does NOT work: the client refuses with "Incompatible auth server: does not support dynamic client registration" and does not fall back to a manually-supplied client id. The earlier table claimed it worked once RFC 8252 loopback matching landed, which was an inference from Anthropic's docs rather than an observation. What does work, verified end to end: a static bearer token bound to <url>/mcp. claude mcp list reports Connected, and tools/list and tools/call both function. The claude.ai custom-connector row is downgraded to unverified for the same reason — it rests on the same inference that just failed for Claude Code.
A reader (or reviewer) hitting the missing /register endpoint should find the reasoning rather than assume an oversight. Records that the MCP spec 2025-11-25 demoted DCR to backwards-compat and made CIMD the SHOULD, what Auth0, Keycloak, Google and Anthropic actually do, and why CIMD is the planned path here.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documents the remote MCP transport shipped in authorizerdev/authorizer#757, and demotes the stdio subcommand it replaces.
Why the page needed rewriting, not editing
docs/core/mcp.mdled withauthorizer mcpand stated that stdio was the only supported transport by design. Both are now false. The deployable transport is--mcp-enabledatPOST <url>/mcp; stdio is deprecated and removed in 2.5.0.The page now opens with the difference that actually decides which one you want:
--mcp-enabled)authorizer mcp)--mcp-bearerThen it walks the discovery chain end to end — 401 →
WWW-Authenticate→ RFC 9728 metadata → OAuth withresource— concretely enough to follow with curl.The client table is deliberately blunt
Authorizer has no RFC 7591 dynamic client registration, so clients that self-register are not supported and a pre-registered client ID is the path. Claude Code needs both loopback redirect URIs registered, because it binds an ephemeral port and RFC 8252 §7.3 requires the server to ignore it.
Both facts are the kind people otherwise discover from an undiagnosable 401, so they are stated in a table rather than buried in prose.
What is kept
The "Authorizer as the authorization server protecting your own MCP server" half is still correct and still needed by anyone running their own resource server. It is demoted rather than removed, since it is no longer the only way to use MCP with Authorizer.
Also included
Two specs, for the record of why the design is what it is:
specs/2026-08-10-mcp-http-transport.md— the transport design: why a path and not a port, how the audience boundary is made structural, what is deferred (CIMD and the consent screen it requires, delegated tokens at/mcp) and why.specs/2026-08-10-mcp-sdk-and-examples-plan.md— the SDK and examples rollout, including the one breaking note for SDK authors: a refresh naming a different resource is nowinvalid_targetrather than silently ignored.Companion PRs: authorizerdev/authorizer#757 (server), authorizer-js and examples.