154 lines
3.3 KiB
Markdown
154 lines
3.3 KiB
Markdown
# MCP Server Integration
|
|
|
|
Agents include a multi-server MCP client for connecting to external MCP servers.
|
|
|
|
## Add an MCP Server
|
|
|
|
```typescript
|
|
import { Agent, callable } from "agents";
|
|
|
|
export class MyAgent extends Agent<Env, State> {
|
|
@callable()
|
|
async addServer(name: string, url: string) {
|
|
const result = await this.addMcpServer(
|
|
name,
|
|
url,
|
|
"https://my-worker.workers.dev", // callback host for OAuth
|
|
"agents" // routing prefix
|
|
);
|
|
|
|
if (result.state === "authenticating") {
|
|
// OAuth required - redirect user to result.authUrl
|
|
return { needsAuth: true, authUrl: result.authUrl };
|
|
}
|
|
|
|
return { ready: true, id: result.id };
|
|
}
|
|
}
|
|
```
|
|
|
|
## Use MCP Tools
|
|
|
|
```typescript
|
|
async onChatMessage() {
|
|
// Get AI-compatible tools from all connected MCP servers
|
|
const mcpTools = this.mcp.getAITools();
|
|
|
|
const allTools = {
|
|
...localTools,
|
|
...mcpTools
|
|
};
|
|
|
|
const result = streamText({
|
|
model: openai("gpt-4o"),
|
|
messages: await convertToModelMessages(this.messages),
|
|
tools: allTools
|
|
});
|
|
|
|
return result.toUIMessageStreamResponse();
|
|
}
|
|
```
|
|
|
|
## List MCP Resources
|
|
|
|
```typescript
|
|
// List all registered servers
|
|
const servers = this.mcp.listServers();
|
|
|
|
// List tools from all servers
|
|
const tools = this.mcp.listTools();
|
|
|
|
// List resources
|
|
const resources = this.mcp.listResources();
|
|
|
|
// List prompts
|
|
const prompts = this.mcp.listPrompts();
|
|
```
|
|
|
|
## Remove Server
|
|
|
|
```typescript
|
|
await this.removeMcpServer(serverId);
|
|
```
|
|
|
|
## Building an MCP Server
|
|
|
|
Use `McpAgent` from the SDK to create an MCP server.
|
|
|
|
**Install dependencies:**
|
|
```bash
|
|
npm install @modelcontextprotocol/sdk zod
|
|
```
|
|
|
|
**Wrangler config:**
|
|
```jsonc
|
|
{
|
|
"durable_objects": {
|
|
"bindings": [{ "name": "MyMCP", "class_name": "MyMCP" }]
|
|
},
|
|
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyMCP"] }]
|
|
}
|
|
```
|
|
|
|
**Server implementation:**
|
|
```typescript
|
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
import { McpAgent } from "agents/mcp";
|
|
import { z } from "zod";
|
|
|
|
type State = { counter: number };
|
|
|
|
export class MyMCP extends McpAgent<Env, State, {}> {
|
|
server = new McpServer({
|
|
name: "MyMCPServer",
|
|
version: "1.0.0"
|
|
});
|
|
|
|
initialState = { counter: 0 };
|
|
|
|
async init() {
|
|
// Register a resource
|
|
this.server.resource("counter", "mcp://resource/counter", (uri) => ({
|
|
contents: [{ text: String(this.state.counter), uri: uri.href }]
|
|
}));
|
|
|
|
// Register a tool
|
|
this.server.registerTool(
|
|
"increment",
|
|
{
|
|
description: "Increment the counter",
|
|
inputSchema: { amount: z.number().default(1) }
|
|
},
|
|
async ({ amount }) => {
|
|
this.setState({ counter: this.state.counter + amount });
|
|
return {
|
|
content: [{ text: `Counter: ${this.state.counter}`, type: "text" }]
|
|
};
|
|
}
|
|
);
|
|
}
|
|
}
|
|
```
|
|
|
|
## Serve MCP Server
|
|
|
|
```typescript
|
|
export default {
|
|
fetch(request: Request, env: Env, ctx: ExecutionContext) {
|
|
const url = new URL(request.url);
|
|
|
|
// SSE transport (legacy)
|
|
if (url.pathname.startsWith("/sse")) {
|
|
return MyMCP.serveSSE("/sse", { binding: "MyMCP" }).fetch(request, env, ctx);
|
|
}
|
|
|
|
// Streamable HTTP transport (recommended)
|
|
if (url.pathname.startsWith("/mcp")) {
|
|
return MyMCP.serve("/mcp", { binding: "MyMCP" }).fetch(request, env, ctx);
|
|
}
|
|
|
|
return new Response("Not found", { status: 404 });
|
|
}
|
|
};
|
|
```
|