You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add `AuthProvider` for composable bearer-token auth; transports adapt `OAuthClientProvider` automatically
6
+
7
+
- New `AuthProvider` interface: `{ token(): Promise<string | undefined>; onUnauthorized?(ctx): Promise<void> }`. Transports call `token()` before every request and `onUnauthorized()` on 401 (then retry once).
8
+
- Transport `authProvider` option now accepts `AuthProvider | OAuthClientProvider`. OAuth providers are adapted internally via `adaptOAuthProvider()` — no changes needed to existing `OAuthClientProvider` implementations.
9
+
- For simple bearer tokens (API keys, gateway-managed tokens, service accounts): `{ authProvider: { token: async () => myKey } }` — one-line object literal, no class.
10
+
- New `adaptOAuthProvider(provider)` export for explicit adaptation.
11
+
- New `handleOAuthUnauthorized(provider, ctx)` helper — the standard OAuth `onUnauthorized` behavior.
12
+
- New `isOAuthClientProvider()` type guard.
13
+
- New `UnauthorizedContext` type.
14
+
- Exported previously-internal auth helpers for building custom flows: `applyBasicAuth`, `applyPostAuth`, `applyPublicAuth`, `executeTokenRequest`.
15
+
16
+
Transports are simplified internally — ~50 lines of inline OAuth orchestration (auth() calls, WWW-Authenticate parsing, circuit-breaker state) moved into the adapter's `onUnauthorized()` implementation. `OAuthClientProvider` itself is unchanged.
MCP servers can require OAuth 2.0 authentication before accepting client connections (see [Authorization](https://modelcontextprotocol.io/specification/latest/basic/authorization) in the MCP specification). Pass an `authProvider` to {@linkcode@modelcontextprotocol/client!client/streamableHttp.StreamableHTTPClientTransport | StreamableHTTPClientTransport} to enable this — the SDK provides built-in providers for common machine-to-machine flows, or you can implement the full {@linkcode@modelcontextprotocol/client!client/auth.OAuthClientProvider | OAuthClientProvider} interface for user-facing OAuth.
116
+
MCP servers can require authentication before accepting client connections (see [Authorization](https://modelcontextprotocol.io/specification/latest/basic/authorization) in the MCP specification). Pass an {@linkcode@modelcontextprotocol/client!client/auth.AuthProvider | AuthProvider} to {@linkcode@modelcontextprotocol/client!client/streamableHttp.StreamableHTTPClientTransport | StreamableHTTPClientTransport}. The transport calls `token()` before every request and `onUnauthorized()` (if provided) on 401, then retries once.
117
+
118
+
### Bearer tokens
119
+
120
+
For servers that accept bearer tokens managed outside the SDK — API keys, tokens from a gateway or proxy, service-account credentials — implement only `token()`. With no `onUnauthorized()`, a 401 throws {@linkcode@modelcontextprotocol/client!client/auth.UnauthorizedError | UnauthorizedError} immediately:
const transport =newStreamableHTTPClientTransport(newURL('http://localhost:3000/mcp'), { authProvider });
126
+
```
127
+
128
+
See [`simpleTokenProvider.ts`](https://github.com/modelcontextprotocol/typescript-sdk/blob/main/examples/client/src/simpleTokenProvider.ts) for a complete runnable example.
Copy file name to clipboardExpand all lines: docs/migration.md
+72-77Lines changed: 72 additions & 77 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -264,6 +264,7 @@ server.registerTool('ping', {
264
264
```
265
265
266
266
This applies to:
267
+
267
268
-`inputSchema` in `registerTool()`
268
269
-`outputSchema` in `registerTool()`
269
270
-`argsSchema` in `registerPrompt()`
@@ -360,25 +361,21 @@ Common method string replacements:
360
361
361
362
### `Protocol.request()`, `ctx.mcpReq.send()`, and `Client.callTool()` no longer take a schema parameter
362
363
363
-
The public `Protocol.request()`, `BaseContext.mcpReq.send()`, and `Client.callTool()` methods no longer accept a Zod result schema argument. The SDK now resolves the correct result schema internally based on the method name. This means you no longer need to import result schemas like `CallToolResultSchema` or `ElicitResultSchema` when making requests.
364
+
The public `Protocol.request()`, `BaseContext.mcpReq.send()`, and `Client.callTool()` methods no longer accept a Zod result schema argument. The SDK now resolves the correct result schema internally based on the method name. This means you no longer need to import result schemas
365
+
like `CallToolResultSchema` or `ElicitResultSchema` when making requests.
|`SdkErrorCode.NotConnected`| Transport is not connected |
602
+
|`SdkErrorCode.AlreadyConnected`| Transport is already connected |
603
+
|`SdkErrorCode.NotInitialized`| Protocol is not initialized |
604
+
|`SdkErrorCode.CapabilityNotSupported`| Required capability is not supported |
605
+
|`SdkErrorCode.RequestTimeout`| Request timed out waiting for response |
606
+
|`SdkErrorCode.ConnectionClosed`| Connection was closed |
607
+
|`SdkErrorCode.SendFailed`| Failed to send message |
608
+
|`SdkErrorCode.ClientHttpNotImplemented`| HTTP POST request failed |
609
+
|`SdkErrorCode.ClientHttpAuthentication`| Server returned 401 after re-authentication|
610
+
|`SdkErrorCode.ClientHttpForbidden`| Server returned 403 after trying upscoping |
611
+
|`SdkErrorCode.ClientHttpUnexpectedContent`| Unexpected content type in HTTP response |
612
+
|`SdkErrorCode.ClientHttpFailedToOpenStream`| Failed to open SSE stream |
613
+
|`SdkErrorCode.ClientHttpFailedToTerminateSession`| Failed to terminate session |
620
614
621
615
#### `StreamableHTTPError` removed
622
616
@@ -647,7 +641,7 @@ try {
647
641
if (errorinstanceofSdkError) {
648
642
switch (error.code) {
649
643
caseSdkErrorCode.ClientHttpAuthentication:
650
-
console.log('Auth failed after completing auth flow');
644
+
console.log('Auth failed — server rejected token after re-auth');
651
645
break;
652
646
caseSdkErrorCode.ClientHttpForbidden:
653
647
console.log('Forbidden after upscoping attempt');
@@ -667,7 +661,8 @@ try {
667
661
668
662
#### Why this change?
669
663
670
-
Previously, `ErrorCode.RequestTimeout` (-32001) and `ErrorCode.ConnectionClosed` (-32000) were used for local timeout/connection errors. However, these errors never cross the wire as JSON-RPC responses - they are rejected locally. Using protocol error codes for local errors was semantically inconsistent.
664
+
Previously, `ErrorCode.RequestTimeout` (-32001) and `ErrorCode.ConnectionClosed` (-32000) were used for local timeout/connection errors. However, these errors never cross the wire as JSON-RPC responses - they are rejected locally. Using protocol error codes for local errors was
665
+
semantically inconsistent.
671
666
672
667
The new design:
673
668
@@ -764,11 +759,11 @@ This means Cloudflare Workers users no longer need to explicitly pass the valida
0 commit comments