Skip to main content
LangChain v1.0Welcome to the new LangChain documentation! If you encounter any issues or have feedback, please open an issue so we can improve. Archived v0 documentation can be found here.See the release notes and migration guide for a complete list of changes and instructions on how to upgrade your code.
Model Context Protocol (MCP) is an open protocol that standardizes how applications provide tools and context to LLMs. LangChain agents can use tools defined on MCP servers using the langchain-mcp-adapters library.

Install

Install the @langchain/mcp-adapters library to use MCP tools in LangGraph:
npm install @langchain/mcp-adapters

Transport types

MCP supports different transport mechanisms for client-server communication:
  • stdio: Client launches server as a subprocess and communicates via standard input/output. Best for local tools and simple setups.
  • Streamable HTTP: Server runs as an independent process handling HTTP requests. Supports remote connections and multiple clients.
  • Server-Sent Events (SSE): a variant of streamable HTTP optimized for real-time streaming communication.

Use MCP tools

@langchain/mcp-adapters enables agents to use tools defined across one or more MCP server.
Accessing multiple MCP servers
import { MultiServerMCPClient } from "@langchain/mcp-adapters";  
import { ChatAnthropic } from "@langchain/anthropic";
import { createAgent } from "langchain";

const client = new MultiServerMCPClient({  
    math: {
        transport: "stdio",  // Local subprocess communication
        command: "node",
        // Replace with absolute path to your math_server.js file
        args: ["/path/to/math_server.js"],
    },
    weather: {
        transport: "sse",  // Server-Sent Events for streaming
        // Ensure you start your weather server on port 8000
        url: "http://localhost:8000/mcp",
    },
});

const tools = await client.getTools();  
const agent = createAgent({
    model: "anthropic:claude-sonnet-4-5",
    tools,  
});

const mathResponse = await agent.invoke({
    messages: [{ role: "user", content: "what's (3 + 5) x 12?" }],
});

const weatherResponse = await agent.invoke({
    messages: [{ role: "user", content: "what is the weather in nyc?" }],
});
MultiServerMCPClient is stateless by default. Each tool invocation creates a fresh MCP ClientSession, executes the tool, and then cleans up.

Custom MCP servers

To create your own MCP servers, you can use the @modelcontextprotocol/sdk library. This library provides a simple way to define tools and run them as servers.
npm install @modelcontextprotocol/sdk
Use the following reference implementations to test your agent with MCP tool servers.
Math server (stdio transport)
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
    CallToolRequestSchema,
    ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

const server = new Server(
    {
        name: "math-server",
        version: "0.1.0",
    },
    {
        capabilities: {
        tools: {},
        },
    }
);

server.setRequestHandler(ListToolsRequestSchema, async () => {
    return {
        tools: [
        {
            name: "add",
            description: "Add two numbers",
            inputSchema: {
            type: "object",
            properties: {
                a: {
                type: "number",
                description: "First number",
                },
                b: {
                type: "number",
                description: "Second number",
                },
            },
            required: ["a", "b"],
            },
        },
        {
            name: "multiply",
            description: "Multiply two numbers",
            inputSchema: {
            type: "object",
            properties: {
                a: {
                type: "number",
                description: "First number",
                },
                b: {
                type: "number",
                description: "Second number",
                },
            },
            required: ["a", "b"],
            },
        },
        ],
    };
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
    switch (request.params.name) {
        case "add": {
        const { a, b } = request.params.arguments as { a: number; b: number };
        return {
            content: [
            {
                type: "text",
                text: String(a + b),
            },
            ],
        };
        }
        case "multiply": {
        const { a, b } = request.params.arguments as { a: number; b: number };
        return {
            content: [
            {
                type: "text",
                text: String(a * b),
            },
            ],
        };
        }
        default:
        throw new Error(`Unknown tool: ${request.params.name}`);
    }
});

async function main() {
    const transport = new StdioServerTransport();
    await server.connect(transport);
    console.error("Math MCP server running on stdio");
}

main();
Weather server (SSE transport)
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import {
    CallToolRequestSchema,
    ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import express from "express";

const app = express();
app.use(express.json());

const server = new Server(
    {
        name: "weather-server",
        version: "0.1.0",
    },
    {
        capabilities: {
        tools: {},
        },
    }
);

server.setRequestHandler(ListToolsRequestSchema, async () => {
    return {
        tools: [
        {
            name: "get_weather",
            description: "Get weather for location",
            inputSchema: {
            type: "object",
            properties: {
                location: {
                type: "string",
                description: "Location to get weather for",
                },
            },
            required: ["location"],
            },
        },
        ],
    };
});

server.setRequestHandler(CallToolRequestSchema, async (request) => {
    switch (request.params.name) {
        case "get_weather": {
        const { location } = request.params.arguments as { location: string };
        return {
            content: [
            {
                type: "text",
                text: `It's always sunny in ${location}`,
            },
            ],
        };
        }
        default:
        throw new Error(`Unknown tool: ${request.params.name}`);
    }
});

app.post("/mcp", async (req, res) => {
    const transport = new SSEServerTransport("/mcp", res);
    await server.connect(transport);
});

const PORT = process.env.PORT || 8000;
app.listen(PORT, () => {
    console.log(`Weather MCP server running on port ${PORT}`);
});

Stateful tool usage

For stateful servers that maintain context between tool calls, use client.session() to create a persistent ClientSession.
Using MCP ClientSession for stateful tool usage
import { loadMCPTools } from "@langchain/mcp-adapters/tools.js";

const client = new MultiServerMCPClient({...});
const session = await client.session("math");
const tools = await loadMCPTools(session);

Additional resources


I