# LangChain MCP Adapters

Ref:

- https://github.com/langchain-ai/langchain-mcp-adapters

This notebook demonstrates how to use MCP (Model Context Protocol) tools with LangChain agents using `langchain-mcp-adapters`.


## Setup

Configure `.env` before running. See `.env.sample`.



```python
import rich
from dotenv import load_dotenv

load_dotenv()
```




    True



## MCP Servers

MCP server files are located in `mcp_servers/` directory.



```python
from pathlib import Path

from rich.syntax import Syntax

mcp_servers_dir = Path("mcp_servers")
math_server = mcp_servers_dir / "math_server.py"
string_server = mcp_servers_dir / "string_server.py"

rich.print(Syntax(math_server.read_text(), "python", padding=(1, 2)))
```


                                                                                                                       
      from mcp.server.fastmcp import FastMCP                                                                           
                                                                                                                       
      mcp = FastMCP("Math")                                                                                            
                                                                                                                       
                                                                                                                       
      @mcp.tool(name="math__add")                                                                                      
      def add(a: int, b: int) -> int:                                                                                  
          """Add two numbers."""                                                                                       
          return a + b                                                                                                 
                                                                                                                       
                                                                                                                       
      @mcp.tool(name="math__multiply")                                                                                 
      def multiply(a: int, b: int) -> int:                                                                             
          """Multiply two numbers."""                                                                                  
          return a * b                                                                                                 
                                                                                                                       
                                                                                                                       
      if __name__ == "__main__":                                                                                       
          mcp.run(transport="stdio")                                                                                   
                                                                                                                       
                                                                                                                       



## Load MCP Tools

Use `load_mcp_tools` to load tools from an MCP server session.

**Note:** There are two ways to load tools:

- `load_mcp_tools(session)`: Uses an existing session. Tools execute within the same session. More efficient for multiple tool calls.
- `client.get_tools()`: Creates a new session for each tool execution. Simpler but has connection overhead per call. Useful for stateless deployments like LangGraph API Server.



```python
from langchain_mcp_adapters.tools import load_mcp_tools
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

server_params = StdioServerParameters(
    command="python",
    args=[str(math_server.resolve())],
)


async def list_tools() -> None:
    """List available tools from the MCP server."""
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await load_mcp_tools(session)
            rich.print("tools =", tools)


await list_tools()
```


    tools =
    [
        StructuredTool(
            name='math__add',
            description='Add two numbers.',
            args_schema={
                'properties': {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}},
                'required': ['a', 'b'],
                'title': 'addArguments',
                'type': 'object'
            },
            response_format='content_and_artifact',
            coroutine=<function convert_mcp_tool_to_langchain_tool.<locals>.call_tool at 0x112dcaac0>
        ),
        StructuredTool(
            name='math__multiply',
            description='Multiply two numbers.',
            args_schema={
                'properties': {'a': {'title': 'A', 'type': 'integer'}, 'b': {'title': 'B', 'type': 'integer'}},
                'required': ['a', 'b'],
                'title': 'multiplyArguments',
                'type': 'object'
            },
            response_format='content_and_artifact',
            coroutine=<function convert_mcp_tool_to_langchain_tool.<locals>.call_tool at 0x112dcb1a0>
        )
    ]



## Create Agent with MCP Tools

Load tools from the MCP server and create a LangChain agent.



