Menu

AI

langchain-mcp-adapters Tutorial (2026): Move to langchain.mcp and MCPAdapter

The langchain-mcp-adapters package is no longer maintained. Learn the new langchain.mcp MCPAdapter, connect MCP servers to an agent, and migrate old code.

By: Irina ShvayaNovember 2, 2026

langchain-mcp-adapters Tutorial (2026): Move to langchain.mcp and MCPAdapter

This tutorial is part of Build an MCP Server, within The MCP Guide. Want it built for you? See MCP development.

If you search for a langchain-mcp-adapters tutorial in November 2026, most results will teach you a package its own maintainers have stopped working on. The langchain-mcp-adapters README now opens with "This repository is no longer actively maintained" and tells you to "migrate to langchain[mcp]."

This guide does two jobs. It shows you how to load MCP tools into a LangChain agent with the new langchain.mcp namespace and its MCPAdapter class. Then it maps every common langchain-mcp-adapters call to its replacement, so you can move old code across. Code was checked against the LangChain MCP docs and langchain 1.4.8 on PyPI on 2 November 2026.

Key Takeaways

  • MCP support now ships inside LangChain as langchain.mcp; install it with pip install "langchain[mcp]" (version 1.4.0 or later).
  • MultiServerMCPClient is replaced by one class, MCPAdapter, used as an async context manager with list_tools().
  • MCPAdapter is built on FastMCP and infers the transport from what you pass it: a URL, a script path, an in-process server or an mcpServers config.
  • The namespace is in beta and raises a LangChainBetaWarning; prompts and resources are not wrapped yet.
  • A string target must be an http or https URL; LangChain rejects other strings so a model cannot trick it into launching a local file.

What changed and why it matters

The old package gave you MultiServerMCPClient, load_mcp_tools and typed connection classes. The migration guide says MCP support "now ships inside LangChain in the langchain.mcp namespace, built on FastMCP," and that MultiServerMCPClient "is collapsed into a single MCPAdapter class."

Two practical effects follow. Your dependency becomes langchain[mcp], which pulls in FastMCP. On PyPI that extra required fastmcp>=4.0.11 on 2 November 2026. And the transport is now inferred, so most per-server transport keys disappear from your config.

The LangChain docs flag that the namespace "requires langchain[mcp]>=1.4.0 and is in beta." Importing it raises a LangChainBetaWarning once per process, and "the API may change." Pin your version.

For the bigger picture of when to use MCP tools versus native LangChain tools, see MCP vs LangChain tools.

Prerequisites

  • Python 3.10 or later (the langchain package on PyPI requires it).
  • An API key for the chat model you plan to use.
  • Node.js, if you want to test with the MCP Inspector.

Install

pip install "langchain[mcp]"

Or with uv:

uv add "langchain[mcp]"

If an old project has the standalone package, remove it in the same step:

pip uninstall langchain-mcp-adapters

Build a small test server

You need an MCP server to talk to. Because langchain[mcp] already installs FastMCP, a tiny FastMCP server is the quickest option. This follows the FastMCP quickstart:

# notes_server.py
from fastmcp import FastMCP

mcp = FastMCP("Notes")

NOTES = {"welcome": "Hello from the notes server."}


@mcp.tool
def list_notes() -> list[str]:
    """List the titles of all saved notes."""
    return sorted(NOTES)


@mcp.tool
def read_note(title: str) -> str:
    """Read one note by its exact title."""
    return NOTES.get(title, f"No note titled {title!r}.")


if __name__ == "__main__":
    mcp.run(transport="http", port=8000)

Run python notes_server.py. FastMCP serves it at http://localhost:8000/mcp. If you want to go deeper on FastMCP itself, read our FastMCP tutorial.

Minimal working example

This is the quickstart pattern from the LangChain docs, pointed at the test server:

import asyncio

from langchain.agents import create_agent
from langchain.mcp import MCPAdapter


async def main():
    async with MCPAdapter("http://localhost:8000/mcp") as adapter:
        tools = await adapter.list_tools()
        agent = create_agent("claude-sonnet-5", tools)
        result = await agent.ainvoke(
            {"messages": [{"role": "user", "content": "What does the welcome note say?"}]}
        )
        print(result["messages"][-1].content)


asyncio.run(main())

list_tools() discovers the server's tools and adapts each one into a normal LangChain tool. The docs note that "the tools hold the client, so the agent stays usable after the context exits." Swap the model string for any model your LangChain setup supports.

Transports: what you pass decides how it connects

The MCP overview page lists the targets MCPAdapter accepts:

TargetTransport
"https://example.com/mcp" (a string URL)Streamable HTTP
Path("weather_server.py")stdio, one subprocess per adapter
A FastMCP server objectIn memory, no subprocess or socket
{"mcpServers": {...}}Several servers behind one adapter
A prebuilt fastmcp.ClientWhatever you configured on it

The in-memory option is the best way to unit-test tools: MCPAdapter(mcp) with the mcp object from notes_server.py runs without a port.

One safety rule is worth knowing. The docs warn that FastMCP tests a string "as a filesystem path before testing it as a URL," so a string naming a .py file could launch it. MCPAdapter therefore "rejects strings that do not match the shape of a URL." Use Path(...) for local scripts.

