Skip to content

feat(with-agent-permissions): drive MCP over HTTP - #21

Merged
lakhansamani merged 2 commits into
mainfrom
feat/mcp-http-agent-example
Aug 15, 2026
Merged

feat(with-agent-permissions): drive MCP over HTTP#21
lakhansamani merged 2 commits into
mainfrom
feat/mcp-http-agent-example

Conversation

@lakhansamani

Copy link
Copy Markdown
Contributor

/mcp accepts RFC 8693 delegated tokens as of authorizerdev/authorizer#773, so this demo drops the deprecated authorizer mcp stdio subcommand and the second database connection it opened.

What changed

  • mcp-agent.mjs speaks Streamable HTTP to the running server instead of spawning a subprocess. No go build, no duplicate provider stack, no --mcp-bearer.
  • The exchange binds to <url>/mcp, not <url>. The audience selects the surface, so a token minted for the bare URL is refused at /mcp — the most common way this gets misconfigured, and now called out in the README's gotchas.
  • run-server.sh passes --mcp-enabled.
  • The control run moves to /graphql, because the user's ordinary login token is — correctly — rejected at /mcp. The run now asserts that rejection explicitly, so the transport difference demonstrates the audience boundary instead of being an awkward footnote. Same operation either way: the MCP tool dispatches to what the GraphQL query calls.

Also fixes a stale claim in with-mcp/README.md that Authorizer has neither DCR nor CIMD. Both ship behind --enable-dynamic-client-registration / --enable-client-id-metadata-document; the note predated them and told readers the browser OAuth path was unreachable.

Verification

Run live against a local server on the feature branch:

== Driving the real MCP server over HTTP (delegated token) ==
  ✓ check_permissions q4-plan -> allowed
  ✓ check_permissions payroll -> DENIED
  ✓ list_permissions includes q4-plan
  ✓ list_permissions EXCLUDES payroll

== The user's ordinary login token cannot open /mcp ==
  ✓ a login token is refused at /mcp

== Control: the same check as the USER, over /graphql ==
  ✓ check_permissions q4-plan -> allowed
  ✓ check_permissions payroll -> allowed (the user CAN see it)

The minted token decodes to aud=http://localhost:8098/mcp, iss=http://localhost:8098 — audience is the MCP resource, issuer the bare URL.

Requires authorizerdev/authorizer#773. Against a server without it, the exchange still succeeds but /mcp returns 401.

Both ship behind --enable-dynamic-client-registration and
--enable-client-id-metadata-document. The note predated them and told
readers the browser OAuth path was unreachable.
/mcp accepts RFC 8693 delegated tokens now, so the demo drops the
deprecated `authorizer mcp` stdio subcommand and the second database
connection it opened.

The exchange binds the token to <url>/mcp, not <url>. The audience
selects the surface, so a token minted for the bare URL is refused at
/mcp — the most common way this is misconfigured.

The control run moves to /graphql because the user's ordinary login
token is, correctly, rejected at /mcp. Same operation either way.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant