Skip to content

Preserve query components in PRM resource URLs#3066

Open
mayankbohradev wants to merge 1 commit into
modelcontextprotocol:mainfrom
mayankbohradev:codex/fix-prm-query-resource
Open

Preserve query components in PRM resource URLs#3066
mayankbohradev wants to merge 1 commit into
modelcontextprotocol:mainfrom
mayankbohradev:codex/fix-prm-query-resource

Conversation

@mayankbohradev

Copy link
Copy Markdown

Summary

Fixes query-bearing protected-resource identifiers in the OAuth protected resource metadata path.

When a server URL includes a query component, for example https://api.example.com/mcp?tenant=a, the SDK now:

  • preserves the query when deriving the RFC 9728 protected resource metadata URL;
  • preserves the query in client fallback PRM discovery URLs;
  • treats different query components as different resource identifiers during PRM resource validation.

Closes #3065.

Why

RFC 9728's well-known URL construction inserts /.well-known/oauth-protected-resource before the resource path and/or query. Dropping the query collapses query-routed resource identifiers, so a deployment using ?tenant=a and ?tenant=b can publish or accept the wrong protected resource metadata.

Tests

  • uv run --frozen pytest tests/client/test_auth.py::TestSEP985Discovery::test_prm_discovery_preserves_server_url_query_component tests/client/test_auth.py::test_validate_resource_rejects_mismatched_query_component tests/server/auth/test_protected_resource.py::test_metadata_url_construction_preserves_query_component tests/shared/test_auth_utils.py::test_check_resource_allowed_rejects_different_queries -q
  • uv run --frozen pytest tests/client/test_auth.py tests/shared/test_auth_utils.py tests/server/auth/test_protected_resource.py tests/interaction/auth/test_discovery.py -q
  • uv run --frozen ruff format src/mcp/server/auth/routes.py src/mcp/client/auth/utils.py src/mcp/shared/auth_utils.py tests/server/auth/test_protected_resource.py tests/client/test_auth.py tests/shared/test_auth_utils.py
  • uv run --frozen ruff check src/mcp/server/auth/routes.py src/mcp/client/auth/utils.py src/mcp/shared/auth_utils.py tests/server/auth/test_protected_resource.py tests/client/test_auth.py tests/shared/test_auth_utils.py
  • uv run --frozen pyright src/mcp/server/auth/routes.py src/mcp/client/auth/utils.py src/mcp/shared/auth_utils.py tests/server/auth/test_protected_resource.py tests/client/test_auth.py tests/shared/test_auth_utils.py
  • ./scripts/test — 5293 passed, 9 skipped, 1 xfailed; coverage 100%; strict-no-cover clean

Note: full uv run --frozen pyright currently reports two errors in unrelated tests/transports/stdio/test_lifecycle.py around os.waitid typing on this machine. The changed files pass scoped pyright as listed above.

AI-assisted (Claude/Codex) for navigation and review; change authored and understood by me.

@mayankbohradev mayankbohradev marked this pull request as ready for review July 6, 2026 08:21
@mayankbohradev

Copy link
Copy Markdown
Author

Hi @maxisbey, I marked this ready for review. GitHub does not let me request reviewers from this fork account, so tagging you here since this is in the v2 auth / protected-resource-metadata path and is linked to #3065.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 6 files

Re-trigger cubic

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.

[v2] RFC 9728 PRM URLs and resource matching drop query components

1 participant