@ai-sdk/mcp 2.0.0-canary.65 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -0
- package/README.md +24 -1
- package/dist/index.d.ts +71 -1
- package/dist/index.js +95 -30
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +1 -0
- package/src/tool/mcp-client.ts +53 -15
- package/src/tool/mcp-http-transport.ts +81 -19
- package/src/tool/mcp-transport.ts +36 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,94 @@
|
|
|
1
1
|
# @ai-sdk/mcp
|
|
2
2
|
|
|
3
|
+
## 2.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 241a8c5: Add Streamable HTTP session hooks, cached initialize metadata, and detach-on-close support for reattaching to MCP sessions.
|
|
8
|
+
|
|
9
|
+
## 2.0.0
|
|
10
|
+
|
|
11
|
+
### Major Changes
|
|
12
|
+
|
|
13
|
+
- 23fa161: fix(mcp): setting redirect: error for MCP transport
|
|
14
|
+
- ef992f8: Remove CommonJS exports from all packages. All packages are now ESM-only (`"type": "module"`). Consumers using `require()` must switch to ESM `import` syntax.
|
|
15
|
+
- 8359612: Start v7 pre-release
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- b79094c: Add `resource_link` content type to `CallToolResultSchema` and `PromptMessageSchema` per MCP spec. Fixes hard rejection when MCP servers return `resource_link` content parts with zod ≥ 4.4.x.
|
|
20
|
+
- 78e0023: fix(mcp): await addClientAuthentication in token exchange and refresh
|
|
21
|
+
- b567a6c: dependency updates
|
|
22
|
+
- e33ad0b: fix(mcp): add optional hook to validate authorization servers
|
|
23
|
+
- e3ea484: fix(mcp): bypass outputSchema validation when tool returns isError
|
|
24
|
+
- 93afb28: feat(mcp): expose server instructions to be accessible through client
|
|
25
|
+
- a00d1d3: feat(mcp): allow custom fetch for HTTP and SSE transports
|
|
26
|
+
- a98bf66: feat(mcp): surface 'serverInfo' exposed from the MCP server
|
|
27
|
+
- 2a150f8: fix(mcp): lock first sse endpoint received via event
|
|
28
|
+
- 2655da8: fix(mcp): use negotiated protocol version in transport request headers
|
|
29
|
+
- 9f0e36c: trigger release for all packages after provenance setup
|
|
30
|
+
- f7bc0b4: feat(mcp): expose `statusCode`, `url`, and `responseBody` on `MCPClientError` for HTTP transport failures
|
|
31
|
+
|
|
32
|
+
`MCPClientError` now carries structured HTTP context when it originates from the
|
|
33
|
+
streamable HTTP transport. This lets downstream consumers (e.g. agent frameworks
|
|
34
|
+
that need to decide whether to fall back from streamable HTTP to legacy SSE
|
|
35
|
+
transport per the MCP spec) branch on the actual response status without parsing
|
|
36
|
+
the error message string.
|
|
37
|
+
|
|
38
|
+
Fields are optional — they remain `undefined` for stdio transport errors and for
|
|
39
|
+
non-response failures (network errors, aborts).
|
|
40
|
+
|
|
41
|
+
- dcefad3: fix(mcp): respond to ping requests with an empty result per JSON-RPC spec (closes #6282)
|
|
42
|
+
- b44b051: fix(mcp): prevent prototype-named tools from bypassing the `schemas` allowlist
|
|
43
|
+
|
|
44
|
+
When using `client.tools({ schemas })` to expose only an explicitly allowed
|
|
45
|
+
subset of an MCP server's tools, the allowlist check used the `in` operator,
|
|
46
|
+
which also matches inherited `Object.prototype` properties. A server-advertised
|
|
47
|
+
tool named `constructor`, `toString`, `__proto__`, etc. would pass the check
|
|
48
|
+
even though the developer never defined it in `schemas`, and was then exposed to
|
|
49
|
+
the model and executable. The check now uses `Object.hasOwn`, so only
|
|
50
|
+
explicitly defined tools are returned.
|
|
51
|
+
|
|
52
|
+
- f634bac: feat(mcp): add new McpProviderMetadata type
|
|
53
|
+
- b9b3899: changeset for #13384
|
|
54
|
+
- 1e89d62: fix(mcp): strip trailing slash from OAuth resource parameter
|
|
55
|
+
- 3e0b82f: fix(mcp): support official sdk protocol version negotiation
|
|
56
|
+
- 1451759: feat(mcp): deprecate name and use clientName for MCPClient
|
|
57
|
+
- 7fc6bd6: Raise minimum supported Node.js version to 22. Supported versions: 22, 24, and 26.
|
|
58
|
+
- 08d2129: feat(mcp): propagate the server name through dynamic tool parts
|
|
59
|
+
- 58c9eb1: feat(mcp): add `redirect` option to `MCPTransportConfig` for controlling HTTP redirect behavior
|
|
60
|
+
- 0c4c275: trigger initial canary release
|
|
61
|
+
- 611f621: feat(mcp): feat(mcp): add support for MCP Apps
|
|
62
|
+
- 9ecd8ae: fix(mcp): add MCP protocol version 2025-11-25 to supported versions
|
|
63
|
+
- 6c17a9f: fix(mcp): deduplicate auth refresh on http transport
|
|
64
|
+
- 69254e0: feat(ai): add toolMetadata for tool specific metdata
|
|
65
|
+
- 258c093: chore: ensure consistent import handling and avoid import duplicates or cycles
|
|
66
|
+
- f0c6770: fix(mcp): prevent mcp oauth credential exfiltration during rediscovery
|
|
67
|
+
- 5463d0d: feat(provider): align tool result output content file part types with top-level message file part types
|
|
68
|
+
- b8396f0: trigger initial beta release
|
|
69
|
+
- b29e087: fix (mcp): handle SSE messages without explicit event fields
|
|
70
|
+
- 90e2d8a: chore: fix unused vars not being flagged by our lint tooling
|
|
71
|
+
- 024a6b4: fix(mcp): validate oauth metadata issuer during discovery
|
|
72
|
+
- 9b0bc8a: fix(mcp): prevent prototype pollution by using secureJsonParse
|
|
73
|
+
- ff5eba1: feat: roll `image-*` tool output types into their equivalent `file-*` types
|
|
74
|
+
|
|
75
|
+
## 2.0.0-beta.67
|
|
76
|
+
|
|
77
|
+
### Patch Changes
|
|
78
|
+
|
|
79
|
+
- Updated dependencies [0416e3e]
|
|
80
|
+
- @ai-sdk/provider@4.0.0-beta.20
|
|
81
|
+
- @ai-sdk/provider-utils@5.0.0-beta.50
|
|
82
|
+
|
|
83
|
+
## 2.0.0-beta.66
|
|
84
|
+
|
|
85
|
+
### Patch Changes
|
|
86
|
+
|
|
87
|
+
- b8396f0: trigger initial beta release
|
|
88
|
+
- Updated dependencies [b8396f0]
|
|
89
|
+
- @ai-sdk/provider-utils@5.0.0-beta.49
|
|
90
|
+
- @ai-sdk/provider@4.0.0-beta.19
|
|
91
|
+
|
|
3
92
|
## 2.0.0-canary.65
|
|
4
93
|
|
|
5
94
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -76,7 +76,7 @@ const result = streamText({
|
|
|
76
76
|
model: 'openai/gpt-5.4',
|
|
77
77
|
tools: await mcpClient.tools(),
|
|
78
78
|
prompt: 'Use the available tools to answer the user question.',
|
|
79
|
-
|
|
79
|
+
onEnd: async () => {
|
|
80
80
|
await mcpClient.close();
|
|
81
81
|
},
|
|
82
82
|
});
|
|
@@ -93,12 +93,35 @@ HTTP is recommended for production deployments:
|
|
|
93
93
|
```ts
|
|
94
94
|
import { createMCPClient } from '@ai-sdk/mcp';
|
|
95
95
|
|
|
96
|
+
const savedSession = await loadMcpSession();
|
|
97
|
+
let currentSessionId = savedSession?.sessionId;
|
|
98
|
+
|
|
96
99
|
const mcpClient = await createMCPClient({
|
|
97
100
|
transport: {
|
|
98
101
|
type: 'http',
|
|
99
102
|
url: 'https://your-server.com/mcp',
|
|
103
|
+
initialSessionId: savedSession?.sessionId,
|
|
104
|
+
initialProtocolVersion: savedSession?.initializeResult.protocolVersion,
|
|
105
|
+
terminateSessionOnClose: false,
|
|
106
|
+
onSessionIdChange: sessionId => {
|
|
107
|
+
currentSessionId = sessionId;
|
|
108
|
+
},
|
|
109
|
+
onSessionExpired: sessionId => {
|
|
110
|
+
if (currentSessionId === sessionId) {
|
|
111
|
+
currentSessionId = undefined;
|
|
112
|
+
void clearMcpSession();
|
|
113
|
+
}
|
|
114
|
+
},
|
|
100
115
|
},
|
|
116
|
+
initialInitializeResult: savedSession?.initializeResult,
|
|
101
117
|
});
|
|
118
|
+
|
|
119
|
+
if (currentSessionId) {
|
|
120
|
+
await saveMcpSession({
|
|
121
|
+
sessionId: currentSessionId,
|
|
122
|
+
initializeResult: mcpClient.initializeResult,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
102
125
|
```
|
|
103
126
|
|
|
104
127
|
SSE is also supported for MCP servers that use Server-Sent Events:
|
package/dist/index.d.ts
CHANGED
|
@@ -273,6 +273,37 @@ type MCPTransportConfig = {
|
|
|
273
273
|
* @default 'error'
|
|
274
274
|
*/
|
|
275
275
|
redirect?: 'follow' | 'error';
|
|
276
|
+
/**
|
|
277
|
+
* Initial MCP session id to send with resumed Streamable HTTP requests after
|
|
278
|
+
* initialization.
|
|
279
|
+
* Only used by the HTTP transport.
|
|
280
|
+
*/
|
|
281
|
+
initialSessionId?: string;
|
|
282
|
+
/**
|
|
283
|
+
* Initial MCP protocol version to send before initialize negotiates one.
|
|
284
|
+
* Only used by the HTTP transport.
|
|
285
|
+
*/
|
|
286
|
+
initialProtocolVersion?: string;
|
|
287
|
+
/**
|
|
288
|
+
* Called when the Streamable HTTP server creates, changes, or clears the MCP
|
|
289
|
+
* session id.
|
|
290
|
+
* Only used by the HTTP transport.
|
|
291
|
+
*/
|
|
292
|
+
onSessionIdChange?: (sessionId: string | undefined) => void;
|
|
293
|
+
/**
|
|
294
|
+
* Called when a Streamable HTTP request returns 404 for an existing MCP
|
|
295
|
+
* session id. The transport clears the session id before reporting the
|
|
296
|
+
* underlying HTTP error.
|
|
297
|
+
* Only used by the HTTP transport.
|
|
298
|
+
*/
|
|
299
|
+
onSessionExpired?: (sessionId: string) => void;
|
|
300
|
+
/**
|
|
301
|
+
* Whether close() should send DELETE for the current MCP session id.
|
|
302
|
+
* Set to false when the application intends to reattach to the session later.
|
|
303
|
+
* Only used by the HTTP transport.
|
|
304
|
+
* @default true
|
|
305
|
+
*/
|
|
306
|
+
terminateSessionOnClose?: boolean;
|
|
276
307
|
/**
|
|
277
308
|
* Optional custom fetch implementation to use for HTTP requests.
|
|
278
309
|
* Useful for runtimes that need a request-local fetch.
|
|
@@ -337,6 +368,34 @@ declare const ClientCapabilitiesSchema: z.ZodObject<{
|
|
|
337
368
|
}, z.core.$loose>>;
|
|
338
369
|
}, z.core.$loose>;
|
|
339
370
|
type ClientCapabilities = z.infer<typeof ClientCapabilitiesSchema>;
|
|
371
|
+
declare const InitializeResultSchema: z.ZodObject<{
|
|
372
|
+
_meta: z.ZodOptional<z.ZodObject<{}, z.core.$loose>>;
|
|
373
|
+
protocolVersion: z.ZodString;
|
|
374
|
+
capabilities: z.ZodObject<{
|
|
375
|
+
experimental: z.ZodOptional<z.ZodObject<{}, z.core.$loose>>;
|
|
376
|
+
logging: z.ZodOptional<z.ZodObject<{}, z.core.$loose>>;
|
|
377
|
+
prompts: z.ZodOptional<z.ZodObject<{
|
|
378
|
+
listChanged: z.ZodOptional<z.ZodBoolean>;
|
|
379
|
+
}, z.core.$loose>>;
|
|
380
|
+
resources: z.ZodOptional<z.ZodObject<{
|
|
381
|
+
subscribe: z.ZodOptional<z.ZodBoolean>;
|
|
382
|
+
listChanged: z.ZodOptional<z.ZodBoolean>;
|
|
383
|
+
}, z.core.$loose>>;
|
|
384
|
+
tools: z.ZodOptional<z.ZodObject<{
|
|
385
|
+
listChanged: z.ZodOptional<z.ZodBoolean>;
|
|
386
|
+
}, z.core.$loose>>;
|
|
387
|
+
elicitation: z.ZodOptional<z.ZodObject<{
|
|
388
|
+
applyDefaults: z.ZodOptional<z.ZodBoolean>;
|
|
389
|
+
}, z.core.$loose>>;
|
|
390
|
+
}, z.core.$loose>;
|
|
391
|
+
serverInfo: z.ZodObject<{
|
|
392
|
+
name: z.ZodString;
|
|
393
|
+
version: z.ZodString;
|
|
394
|
+
title: z.ZodOptional<z.ZodString>;
|
|
395
|
+
}, z.core.$loose>;
|
|
396
|
+
instructions: z.ZodOptional<z.ZodString>;
|
|
397
|
+
}, z.core.$loose>;
|
|
398
|
+
type InitializeResult = z.infer<typeof InitializeResultSchema>;
|
|
340
399
|
type PaginatedRequest = Request & {
|
|
341
400
|
params?: BaseParams & {
|
|
342
401
|
cursor?: string;
|
|
@@ -513,6 +572,12 @@ interface MCPClientConfig {
|
|
|
513
572
|
transport: MCPTransportConfig | MCPTransport;
|
|
514
573
|
/** Optional callback for uncaught errors */
|
|
515
574
|
onUncaughtError?: (error: unknown) => void;
|
|
575
|
+
/**
|
|
576
|
+
* Initialize result from a previous MCP session. When provided, the client
|
|
577
|
+
* starts the transport and reuses this metadata without sending a new
|
|
578
|
+
* initialize request.
|
|
579
|
+
*/
|
|
580
|
+
initialInitializeResult?: InitializeResult;
|
|
516
581
|
/** Optional client name, defaults to 'ai-sdk-mcp-client' */
|
|
517
582
|
clientName?: string;
|
|
518
583
|
/**
|
|
@@ -537,6 +602,11 @@ interface MCPClient {
|
|
|
537
602
|
* @see https://modelcontextprotocol.io/specification/2025-11-25/schema#implementation
|
|
538
603
|
*/
|
|
539
604
|
readonly serverInfo: Configuration;
|
|
605
|
+
/**
|
|
606
|
+
* The full initialize result used by this client, either from the server
|
|
607
|
+
* during initialization or from `initialInitializeResult`.
|
|
608
|
+
*/
|
|
609
|
+
readonly initializeResult: InitializeResult;
|
|
540
610
|
/**
|
|
541
611
|
* Optional instructions provided by the server during the initialize handshake.
|
|
542
612
|
*
|
|
@@ -651,4 +721,4 @@ declare function readMCPAppResource({ client, uri, options, }: {
|
|
|
651
721
|
options?: RequestOptions;
|
|
652
722
|
}): Promise<MCPAppResource>;
|
|
653
723
|
|
|
654
|
-
export { type CallToolResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPAppResource, type MCPAppResourceCSP, type MCPAppResourceMeta, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, MCP_APP_MIME_TYPE, type McpProviderMetadata, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, mcpAppClientCapabilities, readMCPAppResource, splitMCPAppTools };
|
|
724
|
+
export { type CallToolResult, type Configuration, type ElicitResult, ElicitResultSchema, type ElicitationRequest, ElicitationRequestSchema, type InitializeResult, type JSONRPCError, type JSONRPCMessage, type JSONRPCNotification, type JSONRPCRequest, type JSONRPCResponse, type ListToolsResult, type MCPAppResource, type MCPAppResourceCSP, type MCPAppResourceMeta, type MCPClient, type ClientCapabilities as MCPClientCapabilities, type MCPClientConfig, type MCPTransport, MCP_APP_MIME_TYPE, type McpProviderMetadata, type OAuthAuthorizationServerInformation, type OAuthClientInformation, type OAuthClientMetadata, type OAuthClientProvider, type OAuthTokens, UnauthorizedError, auth, createMCPClient, type MCPClient as experimental_MCPClient, type ClientCapabilities as experimental_MCPClientCapabilities, type MCPClientConfig as experimental_MCPClientConfig, createMCPClient as experimental_createMCPClient, mcpAppClientCapabilities, readMCPAppResource, splitMCPAppTools };
|
package/dist/index.js
CHANGED
|
@@ -1503,6 +1503,11 @@ var HttpMCPTransport = class {
|
|
|
1503
1503
|
headers,
|
|
1504
1504
|
authProvider,
|
|
1505
1505
|
redirect = "error",
|
|
1506
|
+
initialSessionId,
|
|
1507
|
+
initialProtocolVersion,
|
|
1508
|
+
onSessionIdChange,
|
|
1509
|
+
onSessionExpired,
|
|
1510
|
+
terminateSessionOnClose = true,
|
|
1506
1511
|
fetch: fetchFn
|
|
1507
1512
|
}) {
|
|
1508
1513
|
this.inboundReconnectAttempts = 0;
|
|
@@ -1516,19 +1521,27 @@ var HttpMCPTransport = class {
|
|
|
1516
1521
|
this.headers = headers;
|
|
1517
1522
|
this.authProvider = authProvider;
|
|
1518
1523
|
this.redirectMode = redirect;
|
|
1524
|
+
this.sessionId = initialSessionId;
|
|
1525
|
+
this.protocolVersion = initialProtocolVersion;
|
|
1526
|
+
this.onSessionIdChange = onSessionIdChange;
|
|
1527
|
+
this.onSessionExpired = onSessionExpired;
|
|
1528
|
+
this.terminateSessionOnClose = terminateSessionOnClose;
|
|
1519
1529
|
this.fetchFn = fetchFn != null ? fetchFn : globalThis.fetch;
|
|
1520
1530
|
}
|
|
1521
1531
|
setProtocolVersion(version) {
|
|
1522
1532
|
this.protocolVersion = version;
|
|
1523
1533
|
}
|
|
1524
|
-
async commonHeaders(
|
|
1534
|
+
async commonHeaders({
|
|
1535
|
+
base,
|
|
1536
|
+
includeSessionId = true
|
|
1537
|
+
}) {
|
|
1525
1538
|
var _a3;
|
|
1526
1539
|
const headers = {
|
|
1527
1540
|
...this.headers,
|
|
1528
1541
|
...base,
|
|
1529
1542
|
"mcp-protocol-version": (_a3 = this.protocolVersion) != null ? _a3 : LATEST_PROTOCOL_VERSION
|
|
1530
1543
|
};
|
|
1531
|
-
if (this.sessionId) {
|
|
1544
|
+
if (includeSessionId && this.sessionId) {
|
|
1532
1545
|
headers["mcp-session-id"] = this.sessionId;
|
|
1533
1546
|
}
|
|
1534
1547
|
if (this.authProvider) {
|
|
@@ -1543,6 +1556,27 @@ var HttpMCPTransport = class {
|
|
|
1543
1556
|
getRuntimeEnvironmentUserAgent2()
|
|
1544
1557
|
);
|
|
1545
1558
|
}
|
|
1559
|
+
setSessionId(sessionId) {
|
|
1560
|
+
var _a3;
|
|
1561
|
+
if (this.sessionId === sessionId) {
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
this.sessionId = sessionId;
|
|
1565
|
+
(_a3 = this.onSessionIdChange) == null ? void 0 : _a3.call(this, sessionId);
|
|
1566
|
+
}
|
|
1567
|
+
applySessionIdFromResponse(response) {
|
|
1568
|
+
const sessionId = response.headers.get("mcp-session-id");
|
|
1569
|
+
if (sessionId) {
|
|
1570
|
+
this.setSessionId(sessionId);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
expireSessionId(sessionId) {
|
|
1574
|
+
var _a3;
|
|
1575
|
+
if (this.sessionId === sessionId) {
|
|
1576
|
+
this.setSessionId(void 0);
|
|
1577
|
+
}
|
|
1578
|
+
(_a3 = this.onSessionExpired) == null ? void 0 : _a3.call(this, sessionId);
|
|
1579
|
+
}
|
|
1546
1580
|
/**
|
|
1547
1581
|
* Runs a single OAuth recovery flow for concurrent 401 responses.
|
|
1548
1582
|
*/
|
|
@@ -1574,8 +1608,8 @@ var HttpMCPTransport = class {
|
|
|
1574
1608
|
var _a3, _b3, _c;
|
|
1575
1609
|
(_a3 = this.inboundSseConnection) == null ? void 0 : _a3.close();
|
|
1576
1610
|
try {
|
|
1577
|
-
if (this.sessionId && this.abortController && !this.abortController.signal.aborted) {
|
|
1578
|
-
const headers = await this.commonHeaders({});
|
|
1611
|
+
if (this.sessionId && this.terminateSessionOnClose && this.abortController && !this.abortController.signal.aborted) {
|
|
1612
|
+
const headers = await this.commonHeaders({ base: {} });
|
|
1579
1613
|
await this.fetchFn(this.url.href, {
|
|
1580
1614
|
method: "DELETE",
|
|
1581
1615
|
headers,
|
|
@@ -1592,9 +1626,14 @@ var HttpMCPTransport = class {
|
|
|
1592
1626
|
const attempt = async (triedAuth = false) => {
|
|
1593
1627
|
var _a3, _b3, _c, _d, _e, _f, _g;
|
|
1594
1628
|
try {
|
|
1629
|
+
const isInitializeRequest = "method" in message && message.method === "initialize";
|
|
1630
|
+
const sessionIdForRequest = isInitializeRequest ? void 0 : this.sessionId;
|
|
1595
1631
|
const headers = await this.commonHeaders({
|
|
1596
|
-
|
|
1597
|
-
|
|
1632
|
+
base: {
|
|
1633
|
+
"Content-Type": "application/json",
|
|
1634
|
+
Accept: "application/json, text/event-stream"
|
|
1635
|
+
},
|
|
1636
|
+
includeSessionId: !isInitializeRequest
|
|
1598
1637
|
});
|
|
1599
1638
|
const init = {
|
|
1600
1639
|
method: "POST",
|
|
@@ -1604,10 +1643,7 @@ var HttpMCPTransport = class {
|
|
|
1604
1643
|
redirect: this.redirectMode
|
|
1605
1644
|
};
|
|
1606
1645
|
const response = await this.fetchFn(this.url.href, init);
|
|
1607
|
-
|
|
1608
|
-
if (sessionId) {
|
|
1609
|
-
this.sessionId = sessionId;
|
|
1610
|
-
}
|
|
1646
|
+
this.applySessionIdFromResponse(response);
|
|
1611
1647
|
if (response.status === 401 && this.authProvider && !triedAuth) {
|
|
1612
1648
|
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
|
|
1613
1649
|
try {
|
|
@@ -1632,7 +1668,12 @@ var HttpMCPTransport = class {
|
|
|
1632
1668
|
const text = await response.text().catch(() => null);
|
|
1633
1669
|
let errorMessage = `MCP HTTP Transport Error: POSTing to endpoint (HTTP ${response.status}): ${text}`;
|
|
1634
1670
|
if (response.status === 404) {
|
|
1635
|
-
|
|
1671
|
+
if (sessionIdForRequest) {
|
|
1672
|
+
this.expireSessionId(sessionIdForRequest);
|
|
1673
|
+
errorMessage += ". The MCP session expired. Create a new client without `initialSessionId` to start a fresh session";
|
|
1674
|
+
} else {
|
|
1675
|
+
errorMessage += ". This server does not support HTTP transport. Try using `sse` transport instead";
|
|
1676
|
+
}
|
|
1636
1677
|
}
|
|
1637
1678
|
const error2 = new MCPClientError({
|
|
1638
1679
|
message: errorMessage,
|
|
@@ -1749,8 +1790,11 @@ var HttpMCPTransport = class {
|
|
|
1749
1790
|
async openInboundSse(triedAuth = false, resumeToken) {
|
|
1750
1791
|
var _a3, _b3, _c, _d, _e, _f;
|
|
1751
1792
|
try {
|
|
1793
|
+
const sessionIdForRequest = this.sessionId;
|
|
1752
1794
|
const headers = await this.commonHeaders({
|
|
1753
|
-
|
|
1795
|
+
base: {
|
|
1796
|
+
Accept: "text/event-stream"
|
|
1797
|
+
}
|
|
1754
1798
|
});
|
|
1755
1799
|
if (resumeToken) {
|
|
1756
1800
|
headers["last-event-id"] = resumeToken;
|
|
@@ -1761,10 +1805,7 @@ var HttpMCPTransport = class {
|
|
|
1761
1805
|
signal: (_a3 = this.abortController) == null ? void 0 : _a3.signal,
|
|
1762
1806
|
redirect: this.redirectMode
|
|
1763
1807
|
});
|
|
1764
|
-
|
|
1765
|
-
if (sessionId) {
|
|
1766
|
-
this.sessionId = sessionId;
|
|
1767
|
-
}
|
|
1808
|
+
this.applySessionIdFromResponse(response);
|
|
1768
1809
|
if (response.status === 401 && this.authProvider && !triedAuth) {
|
|
1769
1810
|
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
|
|
1770
1811
|
try {
|
|
@@ -1784,6 +1825,9 @@ var HttpMCPTransport = class {
|
|
|
1784
1825
|
return;
|
|
1785
1826
|
}
|
|
1786
1827
|
if (!response.ok || !response.body) {
|
|
1828
|
+
if (response.status === 404 && sessionIdForRequest) {
|
|
1829
|
+
this.expireSessionId(sessionIdForRequest);
|
|
1830
|
+
}
|
|
1787
1831
|
const error = new MCPClientError({
|
|
1788
1832
|
message: `MCP HTTP Transport Error: GET SSE failed: ${response.status} ${response.statusText}`,
|
|
1789
1833
|
statusCode: response.status,
|
|
@@ -2005,15 +2049,22 @@ var DefaultMCPClient = class {
|
|
|
2005
2049
|
clientName = name3 != null ? name3 : "ai-sdk-mcp-client",
|
|
2006
2050
|
version = CLIENT_VERSION,
|
|
2007
2051
|
onUncaughtError,
|
|
2008
|
-
capabilities
|
|
2052
|
+
capabilities,
|
|
2053
|
+
initialInitializeResult
|
|
2009
2054
|
}) {
|
|
2010
2055
|
this.requestMessageId = 0;
|
|
2011
2056
|
this.responseHandlers = /* @__PURE__ */ new Map();
|
|
2012
2057
|
this.serverCapabilities = {};
|
|
2013
2058
|
this._serverInfo = { name: "", version: "" };
|
|
2059
|
+
this._initializeResult = {
|
|
2060
|
+
protocolVersion: LATEST_PROTOCOL_VERSION,
|
|
2061
|
+
capabilities: {},
|
|
2062
|
+
serverInfo: this._serverInfo
|
|
2063
|
+
};
|
|
2014
2064
|
this.isClosed = true;
|
|
2015
2065
|
this.onUncaughtError = onUncaughtError;
|
|
2016
2066
|
this.clientCapabilities = capabilities != null ? capabilities : {};
|
|
2067
|
+
this.initialInitializeResult = initialInitializeResult;
|
|
2017
2068
|
if (isCustomMcpTransport(transportConfig)) {
|
|
2018
2069
|
this.transport = transportConfig;
|
|
2019
2070
|
} else {
|
|
@@ -2044,6 +2095,9 @@ var DefaultMCPClient = class {
|
|
|
2044
2095
|
get serverInfo() {
|
|
2045
2096
|
return this._serverInfo;
|
|
2046
2097
|
}
|
|
2098
|
+
get initializeResult() {
|
|
2099
|
+
return this._initializeResult;
|
|
2100
|
+
}
|
|
2047
2101
|
get instructions() {
|
|
2048
2102
|
return this._serverInstructions;
|
|
2049
2103
|
}
|
|
@@ -2051,6 +2105,13 @@ var DefaultMCPClient = class {
|
|
|
2051
2105
|
try {
|
|
2052
2106
|
await this.transport.start();
|
|
2053
2107
|
this.isClosed = false;
|
|
2108
|
+
if (this.initialInitializeResult) {
|
|
2109
|
+
const result2 = InitializeResultSchema.parse(
|
|
2110
|
+
this.initialInitializeResult
|
|
2111
|
+
);
|
|
2112
|
+
this.applyInitializeResult(result2);
|
|
2113
|
+
return this;
|
|
2114
|
+
}
|
|
2054
2115
|
const result = await this.request({
|
|
2055
2116
|
request: {
|
|
2056
2117
|
method: "initialize",
|
|
@@ -2067,19 +2128,7 @@ var DefaultMCPClient = class {
|
|
|
2067
2128
|
message: "Server sent invalid initialize result"
|
|
2068
2129
|
});
|
|
2069
2130
|
}
|
|
2070
|
-
|
|
2071
|
-
throw new MCPClientError({
|
|
2072
|
-
message: `Server's protocol version is not supported: ${result.protocolVersion}`
|
|
2073
|
-
});
|
|
2074
|
-
}
|
|
2075
|
-
this.serverCapabilities = result.capabilities;
|
|
2076
|
-
this._serverInfo = result.serverInfo;
|
|
2077
|
-
if (this.transport.setProtocolVersion) {
|
|
2078
|
-
this.transport.setProtocolVersion(result.protocolVersion);
|
|
2079
|
-
} else {
|
|
2080
|
-
this.transport.protocolVersion = result.protocolVersion;
|
|
2081
|
-
}
|
|
2082
|
-
this._serverInstructions = result.instructions;
|
|
2131
|
+
this.applyInitializeResult(result);
|
|
2083
2132
|
await this.notification({
|
|
2084
2133
|
method: "notifications/initialized"
|
|
2085
2134
|
});
|
|
@@ -2089,6 +2138,22 @@ var DefaultMCPClient = class {
|
|
|
2089
2138
|
throw error;
|
|
2090
2139
|
}
|
|
2091
2140
|
}
|
|
2141
|
+
applyInitializeResult(result) {
|
|
2142
|
+
if (!SUPPORTED_PROTOCOL_VERSIONS.includes(result.protocolVersion)) {
|
|
2143
|
+
throw new MCPClientError({
|
|
2144
|
+
message: `Server's protocol version is not supported: ${result.protocolVersion}`
|
|
2145
|
+
});
|
|
2146
|
+
}
|
|
2147
|
+
this.serverCapabilities = result.capabilities;
|
|
2148
|
+
this._serverInfo = result.serverInfo;
|
|
2149
|
+
this._initializeResult = result;
|
|
2150
|
+
if (this.transport.setProtocolVersion) {
|
|
2151
|
+
this.transport.setProtocolVersion(result.protocolVersion);
|
|
2152
|
+
} else {
|
|
2153
|
+
this.transport.protocolVersion = result.protocolVersion;
|
|
2154
|
+
}
|
|
2155
|
+
this._serverInstructions = result.instructions;
|
|
2156
|
+
}
|
|
2092
2157
|
async close() {
|
|
2093
2158
|
var _a3;
|
|
2094
2159
|
if (this.isClosed) return;
|