```python
from typing import Any

from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
from langgraph.graph.state import CompiledStateGraph

model = ChatAnthropic(model="claude-sonnet-4-5-20250929")


async def run_agent() -> None:
    """Run agent with MCP tools."""
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await load_mcp_tools(session)

            agent: CompiledStateGraph[Any] = create_agent(
                model=model,
                tools=tools,
                system_prompt="You are a helpful math assistant.",
            )

            response = await agent.ainvoke({"messages": [{"role": "user", "content": "What is 5 + 3?"}]})
            rich.print("response =", response)


await run_agent()
```


    response =
    {
        'messages': [
            HumanMessage(
                content='What is 5 + 3?',
                additional_kwargs={},
                response_metadata={},
                id='934fdfbb-9f0a-4fd4-932a-a1a7af5709a4'
            ),
            AIMessage(
                content=[
                    {
                        'id': 'toolu_013up3WT5Ubnsw7oerjJQj7y',
                        'input': {'a': 5, 'b': 3},
                        'name': 'math__add',
                        'type': 'tool_use'
                    }
                ],
                additional_kwargs={},
                response_metadata={
                    'id': 'msg_01Se6RdeWyn28BCWgiMtKEo2',
                    'model': 'claude-sonnet-4-5-20250929',
                    'stop_reason': 'tool_use',
                    'stop_sequence': None,
                    'usage': {
                        'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                        'cache_creation_input_tokens': 0,
                        'cache_read_input_tokens': 0,
                        'input_tokens': 649,
                        'output_tokens': 70,
                        'server_tool_use': None,
                        'service_tier': 'standard'
                    },
                    'model_name': 'claude-sonnet-4-5-20250929',
                    'model_provider': 'anthropic'
                },
                id='lc_run--684d7f12-8ed8-442f-935a-b9cca3dbcac2-0',
                tool_calls=[
                    {
                        'name': 'math__add',
                        'args': {'a': 5, 'b': 3},
                        'id': 'toolu_013up3WT5Ubnsw7oerjJQj7y',
                        'type': 'tool_call'
                    }
                ],
                usage_metadata={
                    'input_tokens': 649,
                    'output_tokens': 70,
                    'total_tokens': 719,
                    'input_token_details': {
                        'cache_read': 0,
                        'cache_creation': 0,
                        'ephemeral_5m_input_tokens': 0,
                        'ephemeral_1h_input_tokens': 0
                    }
                }
            ),
            ToolMessage(
                content='8',
                name='math__add',
                id='a9d3722b-d0b4-4609-8b14-7e4fa8020c72',
                tool_call_id='toolu_013up3WT5Ubnsw7oerjJQj7y'
            ),
            AIMessage(
                content='The answer is **8**.',
                additional_kwargs={},
                response_metadata={
                    'id': 'msg_01Ws6WXpmPCgrdPfS5uU9Wd7',
                    'model': 'claude-sonnet-4-5-20250929',
                    'stop_reason': 'end_turn',
                    'stop_sequence': None,
                    'usage': {
                        'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                        'cache_creation_input_tokens': 0,
                        'cache_read_input_tokens': 0,
                        'input_tokens': 733,
                        'output_tokens': 9,
                        'server_tool_use': None,
                        'service_tier': 'standard'
                    },
                    'model_name': 'claude-sonnet-4-5-20250929',
                    'model_provider': 'anthropic'
                },
                id='lc_run--d6223114-2a27-46e5-9571-6241a0565bf3-0',
                usage_metadata={
                    'input_tokens': 733,
                    'output_tokens': 9,
                    'total_tokens': 742,
                    'input_token_details': {
                        'cache_read': 0,
                        'cache_creation': 0,
                        'ephemeral_5m_input_tokens': 0,
                        'ephemeral_1h_input_tokens': 0
                    }
                }
            )
        ]
    }



## Stream with MCP Tools

You can also stream responses when using MCP tools.



