Model Context Protocol servers expose tools through a standard client interface, so an agent can call external capabilities without a custom adapter for each service. In LangChain, langchain-mcp-adapters loads those server tools as normal LangChain tools for the agent loop.
The local check uses a FastMCP math server over stdio and MultiServerMCPClient to load the server's add tool. A deterministic fake chat model triggers the tool call without an OpenAI, Anthropic, or other provider key, which keeps the first verification focused on MCP wiring.
After the local tool call works, the same client configuration can point at a long-running MCP server over stdio or http. Treat MCP tools like other agent tools by reviewing names, descriptions, arguments, and side effects before exposing them to a model that can call them autonomously.
Related: How to install LangChain with pip
Related: How to create a LangChain agent
Related: How to build a tool-calling agent in LangChain
$ python3 -m pip install --upgrade langchain langchain-mcp-adapters fastmcp
LangChain v1 requires Python 3.10 or newer. fastmcp is only needed here to create the local demo MCP server; existing MCP servers only need the adapter on the client side.
from fastmcp import FastMCP mcp = FastMCP("Math") @mcp.tool() def add(a: int, b: int) -> int: """Add two numbers.""" return a + b if __name__ == "__main__": mcp.run(transport="stdio", show_banner=False)
stdio lets the client launch the server as a subprocess. show_banner=False keeps the demo server from printing an ASCII banner before the MCP session starts.
import asyncio import sys from pathlib import Path from langchain.agents import create_agent from langchain_core.language_models.fake_chat_models import FakeMessagesListChatModel from langchain_core.messages import AIMessage, ToolMessage from langchain_mcp_adapters.client import MultiServerMCPClient class ToolCallingFakeModel(FakeMessagesListChatModel): def bind_tools(self, tools, *, tool_choice=None, **kwargs): return self async def main(): server_path = Path(__file__).with_name("math_mcp_server.py") client = MultiServerMCPClient( { "math": { "transport": "stdio", "command": sys.executable, "args": [str(server_path)], } } ) tools = await client.get_tools() print("MCP tools:", ", ".join(tool.name for tool in tools)) add_tool = next(tool for tool in tools if tool.name == "add") model = ToolCallingFakeModel( responses=[ AIMessage( content="", tool_calls=[ { "name": add_tool.name, "args": {"a": 7, "b": 5}, "id": "call_add", } ], ), AIMessage(content="The MCP add tool returned 12."), ] ) agent = create_agent(model=model, tools=tools) result = await agent.ainvoke( { "messages": [ { "role": "user", "content": "Use the MCP add tool to add 7 and 5.", } ] } ) for message in result["messages"]: if isinstance(message, ToolMessage): content = message.content if isinstance(content, list): text_blocks = [ block.get("text", "") for block in content if isinstance(block, dict) and block.get("type") == "text" ] content = " ".join(text_blocks) print(f"Tool result ({message.name}): {content}") print("Agent reply:", result["messages"][-1].content) if __name__ == "__main__": asyncio.run(main())
The fake model emits one planned tool call and one final response. Replace it with init_chat_model() and provider credentials after the MCP tool route works.
Related: How to call a chat model in LangChain
$ python use_mcp_tools.py MCP tools: add Tool result (add): 12 Agent reply: The MCP add tool returned 12.
client.get_tools() confirms that the MCP server exposed add as a LangChain tool. The tool result and final reply confirm that create_agent() executed the tool call and returned the final agent message.
$ rm math_mcp_server.py use_mcp_tools.py