@langchain/mcp-adapters
Version: 
LangChain.js adapters for Model Context Protocol (MCP)
422 lines (324 loc) • 12.3 kB
Markdown
# LangChain.js MCP Adapters
[](https://www.npmjs.com/package/@langchain/mcp-adapters)
[](https://opensource.org/licenses/MIT)
This library provides a lightweight wrapper that makes [Anthropic Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) tools compatible with [LangChain.js](https://github.com/langchain-ai/langchainjs) and [LangGraph.js](https://github.com/langchain-ai/langgraphjs).
## Features
- 🔌 **Transport Options**
  - Connect to MCP servers via stdio (local) or SSE (remote)
  - Support for custom headers in SSE connections for authentication
  - Configurable reconnection strategies for both transport types
- 🔄 **Multi-Server Management**
  - Connect to multiple MCP servers simultaneously
  - Auto-organize tools by server or access them as a flattened collection
  - Convenient configuration via JSON file
- 🧩 **Agent Integration**
  - Compatible with LangChain.js and LangGraph.js
  - Optimized for OpenAI, Anthropic, and Google models
  - Supports rich content responses including text, images, and embedded resources
- 🛠️ **Development Features**
  - Uses `debug` package for debug logging
  - Flexible configuration options
  - Robust error handling
## Installation
```bash
npm install @langchain/mcp-adapters
```
### Optional Dependencies
For SSE connections with custom headers in Node.js:
```bash
npm install eventsource
```
For enhanced SSE header support:
```bash
npm install extended-eventsource
```
# Example: Manage the MCP Client yourself
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.
```bash
npm install @langchain/mcp-adapters @langchain/langgraph @langchain/core @langchain/openai
export OPENAI_API_KEY=<your_api_key>
```
## Client
```ts
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();
}
```
# Example: Connect to one or more servers via config
The library also allows you to connect to multiple MCP servers and load tools from them:
## Client
```ts
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"],
    },
    // SSE transport example with reconnection configuration
    weather: {
      transport: "sse",
      url: "https://example.com/mcp-weather",
      headers: {
        Authorization: "Bearer token123",
      },
      useNodeEventSource: true,
      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](./examples) directory.
## Tool Configuration Options
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 | `false` | If true, prefixes all tool names with the server name (e.g., `serverName__toolName`) |
| `additionalToolNamePrefix`     | string  | `""`    | Additional prefix to add to tool names (e.g., `prefix__serverName__toolName`)        |
## Response Handling
MCP tools return results in the `content_and_artifact` format which can include:
- **Text content**: Plain text responses
- **Image content**: Base64-encoded images with MIME type
- **Embedded resources**: Files, structured data, or other resources
Example for handling different content types:
```ts
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);
}
```
## Reconnection Strategies
Both transport types support automatic reconnection:
### Stdio Transport Restart
```ts
{
  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
  }
}
```
### SSE Transport Reconnect
```ts
{
  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
  }
}
```
## Error Handling
The library provides different error types to help with debugging:
- **MCPClientError**: For client connection and initialization issues
- **ToolException**: For errors during tool execution
- **ZodError**: For configuration validation errors (invalid connection settings, etc.)
Example error handling:
```ts
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);
  }
}
```
### Common Zod Validation Errors
The library uses Zod for validating configuration. Here are some common validation errors:
- **Missing required parameters**: For example, omitting `command` for stdio transport or `url` for SSE transport
- **Invalid parameter types**: For example, providing a number where a string is expected
- **Invalid connection configuration**: For example, using an invalid URL format for SSE transport
Example Zod error for an invalid SSE URL:
```json
{
  "issues": [
    {
      "code": "invalid_string",
      "validation": "url",
      "path": ["mcpServers", "weather", "url"],
      "message": "Invalid url"
    }
  ],
  "name": "ZodError"
}
```
## Browser Environments
When using in browsers:
- Native EventSource API doesn't support custom headers
- Consider using a proxy or pass authentication via query parameters
- May require CORS configuration on the server side
## Troubleshooting
### Common Issues
1. **Connection Failures**:
   - Verify the MCP server is running
   - Check command paths and network connectivity
2. **Tool Execution Errors**:
   - Examine server logs for error messages
   - Ensure input parameters match the expected schema
3. **Headers Not Applied**:
   - Install the recommended `extended-eventsource` package
   - Set `useNodeEventSource: true` in SSE connections
### Debug Logging
This package makes use of the [debug](https://www.npmjs.com/package/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:
```bash
DEBUG='@langchain/mcp-adapters:*'
```
To output debug logs only from the `client` module:
```bash
DEBUG='@langchain/mcp-adapters:client'
```
To output debug logs only from the `tools` module:
```bash
DEBUG='@langchain/mcp-adapters:tools'
```
## License
MIT
## Acknowledgements
Big thanks to [@vrknetha](https://github.com/vrknetha), [@cawstudios](https://caw.tech) for the initial implementation!
## Contributing
Contributions are welcome! Please check out our [contributing guidelines](CONTRIBUTING.md) for more information.