Skip to content
Cloudflare Docs

McpClient — API reference

Your Agent can connect to external Model Context Protocol (MCP) servers to access tools, resources, and prompts. The Agent class provides three methods to manage MCP connections:

JavaScript
import { Agent } from "agents";
export class MyAgent extends Agent {
async onRequest(request) {
const url = new URL(request.url);
if (url.pathname === "/connect" && request.method === "POST") {
const result = await this.addMcpServer(
"Weather API",
"https://weather-mcp.example.com/mcp",
);
if (result.state === "authenticating") {
return new Response(JSON.stringify({ authUrl: result.authUrl }), {
headers: { "Content-Type": "application/json" },
});
}
return new Response(`Connected: ${result.id}`, { status: 200 });
}
}
}

Connections persist in the Agent's SQL storage, and when an Agent connects to an MCP server, all tools from that server become available automatically.

Agent MCP Client Methods

addMcpServer()

Add a connection to an MCP server and make its tools available to your Agent.

TypeScript
async addMcpServer(
serverName: string,
url: string,
callbackHost?: string,
agentsPrefix?: string,
options?: {
client?: ConstructorParameters<typeof Client>[1];
transport?: {
headers?: HeadersInit;
type?: "sse" | "streamable-http" | "auto";
};
}
): Promise<
| { id: string; state: "authenticating"; authUrl: string }
| { id: string; state: "ready"; authUrl?: undefined }
>

Parameters

  • serverName (string, required) — Display name for the MCP server
  • url (string, required) — URL of the MCP server endpoint
  • callbackHost (string, optional) — Host for OAuth callback URL. If omitted, automatically derived from the incoming request
  • agentsPrefix (string, optional) — URL prefix for OAuth callback path. Default: "agents"
  • options (object, optional) — Connection configuration:
    • client — MCP client configuration options (passed to @modelcontextprotocol/sdk Client constructor). By default, includes CfWorkerJsonSchemaValidator for validating tool parameters against JSON schemas.
    • transport — Transport layer configuration:
      • headers — Custom HTTP headers for authentication
      • type — Transport type: "sse", "streamable-http", or "auto" (tries streamable-http first, falls back to sse)

Returns

A Promise that resolves to a discriminated union based on connection state:

  • When state is "authenticating":

    • id (string) — Unique identifier for this server connection
    • state ("authenticating") — Server is waiting for OAuth authorization
    • authUrl (string) — OAuth authorization URL for user authentication
  • When state is "ready":

    • id (string) — Unique identifier for this server connection
    • state ("ready") — Server is fully connected and operational
    • authUrl (undefined) — Not present when already authenticated

Example

JavaScript
export class MyAgent extends Agent {
async onRequest(request) {
const result = await this.addMcpServer(
"Weather API",
"https://weather-mcp.example.com/mcp",
);
if (result.state === "authenticating") {
// User needs to complete OAuth flow
return new Response(
JSON.stringify({ serverId: result.id, authUrl: result.authUrl }),
{
headers: { "Content-Type": "application/json" },
},
);
}
return new Response(`Connected: ${result.id}`, { status: 200 });
}
}

If the MCP server requires OAuth authentication, authUrl will be returned for user authentication. Connections persist across requests and the Agent will automatically reconnect if the connection is lost.

Related:

removeMcpServer()

Disconnect from an MCP server and clean up its resources.

TypeScript
async removeMcpServer(id: string): Promise<void>

Parameters

  • id (string, required) — Server connection ID returned from addMcpServer()

Returns

A Promise that resolves when disconnection is complete.

Example

JavaScript
export class MyAgent extends Agent {
async onRequest(request) {
const url = new URL(request.url);
if (url.pathname === "/disconnect" && request.method === "POST") {
const { serverId } = await request.json();
await this.removeMcpServer(serverId);
return new Response("Disconnected", { status: 200 });
}
}
}

Disconnects from the MCP server, removes all related resources, and deletes the server record from storage.

getMcpServers()

Get the current state of all MCP server connections.

TypeScript
getMcpServers(): MCPServersState

Parameters

None.

Returns

An MCPServersState object containing:

TypeScript
{
servers: Record<
string,
{
name: string;
server_url: string;
auth_url: string | null;
state:
| "authenticating"
| "connecting"
| "connected"
| "discovering"
| "ready"
| "failed";
capabilities: ServerCapabilities | null;
instructions: string | null;
}
>;
tools: Array<Tool & { serverId: string }>;
prompts: Array<Prompt & { serverId: string }>;
resources: Array<Resource & { serverId: string }>;
resourceTemplates: Array<ResourceTemplate & { serverId: string }>;
}

