This library provides a lightweight wrapper that makes Anthropic Model Context Protocol (MCP) tools compatible with LangChain.js and LangGraph.js.
🔌 Transport Options
🔄 Multi-Server Management
🧩 Agent Integration
🛠️ Development Features
debug
package for debug loggingnpm install @langchain/mcp-adapters
For SSE connections with custom headers in Node.js (does not apply to Streamable HTTP):
npm install eventsource
For enhanced SSE header support (does not apply to Streamable HTTP):
npm install extended-eventsource
This example shows how you can manage your own MCP client and use it to get tools that you can pass to a LangGraph prebuilt ReAcT agent.
npm install @langchain/mcp-adapters @langchain/langgraph @langchain/core @langchain/openai
export OPENAI_API_KEY=<your_api_key>
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { ChatOpenAI } from "@langchain/openai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
import { loadMcpTools } from "@langchain/mcp-adapters";
// Initialize the ChatOpenAI model
const model = new ChatOpenAI({ modelName: "gpt-4" });
// Automatically starts and connects to a MCP reference server
const transport = new StdioClientTransport({
command: "npx",
args: ["-y", "@modelcontextprotocol/server-math"],
});
// Initialize the client
const client = new Client({
name: "math-client",
version: "1.0.0",
});
try {
// Connect to the transport
await client.connect(transport);
// Get tools with custom configuration
const tools = await loadMcpTools("math", client, {
// Whether to throw errors if a tool fails to load (optional, default: true)
throwOnLoadError: true,
// Whether to prefix tool names with the server name (optional, default: false)
prefixToolNameWithServerName: false,
// Optional additional prefix for tool names (optional, default: "")
additionalToolNamePrefix: "",
});
// Create and run the agent
const agent = createReactAgent({ llm: model, tools });
const agentResponse = await agent.invoke({
messages: [{ role: "user", content: "what's (3 + 5) x 12?" }],
});
console.log(agentResponse);
} catch (e) {
console.error(e);
} finally {
// Clean up connection
await client.close();
}
The library also allows you to connect to multiple MCP servers and load tools from them:
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
import { ChatOpenAI } from "@langchain/openai";
import { createReactAgent } from "@langchain/langgraph/prebuilt";
// Create client and connect to server
const client = new MultiServerMCPClient({
// Global tool configuration options
// Whether to throw on errors if a tool fails to load (optional, default: true)
throwOnLoadError: true,
// Whether to prefix tool names with the server name (optional, default: true)
prefixToolNameWithServerName: true,
// Optional additional prefix for tool names (optional, default: "mcp")
additionalToolNamePrefix: "mcp",
// Server configuration
mcpServers: {
// adds a STDIO connection to a server named "math"
math: {
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-math"],
// Restart configuration for stdio transport
restart: {
enabled: true,
maxAttempts: 3,
delayMs: 1000,
},
},
// here's a filesystem server
filesystem: {
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem"],
},
// Sreamable HTTP transport example, with auth headers and automatic SSE fallback disabled (defaults to enabled)
weather: {
url: "https://example.com/weather/mcp",
headers: {
Authorization: "Bearer token123",
}
automaticSSEFallback: false
},
// how to force SSE, for old servers that are known to only support SSE (streamable HTTP falls back automatically if unsure)
github: {
transport: "sse", // also works with "type" field instead of "transport"
url: "https://example.com/mcp",
reconnect: {
enabled: true,
maxAttempts: 5,
delayMs: 2000,
},
},
},
});
const tools = await client.getTools();
// Create an OpenAI model
const model = new ChatOpenAI({
modelName: "gpt-4o",
temperature: 0,
});
// Create the React agent
const agent = createReactAgent({
llm: model,
tools,
});
// Run the agent
try {
const mathResponse = await agent.invoke({
messages: [{ role: "user", content: "what's (3 + 5) x 12?" }],
});
console.log(mathResponse);
} catch (error) {
console.error("Error during agent execution:", error);
// Tools throw ToolException for tool-specific errors
if (error.name === "ToolException") {
console.error("Tool execution failed:", error.message);
}
}
await client.close();
For more detailed examples, see the examples directory.
When loading MCP tools either directly through loadMcpTools
or via MultiServerMCPClient
, you can configure the following options:
Option | Type | Default | Description |
---|---|---|---|
throwOnLoadError |
boolean | true |
Whether to throw an error if a tool fails to load |
prefixToolNameWithServerName |
boolean | true |
If true, prefixes all tool names with the server name (e.g., serverName__toolName ) |
additionalToolNamePrefix |
string | mcp |
Additional prefix to add to tool names (e.g., prefix__serverName__toolName ) |
MCP tools return results in the content_and_artifact
format which can include:
Example for handling different content types:
const tool = tools.find((t) => t.name === "mcp__math__calculate");
const result = await tool.invoke({ expression: "(3 + 5) * 12" });
// Result format: [content, artifacts]
// - content: string | MessageContentComplex[]
// - artifacts: EmbeddedResource[]
const [textContent, artifacts] = result;
// Handle text content
if (typeof textContent === "string") {
console.log("Result:", textContent);
} else {
// Handle complex content (text + images)
textContent.forEach((item) => {
if (item.type === "text") {
console.log("Text:", item.text);
} else if (item.type === "image_url") {
console.log("Image URL:", item.image_url.url);
}
});
}
// Handle artifacts if needed
if (artifacts.length > 0) {
console.log("Received artifacts:", artifacts);
}
Both transport types support automatic reconnection:
{
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-math"],
restart: {
enabled: true, // Enable automatic restart
maxAttempts: 3, // Maximum restart attempts
delayMs: 1000 // Delay between attempts in ms
}
}
{
transport: "sse",
url: "https://example.com/mcp-server",
headers: { "Authorization": "Bearer token123" },
useNodeEventSource: true,
reconnect: {
enabled: true, // Enable automatic reconnection
maxAttempts: 5, // Maximum reconnection attempts
delayMs: 2000 // Delay between attempts in ms
}
}
The library provides different error types to help with debugging:
Example error handling:
try {
const client = new MultiServerMCPClient({
math: {
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-math"],
},
});
const tools = await client.getTools();
const result = await tools[0].invoke({ expression: "1 + 2" });
} catch (error) {
if (error.name === "MCPClientError") {
// Handle connection issues
console.error(`Connection error (${error.serverName}):`, error.message);
} else if (error.name === "ToolException") {
// Handle tool execution errors
console.error("Tool execution failed:", error.message);
} else if (error.name === "ZodError") {
// Handle configuration validation errors
console.error("Configuration error:", error.issues);
// Zod errors contain detailed information about what went wrong
error.issues.forEach((issue) => {
console.error(`- Path: ${issue.path.join(".")}, Error: ${issue.message}`);
});
} else {
// Handle other errors
console.error("Unexpected error:", error);
}
}
The library uses Zod for validating configuration. Here are some common validation errors:
command
for stdio transport or url
for SSE transportExample Zod error for an invalid SSE URL:
{
"issues": [
{
"code": "invalid_string",
"validation": "url",
"path": ["mcpServers", "weather", "url"],
"message": "Invalid url"
}
],
"name": "ZodError"
}
When using in browsers:
Connection Failures:
Tool Execution Errors:
Headers Not Applied:
extended-eventsource
packageuseNodeEventSource: true
in SSE connectionsThis package makes use of the debug package for debug logging.
Logging is disabled by default, and can be enabled by setting the DEBUG
environment variable as per
the instructions in the debug package.
To output all debug logs from this package:
DEBUG='@langchain/mcp-adapters:*'
To output debug logs only from the client
module:
DEBUG='@langchain/mcp-adapters:client'
To output debug logs only from the tools
module:
DEBUG='@langchain/mcp-adapters:tools'
MIT
Big thanks to @vrknetha, @knacklabs for the initial implementation!
Contributions are welcome! Please check out our contributing guidelines for more information.