[v2] RFC 9728 PRM URLs and resource matching drop query components
Dieses Issue hat noch niemand übernommen.
Bewertung
- Schwierigkeit
- 3/5
- Geschätzter Aufwand
- 1-2 Tage
- Anfängerfreundlichkeit
- 74/100
- Issue-Typ
- Bug
- Klarheit
- Klar beschrieben
- Aktivitätsstatus
- Aktiv
- Tech-Stack
- python
- Bereich
- authentication
Rechercherichtung
Beginne mit mcp.server.auth.routes.build_resource_metadata_url(), mcp.client.auth.utils.build_protected_resource_metadata_discovery_urls() und mcp.shared.auth_utils.check_resource_allowed(), und verfolge dann OAuthClientProvider._validate_resource_match(). Stelle die im Issue gezeigten Fälle mit Query-Parametern nach und füge fokussierte Auth-Tests hinzu; fertig ist die Arbeit, wenn Metadaten-URLs die Query beibehalten und unterschiedliche Query-Komponenten nicht mehr übereinstimmen.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Beschreibung
What happened?
While testing the v2 auth/protected-resource-metadata path, I noticed query-bearing resource identifiers are treated as if the query is not part of the resource.
For a resource server URL like:
https://api.example.com/mcp?tenant=a
three SDK paths currently drop or ignore ?tenant=a:
mcp.server.auth.routes.build_resource_metadata_url()returns:
https://api.example.com/.well-known/oauth-protected-resource/mcp
mcp.client.auth.utils.build_protected_resource_metadata_discovery_urls(None, resource)also tries:
https://api.example.com/.well-known/oauth-protected-resource/mcp
https://api.example.com/.well-known/oauth-protected-resource
mcp.shared.auth_utils.check_resource_allowed()treats different query components as matching, so the client accepts protected resource metadata for?tenant=bwhen the server URL was?tenant=a.
This is latent for path-only deployments, but it matters for query-routed or multi-tenant resource identifiers.
What did you expect?
RFC 9728 derives the protected-resource metadata URL by inserting /.well-known/oauth-protected-resource before the protected resource path and/or query. If the resource identifier includes a query component, the derived metadata URL and resource validation should not silently collapse it with a different query.
For https://api.example.com/mcp?tenant=a, I expected the path-specific metadata URL to be:
https://api.example.com/.well-known/oauth-protected-resource/mcp?tenant=a
And a PRM document whose resource is https://api.example.com/mcp?tenant=b should not validate for a client configured with https://api.example.com/mcp?tenant=a.
Code to reproduce
import anyio
from pydantic import AnyHttpUrl, AnyUrl
from mcp.client.auth import OAuthClientProvider
from mcp.client.auth.utils import build_protected_resource_metadata_discovery_urls
from mcp.server.auth.routes import build_resource_metadata_url
from mcp.shared.auth import OAuthClientMetadata, ProtectedResourceMetadata
from mcp.shared.auth_utils import check_resource_allowed
from tests.interaction.auth._harness import InMemoryTokenStorage
async def main() -> None:
resource = "https://api.example.com/mcp?tenant=a"
print(build_resource_metadata_url(AnyHttpUrl(resource)))
print(build_protected_resource_metadata_discovery_urls(None, resource))
print(check_resource_allowed(
"https://api.example.com/mcp?tenant=a",
"https://api.example.com/mcp?tenant=b",
))
provider = OAuthClientProvider(
server_url=resource,
client_metadata=OAuthClientMetadata(
client_name="probe",
client_uri=AnyHttpUrl("https://example.com"),
redirect_uris=[AnyUrl("http://localhost:3030/callback")],
),
storage=InMemoryTokenStorage(),
)
prm = ProtectedResourceMetadata(
resource=AnyHttpUrl("https://api.example.com/mcp?tenant=b"),
authorization_servers=[AnyHttpUrl("https://auth.example.com")],
)
await provider._validate_resource_match(prm)
print("accepted mismatched query")
anyio.run(main)
Current output:
https://api.example.com/.well-known/oauth-protected-resource/mcp
['https://api.example.com/.well-known/oauth-protected-resource/mcp', 'https://api.example.com/.well-known/oauth-protected-resource']
True
accepted mismatched query
SDK version
Current main branch, v2 development line.
Area
Auth
AI-assisted (Claude/Codex) for navigation and review; change authored and understood by me.
- Vorherrschende Sprache
- Python
- Sterne
- 24.3k
- Forks
- 4k
- Ø Merge
- 1 T. 11 Std.
- Gemergte PRs (30 T.)
- 30
Beitragsleitfaden
Erste Schritte
- Lesen Sie das ganze Issue und danach den Beitragsleitfaden des Projekts.
- Schreiben Sie ins Issue, dass Sie es übernehmen — das erspart doppelte Arbeit.
- Forken Sie das Repository und arbeiten Sie in einem Branch.
- Öffnen Sie einen Pull Request, der die Issue-Nummer nennt.
Mehr aus modelcontextprotocol/python-sdk
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
modelcontextprotocol/python-sdk#3566 ·
-
v1 v2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 85/100
modelcontextprotocol/python-sdk#3546 · 5 Kommentare ·
-
v1 v2
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 76/100
modelcontextprotocol/python-sdk#3545 · 1 Kommentar ·
-
v1 v2
Schwierigkeit 1/5 Unter einer Stunde Anfängerfreundlichkeit 91/100
modelcontextprotocol/python-sdk#3508 · 2 Kommentare ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 64/100
modelcontextprotocol/python-sdk#3504 ·
Alle Issues in modelcontextprotocol/python-sdk
Ähnliche Issues
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
anthropics/skills#1811 · 1 Kommentar ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
speaches-ai/speaches#678 ·
-
bug
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
datalayer/mcp-compose#42 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 75/100
conda-forge/spacy-feedstock#177 ·
-
Schwierigkeit 2/5 1-3 Stunden Anfängerfreundlichkeit 70/100
UKGovernmentBEIS/inspect_evals#2523 ·