Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/cloudflare/agents/llms.txt

Use this file to discover all available pages before exploring further.

Overview

McpAgent extends the Agent class to provide a foundation for building MCP servers. It handles transport initialization, session management, and client communication.
import { McpAgent } from "agents/mcp";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";

class MyMcpServer extends McpAgent {
  server = new Server({
    name: "my-mcp-server",
    version: "1.0.0"
  }, {
    capabilities: {
      tools: {}
    }
  });

  async init() {
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: "get_weather",
          description: "Get weather for a location",
          inputSchema: {
            type: "object",
            properties: {
              location: { type: "string" }
            }
          }
        }
      ]
    }));
  }
}

Type Parameters

Env
Cloudflare.Env
default:"Cloudflare.Env"
Environment type containing bindings
State
unknown
default:"unknown"
State type for the Agent
Props
Record<string, unknown>
default:"Record<string, unknown>"
Props passed to the Agent

Abstract Members

server

server
MaybePromise<McpServer | Server>
required
The MCP server instance. Can be a Server or McpServer from the MCP SDK.
server = new Server({
  name: "my-server",
  version: "1.0.0"
}, {
  capabilities: { tools: {}, prompts: {}, resources: {} }
});

init()

init
() => Promise<void>
required
Initialize the MCP server. Called on Agent start. Set up request handlers here.
async init() {
  this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
    tools: [/* ... */]
  }));
}

Methods

elicitInput()

Request user input with a message and schema (elicitation protocol).
params
ElicitInputParams
required
message
string
required
Message to show the user
requestedSchema
unknown
required
JSON schema for the expected input
const result = await this.elicitInput({
  message: "Please enter your name",
  requestedSchema: {
    type: "object",
    properties: {
      name: { type: "string" }
    }
  }
});

console.log("User input:", result);
Returns: Promise<ElicitResult> - User’s response or cancellation

getTransportType()

Get the transport type for this MCP Agent instance.
const transport = this.getTransportType();
// "sse" | "streamable-http" | "rpc"
Returns: "sse" | "streamable-http" | "rpc"
The transport type is determined by the naming scheme: sse:${sessionId}, streamable-http:${sessionId}, or rpc:${sessionId}.

getSessionId()

Get the session ID for this MCP Agent instance.
const sessionId = this.getSessionId();
console.log("Session ID:", sessionId);
Returns: string - Session ID

getWebSocket()

Get the unique WebSocket connection (SSE transport only).
const ws = this.getWebSocket();
if (ws) {
  ws.send("Custom message");
}
Returns: Connection | null - WebSocket connection or null

getRpcTransportOptions()

Override to customize RPC transport behavior (e.g., timeout).
protected getRpcTransportOptions(): RPCServerTransportOptions {
  return { timeout: 120000 }; // 2 minutes
}
Returns: RPCServerTransportOptions

Static Methods

serve()

Create a fetch handler for the MCP server.
path
string
required
URL path to serve the MCP server on
options
ServeOptions
binding
string
default:"MCP_OBJECT"
Name of the Durable Object binding in wrangler.jsonc
transport
'streamable-http' | 'sse'
default:"streamable-http"
MCP transport mode
corsOptions
CorsOptions
CORS configuration
jurisdiction
DurableObjectJurisdiction
Durable Object jurisdiction
export default {
  "/mcp": MyMcpServer.serve("/mcp", {
    binding: "MY_MCP_SERVER",
    transport: "streamable-http"
  })
};
Returns: Fetch handler object

serveSSE()

Create a fetch handler for SSE transport (legacy).
export default {
  "/mcp": MyMcpServer.serveSSE("/mcp")
};
Returns: Fetch handler object

Lifecycle

onStart()

Called when the Agent starts. Sets up the MCP transport and connects the server.
async onStart(props?: Props) {
  // Custom initialization
  console.log("MCP server starting with props:", props);
}

onConnect()

Validates new WebSocket connections for MCP protocol.
async onConnect(conn: Connection, ctx: ConnectionContext) {
  // Custom connection validation
  const authToken = ctx.request.headers.get("Authorization");
  if (!authToken) {
    conn.close(1008, "Unauthorized");
  }
}

Transport Types

Streamable HTTP

Recommended transport for modern MCP clients.
export default {
  "/mcp": MyMcpServer.serve("/mcp", {
    transport: "streamable-http"
  })
};

SSE (Legacy)

Server-Sent Events transport for older clients.
export default {
  "/mcp": MyMcpServer.serve("/mcp", {
    transport: "sse"
  })
};

RPC (Durable Object)

Direct Durable Object binding for internal MCP servers.
// Server side
class InternalMcpServer extends McpAgent {
  // ...
}

// Client side (in another Agent)
await this.mcp.addRpcMcpServer("my-server", env.INTERNAL_MCP_SERVER, {
  props: { config: "value" }
});

Full Example

import { McpAgent } from "agents/mcp";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import {
  ListToolsRequestSchema,
  CallToolRequestSchema,
  type CallToolRequest
} from "@modelcontextprotocol/sdk/types.js";

class WeatherMcpServer extends McpAgent {
  server = new Server({
    name: "weather-server",
    version: "1.0.0"
  }, {
    capabilities: {
      tools: {}
    }
  });

  async init() {
    // List available tools
    this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
      tools: [
        {
          name: "get_weather",
          description: "Get current weather for a location",
          inputSchema: {
            type: "object",
            properties: {
              location: {
                type: "string",
                description: "City name or zip code"
              }
            },
            required: ["location"]
          }
        }
      ]
    }));

    // Handle tool calls
    this.server.setRequestHandler(
      CallToolRequestSchema,
      async (request: CallToolRequest) => {
        if (request.params.name === "get_weather") {
          const { location } = request.params.arguments as {
            location: string;
          };

          // Fetch weather data
          const weather = await this.fetchWeather(location);

          return {
            content: [
              {
                type: "text",
                text: `Weather in ${location}: ${weather.temp}°F, ${weather.condition}`
              }
            ]
          };
        }

        return {
          content: [
            {
              type: "text",
              text: "Unknown tool"
            }
          ],
          isError: true
        };
      }
    );
  }

  private async fetchWeather(location: string) {
    // Implementation
    return { temp: 72, condition: "Sunny" };
  }
}

export default {
  "/mcp": WeatherMcpServer.serve("/mcp")
};

wrangler.jsonc Configuration

{
  "name": "weather-mcp-server",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-28",
  "compatibility_flags": ["nodejs_compat"],
  "durable_objects": {
    "bindings": [
      {
        "name": "WEATHER_MCP_SERVER",
        "class_name": "WeatherMcpServer",
        "script_name": "weather-mcp-server"
      }
    ]
  }
}

Build docs developers (and LLMs) love