Example

JavaScript
export class MyAgent extends Agent {
async onRequest(request) {
const url = new URL(request.url);
if (url.pathname === "/mcp-state") {
const mcpState = this.getMcpServers();
return new Response(JSON.stringify(mcpState, null, 2), {
headers: { "Content-Type": "application/json" },
});
}
}
}

The state field indicates the connection lifecycle:

  • authenticating — Waiting for OAuth authorization to complete
  • connecting — Establishing transport connection
  • connected — Transport connection established
  • discovering — Discovering server capabilities (tools, resources, prompts)
  • ready — Fully connected and operational
  • failed — Connection failed

Use this method to monitor connection status, list available tools, or build UI for connected servers.

Lifecycle Methods

The this.mcp property exposes additional methods for fine-grained control over MCP server connections.

this.mcp.registerServer()

Register a server without immediately connecting. Useful for pre-configuring servers that will be connected later.

TypeScript
async registerServer(
id: string,
options: {
url: string;
name: string;
callbackUrl: string;
clientOptions?: ClientOptions;
transportOptions?: TransportOptions;
}
): Promise<string>

Parameters

  • id (string, required) — Unique identifier for the server
  • options (object, required) — Server configuration:
    • url — MCP server endpoint URL
    • name — Display name for the server
    • callbackUrl — OAuth callback URL
    • clientOptions — MCP client configuration
    • transportOptions — Transport layer settings

Returns

A Promise that resolves to the server ID.

this.mcp.connectToServer()

Establish a connection to a previously registered server.

TypeScript
async connectToServer(id: string): Promise<MCPConnectionResult>

Parameters

  • id (string, required) — Server ID from registerServer()

Returns

A Promise that resolves to an MCPConnectionResult:

TypeScript
type MCPConnectionResult =
| { state: "failed"; error: string }
| { state: "authenticating"; authUrl: string }
| { state: "connected" }

this.mcp.discoverIfConnected()

Check server capabilities if a connection is active.

TypeScript
async discoverIfConnected(
serverId: string,
options?: { timeoutMs?: number }
): Promise<MCPDiscoverResult | undefined>

Parameters

  • serverId (string, required) — Server ID to check
  • options (object, optional):
    • timeoutMs — Discovery timeout in milliseconds

Returns

A Promise that resolves to MCPDiscoverResult if connected, or undefined if not connected:

TypeScript
type MCPDiscoverResult = {
success: boolean;
state: MCPConnectionState;
error?: string;
}

this.mcp.closeConnection()

Close the connection to a specific server while keeping it registered.

TypeScript
async closeConnection(id: string): Promise<void>

this.mcp.closeAllConnections()

Close all active server connections while preserving registrations.

TypeScript
async closeAllConnections(): Promise<void>

Capabilities

this.mcp.getAITools()

Get all discovered MCP tools in a format compatible with the AI SDK.

TypeScript
getAITools(): ToolSet

Returns

A ToolSet object containing all tools from connected MCP servers, ready to use with AI SDK functions like generateText() or streamText().

Example

JavaScript
import { generateText } from "ai";
export class MyAgent extends Agent {
async onRequest(request) {
// Get all MCP tools as AI SDK compatible tools
const tools = this.mcp.getAITools();
const result = await generateText({
model: openai("gpt-4"),
prompt: "What's the weather in San Francisco?",
tools,
});
return new Response(result.text);
}
}

Tools are automatically namespaced by server ID to prevent conflicts when multiple MCP servers expose tools with the same name.

OAuth Configuration

Customize OAuth callback behavior using this.mcp.configureOAuthCallback():

JavaScript
export class MyAgent extends Agent {
onStart() {
this.mcp.configureOAuthCallback({
successRedirect: "/connected",
errorRedirect: "/auth-failed",
});
}
}

You can also provide a customHandler function for full control over the callback response. Refer to the OAuth handling guide for details.

Error Handling

Use error detection utilities to handle connection errors:

JavaScript
import { isUnauthorized, isTransportNotImplemented } from "agents/mcp";
export class MyAgent extends Agent {
async onRequest(request) {
try {
await this.addMcpServer("Server", "https://mcp.example.com/mcp");
} catch (error) {
if (isUnauthorized(error)) {
return new Response("Authentication required", { status: 401 });
} else if (isTransportNotImplemented(error)) {
return new Response("Transport not supported", { status: 400 });
}
throw error;
}
}
}

Next Steps