diff --git a/.changeset/mcp-property-rename.md b/.changeset/mcp-property-rename.md new file mode 100644 index 00000000..39da7da9 --- /dev/null +++ b/.changeset/mcp-property-rename.md @@ -0,0 +1,31 @@ +--- +"@cloudflare/agents": major +--- + +Rename `server` property to `mcp` in MCP-related classes for better developer experience + +## Changes + +- **BREAKING**: Renamed `server` property to `mcp` in `McpAgent` class and related examples +- **BREAKING**: Renamed `mcp` property to `mcpClientManager` in `Agent` class to avoid naming conflicts +- Added backward compatibility support for `server` property in `McpAgent` with deprecation warning +- Updated all MCP examples to use the new `mcp` property naming convention +- Improved property naming consistency across the MCP implementation + +## Migration + +If you're using the `server` property in your `McpAgent` implementations, update your code: + +```ts +// Before +export class MyMcpAgent extends McpAgent { + server = new McpServer({...}); +} + +// After +export class MyMcpAgent extends McpAgent { + mcp = new McpServer({...}); +} +``` + +The `server` property is still supported for backward compatibility but will be removed in a future version. diff --git a/examples/mcp-elicitation-demo/README.md b/examples/mcp-elicitation-demo/README.md index 6c345022..940b00a4 100644 --- a/examples/mcp-elicitation-demo/README.md +++ b/examples/mcp-elicitation-demo/README.md @@ -28,7 +28,7 @@ type Env = { }; export class McpServerAgent extends McpAgent { - server = new McpServer({ + mcp = new McpServer({ name: "Elicitation Demo Server", version: "1.0.0" }) @@ -94,7 +94,7 @@ export class McpServerAgent extends McpAgent { async init() { // Counter tool with user confirmation via elicitation - this.server.tool( + this.mcp.tool( "increment-counter", "Increment the counter with user confirmation", { @@ -162,7 +162,7 @@ export class McpServerAgent extends McpAgent { ); // User creation tool with form-based elicitation - this.server.tool( + this.mcp.tool( "create-user", "Create a new user with form input", { @@ -265,7 +265,7 @@ export class McpServerAgent extends McpAgent { // Direct MCP connection export class MyMcpServer extends McpAgent { async init() { - this.server.tool( + this.mcp.tool( "my-tool", "My tool", { input: z.string() }, diff --git a/examples/mcp-elicitation-demo/src/server.ts b/examples/mcp-elicitation-demo/src/server.ts index 479cdc92..9ad52798 100644 --- a/examples/mcp-elicitation-demo/src/server.ts +++ b/examples/mcp-elicitation-demo/src/server.ts @@ -17,7 +17,7 @@ type Env = { }; export class McpServerAgent extends McpAgent { - server = new McpServer({ + mcp = new McpServer({ name: "Elicitation Demo Server", version: "1.0.0" }); @@ -83,7 +83,7 @@ export class McpServerAgent extends McpAgent { async init() { // Counter tool with user confirmation via elicitation - this.server.tool( + this.mcp.tool( "increment-counter", "Increment the counter with user confirmation", { @@ -151,7 +151,7 @@ export class McpServerAgent extends McpAgent { ); // User creation tool with form-based elicitation - this.server.tool( + this.mcp.tool( "create-user", "Create a new user with form input", { @@ -225,7 +225,7 @@ export class McpServerAgent extends McpAgent { ); // Counter resource - this.server.resource("counter", "mcp://resource/counter", (uri: URL) => { + this.mcp.resource("counter", "mcp://resource/counter", (uri: URL) => { return { contents: [ { @@ -388,7 +388,7 @@ export class MyAgent extends Agent { __clientSession: this.name }; - const result = await this.mcp.callTool({ + const result = await this.mcpClientManager.callTool({ serverId, name: toolName, arguments: enhancedArgs diff --git a/examples/mcp/README.md b/examples/mcp/README.md index e9916aab..2b04831f 100644 --- a/examples/mcp/README.md +++ b/examples/mcp/README.md @@ -19,17 +19,17 @@ Inside your `McpAgent`'s `async init()` method, you can use the MCP SDK to defin ```ts export class MyMCP extends McpAgent { - server = new McpServer({ + mcp = new McpServer({ name: "Demo", version: "1.0.0" }); async init() { - this.server.resource(`counter`, `mcp://resource/counter`, (uri) => { + this.mcp.resource(`counter`, `mcp://resource/counter`, (uri) => { // ... }); - this.server.tool( + this.mcp.tool( "add", "Add two numbers together", { a: z.number(), b: z.number() }, diff --git a/examples/mcp/src/server.ts b/examples/mcp/src/server.ts index ea15708c..6db5892c 100644 --- a/examples/mcp/src/server.ts +++ b/examples/mcp/src/server.ts @@ -9,7 +9,7 @@ type Env = { type State = { counter: number }; export class MyMCP extends McpAgent { - server = new McpServer({ + mcp = new McpServer({ name: "Demo", version: "1.0.0" }); @@ -19,13 +19,13 @@ export class MyMCP extends McpAgent { }; async init() { - this.server.resource("counter", "mcp://resource/counter", (uri) => { + this.mcp.resource("counter", "mcp://resource/counter", (uri) => { return { contents: [{ text: String(this.state.counter), uri: uri.href }] }; }); - this.server.tool( + this.mcp.tool( "add", "Add to the counter, stored in the MCP", { a: z.number() }, diff --git a/packages/agents/README.md b/packages/agents/README.md index 6c8dd59c..1f3a3f52 100644 --- a/packages/agents/README.md +++ b/packages/agents/README.md @@ -411,7 +411,7 @@ type Env = { type State = { counter: number }; export class MyMCP extends McpAgent { - server = new McpServer({ + mcp = new McpServer({ name: "Demo", version: "1.0.0" }); @@ -421,13 +421,13 @@ export class MyMCP extends McpAgent { }; async init() { - this.server.resource("counter", "mcp://resource/counter", (uri) => { + this.mcp.resource("counter", "mcp://resource/counter", (uri) => { return { contents: [{ text: String(this.state.counter), uri: uri.href }] }; }); - this.server.tool( + this.mcp.tool( "add", "Add to the counter, stored in the MCP", { a: z.number() }, diff --git a/packages/agents/src/index.ts b/packages/agents/src/index.ts index 39bac963..feca308a 100644 --- a/packages/agents/src/index.ts +++ b/packages/agents/src/index.ts @@ -291,7 +291,10 @@ export class Agent extends Server { private _ParentClass: typeof Agent = Object.getPrototypeOf(this).constructor; - mcp: MCPClientManager = new MCPClientManager(this._ParentClass.name, "0.0.1"); + mcpClientManager: MCPClientManager = new MCPClientManager( + this._ParentClass.name, + "0.0.1" + ); /** * Initial state for the Agent @@ -441,8 +444,8 @@ export class Agent extends Server { return agentContext.run( { agent: this, connection: undefined, request, email: undefined }, async () => { - if (this.mcp.isCallbackRequest(request)) { - await this.mcp.handleCallbackRequest(request); + if (this.mcpClientManager.isCallbackRequest(request)) { + await this.mcpClientManager.handleCallbackRequest(request); // after the MCP connection handshake, we can send updated mcp state this.broadcast( @@ -1483,7 +1486,7 @@ export class Agent extends Server { }; } - const { id, authUrl, clientId } = await this.mcp.connect(url, { + const { id, authUrl, clientId } = await this.mcpClientManager.connect(url, { client: options?.client, reconnect, transport: { @@ -1500,7 +1503,7 @@ export class Agent extends Server { } async removeMcpServer(id: string) { - this.mcp.closeConnection(id); + this.mcpClientManager.closeConnection(id); this.sql` DELETE FROM cf_agents_mcp_servers WHERE id = ${id}; `; @@ -1514,10 +1517,10 @@ export class Agent extends Server { getMcpServers(): MCPServersState { const mcpState: MCPServersState = { - prompts: this.mcp.listPrompts(), - resources: this.mcp.listResources(), + prompts: this.mcpClientManager.listPrompts(), + resources: this.mcpClientManager.listResources(), servers: {}, - tools: this.mcp.listTools() + tools: this.mcpClientManager.listTools() }; const servers = this.sql` @@ -1526,7 +1529,7 @@ export class Agent extends Server { if (servers && Array.isArray(servers) && servers.length > 0) { for (const server of servers) { - const serverConn = this.mcp.mcpConnections[server.id]; + const serverConn = this.mcpClientManager.mcpConnections[server.id]; mcpState.servers[server.id] = { auth_url: server.auth_url, capabilities: serverConn?.serverCapabilities ?? null, diff --git a/packages/agents/src/mcp/index.ts b/packages/agents/src/mcp/index.ts index 314a5712..da8c1b38 100644 --- a/packages/agents/src/mcp/index.ts +++ b/packages/agents/src/mcp/index.ts @@ -210,8 +210,24 @@ export abstract class McpAgent< */ private _agent: Agent; - get mcp() { - return this._agent.mcp; + get mcpClientManager() { + return this._agent.mcpClientManager; + } + + /** + * Getter that returns the MCP server implementation. + * Supports both 'server' and 'mcp' properties for better developer experience. + * If 'mcp' property is set, use that; otherwise fall back to 'server' property. + */ + get mcpServer(): MaybePromise { + const server = this.mcp ?? this.server; + if (!server) { + throw new Error( + 'Neither the `mcp` nor `server` property is set. Please set "mcp".' + ); + } + + return server; } protected constructor(ctx: DurableObjectState, env: Env) { @@ -333,7 +349,7 @@ export abstract class McpAgent< )) as TransportType; await this._init(this.props); - const server = await this.server; + const server = await this.mcpServer; // Connect to the MCP server if (this._transportType === "sse") { @@ -350,8 +366,17 @@ export abstract class McpAgent< /** * McpAgent API + * @deprecated Use the `mcp` property instead for better developer experience. + */ + server?: MaybePromise; + /** + * This is only set as optional for backward compatibility in case you're + * using the legacy `server` property. It's recommended to use `mcp`. + * + * In the future, we'll make this a required abstract property to implement + * and remove the `server` property. */ - abstract server: MaybePromise; + mcp?: MaybePromise; props!: Props; initRun = false; @@ -430,7 +455,7 @@ export abstract class McpAgent< // This is not the path that the user requested, but the path that the worker // generated. We'll use this path to determine which transport to use. const path = url.pathname; - const server = await this.server; + const server = await this.mcpServer; switch (path) { case "/sse": {