utils
extract_field_from_www_auth
Extract field from WWW-Authenticate header.
Returns:
| Type | Description |
|---|---|
str | None
|
Field value if found in WWW-Authenticate header, None otherwise |
Source code in src/mcp/client/auth/utils.py
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | |
extract_scope_from_www_auth
extract_scope_from_www_auth(
response: Response,
) -> str | None
Extract scope parameter from WWW-Authenticate header as per RFC 6750.
Returns:
| Type | Description |
|---|---|
str | None
|
Scope string if found in WWW-Authenticate header, None otherwise |
Source code in src/mcp/client/auth/utils.py
40 41 42 43 44 45 46 | |
extract_resource_metadata_from_www_auth
extract_resource_metadata_from_www_auth(
response: Response,
) -> str | None
Extract protected resource metadata URL from WWW-Authenticate header as per RFC 9728.
Returns:
| Type | Description |
|---|---|
str | None
|
Resource metadata URL if found in WWW-Authenticate header, None otherwise |
Source code in src/mcp/client/auth/utils.py
49 50 51 52 53 54 55 56 57 58 | |
build_protected_resource_metadata_discovery_urls
build_protected_resource_metadata_discovery_urls(
www_auth_url: str | None, server_url: str
) -> list[str]
Build ordered list of URLs to try for protected resource metadata discovery.
Per SEP-985, the client MUST: 1. Try resource_metadata from WWW-Authenticate header (if present) 2. Fall back to path-based well-known URI: /.well-known/oauth-protected-resource/{path} 3. Fall back to root-based well-known URI: /.well-known/oauth-protected-resource
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
www_auth_url
|
str | None
|
Optional resource_metadata URL extracted from the WWW-Authenticate header |
required |
server_url
|
str
|
Server URL |
required |
Returns:
| Type | Description |
|---|---|
list[str]
|
Ordered list of URLs to try for discovery |
Source code in src/mcp/client/auth/utils.py
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | |
get_client_metadata_scopes
get_client_metadata_scopes(
www_authenticate_scope: str | None,
protected_resource_metadata: (
ProtectedResourceMetadata | None
),
authorization_server_metadata: (
OAuthMetadata | None
) = None,
client_grant_types: list[str] | None = None,
) -> str | None
Select effective scopes and augment for refresh token support.
Source code in src/mcp/client/auth/utils.py
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | |
union_scopes
Merge two space-delimited scope strings, preserving order and dropping duplicates.
SEP-2350: on step-up re-authorization the client requests the union of previously requested scopes and the newly challenged scopes, so escalating one operation does not drop the permissions granted for another. Previously requested scopes come first; new scopes are appended in order.
Source code in src/mcp/client/auth/utils.py
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 | |
build_oauth_authorization_server_metadata_discovery_urls
build_oauth_authorization_server_metadata_discovery_urls(
auth_server_url: str | None, server_url: str
) -> list[str]
Generate an ordered list of URLs for authorization server metadata discovery.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
auth_server_url
|
str | None
|
OAuth Authorization Server Metadata URL if found, otherwise None |
required |
server_url
|
str
|
URL for the MCP server, used as a fallback if auth_server_url is None |
required |
Source code in src/mcp/client/auth/utils.py
156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 | |
handle_protected_resource_response
async
handle_protected_resource_response(
response: Response,
) -> ProtectedResourceMetadata | None
Handle protected resource metadata discovery response.
Per SEP-985, supports fallback when discovery fails at one URL.
Returns:
| Type | Description |
|---|---|
ProtectedResourceMetadata | None
|
ProtectedResourceMetadata if successfully discovered, None if we should try next URL |
Source code in src/mcp/client/auth/utils.py
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |
validate_authorization_response_iss
validate_authorization_response_iss(
iss: str | None, oauth_metadata: OAuthMetadata | None
) -> None
Validate the RFC 9207 iss authorization-response parameter.
Per RFC 9207 section 2.4, the client compares iss against the issuer of the
authorization server the request was sent to, using simple string comparison
(RFC 3986 section 6.2.1, i.e. without URL normalization), and rejects on mismatch.
A response that omits iss is rejected only when the server advertised support via
authorization_response_iss_parameter_supported.
Raises:
| Type | Description |
|---|---|
OAuthFlowError
|
If |
Source code in src/mcp/client/auth/utils.py
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | |
validate_metadata_issuer
validate_metadata_issuer(
oauth_metadata: OAuthMetadata, expected_issuer: str
) -> None
Validate that authorization server metadata issuer matches the discovery issuer.
Per RFC 8414 section 3.3 / SEP-2468, the issuer in the metadata must match the issuer
used to construct the well-known URL, compared as a simple string (RFC 3986 section 6.2.1).
Raises:
| Type | Description |
|---|---|
OAuthFlowError
|
If the metadata issuer does not match |
Source code in src/mcp/client/auth/utils.py
260 261 262 263 264 265 266 267 268 269 270 271 272 | |
create_client_registration_request
create_client_registration_request(
auth_server_metadata: OAuthMetadata | None,
client_metadata: OAuthClientMetadata,
auth_base_url: str,
) -> Request
Build a client registration request.
Source code in src/mcp/client/auth/utils.py
279 280 281 282 283 284 285 286 287 288 289 290 291 | |
handle_registration_response
async
handle_registration_response(
response: Response,
) -> OAuthClientInformationFull
Handle registration response.
Source code in src/mcp/client/auth/utils.py
294 295 296 297 298 299 300 301 302 303 304 305 | |
is_valid_client_metadata_url
Validate that a URL is suitable for use as a client_id (CIMD).
The URL must be HTTPS with a non-root pathname.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
url
|
str | None
|
The URL to validate |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if the URL is a valid HTTPS URL with a non-root pathname |
Source code in src/mcp/client/auth/utils.py
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | |
credentials_match_issuer
credentials_match_issuer(
client_info: OAuthClientInformationFull,
issuer: str,
client_metadata_url: str | None,
) -> bool
Whether stored client credentials may be reused against issuer (SEP-2352).
A URL-based client ID (CIMD) is portable across authorization servers — the same self-hosted
document is resolved by whichever server is in use — so it always matches; CIMD is identified
by the client ID being the configured client_metadata_url, not by URL shape (a registration
server may also issue URL-shaped IDs that are bound to it). Credentials with a recorded issuer
match only when it equals issuer (simple string comparison). Credentials with no recorded
issuer (pre-registered, or stored before issuer binding existed) carry no binding to enforce
and are left as-is.
Source code in src/mcp/client/auth/utils.py
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | |
should_use_client_metadata_url
should_use_client_metadata_url(
oauth_metadata: OAuthMetadata | None,
client_metadata_url: str | None,
) -> bool
Determine if URL-based client ID (CIMD) should be used instead of DCR.
URL-based client IDs should be used when: 1. The server advertises client_id_metadata_document_supported=True 2. The client has a valid client_metadata_url configured
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
oauth_metadata
|
OAuthMetadata | None
|
OAuth authorization server metadata |
required |
client_metadata_url
|
str | None
|
URL-based client ID (already validated) |
required |
Returns:
| Type | Description |
|---|---|
bool
|
True if CIMD should be used, False if DCR should be used |
Source code in src/mcp/client/auth/utils.py
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | |
create_client_info_from_metadata_url
create_client_info_from_metadata_url(
client_metadata_url: str,
redirect_uris: list[AnyUrl] | None = None,
) -> OAuthClientInformationFull
Create client information using a URL-based client ID (CIMD).
When using URL-based client IDs, the URL itself becomes the client_id and no client_secret is used (token_endpoint_auth_method="none").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
client_metadata_url
|
str
|
The URL to use as the client_id |
required |
redirect_uris
|
list[AnyUrl] | None
|
The redirect URIs from the client metadata (passed through for compatibility with OAuthClientInformationFull which inherits from OAuthClientMetadata) |
None
|
Returns:
| Type | Description |
|---|---|
OAuthClientInformationFull
|
OAuthClientInformationFull with the URL as client_id |
Source code in src/mcp/client/auth/utils.py
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | |
handle_token_response_scopes
async
handle_token_response_scopes(
response: Response,
) -> OAuthToken
Parse and validate a token response.
Parses token response JSON. Callers should check response.status_code before calling.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
response
|
Response
|
HTTP response from token endpoint (status already checked by caller) |
required |
Returns:
| Type | Description |
|---|---|
OAuthToken
|
Validated OAuthToken model |
Raises:
| Type | Description |
|---|---|
OAuthTokenError
|
If response JSON is invalid |
Source code in src/mcp/client/auth/utils.py
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | |