跳到正文
LangChain Blog·· 2026-09-04精选AI 评分62

LangChain 将 MCP 支持并入主包,适配无状态协议与 elicitation

MCP in LangChain: Stateless Protocol, Elicitation, and More!

AI 导读

LangChain 重构了 MCP 支持,将其从独立的 langchain-mcp-adapters 移入主包 langchain.mcp,基于 FastMCP 构建,通过 pip install "langchain[mcp]" 安装,要求 langchain[mcp]>=1.4.0 且处于 beta。

推荐理由

LangChain 把 MCP 支持并入主包并适配无状态新规范,读者可据此判断现有适配层与缓存、elicitation 流程的迁移成本。

正文 · AI 翻译

MCP 官方的 Tier 1 SDK 每月下载量已接近五亿次,而且使用量还在加速攀升:ChatGPT 用户发起的 MCP 工具调用在 2026 年全年增长了 98 倍,仅 8 月就翻了一倍多。

Model Context Protocol(MCP)是将智能体连接到工具的最流行方式。今年 7 月,该协议迎来了自发布以来最大的一次重写。我们改造了 LangChain 中的 MCP 支持,以匹配新规范和其背后不断增长的需求。

有三点变化:

  • MCP 支持移入主包。它现在位于 langchain.mcp 中,而不再需要单独安装 langchain-mcp-adapters。
  • 它构建在 FastMCP 之上。传输、认证、连接管理和协议协商都由底层的客户端提供,因此旧规范和新规范上的服务器都能正常工作。
  • 现已支持通过中断实现的 elicitation 以及客户端缓存。新规范将服务器在调用中途发起的 elicitation 变成可重试的一轮交互,我们将其呈现为 LangGraph 中断。新规范还让工具列表可缓存,因此工具目录不再需要在每次运行时重新获取。

新的无状态规范

过去(在旧规范下),每次 MCP 调用都要经过一个围绕会话构建的协议。通过 MCP 调用工具,过去意味着要先打开一个会话。客户端和服务器握手,服务器返回一个会话 ID,之后每个请求都必须携带它,这就把该客户端绑定到了签发该 ID 的那一个服务器实例上。

要以任意规模运行远程服务器,就意味着需要粘性路由和共享会话存储。

这一切在新 MCP 规范中发生了改变,新规范启用了无状态核心。MCP 团队称无状态核心是开发者呼声最高的功能之一,他们希望服务器具备更好的可靠性和可扩展性。在新规范中,已经没有任何东西需要绑定了。重新部署不再会杀死活动会话,因为根本不存在会话。

这带来了两项能力,如今都已进入 langchain.mcp:

  • 缓存:服务器可以声明其工具列表保持新鲜的时间,这样客户端就不必在每次运行时重新获取。
  • Elicitation:工具可以暂停下来向调用方询问某些信息,比如确认删除或补充模型遗漏的参数,而无需在等待期间一直保持连接打开。

阅读 MCP 团队的公告,了解更多关于此次修订的信息

一等公民的 MCP 支持

我们把 MCP 支持移入了 langchain,使其成为智能体的一等公民。它通过 mcp extra 安装:‍

pip install "langchain[mcp]"

从旧包迁移过来时,MultiServerMCPClient 会合并为一个 MCPAdapter 类。阅读迁移指南,了解更详细的采用说明。基本用法如下:‍

from deepagents import create_deep_agent
from langchain.mcp import MCPAdapter


async def main():
    async with MCPAdapter("https://example.com/mcp") as adapter:
        agent = create_deep_agent(
            model="google_genai:gemini-3.8-flash", tools=
            await adapter.list_tools()
        )
        return await agent.ainvoke(
            {"messages": [{"role": "user", "content": "..."}]}
        )

这些工具就是普通的 LangChain 工具,因此它们可以去任何工具能去的地方:create_deep_agent、create_agent,或者你自己搭建的图。

构建在 FastMCP 之上

FastMCP 在传输层之上提供了清晰的抽象:连接、认证、缓存和协议协商。它的客户端接口可直接供你使用。

