MCPcopy Index your code
hub / github.com/modelcontextprotocol/python-sdk / connect_with_oauth

Function connect_with_oauth

tests/interaction/auth/_harness.py:397–476  ·  view source on GitHub ↗

Connect a `Client` to a server's bearer-gated streamable-HTTP app, completing OAuth in process. Yields the connected `Client` and the `HeadlessOAuth` whose `authorize_url` records what the SDK put on the authorize request. `on_request` records every HTTP request the underlying `httpx.As

(
    server: Server,
    *,
    provider: InMemoryAuthorizationServerProvider,
    settings: AuthSettings | None = None,
    storage: InMemoryTokenStorage | None = None,
    client_metadata: OAuthClientMetadata | None = None,
    client_metadata_url: str | None = None,
    headless: HeadlessOAuth | None = None,
    auth: httpx.Auth | None = None,
    verify_tokens: bool = True,
    app_shim: Callable[[ASGIApp], ASGIApp] | None = None,
    on_request: Callable[[httpx.Request], None] | None = None,
)

Source from the content-addressed store, hash-verified

395
396@asynccontextmanager
397async def connect_with_oauth(
398 server: Server,
399 *,
400 provider: InMemoryAuthorizationServerProvider,
401 settings: AuthSettings | None = None,
402 storage: InMemoryTokenStorage | None = None,
403 client_metadata: OAuthClientMetadata | None = None,
404 client_metadata_url: str | None = None,
405 headless: HeadlessOAuth | None = None,
406 auth: httpx.Auth | None = None,
407 verify_tokens: bool = True,
408 app_shim: Callable[[ASGIApp], ASGIApp] | None = None,
409 on_request: Callable[[httpx.Request], None] | None = None,
410) -> AsyncIterator[tuple[Client, HeadlessOAuth]]:
411 """Connect a `Client` to a server's bearer-gated streamable-HTTP app, completing OAuth in process.
412
413 Yields the connected `Client` and the `HeadlessOAuth` whose `authorize_url` records what the
414 SDK put on the authorize request. `on_request` records every HTTP request the underlying
415 `httpx.AsyncClient` issues, including those yielded from inside the auth flow.
416
417 `headless`: supply a pre-configured `HeadlessOAuth` to override the callback behaviour
418 (state mismatch, error redirects). `verify_tokens=False` mounts the MCP endpoint without
419 the bearer middleware so a flow driven by a shimmed 401 completes regardless of the granted
420 scopes. `app_shim` wraps the built Starlette app before it reaches the bridge transport,
421 for tests that need to intercept or rewrite specific server responses.
422
423 `auth`: supply a pre-built `httpx.Auth` (such as `ClientCredentialsOAuthProvider`) to use
424 instead of constructing the default `OAuthClientProvider`; in that case `storage`,
425 `client_metadata`, `client_metadata_url`, and `headless` are unused (the yielded
426 `HeadlessOAuth` is never invoked and its `authorize_url` stays None).
427 """
428 settings = settings if settings is not None else auth_settings()
429 storage = storage if storage is not None else InMemoryTokenStorage()
430 client_metadata = client_metadata if client_metadata is not None else oauth_client_metadata()
431 headless = headless if headless is not None else HeadlessOAuth()
432
433 oauth = (
434 auth
435 if auth is not None
436 else OAuthClientProvider(
437 server_url=f"{BASE_URL}/mcp",
438 client_metadata=client_metadata,
439 storage=storage,
440 redirect_handler=headless.redirect_handler,
441 callback_handler=headless.callback_handler,
442 client_metadata_url=client_metadata_url,
443 )
444 )
445
446 app: ASGIApp = server.streamable_http_app(
447 auth=settings,
448 token_verifier=ProviderTokenVerifier(provider) if verify_tokens else None,
449 auth_server_provider=provider,
450 transport_security=NO_DNS_REBINDING_PROTECTION,
451 )
452 if app_shim is not None:
453 app = app_shim(app)
454

Calls 12

OAuthClientProviderClass · 0.90
ClientClass · 0.90
streamable_http_clientFunction · 0.90
auth_settingsFunction · 0.85
oauth_client_metadataFunction · 0.85
HeadlessOAuthClass · 0.85
bindMethod · 0.80
streamable_http_appMethod · 0.45
runMethod · 0.45