Skip to content

Request offline_access scope when supported (SEP-2207)#365

Merged
koic merged 1 commit into
modelcontextprotocol:mainfrom
koic:conformance_client_auth_offline_access_scope
May 31, 2026
Merged

Request offline_access scope when supported (SEP-2207)#365
koic merged 1 commit into
modelcontextprotocol:mainfrom
koic:conformance_client_auth_offline_access_scope

Conversation

@koic
Copy link
Copy Markdown
Member

@koic koic commented May 29, 2026

Motivation and Context

SEP-2207 describes how an OAuth client obtains refresh tokens: it declares the refresh_token grant type in its client metadata and requests the offline_access scope, but only when the authorization server advertises offline_access in its metadata scopes_supported. Requesting offline_access when the server does not list it is forbidden.

The Ruby SDK already supports the refresh grant (Flow#refresh!) but never requested offline_access, so it could not obtain a refresh token from a server that gates it behind that scope. This aligns the SDK with the Python and TypeScript SDKs and makes the auth/offline-access-scope conformance scenario pass (previously it reported one warning, sep-2207-client-metadata-grant-types, and was listed in the expected-failures baseline).

The change adds:

  • Flow#augment_scope_with_offline_access, called from run! after resolve_scope, appends offline_access to the requested scope when both the client opted into refresh tokens (its registered grant_types include refresh_token) and the authorization server advertises offline_access in its metadata scopes_supported. Already-present offline_access is not duplicated. Gating on the server advertisement keeps the SDK from ever requesting the scope where it is not supported.
  • conformance/client.rb declares refresh_token in grant_types, an honest reflection of the SDK's refresh support, which clears the SEP-2207 grant-types warning.
  • auth/offline-access-scope is removed from conformance/expected_failures.yml.

How Has This Been Tested?

New Flow tests cover: offline_access is requested when the server advertises it and the client declared the refresh_token grant; offline_access is NOT requested when the client did not declare the grant; offline_access is NOT requested when the server does not advertise it (even with the grant declared); and offline_access is not duplicated when it is already part of the resolved scope.

Conformance: auth/offline-access-scope now passes 14/14 with no warnings, and auth/offline-access-not-supported still passes 13/13 (no regression). bundle exec rake test, bundle exec rake rubocop, and bundle exec rake conformance are all green.

Breaking Changes

None. offline_access is appended only when the client's own grant_types opt into refresh tokens and the authorization server advertises the scope, so existing clients that do neither see no change in the scope they request.

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

@koic koic force-pushed the conformance_client_auth_offline_access_scope branch 2 times, most recently from 0ae44e8 to 3d22e05 Compare May 29, 2026 04:12
## Motivation and Context

SEP-2207 describes how an OAuth client obtains refresh tokens: it
declares the `refresh_token` grant type in its client metadata and
requests the `offline_access` scope, but only when the authorization
server advertises `offline_access` in its metadata `scopes_supported`.
Requesting `offline_access` when the server does not list it is forbidden.

The Ruby SDK already supports the refresh grant (`Flow#refresh!`) but never
requested `offline_access`, so it could not obtain a refresh token from a server
that gates it behind that scope. This aligns the SDK with the Python and TypeScript SDKs
and makes the `auth/offline-access-scope` conformance scenario pass
(previously it reported one warning, `sep-2207-client-metadata-grant-types`,
and was listed in the expected-failures baseline).

The change adds:

- `Flow#augment_scope_with_offline_access`, called from `run!` after
  `resolve_scope`, appends `offline_access` to the requested scope when
  both the client opted into refresh tokens (its registered
  `grant_types` include `refresh_token`) and the authorization server
  advertises `offline_access` in its metadata `scopes_supported`.
  Already-present `offline_access` is not duplicated. Gating on the server
  advertisement keeps the SDK from ever requesting the scope where it is not supported.
- `conformance/client.rb` declares `refresh_token` in `grant_types`, an honest reflection
  of the SDK's refresh support, which clears the SEP-2207 grant-types warning.
- `auth/offline-access-scope` is removed from `conformance/expected_failures.yml`.

## How Has This Been Tested?

New `Flow` tests cover: `offline_access` is requested when the server advertises it
and the client declared the `refresh_token` grant; `offline_access` is NOT requested
when the client did not declare the grant; `offline_access` is NOT requested
when the server does not advertise it (even with the grant declared);
and `offline_access` is not duplicated when it is already part of the resolved scope.

Conformance: `auth/offline-access-scope` now passes 14/14 with no warnings,
and `auth/offline-access-not-supported` still passes 13/13 (no regression).
`bundle exec rake test`, `bundle exec rake rubocop`, and `bundle exec rake conformance`
are all green.

## Breaking Changes

None. `offline_access` is appended only when the client's own `grant_types` opt
into refresh tokens and the authorization server advertises the scope, so existing clients
that do neither see no change in the scope they request.
@koic koic force-pushed the conformance_client_auth_offline_access_scope branch from 3d22e05 to fdca6f5 Compare May 29, 2026 04:14
@koic koic merged commit cf44475 into modelcontextprotocol:main May 31, 2026
11 checks passed
@koic koic deleted the conformance_client_auth_offline_access_scope branch May 31, 2026 16:09
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.

2 participants