docs(mcp): point examples at the HTTP transport - #18
Merged
Conversation
- Go examples: import path -> authorizer-go/v2, pin v2.2.0-rc.4; drop local `replace` directives now that the tag ships the client_credentials/client_assertion APIs (pulls authorizer-proto-go). - Python examples: bump authorizer-py to 0.3.0rc3 (pulls authorizer-proto). - with-rag-fga: PaginatedRequest was removed in 0.3.0rc3; use ListUsersRequest. - with-agents-python: switch editable-local install to released authorizer-py. - Refresh stale README/Dockerfile notes about the removed replaces.
Bump every example depending on authorizer-js or authorizer-react to the released RCs, matching each file's existing caret pin style. - authorizer-js ^3.2.1 -> ^3.3.0-rc.4: with-nextjs, with-nextjs-13, with-react-native-expo, with-express-js (direct); with-vanilla-js and with-vanilla-js-custom-ui via the unpkg UMD CDN URL. - authorizer-react ^2.0.7 -> ^2.2.0-rc.3: with-nextjs, with-nextjs-13, with-react, with-gatsbyjs. Transitive authorizer-js dedupes up to 3.3.0-rc.4 in each lockfile. - No code changes needed: no example calls the flattened admin pagination API, sets is_multi_factor_auth_enabled on signup, or composes AuthorizerVerifyOtp directly, so none of the RC breaking changes apply.
# Conflicts: # with-agents-python/README.md # with-agents-python/demo.py # with-express-js/package-lock.json # with-express-js/package.json # with-gatsbyjs/package.json # with-go/go.mod # with-go/go.sum # with-nextjs-13/package-lock.json # with-nextjs-13/package.json # with-nextjs/package-lock.json # with-nextjs/package.json # with-python/README.md # with-react-native-expo/package-lock.json # with-react-native-expo/package.json # with-react/package-lock.json # with-react/package.json # with-vanilla-js-custom-ui/index.html # with-vanilla-js-custom-ui/login.html # with-vanilla-js/index.html
rc.18 DeleteUserRequest dropped `email` for `id` (a phone-only signup has no email). The three raw-GraphQL callers now resolve the id via _user first.
The vendored gen/ stubs predated the DeleteUserRequest email->id change, so they no longer matched rc.18. Depend on authorizer-proto-go v0.2.0-rc.1 -- the same module the Go SDK uses -- and drop ~10k lines of vendored code. Both Go examples hit the 2.4.0 MFA offer and neither settled it: authorizer-go keeps no cookie jar and gRPC has no cookies at all, so skip_mfa_setup could not find its session. Each now relays the mfa_session by hand (net/http response cookies; set-cookie response metadata over gRPC).
0.3.0rc4 has the typed skip_mfa_setup and the flattened admin pagination, so with-python drops both 0.2.0 escape hatches and uses AuthorizerAdminClient .users() directly. with-agents-python and with-rag-fga never settled the 2.4.0 MFA offer, so neither could get a token against a default server: httpx keeps the mfa_session cookie in its jar but will not replay a Secure cookie over plain http (--app-cookie-secure defaults to true). Both now pass it by hand, as with-python already did.
authorizer-js ^4.0.0-rc.0 (deleteUser takes id, matching the server's DeleteUserRequest), authorizer-react ^2.2.0-rc.7 (which requires that js major, and moves @storybook/preset-scss out of runtime deps), authorizer-vue 1.0.0-beta.2. Locks regenerated -- each resolves a single deduped copy.
…not allow Section 8 asserted the pre-2.4.0 behaviour: no agent type in the model and the agent inherits the user's full authority. rc.18 fails closed instead -- the agent half of perms(agent) n perms(user) cannot be evaluated, so the check is denied, and --fga-allow-unconstrained-agents is the opt-out for deployments still migrating. Also make SERVER_DIR overridable in run-server.sh and mcp-agent.mjs, so the demos can be pointed at a specific server checkout.
rc.18 enforces RFC 6238 5.2 -- a code the server already accepted is rejected on a second attempt. Enrollment and the login challenge run seconds apart, inside one 30s step, so the recipe was replaying the same code and failing with 'invalid otp'. Also make SERVER_DIR overridable in run-server.sh.
The authorizer image runs as uid 1000. A named volume mounted at /data is created root-owned, so the process could not create the SQLite file and every one of these stacks died at boot with 'unable to open database file'. Put the db under /authorizer, which the image chowns to that uid. with-microservices: the gateway forwarded X-User-Email from req.auth.email, but an access token carries no email claim -- profile claims are in the ID token and at /userinfo -- so it was always empty. Forward the sub only and say why.
with-mcp's bonus section described `authorizer mcp` (stdio) as the built-in option. It now leads with `--mcp-enabled`, the discovery chain a client walks on its own, and the client-registration steps that actually matter in practice — Authorizer has no RFC 7591 dynamic registration, so a pre-created client ID is the path, and Claude Code needs both loopback redirect URIs registered because it binds an ephemeral port. with-agent-permissions deliberately STAYS on stdio, and now says why: it drives the tools with an RFC 8693 delegated token, and the HTTP surface does not accept those. Delegated tokens are stateless, so they fail the session check the HTTP path requires; widening it is a separate decision. Silently leaving the example on a deprecated transport with no explanation would read as an oversight.
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 offers no manual client-id fallback. The previous text described registering redirect URIs for an OAuth flow that cannot start. Replaced with the static-token path, which is verified working end to end: claude mcp list reports Connected, and tools/list and tools/call both function.
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.
Points the examples at the remote MCP transport shipped in authorizerdev/authorizer#757.
with-mcpIts bonus section described
authorizer mcp(stdio) as Authorizer's built-in MCP server. That is now the deprecated one. It leads with--mcp-enabled, shows the discovery chain a client walks unaided, and states the two client-registration facts that otherwise surface as an undiagnosable 401:The main body of the example — protecting your own MCP server with Authorizer-issued tokens — is unchanged and still correct.
with-agent-permissionsstays on stdio, deliberatelyThis one cannot move, and the README now says why rather than leaving it looking neglected.
It drives the MCP tools with an RFC 8693 delegated token, and the HTTP surface does not accept those: delegated tokens are stateless, so they fail the session check the HTTP path requires. Widening that path gives up the byte-for-byte comparison against a stored token and is a separate decision, tracked in the transport spec.
So agent-delegation over MCP is a stdio-only story until that lands. Worth knowing before anyone tries to "modernise" the example and finds it 401s.
Verification
Docs-only — no example code changed. The stdio path these examples depend on still works:
make smokein the server repo exercises it end to end (mcp_stdio), and I confirmed the binary still serves it, now printing the deprecation notice.Companion PRs: authorizerdev/authorizer#757 (server), authorizerdev/docs#85, authorizerdev/authorizer-js#54.