```python
async def stream_agent() -> None:
    """Stream agent output with MCP tools."""
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await load_mcp_tools(session)

            agent: CompiledStateGraph[Any] = create_agent(
                model=model,
                tools=tools,
                system_prompt="You are a helpful math assistant.",
            )

            async for chunk in agent.astream({"messages": [{"role": "user", "content": "What is 7 * 8?"}]}):
                rich.print("chunk =", chunk)


await stream_agent()
```


    chunk =
    {
        'model': {
            'messages': [
                AIMessage(
                    content=[
                        {
                            'id': 'toolu_01NHme3fRFwVjQ6sfLKdqVrh',
                            'input': {'a': 7, 'b': 8},
                            'name': 'math__multiply',
                            'type': 'tool_use'
                        }
                    ],
                    additional_kwargs={},
                    response_metadata={
                        'id': 'msg_011BpoCH4Hu2o4sYGv3pFehk',
                        'model': 'claude-sonnet-4-5-20250929',
                        'stop_reason': 'tool_use',
                        'stop_sequence': None,
                        'usage': {
                            'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                            'cache_creation_input_tokens': 0,
                            'cache_read_input_tokens': 0,
                            'input_tokens': 649,
                            'output_tokens': 70,
                            'server_tool_use': None,
                            'service_tier': 'standard'
                        },
                        'model_name': 'claude-sonnet-4-5-20250929',
                        'model_provider': 'anthropic'
                    },
                    id='lc_run--0fb52d04-0f4c-4ec2-a3b1-09560f41044a-0',
                    tool_calls=[
                        {
                            'name': 'math__multiply',
                            'args': {'a': 7, 'b': 8},
                            'id': 'toolu_01NHme3fRFwVjQ6sfLKdqVrh',
                            'type': 'tool_call'
                        }
                    ],
                    usage_metadata={
                        'input_tokens': 649,
                        'output_tokens': 70,
                        'total_tokens': 719,
                        'input_token_details': {
                            'cache_read': 0,
                            'cache_creation': 0,
                            'ephemeral_5m_input_tokens': 0,
                            'ephemeral_1h_input_tokens': 0
                        }
                    }
                )
            ]
        }
    }




    chunk =
    {
        'tools': {
            'messages': [
                ToolMessage(
                    content='56',
                    name='math__multiply',
                    id='788ba5d8-4e4f-472c-b98e-60af170b5c99',
                    tool_call_id='toolu_01NHme3fRFwVjQ6sfLKdqVrh'
                )
            ]
        }
    }




    chunk =
    {
        'model': {
            'messages': [
                AIMessage(
                    content='7 × 8 = **56**',
                    additional_kwargs={},
                    response_metadata={
                        'id': 'msg_013uBEweZnqapQBAw4cxPBCK',
                        'model': 'claude-sonnet-4-5-20250929',
                        'stop_reason': 'end_turn',
                        'stop_sequence': None,
                        'usage': {
                            'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                            'cache_creation_input_tokens': 0,
                            'cache_read_input_tokens': 0,
                            'input_tokens': 733,
                            'output_tokens': 13,
                            'server_tool_use': None,
                            'service_tier': 'standard'
                        },
                        'model_name': 'claude-sonnet-4-5-20250929',
                        'model_provider': 'anthropic'
                    },
                    id='lc_run--6b18b6e8-1d6b-4bda-9965-f93eb86d7344-0',
                    usage_metadata={
                        'input_tokens': 733,
                        'output_tokens': 13,
                        'total_tokens': 746,
                        'input_token_details': {
                            'cache_read': 0,
                            'cache_creation': 0,
                            'ephemeral_5m_input_tokens': 0,
                            'ephemeral_1h_input_tokens': 0
                        }
                    }
                )
            ]
        }
    }



## Multiple MCP Servers

Use `MultiServerMCPClient` with `load_mcp_tools` for explicit session control.

See `mcp_servers/string_server.py` for the string server implementation.



```python
rich.print(Syntax(string_server.read_text(), "python", padding=(1, 2)))
```


                                                                                                                       
      from mcp.server.fastmcp import FastMCP                                                                           
                                                                                                                       
      mcp = FastMCP("String")                                                                                          
                                                                                                                       
                                                                                                                       
      @mcp.tool(name="string__uppercase")                                                                              
      def uppercase(text: str) -> str:                                                                                 
          """Convert text to uppercase."""                                                                             
          return text.upper()                                                                                          
                                                                                                                       
                                                                                                                       
      @mcp.tool(name="string__reverse")                                                                                
      def reverse(text: str) -> str:                                                                                   
          """Reverse a string."""                                                                                      
          return text[::-1]                                                                                            
                                                                                                                       
                                                                                                                       
      if __name__ == "__main__":                                                                                       
          mcp.run(transport="stdio")                                                                                   
                                                                                                                       
                                                                                                                       




