agents 0.30.0 → 0.31.0
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/README.md +4 -2
- package/dist/{agent-routing-CDbpVjYq.d.ts → agent-routing-wS1TimZ_.d.ts} +64 -603
- package/dist/agent-routing.d.ts +1 -1
- package/dist/agent-tool-types.d.ts +1 -1
- package/dist/{agent-tools-C8DH8Yii.d.ts → agent-tools-Bamxxb6Y.d.ts} +2 -2
- package/dist/agent-tools.d.ts +1 -1
- package/dist/{ai-iXw0uOGj.d.ts → ai-CDn3Abax.d.ts} +30 -4
- package/dist/{ai-sdk-DRPh2rRa.js → ai-sdk-Kon40i0q.js} +2 -36
- package/dist/ai-sdk-Kon40i0q.js.map +1 -0
- package/dist/ai-sdk-hW3vntnk.d.ts +72 -0
- package/dist/browser/ai.d.ts +1 -1
- package/dist/browser/ai.js +16 -3
- package/dist/browser/ai.js.map +1 -1
- package/dist/browser/index.d.ts +64 -16
- package/dist/browser/index.js +4 -4
- package/dist/browser/tools/ai-sdk.d.ts +7 -70
- package/dist/browser/tools/ai-sdk.js +4 -4
- package/dist/browser/tools/ai-sdk.js.map +1 -1
- package/dist/browser/tools/pi.d.ts +9 -15
- package/dist/browser/tools/pi.js +6 -14
- package/dist/browser/tools/pi.js.map +1 -1
- package/dist/browser/tools/tanstack-ai.d.ts +46 -23
- package/dist/browser/tools/tanstack-ai.js +8 -4
- package/dist/browser/tools/tanstack-ai.js.map +1 -1
- package/dist/{browser-DccPw_wW.js → browser-1eUbPvC2.js} +413 -14
- package/dist/browser-1eUbPvC2.js.map +1 -0
- package/dist/{browser-DlXhSAdf.d.ts → browser-D9RNpJuT.d.ts} +254 -20
- package/dist/browser-tool-BhjCcNVE.d.ts +71 -0
- package/dist/browser-tool-lGnvEBLJ.js +497 -0
- package/dist/browser-tool-lGnvEBLJ.js.map +1 -0
- package/dist/capability-id-B3J8Nok_.js +13 -0
- package/dist/capability-id-B3J8Nok_.js.map +1 -0
- package/dist/chat/index.d.ts +2 -2
- package/dist/chat-sdk/index.d.ts +3 -3
- package/dist/chat-sdk/index.js +1 -1
- package/dist/client-4OlMIJx-.js.map +1 -1
- package/dist/{client-BnYbNT3z.js → client-DMWujQJ1.js} +68 -244
- package/dist/client-DMWujQJ1.js.map +1 -0
- package/dist/{client-C27CtRZr.d.ts → client-wn4-yqGz.d.ts} +9 -7
- package/dist/client.d.ts +1 -1
- package/dist/{connector-DAXBOIIi.js → connector-CM-uuxKM.js} +96 -8
- package/dist/connector-CM-uuxKM.js.map +1 -0
- package/dist/{connector-20DJ6p4k.d.ts → connector-DZ71EjE-.d.ts} +109 -9
- package/dist/experimental/webmcp.js +1 -1
- package/dist/{handler-stateless-Bly_nSH3.js → handler-stateless-B5hU3dxK.js} +35 -2
- package/dist/handler-stateless-B5hU3dxK.js.map +1 -0
- package/dist/{handler-stateless-DxYpJ_XF.d.ts → handler-stateless-C90kD5_R.d.ts} +3 -47
- package/dist/harness/container/index.d.ts +15 -15
- package/dist/harness/opencode/index.js.map +1 -1
- package/dist/harness/pi/index.d.ts +7 -3
- package/dist/harness/pi/index.js +46 -15
- package/dist/harness/pi/index.js.map +1 -1
- package/dist/harness/think/index.d.ts +2 -1
- package/dist/{images-xaDv2Fqe.js → images-CfuRCjwq.js} +1 -5
- package/dist/images-CfuRCjwq.js.map +1 -0
- package/dist/{index-DCxk3OSJ.d.ts → index-8k4qsX1T.d.ts} +2 -28
- package/dist/index.d.ts +14 -14
- package/dist/index.js +2 -2
- package/dist/internal-hosts-Kfp5A392.d.ts +230 -0
- package/dist/internal-kmw70xwR.js.map +1 -1
- package/dist/invoker-BC1SZ3q1.js +26 -0
- package/dist/invoker-BC1SZ3q1.js.map +1 -0
- package/dist/invoker-DoLFPJZV.d.ts +21 -0
- package/dist/mcp/client/index.d.ts +15 -1
- package/dist/mcp/client/index.js +2 -2
- package/dist/mcp/client/x402.d.ts +7 -5
- package/dist/mcp/client/x402.js +34 -1
- package/dist/mcp/client/x402.js.map +1 -1
- package/dist/mcp/index.d.ts +561 -27
- package/dist/mcp/index.js +180 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/server/index.d.ts +1 -1
- package/dist/mcp/server/index.js +1 -1
- package/dist/models/ai-sdk/index.d.ts +2 -2
- package/dist/models/ai-sdk/index.js +1 -1
- package/dist/models/opencode/index.d.ts +2 -2
- package/dist/models/opencode/index.js +1 -1
- package/dist/models/pi-ai/index.d.ts +3 -28
- package/dist/models/pi-ai/index.js +31 -16
- package/dist/models/pi-ai/index.js.map +1 -1
- package/dist/protocol-BEgrJYC5.d.ts +29 -29
- package/dist/react.d.ts +2 -2
- package/dist/routing/index.d.ts +1 -1
- package/dist/serializable.d.ts +1 -1
- package/dist/{session-store-yvwq1f9x.js → session-7CDgVE0z.js} +455 -33
- package/dist/session-7CDgVE0z.js.map +1 -0
- package/dist/{session-store-_IK6dV-w.d.ts → session-store-B7Ca-u1t.d.ts} +8 -1
- package/dist/settings-Dk2il2Hf.js.map +1 -1
- package/dist/{src-DfLzdwlK.js → src-BGolXG_H.js} +18 -2
- package/dist/src-BGolXG_H.js.map +1 -0
- package/dist/sub-routing.d.ts +12 -12
- package/dist/tool-CTp72Jb_.d.ts +10 -10
- package/dist/tool-DoVberpN.d.ts +22 -22
- package/dist/tool-helpers-BodWi4gd.js +256 -0
- package/dist/tool-helpers-BodWi4gd.js.map +1 -0
- package/dist/{transport-CPh7YGiw.d.ts → transport-5moD2pW5.d.ts} +1 -43
- package/dist/types-D2naO3rA.d.ts +49 -0
- package/dist/voice/index.d.ts +1 -1
- package/dist/workflow-types.d.ts +1 -1
- package/dist/workflows.d.ts +1 -1
- package/dist/workflows.js +1 -1
- package/docs/browse-the-web.md +247 -413
- package/docs/get-current-agent.md +4 -7
- package/docs/harnesses/pi.md +28 -28
- package/docs/human-in-the-loop.md +3 -7
- package/docs/index.md +6 -6
- package/docs/mcp-client.md +4 -28
- package/docs/mcp-servers.md +137 -411
- package/docs/mcp-transports.md +30 -289
- package/docs/models-pi-ai.md +9 -11
- package/docs/models.md +1 -8
- package/docs/routing.md +0 -2
- package/docs/securing-mcp-servers.md +120 -304
- package/package.json +8 -3
- package/dist/ai-sdk-DRPh2rRa.js.map +0 -1
- package/dist/browser-DccPw_wW.js.map +0 -1
- package/dist/browser-tool-B1mhifin.js +0 -616
- package/dist/browser-tool-B1mhifin.js.map +0 -1
- package/dist/browser-tool-Cxjk5sgG.d.ts +0 -92
- package/dist/client-BnYbNT3z.js.map +0 -1
- package/dist/connector-DAXBOIIi.js.map +0 -1
- package/dist/handler-stateless-Bly_nSH3.js.map +0 -1
- package/dist/images-xaDv2Fqe.js.map +0 -1
- package/dist/invoker-CG0_p_Wq.d.ts +0 -20
- package/dist/invoker-CHMnoxIA.js +0 -57
- package/dist/invoker-CHMnoxIA.js.map +0 -1
- package/dist/session-store-yvwq1f9x.js.map +0 -1
- package/dist/src-DfLzdwlK.js.map +0 -1
- package/dist/tool-helpers-O5BDVEAY.js +0 -58
- package/dist/tool-helpers-O5BDVEAY.js.map +0 -1
package/docs/mcp-transports.md
CHANGED
|
@@ -1,314 +1,55 @@
|
|
|
1
1
|
# MCP Transports
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
This page covers the transport your MCP server uses and the transports an Agent can use to connect to other MCP servers.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Server: Streamable HTTP
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
The Agents SDK has two server paths:
|
|
10
|
-
|
|
11
|
-
- Current SDK v2 servers use `createMcpHandler`, a per-request stateless Worker handler with no Durable Object or WebSocket bridge.
|
|
12
|
-
- Retained SDK v1 servers use the deprecated, feature-frozen `McpAgent`, which provides sessionful transports through a Durable Object and internal WebSocket bridge.
|
|
13
|
-
|
|
14
|
-
The current stateless handler also accepts stateless 2025-era Streamable HTTP requests by default. It does not expose standalone legacy SSE.
|
|
15
|
-
|
|
16
|
-
### Legacy `McpAgent` architecture
|
|
17
|
-
|
|
18
|
-
When a client connects to your MCP server:
|
|
19
|
-
|
|
20
|
-
1. The client makes an HTTP request to your Worker with a JSON-RPC message in the body
|
|
21
|
-
2. Your Worker upgrades the connection to a WebSocket
|
|
22
|
-
3. The WebSocket connects to your `McpAgent` Durable Object which manages connection state
|
|
23
|
-
4. JSON-RPC messages flow bidirectionally over the WebSocket
|
|
24
|
-
5. Your Worker streams responses back to the client using Server-Sent Events (SSE)
|
|
25
|
-
|
|
26
|
-
This is all handled automatically by the `McpAgent.serve()` method:
|
|
7
|
+
[`createMcpHandler`](./mcp-servers.md) serves Streamable HTTP. Each request is handled on its own, with a fresh `McpServer` from your factory, so there are no sessions, Durable Objects, or WebSockets behind the endpoint.
|
|
27
8
|
|
|
28
9
|
```typescript
|
|
29
|
-
import {
|
|
30
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
31
|
-
|
|
32
|
-
export class MyMCP extends McpAgent {
|
|
33
|
-
server = new McpServer({ name: "Demo", version: "1.0.0" });
|
|
34
|
-
|
|
35
|
-
async init() {
|
|
36
|
-
// Define your tools, resources, prompts
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Serve with Streamable HTTP transport
|
|
41
|
-
export default MyMCP.serve("/mcp");
|
|
42
|
-
```
|
|
10
|
+
import { createMcpHandler } from "agents/mcp/server";
|
|
43
11
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
- Handles CORS preflight requests
|
|
47
|
-
- Manages WebSocket upgrades
|
|
48
|
-
- Routes messages to your Durable Object
|
|
49
|
-
|
|
50
|
-
### Connection from clients
|
|
51
|
-
|
|
52
|
-
The Agents MCP client uses `"auto"` by default. It tries Streamable HTTP first and falls back to legacy SSE only when the endpoint reports that Streamable HTTP is unsupported:
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
await agent.addMcpServer("my-server", "https://your-worker.workers.dev/mcp");
|
|
12
|
+
const handler = createMcpHandler(createServer, { route: "/mcp" });
|
|
56
13
|
```
|
|
57
14
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
The **auto** transport serves both Streamable HTTP and legacy SSE on the same endpoint. Capable clients use Streamable HTTP automatically, while older SSE-only clients continue to work.
|
|
15
|
+
The same endpoint serves:
|
|
61
16
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
The handler distinguishes between the two protocols based on the request shape — no configuration or content negotiation is required from clients. This is useful when migrating from SSE to Streamable HTTP without breaking existing clients.
|
|
17
|
+
- Stateless clients on draft MCP `2026-07-28`
|
|
18
|
+
- 2025-era Streamable HTTP clients, for tools, resources, and prompts (the default `legacy: "stateless"` lane)
|
|
67
19
|
|
|
68
|
-
|
|
20
|
+
It does not serve the standalone SSE transport. Set `legacy: "reject"` to accept only Stateless clients. See [2025-era clients](./mcp-servers.md#2025-era-clients) for what that lane does not support.
|
|
69
21
|
|
|
70
|
-
|
|
22
|
+
## Client: connecting to MCP servers
|
|
71
23
|
|
|
72
|
-
|
|
24
|
+
An Agent connects to remote MCP servers with `addMcpServer()`. The `transport.type` option picks the transport:
|
|
73
25
|
|
|
74
26
|
```typescript
|
|
75
|
-
//
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
// Client
|
|
79
|
-
await agent.addMcpServer("my-server", url);
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## RPC Transport (Experimental)
|
|
83
|
-
|
|
84
|
-
The **RPC transport** is a custom transport designed for internal applications where your MCP server and agent are both running on Cloudflare. They can even run in the same Worker! It sends JSON-RPC messages directly over Cloudflare's RPC bindings without going over the public internet.
|
|
85
|
-
|
|
86
|
-
### Why use RPC transport?
|
|
87
|
-
|
|
88
|
-
- **Faster**: No network overhead - direct function calls
|
|
89
|
-
- **Simpler**: No HTTP endpoints, no connection management
|
|
90
|
-
- **Internal only**: Perfect for agents calling MCP servers within the same Worker
|
|
91
|
-
|
|
92
|
-
**Note**: RPC transport does not support authentication. Use HTTP/SSE for external connections that require OAuth.
|
|
93
|
-
|
|
94
|
-
### Connecting an Agent to an McpAgent via RPC
|
|
95
|
-
|
|
96
|
-
The RPC transport uses Durable Object bindings to connect your `Agent` (MCP client) directly to your `McpAgent` (MCP server).
|
|
97
|
-
|
|
98
|
-
#### Step 1: Define your MCP server
|
|
99
|
-
|
|
100
|
-
Create your `McpAgent` with the tools you want to expose:
|
|
101
|
-
|
|
102
|
-
```typescript
|
|
103
|
-
import { McpAgent } from "agents/mcp";
|
|
104
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
105
|
-
import { z } from "zod";
|
|
106
|
-
|
|
107
|
-
type State = { counter: number };
|
|
108
|
-
|
|
109
|
-
export class MyMCP extends McpAgent<Env, State> {
|
|
110
|
-
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
|
|
111
|
-
initialState: State = { counter: 0 };
|
|
112
|
-
|
|
113
|
-
async init() {
|
|
114
|
-
this.server.tool(
|
|
115
|
-
"add",
|
|
116
|
-
"Add to the counter",
|
|
117
|
-
{ amount: z.number() },
|
|
118
|
-
async ({ amount }) => {
|
|
119
|
-
this.setState({ counter: this.state.counter + amount });
|
|
120
|
-
return {
|
|
121
|
-
content: [
|
|
122
|
-
{
|
|
123
|
-
type: "text",
|
|
124
|
-
text: `Added ${amount}, total is now ${this.state.counter}`
|
|
125
|
-
}
|
|
126
|
-
]
|
|
127
|
-
};
|
|
128
|
-
}
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
#### Step 2: Connect your Agent to the MCP server
|
|
135
|
-
|
|
136
|
-
In your `Agent`, call `addMcpServer()` with the Durable Object binding in `onStart()`:
|
|
137
|
-
|
|
138
|
-
```typescript
|
|
139
|
-
import { AIChatAgent } from "agents/ai-chat-agent";
|
|
140
|
-
|
|
141
|
-
export class Chat extends AIChatAgent<Env> {
|
|
142
|
-
async onStart(): Promise<void> {
|
|
143
|
-
// Pass the DO namespace binding directly
|
|
144
|
-
await this.addMcpServer("my-mcp", this.env.MyMCP);
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
async onChatMessage(onFinish) {
|
|
148
|
-
const allTools = this.mcp.getAITools();
|
|
149
|
-
|
|
150
|
-
const result = streamText({
|
|
151
|
-
model,
|
|
152
|
-
tools: allTools
|
|
153
|
-
// ...
|
|
154
|
-
});
|
|
27
|
+
// Default: try Streamable HTTP, fall back to SSE
|
|
28
|
+
await this.addMcpServer("my-server", "https://example.com/mcp");
|
|
155
29
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
```
|
|
160
|
-
|
|
161
|
-
RPC connections are automatically restored after Durable Object hibernation, just like HTTP connections. The binding name and props are persisted to storage so the connection can be re-established without any extra code.
|
|
162
|
-
|
|
163
|
-
**Deduplication:** For RPC transport, if `addMcpServer` is called with a name that already has an active connection, the existing connection is returned instead of creating a duplicate. For HTTP transport, deduplication matches on both server name and URL (see [MCP Client API](./mcp-client.md) for details). This makes it safe to call `addMcpServer` in `onStart()` without worrying about creating multiple connections on restart.
|
|
164
|
-
|
|
165
|
-
#### Step 3: Configure Durable Object bindings
|
|
166
|
-
|
|
167
|
-
In your `wrangler.jsonc`, define bindings for both Durable Objects:
|
|
168
|
-
|
|
169
|
-
```jsonc
|
|
170
|
-
{
|
|
171
|
-
"durable_objects": {
|
|
172
|
-
"bindings": [
|
|
173
|
-
{ "name": "Chat", "class_name": "Chat" },
|
|
174
|
-
{ "name": "MyMCP", "class_name": "MyMCP" }
|
|
175
|
-
]
|
|
176
|
-
},
|
|
177
|
-
"migrations": [
|
|
178
|
-
{
|
|
179
|
-
"new_sqlite_classes": ["MyMCP", "Chat"],
|
|
180
|
-
"tag": "v1"
|
|
181
|
-
}
|
|
182
|
-
]
|
|
183
|
-
}
|
|
184
|
-
```
|
|
185
|
-
|
|
186
|
-
#### Step 4: Set up your Worker fetch handler
|
|
187
|
-
|
|
188
|
-
Route requests to your Chat agent:
|
|
189
|
-
|
|
190
|
-
```typescript
|
|
191
|
-
import { routeAgentRequest } from "agents";
|
|
192
|
-
|
|
193
|
-
export default {
|
|
194
|
-
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
|
195
|
-
const url = new URL(request.url);
|
|
196
|
-
|
|
197
|
-
// Optionally expose the MCP server via HTTP as well
|
|
198
|
-
if (url.pathname.startsWith("/mcp")) {
|
|
199
|
-
return MyMCP.serve("/mcp").fetch(request, env, ctx);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
const response = await routeAgentRequest(request, env);
|
|
203
|
-
if (response) return response;
|
|
204
|
-
|
|
205
|
-
return new Response("Not found", { status: 404 });
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
```
|
|
209
|
-
|
|
210
|
-
### Passing props from client to server
|
|
211
|
-
|
|
212
|
-
Since RPC transport does not have an OAuth flow, you can pass user context (like userId, role, etc.) directly as props:
|
|
213
|
-
|
|
214
|
-
```typescript
|
|
215
|
-
await this.addMcpServer("my-mcp", this.env.MyMCP, {
|
|
216
|
-
props: { userId: "user-123", role: "admin" }
|
|
30
|
+
// Force a transport
|
|
31
|
+
await this.addMcpServer("my-server", "https://example.com/mcp", {
|
|
32
|
+
transport: { type: "streamable-http" }
|
|
217
33
|
});
|
|
218
|
-
```
|
|
219
34
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
State,
|
|
226
|
-
{ userId?: string; role?: string }
|
|
227
|
-
> {
|
|
228
|
-
async init() {
|
|
229
|
-
this.server.tool("whoami", "Get current user info", {}, async () => {
|
|
230
|
-
const userId = this.props?.userId || "anonymous";
|
|
231
|
-
const role = this.props?.role || "guest";
|
|
232
|
-
|
|
233
|
-
return {
|
|
234
|
-
content: [{ type: "text", text: `User ID: ${userId}, Role: ${role}` }]
|
|
235
|
-
};
|
|
236
|
-
});
|
|
35
|
+
// Send extra headers, for example an API key
|
|
36
|
+
await this.addMcpServer("my-server", "https://example.com/mcp", {
|
|
37
|
+
transport: {
|
|
38
|
+
type: "streamable-http",
|
|
39
|
+
headers: { Authorization: `Bearer ${this.env.API_KEY}` }
|
|
237
40
|
}
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
The props are:
|
|
242
|
-
|
|
243
|
-
- **Type-safe**: TypeScript extracts the Props type from your McpAgent generic
|
|
244
|
-
- **Persistent**: Stored in Durable Object storage via `updateProps()`
|
|
245
|
-
- **Available immediately**: Set before any tool calls are made
|
|
246
|
-
|
|
247
|
-
This is useful for:
|
|
248
|
-
|
|
249
|
-
- User authentication context
|
|
250
|
-
- Tenant/organization IDs
|
|
251
|
-
- Feature flags or permissions
|
|
252
|
-
- Any per-connection configuration
|
|
253
|
-
|
|
254
|
-
### How RPC transport works under the hood
|
|
255
|
-
|
|
256
|
-
When you call `addMcpServer()` with a Durable Object binding, the SDK:
|
|
257
|
-
|
|
258
|
-
1. Creates an `RPCClientTransport` that wraps the DO stub
|
|
259
|
-
2. Calls `handleMcpMessage()` on the `McpAgent` for each JSON-RPC message
|
|
260
|
-
3. The `McpAgent` routes messages through its `RPCServerTransport` to the MCP server
|
|
261
|
-
4. Responses flow back synchronously through the RPC call
|
|
262
|
-
|
|
263
|
-
This happens entirely within your Worker's execution context using Cloudflare's RPC mechanism - no HTTP, no WebSockets, no public internet.
|
|
264
|
-
|
|
265
|
-
The RPC transport fully supports:
|
|
266
|
-
|
|
267
|
-
- JSON-RPC 2.0 validation (via the MCP SDK's schema)
|
|
268
|
-
- Batch requests
|
|
269
|
-
- Notifications (messages without `id` field)
|
|
270
|
-
- Automatic reconnection after Durable Object hibernation (when called from `onStart()`)
|
|
271
|
-
|
|
272
|
-
### Configuring RPC Transport Server Timeout
|
|
273
|
-
|
|
274
|
-
The RPC transport has a configurable timeout for waiting for tool responses. By default, the server will wait **60 seconds** for a tool handler to respond. You can customize this by overriding `getRpcTransportOptions()` in your `McpAgent`:
|
|
275
|
-
|
|
276
|
-
```typescript
|
|
277
|
-
export class MyMCP extends McpAgent<Env, State> {
|
|
278
|
-
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
|
|
279
|
-
|
|
280
|
-
protected getRpcTransportOptions() {
|
|
281
|
-
return { timeout: 120000 }; // 2 minutes
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
async init() {
|
|
285
|
-
this.server.tool(
|
|
286
|
-
"long-running-task",
|
|
287
|
-
"A tool that takes a while",
|
|
288
|
-
{ input: z.string() },
|
|
289
|
-
async ({ input }) => {
|
|
290
|
-
await longRunningOperation(input);
|
|
291
|
-
return {
|
|
292
|
-
content: [{ type: "text", text: "Task completed" }]
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
);
|
|
296
|
-
}
|
|
297
|
-
}
|
|
41
|
+
});
|
|
298
42
|
```
|
|
299
43
|
|
|
300
|
-
|
|
44
|
+
| `transport.type` | Use when |
|
|
45
|
+
| ------------------- | ------------------------------------------------- |
|
|
46
|
+
| `"auto"` (default) | You do not know which transport the server speaks |
|
|
47
|
+
| `"streamable-http"` | The server supports Streamable HTTP |
|
|
48
|
+
| `"sse"` | The server only supports the older SSE transport |
|
|
301
49
|
|
|
302
|
-
|
|
303
|
-
| --------------------------------- | --------------------------------------------------- | ------------------------------------------ | -------------------------------------- |
|
|
304
|
-
| **Streamable HTTP** | New servers and external MCP connections | Current standard transport; supports OAuth | Slight network overhead |
|
|
305
|
-
| **Client `auto`** | The remote server's HTTP transport is not known | Tries Streamable HTTP, then legacy SSE | May make a fallback connection attempt |
|
|
306
|
-
| **Legacy `McpAgent` server auto** | An existing server must accept both HTTP transports | Serves both protocols on one endpoint | Uses the deprecated server path |
|
|
307
|
-
| **RPC** | Internal agents | Fastest, simplest setup | No auth, Service Bindings only |
|
|
308
|
-
| **SSE** | Legacy compatibility | Backwards compatible | Deprecated, use Streamable HTTP |
|
|
50
|
+
`"auto"` tries Streamable HTTP first and falls back to SSE only when the server reports that Streamable HTTP is unsupported. The client negotiates the protocol version on every connection, so it works with both Stateless and 2025-era servers. See [Connecting to MCP Servers](./mcp-client.md) for OAuth, retries, and the rest of the client API.
|
|
309
51
|
|
|
310
52
|
## Examples
|
|
311
53
|
|
|
312
|
-
-
|
|
313
|
-
-
|
|
314
|
-
- **MCP Client**: See [`examples/mcp-client`](https://github.com/cloudflare/agents/tree/main/examples/mcp-client)
|
|
54
|
+
- [`examples/mcp-worker`](https://github.com/cloudflare/agents/tree/main/examples/mcp-worker): a server built with `createMcpHandler`
|
|
55
|
+
- [`examples/mcp-client`](https://github.com/cloudflare/agents/tree/main/examples/mcp-client): an Agent that connects to MCP servers
|
package/docs/models-pi-ai.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Models for pi-ai
|
|
1
|
+
# Models for pi-ai
|
|
2
2
|
|
|
3
3
|
`agents/models/pi-ai` is the [pi-ai](https://github.com/earendil-works/pi/tree/main/packages/ai)
|
|
4
4
|
twin of [`agents/models/ai-sdk`](./models.md): the same `createAI` factory, the same options,
|
|
@@ -21,7 +21,7 @@ import { getBuiltinModel } from "@earendil-works/pi-ai/providers/all";
|
|
|
21
21
|
|
|
22
22
|
const ai = createAI({ binding: env.AI, id: "prod", cacheTtl: 60 });
|
|
23
23
|
|
|
24
|
-
ai("@cf/zai-org/glm-
|
|
24
|
+
ai("@cf/zai-org/glm-5.3-flash"); // Workers AI: our catalog, our compat layer
|
|
25
25
|
ai(getBuiltinModel("anthropic", "claude-opus-4-8")); // their model, our transport
|
|
26
26
|
```
|
|
27
27
|
|
|
@@ -47,7 +47,6 @@ design: a model this package cannot name exactly is yours to construct.
|
|
|
47
47
|
`env.AI.run`, other model objects through the binding's `fetch` to AI Gateway's
|
|
48
48
|
provider-native path. With [an account id and API token](#account-id-and-api-token) the
|
|
49
49
|
same requests go over HTTP instead.
|
|
50
|
-
5. Everything here is in beta and may change in a minor release.
|
|
51
50
|
|
|
52
51
|
## Quick start
|
|
53
52
|
|
|
@@ -66,7 +65,7 @@ import { createAI } from "agents/models/pi-ai";
|
|
|
66
65
|
export default {
|
|
67
66
|
async fetch(_request: Request, env: { AI: Ai }) {
|
|
68
67
|
const ai = createAI({ binding: env.AI });
|
|
69
|
-
const reply = await ai.complete(ai("@cf/zai-org/glm-
|
|
68
|
+
const reply = await ai.complete(ai("@cf/zai-org/glm-5.3-flash"), {
|
|
70
69
|
messages: [{ role: "user", content: "Hello", timestamp: Date.now() }]
|
|
71
70
|
});
|
|
72
71
|
// `content` is an array of parts — text, thinking, tool calls.
|
|
@@ -103,7 +102,7 @@ Workers AI and catalog models go to AI Gateway's
|
|
|
103
102
|
|
|
104
103
|
```ts
|
|
105
104
|
// 1. Workers AI — ours.
|
|
106
|
-
ai("@cf/zai-org/glm-
|
|
105
|
+
ai("@cf/zai-org/glm-5.3-flash");
|
|
107
106
|
|
|
108
107
|
// 2. pi-ai's Cloudflare AI Gateway catalog — a string, resolved by pi, not us.
|
|
109
108
|
ai("anthropic/claude-opus-4.8");
|
|
@@ -181,7 +180,7 @@ import { createModels } from "@earendil-works/pi-ai/models";
|
|
|
181
180
|
const models = createModels();
|
|
182
181
|
models.setProvider(ai.provider); // provider id: "cloudflare"
|
|
183
182
|
models.getModel("cloudflare", "anthropic/claude-opus-4.8");
|
|
184
|
-
models.streamSimple(ai("@cf/zai-org/glm-
|
|
183
|
+
models.streamSimple(ai("@cf/zai-org/glm-5.3-flash"), context);
|
|
185
184
|
```
|
|
186
185
|
|
|
187
186
|
The provider's static list is every Workers AI id pi-ai knows plus every `<provider>/<id>` in
|
|
@@ -206,7 +205,7 @@ ai("anthropic/claude-opus-4.8", {
|
|
|
206
205
|
requestTimeoutMs: 30_000,
|
|
207
206
|
retries: { maxAttempts: 3, backoff: "exponential", retryDelayMs: 500 },
|
|
208
207
|
byokAlias: "team-a", // which stored BYOK key, by alias
|
|
209
|
-
fallback: ["@cf/zai-org/glm-
|
|
208
|
+
fallback: ["@cf/zai-org/glm-5.3-flash"], // ids or models, in any mix
|
|
210
209
|
headers: { "x-request-source": "docs" },
|
|
211
210
|
sessionAffinity: "chat-42", // Workers AI prefix-cache routing
|
|
212
211
|
reasoningEffort: "low", // "low" | "medium" | "high" | null
|
|
@@ -336,7 +335,7 @@ and are not resumed. The run id is on the `cloudflare` diagnostic as `runId`.
|
|
|
336
335
|
## Fallback
|
|
337
336
|
|
|
338
337
|
```ts
|
|
339
|
-
ai(claude, { fallback: ["@cf/zai-org/glm-
|
|
338
|
+
ai(claude, { fallback: ["@cf/zai-org/glm-5.3-flash"] });
|
|
340
339
|
```
|
|
341
340
|
|
|
342
341
|
Legs may be Workers AI ids or models, in any mix. They are tried in order: a leg is abandoned
|
|
@@ -368,11 +367,10 @@ Image generation is Workers AI only. The knobs a model takes are the model's:
|
|
|
368
367
|
in a `cloudflare-compat` diagnostic on the result rather than sent and ignored.
|
|
369
368
|
Every other model in the catalog takes the full set.
|
|
370
369
|
|
|
371
|
-
##
|
|
370
|
+
## Requirements
|
|
372
371
|
|
|
373
372
|
This subpath needs `@earendil-works/pi-ai@~1.4.0`, an optional peer of `agents`. `agents`
|
|
374
|
-
takes no vendor package as a dependency, optional or otherwise.
|
|
375
|
-
and may change in a minor release. An unlisted `@cf/` id resolves with default metadata (a
|
|
373
|
+
takes no vendor package as a dependency, optional or otherwise. An unlisted `@cf/` id resolves with default metadata (a
|
|
376
374
|
128k context window, 8192 output tokens, zero cost); pass overrides when you know better.
|
|
377
375
|
|
|
378
376
|
## See also
|
package/docs/models.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Models
|
|
1
|
+
# Models
|
|
2
2
|
|
|
3
3
|
`agents/models/ai-sdk` is Cloudflare's AI SDK provider. It takes two call
|
|
4
4
|
forms, through the `AI` binding or
|
|
@@ -557,13 +557,6 @@ try {
|
|
|
557
557
|
On a model object this covers the gateway's own failures; a vendor's own error
|
|
558
558
|
is raised by that vendor's provider in its own error type.
|
|
559
559
|
|
|
560
|
-
## Experimental
|
|
561
|
-
|
|
562
|
-
This module is experimental. The surface may change in a minor release, and
|
|
563
|
-
every exported symbol is tagged `@experimental`. It ships from `agents` first;
|
|
564
|
-
the plan is for `cloudflare/ai` to re-export it and deprecate the older
|
|
565
|
-
`workers-ai-provider` / `ai-gateway-provider` packages.
|
|
566
|
-
|
|
567
560
|
## See also
|
|
568
561
|
|
|
569
562
|
- [Models for pi-ai](./models-pi-ai.md) — the same factory for pi-ai and pi-durable
|
package/docs/routing.md
CHANGED
|
@@ -300,8 +300,6 @@ export default {
|
|
|
300
300
|
|
|
301
301
|
For agent-specific initialization, use `getAgentByName` instead where you control exactly which agent receives the props.
|
|
302
302
|
|
|
303
|
-
> **Note:** For `McpAgent`, props are automatically stored and accessible via `this.props`. See [MCP Servers](/mcp-servers) for details.
|
|
304
|
-
|
|
305
303
|
### Hooks
|
|
306
304
|
|
|
307
305
|
`routeAgentRequest` supports hooks for intercepting requests before they reach agents:
|