← Vytvářejte agenty na Cloudflare / agents / model-context-protocol / protocol
Transport
Specifikace Model Context Protocol (MCP) definuje dva standardní transportní mechanismy ↗ pro komunikaci mezi klienty a servery:
- stdio : Komunikace přes standardní vstup a výstup, určená pro lokální připojení MCP.
- Streamable HTTP : Standardní přenosová metoda pro vzdálená připojení MCP, zavedeno ↗ v březnu 2025. Používá jediný HTTP koncový bod pro obousměrnou komunikaci.
Servery MCP vytvořené pomocí Agents SDK použít createMcpHandler ke zpracování transportu Streamable HTTP.
Implementace vzdáleného transportu MCP
Použijte createMcpHandler pro vytvoření MCP serveru, který zpracovává transport Streamable HTTP. Toto je doporučený postup pro nové MCP servery.
Rychlý start
K vytvoření vzdáleného MCP serveru můžete použít tlačítko "Deploy to Cloudflare".
Vzdálený MCP server (bez ověřování)
Vytvořte server MCP pomocí createMcpHandler. Zobrazte úplný příklad na GitHubu ↗.
import { createMcpHandler } from "agents/mcp/server";
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";
function createServer() {
const server = new McpServer({
name: "My MCP Server",
version: "1.0.0",
});
server.registerTool(
"hello",
{
description: "Returns a greeting message",
inputSchema: { name: z.string().optional() },
},
async ({ name }) => {
return {
content: [{ text: `Hello, ${name ?? "World"}!`, type: "text" }],
};
},
);
return server;
}
export default {
fetch(request, env, ctx) {
return createMcpHandler(createServer)(request, env, ctx);
},
};import { createMcpHandler } from "agents/mcp/server";
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";
function createServer() {
const server = new McpServer({
name: "My MCP Server",
version: "1.0.0",
});
server.registerTool(
"hello",
{
description: "Returns a greeting message",
inputSchema: { name: z.string().optional() },
},
async ({ name }) => {
return {
content: [{ text: `Hello, ${name ?? "World"}!`, type: "text" }],
};
},
);
return server;
}
export default {
fetch(request, env, ctx) {
return createMcpHandler(createServer)(request, env, ctx);
},
} satisfies ExportedHandler;Server MCP s ověřováním
Pokud váš server MCP implementuje autentizaci a autorizaci pomocí Workers OAuth Provider ↗ knihovnu, použijte createMcpHandler hodnotou apiRoute a apiHandler vlastnosti. Zobrazte úplný příklad na GitHubu ↗.
export default new OAuthProvider({
apiRoute: "/mcp",
apiHandler: createMcpHandler(createServer),
// ... other OAuth configuration
});export default new OAuthProvider({
apiRoute: "/mcp",
apiHandler: createMcpHandler(createServer),
// ... other OAuth configuration
});Servery, které potřebují protokolové relace
MCP nemá na bezstavové cestě žádnou relaci na úrovni protokolu. Aplikace mohou trvalá obchodní data ukládat za samostatnou hranicí úložiště.
Při migraci starších relací si mohou stávající servery ponechat dočasnou createLegacyMcpHandler hodnotou WorkerTransport nebo McpAgent route vedle nové bezstavové route. Tato API podporují stav transportu, přehrávání událostí, odesílanou elicitaci, sampling a požadavky na roots. McpAgent je zastaralé a jeho funkce se dále nerozvíjejí.
Přidejte bezstavovou route ještě před přechodem klientů a ponechte v provozu obě dráhy, dokud nedoběhnou stávající relace. Viz Migrovat na MCP SDK v2 pro postupnou migraci. Viz McpAgent: Obnovitelnost streamu pro stávající chování streamu.
Transport RPC
Transport RPC je určen pro interní aplikace, kde server MCP i agent běží na Cloudflare, mohou dokonce běžet ve stejném Workeru. Zprávy JSON-RPC odesílá přímo přes Cloudflare Vazby RPC aniž by šlo přes veřejný internet.
- Rychlejší : žádná síťová režie, přímá volání funkcí mezi Durable Objects
- Jednodušší : žádné koncové body HTTP, žádná správa připojení
- Pouze interní : ideální pro agenty volající servery MCP v rámci stejného Workeru
Transport RPC nepodporuje ověřování. Pro externí připojení, která vyžadují OAuth, použijte Streamable HTTP.
Připojte Agenta k existujícímu McpAgent přes RPC
1. Definujte svůj server MCP
Vytvořte svůj McpAgent s nástroji, které chcete zpřístupnit:
import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
export class MyMCP extends McpAgent {
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
initialState = { counter: 0 };
async init() {
this.server.tool(
"add",
"Add to the counter",
{ amount: z.number() },
async ({ amount }) => {
this.setState({ counter: this.state.counter + amount });
return {
content: [
{
type: "text",
text: `Added ${amount}, total is now ${this.state.counter}`,
},
],
};
},
);
}
}import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
type State = { counter: number };
export class MyMCP extends McpAgent<Env, State> {
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
initialState: State = { counter: 0 };
async init() {
this.server.tool(
"add",
"Add to the counter",
{ amount: z.number() },
async ({ amount }) => {
this.setState({ counter: this.state.counter + amount });
return {
content: [
{
type: "text",
text: `Added ${amount}, total is now ${this.state.counter}`,
},
],
};
},
);
}
}2. Připojte svého Agenta k serveru MCP
Ve vašem Agent, zavolejte addMcpServer() s vazbou Durable Object v onStart():
import { AIChatAgent } from "@cloudflare/ai-chat";
export class Chat extends AIChatAgent {
async onStart() {
// Pass the DO namespace binding directly
await this.addMcpServer("my-mcp", this.env.MyMCP);
}
async onChatMessage(onFinish) {
const allTools = this.mcp.getAITools();
const result = streamText({
model,
tools: allTools,
// ...
});
return createUIMessageStreamResponse({ stream: result });
}
}import { AIChatAgent } from "@cloudflare/ai-chat";
export class Chat extends AIChatAgent<Env> {
async onStart(): Promise<void> {
// Pass the DO namespace binding directly
await this.addMcpServer("my-mcp", this.env.MyMCP);
}
async onChatMessage(onFinish) {
const allTools = this.mcp.getAITools();
const result = streamText({
model,
tools: allTools,
// ...
});
return createUIMessageStreamResponse({ stream: result });
}
}Připojení RPC se po hibernaci Durable Object obnovují automaticky, stejně jako připojení HTTP. Název vazby a vlastnosti (props) se ukládají do úložiště, takže lze připojení znovu navázat bez nutnosti psát další kód.
Pro přenos RPC, pokud addMcpServer se volá s názvem, který už má aktivní připojení, vrátí se stávající připojení místo vytvoření duplicity. U HTTP transportu se deduplikace shoduje jak na názvu serveru, tak na URL (viz API klienta MCP pro podrobnosti). Díky tomu je bezpečné to volat v onStart().
3. Nakonfigurujte vazby Durable Object
Ve vašem wrangler.jsonc, definujte vazby pro oba Durable Objects:
{
"durable_objects": {
"bindings": [
{ "name": "Chat", "class_name": "Chat" },
{ "name": "MyMCP", "class_name": "MyMCP" },
],
},
"migrations": [
{
"new_sqlite_classes": ["MyMCP", "Chat"],
"tag": "v1",
},
],
}4. Nastavte fetch handler svého Workeru
Směrujte požadavky na svého Chat agenta:
import { routeAgentRequest } from "agents";
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
// Optionally expose the MCP server via HTTP as well
if (url.pathname.startsWith("/mcp")) {
return MyMCP.serve("/mcp").fetch(request, env, ctx);
}
const response = await routeAgentRequest(request, env);
if (response) return response;
return new Response("Not found", { status: 404 });
},
};import { routeAgentRequest } from "agents";
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext) {
const url = new URL(request.url);
// Optionally expose the MCP server via HTTP as well
if (url.pathname.startsWith("/mcp")) {
return MyMCP.serve("/mcp").fetch(request, env, ctx);
}
const response = await routeAgentRequest(request, env);
if (response) return response;
return new Response("Not found", { status: 404 });
},
} satisfies ExportedHandler<Env>;Předávání props serveru MCP
Protože RPC transport nemá OAuth flow, můžete kontext uživatele předat přímo jako props:
await this.addMcpServer("my-mcp", this.env.MyMCP, {
props: { userId: "user-123", role: "admin" },
});await this.addMcpServer("my-mcp", this.env.MyMCP, {
props: { userId: "user-123", role: "admin" },
});Váš McpAgent pak mohou přistupovat k těmto props:
export class MyMCP extends McpAgent {
async init() {
this.server.tool("whoami", "Get current user info", {}, async () => {
const userId = this.props?.userId || "anonymous";
const role = this.props?.role || "guest";
return {
content: [{ type: "text", text: `User ID: ${userId}, Role: ${role}` }],
};
});
}
}export class MyMCP extends McpAgent<
Env,
State,
{ userId?: string; role?: string }
> {
async init() {
this.server.tool("whoami", "Get current user info", {}, async () => {
const userId = this.props?.userId || "anonymous";
const role = this.props?.role || "guest";
return {
content: [{ type: "text", text: `User ID: ${userId}, Role: ${role}` }],
};
});
}
}Props jsou typově bezpečné (TypeScript extrahuje typ Props z vašeho McpAgent generický typ), trvalé (uložené v úložišti Durable Object) a dostupné okamžitě ještě předtím, než dojde k jakémukoli volání nástroje.
Konfigurace časového limitu transportního serveru RPC
Přenos RPC má nastavitelný časový limit čekání na odpovědi nástrojů. Server ve výchozím nastavení čeká 60 sekund na odpověď obslužné rutiny nástroje. Toto chování můžete upravit přepsáním getRpcTransportOptions() ve vašem McpAgent:
export class MyMCP extends McpAgent {
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
getRpcTransportOptions() {
return { timeout: 120000 }; // 2 minutes
}
async init() {
this.server.tool(
"long-running-task",
"A tool that takes a while",
{ input: z.string() },
async ({ input }) => {
await longRunningOperation(input);
return {
content: [{ type: "text", text: "Task completed" }],
};
},
);
}
}export class MyMCP extends McpAgent<Env, State> {
server = new McpServer({ name: "MyMCP", version: "1.0.0" });
protected getRpcTransportOptions() {
return { timeout: 120000 }; // 2 minutes
}
async init() {
this.server.tool(
"long-running-task",
"A tool that takes a while",
{ input: z.string() },
async ({ input }) => {
await longRunningOperation(input);
return {
content: [{ type: "text", text: "Task completed" }],
};
},
);
}
}Výběr transportu
| Transport | Kdy použít | Výhody | Nevýhody |
|---|---|---|---|
| Streamable HTTP | Externí servery MCP, produkční aplikace | Standardní protokol, zabezpečený, podporuje autentizaci | Mírná síťová režie |
| RPC | Interní agenti na Cloudflare | Nejrychlejší, nejjednodušší nastavení | Žádná autentizace, pouze vazby Durable Object |
| SSE | Kompatibilita s dřívějšími klienty | Zpětně kompatibilní | Zastaralé, použijte Streamable HTTP |
Migrovat z McpAgent
Pokud endpoint nepoužívá starší stavové funkce, přejděte rovnou na bezstavovou factory serveru z @modelcontextprotocol/server a předat jej createMcpHandler.
Pokud toto řešení závisí na stavu relace MCP, na RPC, na požadavcích odesílaných serverem klientovi, na samostatných streamech nebo na přehrávání, navrhněte nejprve bezstavové ekvivalenty. Stav aplikace přesuňte například do explicitního úložiště a požadavky na vstup odesílané serverem nahraďte bezstavovou elicitací. Bezstavovou a starší trasu provozujte souběžně, dokud klienti nepřejdou na novou verzi a stávající relace nedoběhnou.
Viz Migrovat na MCP SDK v2 pro mapování funkcí, směrování napříč oběma generacemi a kroky nasazení.
Testování s klienty MCP
Svůj MCP server můžete otestovat pomocí MCP klienta, který podporuje vzdálená připojení, nebo použít mcp-remote ↗, adaptér, který umožňuje MCP klientům podporujícím jen lokální připojení pracovat se vzdálenými MCP servery.
Postupujte podle tento průvodce pro pokyny, jak připojit vzdálený server MCP ke Claude Desktop, Cursor, Windsurf a dalším klientům MCP.