Send application_type during Dynamic Client Registration (SEP-837) (#2930)
This commit is contained in:
committed by
GitHub
parent
60f37e9d7c
commit
cf41441e44
@@ -28,32 +28,6 @@ client:
|
||||
# branch takes the per-request _meta path.
|
||||
- tools_call
|
||||
|
||||
# --- SEP-837 (application_type during DCR) ---
|
||||
# The sep-837-application-type-present check only fires on 2026-version
|
||||
# runs; the client omits application_type during Dynamic Client
|
||||
# Registration, so every auth scenario that reaches DCR fails it on this
|
||||
# leg (the same scenarios pass at their default version in the 2025 legs).
|
||||
- auth/metadata-default
|
||||
- auth/metadata-var1
|
||||
- auth/metadata-var2
|
||||
- auth/metadata-var3
|
||||
- auth/scope-from-www-authenticate
|
||||
- auth/scope-from-scopes-supported
|
||||
- auth/scope-omitted-when-undefined
|
||||
- auth/token-endpoint-auth-basic
|
||||
- auth/token-endpoint-auth-post
|
||||
- auth/token-endpoint-auth-none
|
||||
- auth/offline-access-not-supported
|
||||
# SEP-2468 (authorization response iss parameter) is implemented, but these
|
||||
# 2026-introduced scenarios reach DCR and so still fail the application_type
|
||||
# check above; they unblock with SEP-837, not SEP-2468.
|
||||
- auth/iss-supported
|
||||
- auth/iss-not-advertised
|
||||
- auth/iss-supported-missing
|
||||
- auth/iss-wrong-issuer
|
||||
- auth/iss-unexpected
|
||||
- auth/iss-normalized
|
||||
|
||||
# --- Auth scenarios cut short by the 2026 connection lifecycle ---
|
||||
# The auth fixture flow drives the 2025 stateful lifecycle; the 2026-mode
|
||||
# mock rejects the MCP POST before the scope-escalation behaviour these
|
||||
|
||||
@@ -26,18 +26,6 @@ client:
|
||||
# SEP-2352 (authorization server migration): client does not re-register when
|
||||
# PRM authorization_servers changes.
|
||||
- auth/authorization-server-migration
|
||||
# SEP-837 (application_type during DCR): the check fires on every non-legacy
|
||||
# spec version (the default LATEST is 2026-07-28). The client omits
|
||||
# application_type during Dynamic Client Registration, so every scenario that
|
||||
# reaches DCR fails it. SEP-2468 iss validation is implemented, so these now
|
||||
# fail only on the application_type check, not on iss.
|
||||
- auth/offline-access-not-supported
|
||||
- auth/iss-supported
|
||||
- auth/iss-not-advertised
|
||||
- auth/iss-supported-missing
|
||||
- auth/iss-wrong-issuer
|
||||
- auth/iss-unexpected
|
||||
- auth/iss-normalized
|
||||
|
||||
# --- Pre-existing scenarios that fail on checks added after conformance 0.1.15 ---
|
||||
# SEP-990 (enterprise-managed authorization extension): no fixture handler /
|
||||
|
||||
@@ -1303,6 +1303,21 @@ If you relied on extra fields round-tripping through MCP types, move that data i
|
||||
|
||||
## New Features
|
||||
|
||||
### OAuth Dynamic Client Registration sends `application_type` (SEP-837)
|
||||
|
||||
`OAuthClientMetadata` now carries an `application_type` field that is sent during Dynamic Client Registration. It defaults to `"native"`, which suits MCP clients that use loopback redirect URIs (CLI and desktop apps); browser-based clients served from a non-local host should set it to `"web"`:
|
||||
|
||||
```python
|
||||
from mcp.shared.auth import OAuthClientMetadata
|
||||
|
||||
client_metadata = OAuthClientMetadata(
|
||||
redirect_uris=["https://app.example.com/callback"],
|
||||
application_type="web",
|
||||
)
|
||||
```
|
||||
|
||||
Under OIDC, omitting `application_type` defaults to `"web"`, which an authorization server may reject for the `localhost` redirect URIs native clients use; sending `"native"` avoids that. Non-OIDC servers ignore the parameter.
|
||||
|
||||
### 2025-11-25 and 2026-07-28 protocol fields modeled
|
||||
|
||||
`mcp.types` models the 2025-11-25 and 2026-07-28 protocol fields (e.g. `resultType`, `ttlMs`/`cacheScope` on cacheable results, `inputResponses`/`requestState` on retried requests), so inbound payloads carrying these keys parse into typed fields and round-trip. `ttlMs`/`cacheScope` default to `0`/`"private"` (immediately stale, not shared-cacheable); `resultType` defaults to `"complete"` on concrete results (`None` on `EmptyResult`); the server strips all of them from the wire at pre-2026 versions.
|
||||
|
||||
@@ -67,6 +67,9 @@ class OAuthClientMetadata(BaseModel):
|
||||
# servers may also return additional types they support
|
||||
response_types: list[str] = ["code"]
|
||||
scope: str | None = None
|
||||
# SEP-837: OIDC application_type. Defaults to "native" since MCP clients typically use
|
||||
# loopback redirect URIs; set "web" for remote browser-based clients on a non-local host.
|
||||
application_type: Literal["web", "native"] = "native"
|
||||
|
||||
# these fields are currently unused, but we support & store them for potential
|
||||
# future use
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Tests for refactored OAuth client authentication implementation."""
|
||||
|
||||
import base64
|
||||
import json
|
||||
import time
|
||||
from unittest import mock
|
||||
from urllib.parse import parse_qs, quote, unquote, urlparse
|
||||
@@ -1049,6 +1050,21 @@ class TestCreateClientRegistrationRequest:
|
||||
assert request.method == "POST"
|
||||
|
||||
|
||||
def test_registration_request_sends_application_type():
|
||||
"""SEP-837: the DCR body carries application_type, defaulting to native and overridable."""
|
||||
redirect_uris: list[AnyUrl] = [AnyUrl("http://localhost:3000/callback")]
|
||||
|
||||
default_request = create_client_registration_request(
|
||||
None, OAuthClientMetadata(redirect_uris=redirect_uris), "https://auth.example.com"
|
||||
)
|
||||
assert json.loads(default_request.content)["application_type"] == "native"
|
||||
|
||||
web_request = create_client_registration_request(
|
||||
None, OAuthClientMetadata(redirect_uris=redirect_uris, application_type="web"), "https://auth.example.com"
|
||||
)
|
||||
assert json.loads(web_request.content)["application_type"] == "web"
|
||||
|
||||
|
||||
class TestAuthFlow:
|
||||
"""Test the auth flow in httpx."""
|
||||
|
||||
|
||||
@@ -203,6 +203,7 @@ async def test_the_dcr_request_carries_the_client_metadata() -> None:
|
||||
"grant_types": ["authorization_code", "refresh_token"],
|
||||
"response_types": ["code"],
|
||||
"scope": "mcp",
|
||||
"application_type": "native",
|
||||
"client_name": "interaction-suite",
|
||||
"software_id": "interaction-test-suite",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user