Skip to content
Effect 4.0 is here. One ecosystem. Zero dependencies.

McpClient

Connects to MCP servers with scoped Effect clients.

Clients discover tools, prompts and resources using the protocol revision selected by their transport. callTool returns tool-reported errors as results; supplying a schema turns them into a ToolError reason that retains the original result. Transport and protocol failures fail the Effect. Interactive server requests, subscriptions, OAuth and retries are not included.

12 exports Since v4.0.6 Source

Constructors

Since v4.0.6

Creates a Streamable HTTP transport with request-owned JSON or SSE responses.

Signature

declare const http: (options: {
readonly headers?: Readonly<Record<string, string>>;
readonly maxMessageBytes?: ByteSize.Input;
readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>;
readonly url: string | URL;
}) => Effect.Effect<Transport, McpClientError, HttpClient.HttpClient | Scope.Scope>
Since v4.0.6

Constructs and connects a client using the supplied MCP transport service and its protocol adapter.

Details

name, version and the optional title, description, websiteUrl and icons identify the client to the server. timeout defaults to 60 seconds and bounds initialization and each complete listTools, listPrompts or listResources scan. callTool, getPrompt and readResource have no deadline unless their own timeout option is supplied. Schema decoding requires the schema's services from the caller.

Signature

declare const make: (options: {
readonly description?: string;
readonly icons?: ReadonlyArray<McpSchema.Icon>;
readonly name: string;
readonly timeout?: Duration.Input;
readonly title?: string;
readonly version: string;
readonly websiteUrl?: string;
}) => Effect.Effect<McpClient, McpClientError, Scope.Scope | Transport>
Since v4.0.6

Starts a scoped subprocess using newline-delimited JSON-RPC.

Signature

declare const stdio: (options: {
readonly command: ChildProcess.Command;
readonly maxMessageBytes?: ByteSize.Input;
readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>;
}) => Effect.Effect<Transport, McpClientError, ChildProcessSpawner | Scope.Scope>
Since v4.0.6

Discovers remote tools and binds their handlers using the standard Toolkit implementation.

Details

Pass an optional prefix such as "reports__" to qualify model tool names. Remote JSON Schemas are advertised without local schema import. Results become text; tool-reported and operational failures fail the Effect. Use Tool.make or Tool.dynamic with Toolkit.make for custom validation, approval or results. Build a new toolkit to discover changes between model turns.

Signature

declare const toolkit: (client: McpClient, prefix?: string) => Effect.Effect<Toolkit.WithHandler<Record<string, Tool.Tool<string, {
readonly failure: typeof McpClientError;
readonly failureMode: "error";
readonly parameters: typeof Schema.Unknown;
readonly success: typeof Schema.String;
}>>>, McpClientError>

Guards

Returns whether a value is an MCP client.

Signature

declare function isMcpClient(value: unknown): value is McpClient

Layers

Provides a connected MCP client over Streamable HTTP using the HTTP client.

Details

The layer scope owns the client and connection. The options are those of make and http.

See

Signature

declare const layerHttp: (options: {
readonly description?: string;
readonly headers?: Readonly<Record<string, string>>;
readonly icons?: ReadonlyArray<McpSchema.Icon>;
readonly maxMessageBytes?: ByteSize.Input;
readonly name: string;
readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>;
readonly timeout?: Duration.Input;
readonly title?: string;
readonly url: string | URL;
readonly version: string;
readonly websiteUrl?: string;
}) => Layer.Layer<McpClient, McpClientError, HttpClient.HttpClient>

Example Providing an HTTP client connection

import { Layer } from "effect"
import { McpClient, McpProtocol } from "effect/ai"
import { FetchHttpClient } from "effect/http"
const ClientLayer = McpClient.layerHttp({
name: "report-workflow",
version: "1.0.0",
protocol: McpProtocol.v2026_07_28,
url: "http://localhost:3000/mcp"
}).pipe(Layer.provide(FetchHttpClient.layer))

Provides a connected MCP client over stdio using the child process spawner.

Details

The layer scope owns the client and subprocess. The options are those of make and stdio.

See

Signature

declare const layerStdio: (options: {
readonly command: ChildProcess.Command;
readonly description?: string;
readonly icons?: ReadonlyArray<McpSchema.Icon>;
readonly maxMessageBytes?: ByteSize.Input;
readonly name: string;
readonly protocol: McpProtocol.ProtocolAdapter<ProtocolVersion>;
readonly timeout?: Duration.Input;
readonly title?: string;
readonly version: string;
readonly websiteUrl?: string;
}) => Layer.Layer<McpClient, McpClientError, ChildProcessSpawner>

Models

McpClient

interface
Since v4.0.6

A scoped connection to one MCP server.

Signature

interface McpClient {
readonly "~effect/ai/McpClient": "~effect/ai/McpClient";
readonly callTool: {
(params: {
readonly arguments?: {
[key: string]: any;
};
readonly schema?: undefined;
readonly tool: Tool;
}, options?: {
readonly timeout?: Input;
}): Effect<CallToolResult, McpClientError>;
<S extends Top>(params: {
readonly arguments?: {
[key: string]: any;
};
readonly schema: S;
readonly tool: Tool;
}, options?: {
readonly timeout?: Input;
}): Effect<S["Type"], McpClientError, S["DecodingServices"]>;
<S extends Top = never>(params: {
readonly arguments?: {
[key: string]: any;
};
readonly schema?: S;
readonly tool: Tool;
}, options?: {
readonly timeout?: Input;
}): Effect<CallToolResult | S["Type"], McpClientError, S["DecodingServices"]>;
};
readonly getPrompt: (params: {
readonly arguments?: {
[key: string]: string;
};
readonly prompt: Prompt;
}, options?: {
readonly timeout?: Input;
}) => Effect<GetPromptResult, McpClientError>;
readonly instructions?: string;
readonly listPrompts: (options?: {
readonly timeout?: Input;
}) => Effect<readonly Array<Prompt>, McpClientError>;
readonly listResources: (options?: {
readonly timeout?: Input;
}) => Effect<readonly Array<Resource>, McpClientError>;
readonly listTools: (options?: {
readonly timeout?: Input;
}) => Effect<readonly Array<Tool>, McpClientError>;
readonly protocolVersion: ProtocolVersion;
readonly readResource: (params: {
readonly uri: string;
}, options?: {
readonly timeout?: Input;
}) => Effect<ReadResourceResult, McpClientError>;
readonly serverInfo: Implementation | undefined;
}
Since v4.0.6

Supported MCP wire protocol revisions.

Signature

type ProtocolVersion = "2025-11-25" | "2026-07-28"

Transport

interface
Since v4.0.6

Exchanges JSON-RPC messages with one MCP server using its protocol adapter.

Signature

interface Transport {
readonly "~effect/ai/McpClient/Transport": "~effect/ai/McpClient/Transport";
readonly isCallable: (tool: Tool) => boolean;
readonly notify: (message: JsonRpcNotification) => Effect<void, McpClientError>;
readonly protocol: ProtocolAdapter<ProtocolVersion>;
readonly request: (message: {
readonly id: string | number;
readonly jsonrpc: "2.0";
readonly method: string;
readonly params?: {
[key: string]: unknown;
};
}, tool?: Tool) => Effect<JsonRpcResponse, McpClientError>;
}

Services

Service tag for applications that provide one default MCP connection.

Signature

declare const McpClient: Context.Service<McpClient, McpClient>

Service supplied by the built-in MCP transport constructors and layers.

Details

Transport construction owns cleanup through its Effect scope.

Signature

declare const Transport: Context.Service<Transport, Transport>