MCP 现在有两个不同的协议“时代”,这意味着客户端需要能够与两种不同的协议进行协商。 FastMCP 按连接处理这一点:它会尝试新协议,并对尚未升级的服务器回退到握手流程。无论哪种情况,你的代码都不需要改变。FastMCP 4 的新特性中有详细说明。

用 ClientGroup 为每个服务器提供自己的连接,每个连接都保留其支持的最佳时代,以及自己的凭据:‍

from langchain.mcp import MCPAdapter
from deepagents import create_deep_agent
from fastmcp import ClientGroup

group = ClientGroup(
    {
        # Hasn't upgraded yet, so pin the handshake era. Auth is OAuth 2.1.
        "billing": Client("https://billing.internal/mcp", mode="legacy", auth="oauth"),
        # Negotiates the newest era it understands, with a bearer token.
        "docs": Client("https://docs.internal/mcp", mode="auto", auth=docs_token),
    }
)

async with MCPAdapter(group) as adapter:
    # billing_search and docs_search, so the two stay distinct.
    tools = await adapter.list_tools()
    agent = create_deep_agent(model="google_genai:gemini-3.8-flash", tools=tools)

工具名称会加上其来源服务器的前缀,因此每个服务器上的 search 工具会以 billing_search 和 docs_search 的形式出现。如果你的服务器之间不需要区分,一个普通的配置字典就足够了;连接指南介绍了何时使用哪种方式。

客户端的其余部分可以直接使用:

  • 认证:bearer 令牌、完整的 OAuth 2.1 流程、机器对机器凭据、CIMD,或任何 httpx2.Auth
  • 传输:可流式 HTTP、stdio 和内存中,可从目标推断,或针对标头、SSL 和共享 httpx2 池进行配置
  • 缓存:在服务器 TTL 允许的范围内保留列表结果
  • 进度和日志:来自长时间运行调用的通知

FastMCP 还让你可以轻松构建和测试自己的服务器。FastMCP 实例是有效的适配器目标,无需子进程和套接字,因此代理可以在进程内针对真实的 MCP 服务器运行。

通过中断进行引导

引导是 MCP 的人在回路支持:一个工具在未先向调用者询问某些信息的情况下无法完成。无状态规范将其转变为一种普通请求,客户端附带答案重试,这让我们能够用你已经在使用的中断原语来支持它。运行暂停,审查代理工作的任何人给出答案,然后恢复:‍

paused = await agent.ainvoke(
    {"messages": [{"role": "user", "content": "Book a table for 4."}]}, config
)
question = paused["__interrupt__"][0].value.requests[0]

answer = {"action": "accept", "content": {"date": "2026-09-14"}}
result = await agent.ainvoke(
    Command(resume={"responses": {question["key"]: answer}}), config
)

‍除了检查点器之外无需任何设置,这样暂停的运行就有地方等待。引导文档介绍了如何拒绝问题,以及如何将破坏性工具置于相同的审批流程之后。

客户端缓存

每次代理运行都从发现存在哪些工具开始,这意味着在模型看到任何内容之前,需要一次往返请求来发现工具。服务器现在可以说明其工具列表保持新鲜的时间,因此目录可以从缓存中提供。cache=True 为你提供一个遵循这些提示的内存缓存:

from fastmcp import Client
from langchain.mcp import MCPAdapter

client = Client("https://billing.internal/mcp", cache=True)

async with MCPAdapter(client) as adapter:
    # "use" is the default once a cache is configured: serve a cached catalog
    # while the server's TTL holds, and store what it does fetch.
    tools = await adapter.list_tools(cache_mode="use")
    agent = create_deep_agent(
        model="google_genai:gemini-3.8-flash", 
        tools=tools
    )

缓存属于客户端,因此每个调用者一个客户端可以防止目录交叉。有关 TTL、共享存储和其他缓存模式,请参阅响应缓存。

开始使用

uv pip install "langchain[mcp]"

该命名空间需要 langchain[mcp]>=1.4.0 且处于测试阶段,因此 API 可能仍会变化。我们今天发布 Python 支持,TypeScript 支持即将推出。

来源:LangChain Blog · langchain.com