Skip to content

Let the client_credentials and jwt-bearer grants run without Protected Resource Metadata - #557

Merged
koic merged 1 commit into
modelcontextprotocol:mainfrom
koic:run_the_extension_grants_without_protected_resource_metadata
Sep 18, 2026
Merged

koic merged 1 commit into
modelcontextprotocol:mainfrom
koic:run_the_extension_grants_without_protected_resource_metadata

Conversation

@koic

@koic koic commented Sep 17, 2026

Copy link
Copy Markdown
Member

Motivation and Context

When a server publishes no Protected Resource Metadata, discovery takes the legacy 2025-03-26 path and prm is nil. The authorization-code branch of run! allowed for that by passing prm || {} to resolve_scope, but run_client_credentials! and run_jwt_bearer! passed prm as is, and resolve_scope then called prm["scopes_supported"] on nil. Without a non-empty challenge scope, a ClientCredentialsProvider or CrossAppAccessProvider pointed at such a server therefore failed with NoMethodError after discovery and before the token request or the ID-JAG callback, instead of running its grant against the legacy authorization base the way Provider does.

resolve_scope now treats a missing PRM as advertising no scopes, so the challenge scope or the provider's own scope applies, and the authorization-code branch passes prm unchanged like the other two.

How Has This Been Tested?

New tests in test/mcp/client/oauth/flow_test.rb run the client_credentials grant against a PRM-less server with metadata at the origin, checking the provider's scope, the resource, and the recorded issuer, and run the jwt-bearer grant against a server without any metadata, checking the default token endpoint, the assertion audience, the resource, and the recorded issuer. Both raise NoMethodError against the previous library.

Breaking Changes

None.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

…d Resource Metadata

## Motivation and Context

When a server publishes no Protected Resource Metadata, discovery takes the legacy 2025-03-26 path and `prm` is `nil`.
The authorization-code branch of `run!` allowed for that by passing `prm || {}` to `resolve_scope`,
but `run_client_credentials!` and `run_jwt_bearer!` passed `prm` as is, and `resolve_scope` then
called `prm["scopes_supported"]` on `nil`. Without a non-empty challenge scope, a `ClientCredentialsProvider` or
`CrossAppAccessProvider` pointed at such a server therefore failed with `NoMethodError` after discovery and before
the token request or the ID-JAG callback, instead of running its grant against the legacy authorization base
the way `Provider` does.

`resolve_scope` now treats a missing PRM as advertising no scopes, so the challenge scope or the provider's own scope applies,
and the authorization-code branch passes `prm` unchanged like the other two.

## How Has This Been Tested?

New tests in `test/mcp/client/oauth/flow_test.rb` run the `client_credentials` grant against a PRM-less server with metadata
at the origin, checking the provider's scope, the `resource`, and the recorded issuer, and run the `jwt-bearer` grant against
a server without any metadata, checking the default token endpoint, the assertion audience, the `resource`, and the recorded
issuer. Both raise `NoMethodError` against the previous library.

## Breaking Changes

None.
@koic
koic merged commit 2c33ad0 into modelcontextprotocol:main Sep 18, 2026
11 checks passed
@koic
koic deleted the run_the_extension_grants_without_protected_resource_metadata branch September 18, 2026 15:12
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