```python
from contextlib import AsyncExitStack

from langchain_mcp_adapters.client import MultiServerMCPClient

multi_client = MultiServerMCPClient(
    {
        "math": {
            "command": "python",
            "args": [str(math_server.resolve())],
            "transport": "stdio",
        },
        "string": {
            "command": "python",
            "args": [str(string_server.resolve())],
            "transport": "stdio",
        },
    }
)


async def run_multi_server_agent() -> None:
    """Run agent with multiple MCP servers."""
    async with AsyncExitStack() as stack:
        math_session = await stack.enter_async_context(multi_client.session("math"))
        string_session = await stack.enter_async_context(multi_client.session("string"))

        tools = []
        tools.extend(await load_mcp_tools(math_session))
        tools.extend(await load_mcp_tools(string_session))

        rich.print("Available tools:", [t.name for t in tools])

        agent: CompiledStateGraph[Any] = create_agent(
            model=model,
            tools=tools,
            system_prompt="You are a helpful assistant with math and string tools.",
        )

        response = await agent.ainvoke(
            {"messages": [{"role": "user", "content": "Add 10 and 20, then reverse the string 'hello'"}]}
        )
        rich.print("response =", response)


await run_multi_server_agent()
```


    Available tools:
    ['math__add', 'math__multiply', 'string__uppercase', 'string__reverse']




    response =
    {
        'messages': [
            HumanMessage(
                content="Add 10 and 20, then reverse the string 'hello'",
                additional_kwargs={},
                response_metadata={},
                id='88a5e35c-e851-481b-8c6c-84b5c542e8b4'
            ),
            AIMessage(
                content=[
                    {
                        'text': "I'll help you add 10 and 20, and reverse the string 'hello'. Since these operations 
    are independent, I can do both at the same time.",
                        'type': 'text'
                    },
                    {
                        'id': 'toolu_01MEvKzTQf2aM1SCdnLq4LCb',
                        'input': {'a': 10, 'b': 20},
                        'name': 'math__add',
                        'type': 'tool_use'
                    },
                    {
                        'id': 'toolu_015QWvHHJiswy4ECSp3AAEet',
                        'input': {'text': 'hello'},
                        'name': 'string__reverse',
                        'type': 'tool_use'
                    }
                ],
                additional_kwargs={},
                response_metadata={
                    'id': 'msg_012og99rbiKwVjT7Den1LVUW',
                    'model': 'claude-sonnet-4-5-20250929',
                    'stop_reason': 'tool_use',
                    'stop_sequence': None,
                    'usage': {
                        'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                        'cache_creation_input_tokens': 0,
                        'cache_read_input_tokens': 0,
                        'input_tokens': 764,
                        'output_tokens': 142,
                        'server_tool_use': None,
                        'service_tier': 'standard'
                    },
                    'model_name': 'claude-sonnet-4-5-20250929',
                    'model_provider': 'anthropic'
                },
                id='lc_run--f133a1cd-4f84-43e3-8af4-29d6778f02b3-0',
                tool_calls=[
                    {
                        'name': 'math__add',
                        'args': {'a': 10, 'b': 20},
                        'id': 'toolu_01MEvKzTQf2aM1SCdnLq4LCb',
                        'type': 'tool_call'
                    },
                    {
                        'name': 'string__reverse',
                        'args': {'text': 'hello'},
                        'id': 'toolu_015QWvHHJiswy4ECSp3AAEet',
                        'type': 'tool_call'
                    }
                ],
                usage_metadata={
                    'input_tokens': 764,
                    'output_tokens': 142,
                    'total_tokens': 906,
                    'input_token_details': {
                        'cache_read': 0,
                        'cache_creation': 0,
                        'ephemeral_5m_input_tokens': 0,
                        'ephemeral_1h_input_tokens': 0
                    }
                }
            ),
            ToolMessage(
                content='30',
                name='math__add',
                id='5d24c11a-03ed-4ef9-bf7f-aea639c1f9fd',
                tool_call_id='toolu_01MEvKzTQf2aM1SCdnLq4LCb'
            ),
            ToolMessage(
                content='olleh',
                name='string__reverse',
                id='58bf274e-09c4-4938-bead-1a32759e49be',
                tool_call_id='toolu_015QWvHHJiswy4ECSp3AAEet'
            ),
            AIMessage(
                content="Perfect! Here are the results:\n- **10 + 20 = 30**\n- **'hello' reversed = 'olleh'**",
                additional_kwargs={},
                response_metadata={
                    'id': 'msg_01DMUxaxmYHnEgx5Z9q6rJQi',
                    'model': 'claude-sonnet-4-5-20250929',
                    'stop_reason': 'end_turn',
                    'stop_sequence': None,
                    'usage': {
                        'cache_creation': {'ephemeral_1h_input_tokens': 0, 'ephemeral_5m_input_tokens': 0},
                        'cache_creation_input_tokens': 0,
                        'cache_read_input_tokens': 0,
                        'input_tokens': 972,
                        'output_tokens': 37,
                        'server_tool_use': None,
                        'service_tier': 'standard'
                    },
                    'model_name': 'claude-sonnet-4-5-20250929',
                    'model_provider': 'anthropic'
                },
                id='lc_run--dfb6edd0-0439-467f-9fb4-e0c7fadbc211-0',
                usage_metadata={
                    'input_tokens': 972,
                    'output_tokens': 37,
                    'total_tokens': 1009,
                    'input_token_details': {
                        'cache_read': 0,
                        'cache_creation': 0,
                        'ephemeral_5m_input_tokens': 0,
                        'ephemeral_1h_input_tokens': 0
                    }
                }
            )
        ]
    }


