@ai-sdk/mcp 1.0.42 → 1.0.43
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 +6 -0
- package/README.md +134 -0
- package/dist/index.js +20 -10
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +20 -10
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/tool/mcp-http-transport.ts +25 -10
package/CHANGELOG.md
CHANGED
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# AI SDK - Model Context Protocol Client
|
|
2
|
+
|
|
3
|
+
The **Model Context Protocol (MCP) client** for the
|
|
4
|
+
[AI SDK](https://ai-sdk.dev/docs) lets you connect to MCP servers and use their
|
|
5
|
+
tools with AI SDK functions like `generateText` and `streamText`.
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
The MCP client is available in the `@ai-sdk/mcp` module. You can install it with
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm i @ai-sdk/mcp ai zod
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Skill for Coding Agents
|
|
16
|
+
|
|
17
|
+
If you use coding agents such as Claude Code or Cursor, we highly recommend
|
|
18
|
+
adding the AI SDK skill to your repository:
|
|
19
|
+
|
|
20
|
+
```shell
|
|
21
|
+
npx skills add vercel/ai
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
Create an MCP client with `createMCPClient()`, fetch the server tools with
|
|
27
|
+
`mcpClient.tools()`, and pass them to an AI SDK call:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { createMCPClient } from '@ai-sdk/mcp';
|
|
31
|
+
import { generateText, isStepCount } from 'ai';
|
|
32
|
+
|
|
33
|
+
const mcpClient = await createMCPClient({
|
|
34
|
+
transport: {
|
|
35
|
+
type: 'http',
|
|
36
|
+
url: 'https://your-server.com/mcp',
|
|
37
|
+
headers: {
|
|
38
|
+
Authorization: `Bearer ${process.env.MCP_API_KEY}`,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
const tools = await mcpClient.tools();
|
|
45
|
+
|
|
46
|
+
const { text } = await generateText({
|
|
47
|
+
model: 'openai/gpt-5.4',
|
|
48
|
+
tools,
|
|
49
|
+
stopWhen: isStepCount(10),
|
|
50
|
+
prompt: 'Use the available tools to answer the user question.',
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
console.log(text);
|
|
54
|
+
} finally {
|
|
55
|
+
await mcpClient.close();
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The client converts MCP tool definitions into AI SDK tools, so model calls can
|
|
60
|
+
use them through the standard `tools` option.
|
|
61
|
+
|
|
62
|
+
For streaming responses, close the MCP client when the stream finishes:
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { createMCPClient } from '@ai-sdk/mcp';
|
|
66
|
+
import { streamText } from 'ai';
|
|
67
|
+
|
|
68
|
+
const mcpClient = await createMCPClient({
|
|
69
|
+
transport: {
|
|
70
|
+
type: 'http',
|
|
71
|
+
url: 'https://your-server.com/mcp',
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
const result = streamText({
|
|
76
|
+
model: 'openai/gpt-5.4',
|
|
77
|
+
tools: await mcpClient.tools(),
|
|
78
|
+
prompt: 'Use the available tools to answer the user question.',
|
|
79
|
+
onFinish: async () => {
|
|
80
|
+
await mcpClient.close();
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
for await (const textPart of result.textStream) {
|
|
85
|
+
process.stdout.write(textPart);
|
|
86
|
+
}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Transports
|
|
90
|
+
|
|
91
|
+
HTTP is recommended for production deployments:
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
import { createMCPClient } from '@ai-sdk/mcp';
|
|
95
|
+
|
|
96
|
+
const mcpClient = await createMCPClient({
|
|
97
|
+
transport: {
|
|
98
|
+
type: 'http',
|
|
99
|
+
url: 'https://your-server.com/mcp',
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
SSE is also supported for MCP servers that use Server-Sent Events:
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
const mcpClient = await createMCPClient({
|
|
108
|
+
transport: {
|
|
109
|
+
type: 'sse',
|
|
110
|
+
url: 'https://your-server.com/sse',
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
For local MCP servers, you can use stdio transport from the `@ai-sdk/mcp/mcp-stdio`
|
|
116
|
+
subpath:
|
|
117
|
+
|
|
118
|
+
```ts
|
|
119
|
+
import { createMCPClient } from '@ai-sdk/mcp';
|
|
120
|
+
import { Experimental_StdioMCPTransport } from '@ai-sdk/mcp/mcp-stdio';
|
|
121
|
+
|
|
122
|
+
const mcpClient = await createMCPClient({
|
|
123
|
+
transport: new Experimental_StdioMCPTransport({
|
|
124
|
+
command: 'node',
|
|
125
|
+
args: ['server.js'],
|
|
126
|
+
}),
|
|
127
|
+
});
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Documentation
|
|
131
|
+
|
|
132
|
+
Please check out the
|
|
133
|
+
[AI SDK MCP documentation](https://ai-sdk.dev/docs/ai-sdk-core/mcp-tools) for
|
|
134
|
+
more information.
|
package/dist/index.js
CHANGED
|
@@ -1351,6 +1351,24 @@ var HttpMCPTransport = class {
|
|
|
1351
1351
|
(0, import_provider_utils4.getRuntimeEnvironmentUserAgent)()
|
|
1352
1352
|
);
|
|
1353
1353
|
}
|
|
1354
|
+
/**
|
|
1355
|
+
* Runs a single OAuth recovery flow for concurrent 401 responses.
|
|
1356
|
+
*/
|
|
1357
|
+
authorizeOnce(resourceMetadataUrl) {
|
|
1358
|
+
if (!this.authProvider) {
|
|
1359
|
+
return Promise.resolve("REDIRECT");
|
|
1360
|
+
}
|
|
1361
|
+
if (!this.authPromise) {
|
|
1362
|
+
this.authPromise = auth(this.authProvider, {
|
|
1363
|
+
serverUrl: this.url,
|
|
1364
|
+
resourceMetadataUrl,
|
|
1365
|
+
fetchFn: this.fetchFn
|
|
1366
|
+
}).finally(() => {
|
|
1367
|
+
this.authPromise = void 0;
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
return this.authPromise;
|
|
1371
|
+
}
|
|
1354
1372
|
async start() {
|
|
1355
1373
|
if (this.abortController) {
|
|
1356
1374
|
throw new MCPClientError({
|
|
@@ -1401,11 +1419,7 @@ var HttpMCPTransport = class {
|
|
|
1401
1419
|
if (response.status === 401 && this.authProvider && !triedAuth) {
|
|
1402
1420
|
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
|
|
1403
1421
|
try {
|
|
1404
|
-
const result = await
|
|
1405
|
-
serverUrl: this.url,
|
|
1406
|
-
resourceMetadataUrl: this.resourceMetadataUrl,
|
|
1407
|
-
fetchFn: this.fetchFn
|
|
1408
|
-
});
|
|
1422
|
+
const result = await this.authorizeOnce(this.resourceMetadataUrl);
|
|
1409
1423
|
if (result !== "AUTHORIZED") {
|
|
1410
1424
|
const error2 = new UnauthorizedError();
|
|
1411
1425
|
throw error2;
|
|
@@ -1551,11 +1565,7 @@ var HttpMCPTransport = class {
|
|
|
1551
1565
|
if (response.status === 401 && this.authProvider && !triedAuth) {
|
|
1552
1566
|
this.resourceMetadataUrl = extractResourceMetadataUrl(response);
|
|
1553
1567
|
try {
|
|
1554
|
-
const result = await
|
|
1555
|
-
serverUrl: this.url,
|
|
1556
|
-
resourceMetadataUrl: this.resourceMetadataUrl,
|
|
1557
|
-
fetchFn: this.fetchFn
|
|
1558
|
-
});
|
|
1568
|
+
const result = await this.authorizeOnce(this.resourceMetadataUrl);
|
|
1559
1569
|
if (result !== "AUTHORIZED") {
|
|
1560
1570
|
const error = new UnauthorizedError();
|
|
1561
1571
|
(_b3 = this.onerror) == null ? void 0 : _b3.call(this, error);
|