Skip to content

fix(mcp): add RFC 9728 resource to protected resource metadata - #5521

Open
diegohh0411 wants to merge 7 commits into
macro-inc:mainfrom
diegohh0411:fix/mcp-protected-resource-metadata
Open

fix(mcp): add RFC 9728 resource to protected resource metadata#5521
diegohh0411 wants to merge 7 commits into
macro-inc:mainfrom
diegohh0411:fix/mcp-protected-resource-metadata

Conversation

@diegohh0411

@diegohh0411 diegohh0411 commented Aug 9, 2026

Copy link
Copy Markdown

Summary

Strict MCP clients (Grok Build / rmcp) fail OAuth discovery when protected resource metadata is missing the RFC 9728 resource field. This PR fills that out and a couple of related gaps that came up while wiring Grok.

What changed:

  • protected_resource_metadata now returns resource ({public_url}/mcp) and resource_name ("Macro MCP"), still using the existing public_url / MCP_PUBLIC_URL wiring. No new env vars.
  • Keeps authorization_server / authorization_servers. Does not invent scopes_supported (we do not have resource-level MCP scopes today; FusionAuth scopes are identity scopes, not MCP resource scopes).
  • Origin, path-insertion, and path-style PRM well-known URLs all serve the same document (pre-existing multi-path layout; WWW-Authenticate still points at /.well-known/oauth-protected-resource/mcp).
  • Grok Build added next to Claude Code / Codex in the in-app MCP setup cards and in apps/docs/AI/mcp/overview.mdx.

Fixes #5519

Note on the tokio dev-dependency

mcp_auth_proxy production code is already async (axum, redis aio/tokio-comp, FusionAuth). It does not call tokio:: by name, so Tokio only showed up transitively before this PR. That is fine for the service itself.

The route tests for the three discovery URLs use #[tokio::test] + tower::ServiceExt::oneshot. That needs a direct tokio link with macros/rt so the crate can resolve tokio::test. A transitive dep is not enough.

Putting tokio under [dev-dependencies] matches other library-style crates here (mcp_client, fusionauth, etc.). Runtime binaries like mcp_service already declare Tokio for the process; this crate does not need that. Test-only is the smaller footprint.

Test plan

  • cargo test -p mcp_auth_proxy (domain metadata + route discovery)
  • Unit test: resource, AS fields, resource_name, no scopes_supported
  • Route tests: origin + path-insertion + path-style PRM return the doc
  • cargo clippy -p mcp_auth_proxy --all-targets -- -D warnings
  • Manual UI: Grok Build dropdown in Settings → MCP server
  • After deploy: curl well-known PRM and confirm resource is present
  • After deploy: Grok /mcps → authenticate Macro MCP (i) gets past metadata discovery

Questions for maintainers

A few judgment calls where I'd rather get a maintainer read than invent house style:

  1. Route tests vs full mcp_router. Discovery tests use a small router that only mounts the three PRM paths (same handlers as production). That keeps JWT validation and a dummy MCP nest out of the harness. If you prefer route tests to call the real mcp_router factory so the path table cannot drift, I can rework that.

  2. Trailing slash on MCP_PUBLIC_URL. resource is built as {public_url}/mcp. RFC 9728 wants an exact string match with the client's resource URL. I have not normalized a trailing slash on the base. Worth a trim if that config is easy to mis-set in deploy.

  3. Shared test doubles. NoopInflightAuth / DummyOAuthProvider are duplicated in the domain and route test modules. I left them local so a shared #[cfg(test)] support module does not grow the crate surface for a small metadata fix. Fine to extract if you want one place for fakes.

Happy to adjust any of these in a follow-up commit.

Spec for fixing missing required resource field so MCP OAuth clients
(e.g. Grok/rmcp) can complete discovery.
Failing test for required resource and recommended resource_name
before the metadata implementation.

Refs: macro-inc#5519
Strict MCP clients (Grok/rmcp) require the resource field on
protected resource metadata. Derive resource and resource_name
from the existing public_url; omit scopes_supported.

Fixes: macro-inc#5519
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ff16d006-0c73-403e-b9e9-0dd023d67e3b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Updated MCP protected-resource metadata to align with RFC 9728.
    • Added a public MCP resource URL and the display name “Macro MCP.”
    • Preserved authorization server metadata while omitting unsupported scope information.
  • Tests

    • Added coverage verifying the updated metadata and RFC 9728-compliant fields.
  • Documentation

    • Added an approved design document describing the metadata updates and verification criteria.

Walkthrough

The change adds an RFC 9728 design for Macro MCP protected-resource metadata. The service now includes resource_name with the value "Macro MCP" while retaining the existing resource and authorization server fields. New tests verify these fields and confirm that scopes_supported is omitted.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The implementation adds the required RFC 9728 resource, recommended resource_name, existing authorization server fields, tests, and no new configuration for [#5519].
Out of Scope Changes check ✅ Passed The design document and unit tests support the linked RFC 9728 metadata fix, and no unrelated code changes are present.
Title check ✅ Passed The title uses conventional commits format, stays under 72 characters, and accurately describes the RFC 9728 metadata change.
Description check ✅ Passed The description clearly explains the metadata changes, rationale, tests, and deployment checks related to the pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/specs/2026-08-08-mcp-protected-resource-metadata-design.md`:
- Around line 10-15: Ensure protected-resource metadata routes identify the same
resource as their returned resource value. In
docs/superpowers/specs/2026-08-08-mcp-protected-resource-metadata-design.md
lines 10-15, make /.well-known/oauth-protected-resource/mcp canonical for
{public_url}/mcp and remove or define redirects for incompatible aliases; in
services/mcp_auth_proxy/src/domain/service.rs lines 202-205, serve metadata only
on the canonical route or redirect aliases before metadata handling, and add
route-level coverage for canonical discovery.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 11b9a110-5ca9-45f7-bd01-f49817d7976d

📥 Commits

Reviewing files that changed from the base of the PR and between a4e2525 and fdc6feb.

📒 Files selected for processing (3)
  • docs/superpowers/specs/2026-08-08-mcp-protected-resource-metadata-design.md
  • services/mcp_auth_proxy/src/domain/service.rs
  • services/mcp_auth_proxy/src/domain/service/test.rs

Comment thread docs/superpowers/specs/2026-08-08-mcp-protected-resource-metadata-design.md Outdated
@diegohh0411
diegohh0411 marked this pull request as draft August 9, 2026 12:58
Add Grok Build to the in-app MCP setup cards and docs overview.
Redirect origin-root protected-resource metadata to the RFC 9728
canonical path for /mcp, keep path-style discovery, and cover the
routes with unit tests (CodeRabbit review).

Refs: macro-inc#5519
@diegohh0411
diegohh0411 force-pushed the fix/mcp-protected-resource-metadata branch from df3d2ad to 092e675 Compare August 10, 2026 10:27
Only checking the first element would miss extra or wrong entries.
Keep serving protected resource metadata at
/.well-known/oauth-protected-resource instead of 308ing to the
path-insertion URL. That preserves the pre-existing multi-path layout
maintainers may rely on; the RFC-required resource field is still the
core fix.
@diegohh0411
diegohh0411 marked this pull request as ready for review August 10, 2026 21:10

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove the spec file

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.

fix(mcp): protected resource metadata missing RFC 9728 resource field

2 participants