@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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @ai-sdk/mcp
2
2
 
3
+ ## 1.0.43
4
+
5
+ ### Patch Changes
6
+
7
+ - e2b923f: fix(mcp): deduplicate auth refresh on http transport
8
+
3
9
  ## 1.0.42
4
10
 
5
11
  ### Patch Changes
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 auth(this.authProvider, {
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 auth(this.authProvider, {
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);