Connect several servers

Use the standard mcpServers shape. The migration guide's example:

from langchain.mcp import MCPAdapter

config = {
    "mcpServers": {
        "math": {"command": "python", "args": ["/path/to/math_server.py"]},
        "weather": {"url": "http://localhost:8000/mcp"},
    }
}
async with MCPAdapter(config) as adapter:
    tools = await adapter.list_tools()

For a multi-server config, prefixing is automatic and tool names become {server}_{tool}. That stops two servers that both have a search tool from colliding.

Migration cheat sheet

From the migration guide:

Old (langchain-mcp-adapters)New (langchain.mcp)
from langchain_mcp_adapters.client import MultiServerMCPClientfrom langchain.mcp import MCPAdapter
from langchain_mcp_adapters.tools import load_mcp_toolsMCPAdapter(...).list_tools()
convert_mcp_tool_to_langchain_toolas_langchain_tool (renamed)
MCPToolArtifactfrom langchain.mcp import MCPToolArtifact
client.get_tools()await adapter.list_tools()
"transport": "stdio" / "http" keysRemoved; inferred from command or url
tool_name_prefixAutomatic for multi-server configs
handle_tool_errorsRemoved as a flag (see below)
tool_interceptorsLangChain @wrap_tool_call middleware
Per-connection headersStreamableHttpTransport(url, headers=...)

Before you migrate, search the codebase for these. The guide marks them as gaps to stop and review:

  • get_prompt and get_resources: "Not supported."
  • WebsocketConnection: no FastMCP transport; move the server to Streamable HTTP.
  • SSEConnection: still possible through Client(SSETransport(url)), but the transport is deprecated.
  • to_fastmcp: listed as a feature to review, with no named replacement.

How errors behave now

The Tools page says a server result with isError=True becomes a ToolMessage with status="error", so the agent can read the message and try again. Transport or session failures still raise. You no longer choose this with a flag.

Structured results land on the ToolMessage as an MCPToolArtifact, and image or file content is converted to LangChain content blocks.

Add a tool

Adding a tool happens on the server, not in LangChain. Add another decorated function to notes_server.py, restart it, and the next list_tools() call picks it up:

@mcp.tool
def count_notes() -> int:
    """Return how many notes are saved."""
    return len(NOTES)

Write the docstring for the model. It becomes the tool description the agent reads when it decides what to call.

Test with the MCP Inspector

Check the server on its own before you blame the agent:

npx @modelcontextprotocol/inspector --cli http://localhost:8000/mcp --transport http --method tools/list

If the tools appear here but not in LangChain, the problem is on the client side. Our MCP Inspector lesson shows how to call tools and script these checks in CI.

Deploy notes

  • Run remote servers over Streamable HTTP. stdio targets start a subprocess per adapter, which suits local tools and tests, not shared services.
  • Keep tokens in headers or a fastmcp.Client with auth=, not in URLs.
  • Read tool annotations defensively. Each adapted tool may carry MCP hints such as destructive_hint under tool.metadata["mcp"], but every field is optional. Our tool annotations guide explains why hints are advisory.

Pitfalls

  • Copying old blog code. from langchain_mcp_adapters... imports still work only if the retired package is installed. New projects should not add it.
  • Stale server examples. The old README's server uses from mcp.server.fastmcp import FastMCP. The official Python SDK v2 removed that path; use from fastmcp import FastMCP or the SDK's MCPServer.
  • Passing a bare string path. Use Path(...). Strings must be URLs.
  • Expecting prompts and resources. The adapter wraps tools only, for now.

Next step

Work through the free MCP course to understand what the adapter hides. If you need a production MCP server behind your LangChain agents, our MCP development team can build and secure it.

More in the MCP Guide

Free tools: server.json Validator · MCP Error Code Lookup

Latest research: State of MCP: October 2026

Frequently asked questions

Is langchain-mcp-adapters deprecated?

Its README says it is "no longer actively maintained" and points to langchain[mcp]. LangChain publishes a step-by-step migration guide from MultiServerMCPClient to MCPAdapter.

Does MCPAdapter work with LangGraph?

Yes. list_tools() returns standard LangChain tools, and LangGraph graphs use LangChain tools. Our LangGraph MCP tutorial shows the graph wiring.

Can I still use SSE servers?

The migration guide says SSE works through Client(SSETransport(url)) passed to MCPAdapter, but the transport is deprecated. Ask the server owner for a Streamable HTTP endpoint.

Why do my tool names now have a prefix?

A multi-server mcpServers config prefixes names automatically as {server}_{tool}. Point an adapter at a single server if you want the original names.

You Might Also like to Read

Get a FREE Website Audit

Enter your website and get a 20–30 page SEO, GEO, AEO & CRO audit within 24 hours. Completely free.

Don't have a site yet? Get in touch →

Ready to speak with a marketing expert?
Give us a call! (916) 866-7893

Websites Launched
1407
Websites Launched
Marketing Experts
29
Marketing Experts
Hours of Dedicated Work
204533
Hours of Dedicated Work
Irina S.Benjamin G.Jeanette M.David G.