feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat: use scopes_supported from resource metadata by default (fixes #580) - #757

Merged
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes
Mar 2, 2026
Merged

feat: use scopes_supported from resource metadata by default (fixes #580)#757
pcarleton merged 6 commits into
modelcontextprotocol:v1.xfrom
antogyn:feat/use-metadata-scopes

Conversation

@antogyn

Copy link
Copy Markdown
Contributor

If available, all scopes in the field scopes_supported from /.well-known/oauth-protected-resource are used by default in:

  • DCR
  • the authorization url

Motivation and Context

See #580

How Has This Been Tested?

I tested this on a custom build of mcp-remote and it works well for the authorization endpoint

I didn't test DCR though because it's not available in my setup, but if you have a suggestion to test it I can do that too

Breaking Changes

It can technically be breaking since the default value is different

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

Additional context

@pcarletonpcarleton left a comment

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.

Overall this change looks good (And consistent with SEP-835), but it has some conflicts with the main branch. if you're able to resolve those, we can merge this in.

@antogyn
antogynforce-pushed the feat/use-metadata-scopes branch from 8386834 to 42d0fd5CompareSeptember 30, 2025 20:56
@antogyn

Copy link
Copy Markdown
ContributorAuthor

Done, thanks for taking a look at this

@antogyn

Copy link
Copy Markdown
ContributorAuthor

Hey @pcarleton, is this still relevant? I resolved the conflicts last month but it didn't get merged, so now there are new conflicts, should I resolve them again or close the MR?

@felixweinbergerfelixweinberger mentioned this pull request Oct 30, 2025
@pcarleton

Copy link
Copy Markdown
Member

hey @antogyn sorry for the slow response. this is still necessary. i'll work on fixing the merge conflicts

@pcarleton
pcarleton requested a review from a team as a code ownerNovember 6, 2025 19:01
pcarleton
pcarleton previously approved these changes Nov 6, 2025
Resolved conflicts in src/client/auth.ts and test/client/auth.test.ts:
- Kept v1.x scope precedence for authorization URL (from SEP-835/modelcontextprotocol#1133)
- Added resourceMetadata to registerClient call in DCR fallback path
- Removed duplicate auth URL scope test (already covered by modelcontextprotocol#1133)
- Kept registerClient scopes_supported test from modelcontextprotocol#757
@pcarleton
pcarleton requested a review from a team as a code ownerMarch 2, 2026 11:11
@changeset-bot

changeset-botBot commented Mar 2, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 41ede96

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@pcarleton
pcarleton changed the base branch from main to v1.xMarch 2, 2026 11:11
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7cdefd3

The changes in this PR will be included in the next version bump.

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pcarleton

Copy link
Copy Markdown
Member

Resolved merge conflicts and rebased onto v1.x.

What remains from the original PR:

  • registerClient now accepts resourceMetadata and uses scopes_supported as the DCR scope fallback
  • Unit test for the DCR scope behavior

What was dropped (already on v1.x via #1133/SEP-835):

  • Authorization URL scope fallback — already implemented with slightly different precedence (PRM scopes prioritized over clientMetadata.scope)
  • The auth-URL scope test was removed as a duplicate of the existing test at test/client/auth.test.ts:2729

Previously, the authorization URL scope was computed inline (SEP-835
precedence: WWW-Auth -> PRM scopes_supported -> clientMetadata.scope)
but DCR used a different precedence (clientMetadata.scope -> PRM).
This could cause mismatches where a client registers with one scope
but requests a different scope during authorize, leading to invalid_scope
errors from strict authorization servers.
Now we compute resolvedScope once using the SEP-835 precedence and
pass it to both registerClient and startAuthorization. This matches
the Python SDK's single-source-of-truth approach (oauth2.py:569-574)
while keeping the TypeScript SDK's clientMetadata.scope fallback
behavior.
registerClient's API is changed from accepting resourceMetadata to
accepting an optional scope string directly. This is simpler and
leaves scope resolution policy to the caller rather than duplicating
it inside registerClient.
@pkg-pr-new

pkg-pr-newBot commented Mar 2, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@modelcontextprotocol/sdk@757

commit: a103efb

@pcarleton

Copy link
Copy Markdown
Member

Pushed one more commit to unify scope resolution. Now scope is computed once in authInternal using the SEP-835 precedence:

  1. scope arg (from WWW-Authenticate header)
  2. PRM scopes_supported
  3. provider.clientMetadata.scope (user-configured fallback)

...and that single resolvedScope is used for both DCR and the authorize URL.

This matches the Python SDK's single-source-of-truth approach (oauth2.py:569-574) and avoids scope mismatches where the client registers with one scope but requests a different one during authorize.

API change:registerClient now takes an optional scope string instead of resourceMetadata. Simpler, and keeps scope-selection policy in one place.

@pcarleton
pcarleton merged commit c9b58d1 into modelcontextprotocol:v1.xMar 2, 2026
7 checks passed
pcarleton added a commit that referenced this pull request Mar 2, 2026
) (#757)
Co-authored-by: Paul Carleton <paulc@anthropic.com>
pcarleton added a commit that referenced this pull request Mar 2, 2026
…-port #757) (#1614)
Co-authored-by: Anthony Giniers <antogyn@gmail.com>
@felixweinbergerfelixweinberger mentioned this pull request Mar 25, 2026
9 tasks
Sign up for freeto 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.

4 participants

@antogyn@pcarleton@mattzcarey@ihrpr