MCP技术毋须多言了,上半年火的一塌糊涂,现在进入冷静期了。
langchain 本身就很方便的集成进程内的工具,但是加上 MCP的功能,就如虎添翼,可以充分利用网上上万的MCP的服务。
langchain 自从上个月融资了1.25亿美元之后,资金充足,也更加有动力推进产品的演化,相继发布了langchain/langgraph 1.0的版本。 langchain 1.0中统一了agent的创建,使用create_agent代替之前的create_tool_calling_agent、create_react_agent、create_json_agent、create_xml_agent等。
这篇文章介绍 2(MCP的两种模式sse、stdio) x 2 (经典的langchain agent和1.0最新版create_agent两个模式)一共4个例子,介绍了langchain如何使用MCP 工具丰富其功能。
先决条件 在运行这些示例之前,请确保您已安装必要的库。您通常可以使用 pip 进行安装:
1 pip install langchain langchain-openai langchain-classic langchain-mcp-adapters mcp
此外,请确保您的环境中已安装 python3。
共同组件 这两个示例都共享几个核心组件和一个共同目标:使用 LangChain Agent 通过 MCP 服务器提供的工具来回答一个简单的数学问题。
LLM 配置 :两个示例都使用 ChatOpenAI,配置为 deepseek-v3 模型,温度为 0。 这是我使用百度云上提供的deepseek服务,你要是使用deepseek官方的服务,需要修改模型为deepseek-chat。 我已经把KEY和调用地址配置在环境变量中了,所以在代码中不用显示指定:
1 2 export OPENAI_API_KEY=bce-v3/abcsfsfdskgergerthntjrweeuidfu8324refbif3export OPENAI_API_BASE=https://qianfan.baidubce.com/v2
创建模型对象: 1 llm = ChatOpenAI(model="deepseek-v3" , temperature=0 )
Agent 提示 :ChatPromptTemplate 用于定义 Agent 的角色并构建对话。它包括一个系统消息、可选的聊天历史记录、人类输入以及 Agent 暂存区(用于规划其行动)的占位符。1 2 3 4 5 6 7 8 prompt = ChatPromptTemplate.from_messages( [ ("system" , "你是一个可以使用工具的得力助手。 தயவுசெய்து கருவிகளைப் பயன்படுத்தவும்." ), MessagesPlaceholder("chat_history" , optional=True ), ("human" , "{input}" ), MessagesPlaceholder("agent_scratchpad" ), ] )
Agent 创建和执行 :create_tool_calling_agent 函数用于构建能够使用工具的 Agent ,AgentExecutor 用于运行 Agent 。1 2 agent = create_tool_calling_agent(llm, tools, prompt) agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True )
任务 : Agent 被调用,输入为“123 + 456 等于多少?”。
MCP 服务 Stdio服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import asynciofrom mcp.server import FastMCPserver = FastMCP(name="math_server" , log_level="ERROR" ) @server.tool() def add (a: int , b: int ) -> int : """将两个整数相加。""" return a + b async def main (): await server.run_stdio_async() if __name__ == "__main__" : asyncio.run(main())
sse 服务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import asynciofrom typing import Annotatedfrom mcp.server import FastMCPserver = FastMCP(name="math_server" , instructions="一个可以做加法的简单数学服务器。" , log_level="ERROR" ) @server.tool() def add ( a: Annotated[int , "第一个整数" ], b: Annotated[int , "第二个整数" ] ) -> int : """将两个整数相加。""" return a + b async def main (): await server.run_sse_async() if __name__ == "__main__" : asyncio.run(main())
此示例演示了如何设置一个 MCP 服务器,该服务器通过标准输入和输出流与客户端通信。这适用于本地、单进程交互,其中服务器可以作为子进程生成。
目的 example_1_mcp_tool_stdio.py 脚本展示了如何:
定义一个通过 stdio 暴露工具的 MCP 服务器。
创建一个 stdio_client 来连接到此服务器。
将服务器提供的工具加载到 LangChain Agent 中。
使用 Agent 解决需要加载工具的问题。
关键组件和代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 import asyncioimport osfrom pathlib import Pathfrom langchain_openai import ChatOpenAIfrom langchain_classic.agents import AgentExecutor, create_tool_calling_agentfrom langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderfrom langchain_mcp_adapters.tools import load_mcp_toolsfrom mcp.client.stdio import stdio_clientfrom mcp import ClientSession, StdioServerParametersasync def run_mcp_tool_example (): mcp_server_path = Path(__file__).parent / "mcp_math_server_stdio.py" server_params = StdioServerParameters( command="python3" , args=[str (mcp_server_path)], ) 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) print ("正在调用 agent 回答一个数学问题..." ) response = await agent_executor.ainvoke( {"input" : "123 + 456 等于多少?" , "chat_history" : []} ) print (f"Agent 回答: {response['output' ]} " ) if __name__ == "__main__" : asyncio.run(run_mcp_tool_example())
如何运行 要运行此示例,只需执行 Python 脚本:
1 python3 example_1_mcp_tool_stdio.py
您将看到 Agent 的思考过程和最终答案打印到控制台。
此示例演示了如何集成一个 MCP 服务器,该服务器通过 HTTP 上的服务器发送事件(SSE)暴露其工具。此方法更适用于工具服务器可能是独立网络服务的情况。
目的 example_1_mcp_tool_sse.py 脚本展示了如何:
将 MCP SSE 服务器作为单独的进程启动。
创建一个 MultiServerMCPClient 来连接到此基于 HTTP 的服务器。
将服务器提供的工具加载到 LangChain Agent 中。
使用 Agent 解决需要加载工具的问题。
关键组件和代码演练 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import asyncioimport osfrom pathlib import Pathimport sysfrom langchain_openai import ChatOpenAIfrom langchain_classic.agents import AgentExecutor, create_tool_calling_agentfrom langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholderfrom langchain_mcp_adapters.client import MultiServerMCPClientasync def run_mcp_tool_example (): mcp_server_path = Path(__file__).parent / "mcp_math_server_sse.py" server_process = await asyncio.create_subprocess_exec( sys.executable, str (mcp_server_path), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) await asyncio.sleep(5 ) client = MultiServerMCPClient( { "math" : { "transport" : "sse" , "url" : "http://localhost:8000/sse" , }, } ) tools = await client.get_tools() print ("正在调用 agent 回答一个数学问题..." ) response = await agent_executor.ainvoke( {"input" : "123 + 456 等于多少?" , "chat_history" : []} ) print (f"Agent 回答: {response['output' ]} " ) server_process.terminate() await server_process.wait() if __name__ == "__main__" : asyncio.run(run_mcp_tool_example())
如何运行 要运行此示例,只需执行 Python 脚本:
1 python3 example_1_mcp_tool_sse.py
您将看到 Agent 的思考过程和最终答案打印到控制台。请注意,在此示例中,AgentExecutor 的 verbose 标志设置为 False,以避免 SSE 服务器子进程产生过多的输出。
比较:Stdio 与 SSE
Stdio(标准 I/O) :
简单性 :更易于设置本地、单机通信。
执行 :MCP 服务器通常作为客户端应用程序的子进程生成。
用例 :适用于紧密耦合的组件,或者当您希望将工具服务器直接与应用程序捆绑时。
SSE(服务器发送事件) :
灵活性 :允许 MCP 服务器作为独立的网络服务运行,可能在不同的机器上。
可伸缩性 :可以成为更大微服务架构的一部分。
执行 :客户端连接到正在运行的 HTTP 端点。服务器需要单独启动(如示例中通过 asyncio.create_subprocess_exec 所示)。
用例 :适用于分布式系统、基于 Web 的应用程序,或者当工具服务器需要被多个客户端访问时。
这两种方法都有效地允许 LangChain Agent 发现和利用使用多客户端协议定义的工具,从而为这些工具的部署和访问提供了灵活性。
这两个示例都是langchain经典的Agent开发模型,他们演示了langchain将 MCP 工具与 LangChain Agent 集成的强大功能和灵活性。无论它们是通过 stdio 还是 SSE 暴露。这使得健壮且可伸缩的 Agent 应用程序成为可能。
接下来我介绍如何使用 Langchain 1.0 中新的 create_agent 函数来构建 Agent ,并将其与 MCP 工具集成。与之前的示例不同,create_agent 提供了一种更简洁的方式来定义 Agent ,直接接受 LLM 模型、工具列表和系统提示,并返回一个可流式传输的图(graph)对象。
示例 3:使用 Langchain 1.0 create_agent 的 MCP SSE 工具集成 此示例展示了如何将 MCP SSE 服务器提供的工具与 Langchain 1.0 的 create_agent 函数结合使用。它演示了如何启动 SSE 服务器、获取工具,然后使用新的 Agent 创建和调用模式来解决数学问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 import asyncioimport osfrom pathlib import Pathimport sysfrom langchain_openai import ChatOpenAIfrom langchain.agents import create_agentfrom langchain_mcp_adapters.client import MultiServerMCPClientasync def run_mcp_sse_new_agent_example (): server_process = None try : mcp_server_path = Path(__file__).parent / "mcp_math_server_sse.py" server_process = await asyncio.create_subprocess_exec( sys.executable, str (mcp_server_path), stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE, ) await asyncio.sleep(5 ) client = MultiServerMCPClient( { "math" : { "transport" : "sse" , "url" : "http://localhost:8000/sse" , }, } ) tools = await client.get_tools() llm = ChatOpenAI(model="deepseek-v3" , temperature=0 ) graph = create_agent( model=llm, tools=tools, system_prompt="你是一个可以使用工具的得力助手。 தயவுசெய்து கருவிகளைப் பயன்படுத்தவும்." , ) print ("正在调用 agent 回答一个数学问题..." ) inputs = {"messages" : [{"role" : "user" , "content" : "123 + 456 等于多少?" }]} async for chunk in graph.astream(inputs, stream_mode="updates" ): print (chunk) finally : if server_process and server_process.returncode is None : print ("\nTerminating server process..." ) server_process.terminate() await server_process.wait() elif server_process and server_process.returncode is not None : print (f"\nServer process exited with code: {server_process.returncode} " ) if server_process and server_process.stderr: stderr_output = await server_process.stderr.read() if stderr_output: print ("\nServer stderr output:" ) print (stderr_output.decode()) if __name__ == "__main__" : asyncio.run(run_mcp_sse_new_agent_example())
示例 4:使用 Langchain 1.0 create_agent 的 MCP Stdio 工具集成 此示例演示了如何将 MCP Stdio 服务器提供的工具与 Langchain 1.0 的 create_agent 函数结合使用。它展示了如何通过 stdio 客户端连接到服务器、获取工具,然后使用新的 Agent 创建和调用模式来解决数学问题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import asyncioimport osfrom pathlib import Pathfrom langchain_openai import ChatOpenAIfrom langchain.agents import create_agentfrom langchain_mcp_adapters.tools import load_mcp_toolsfrom mcp.client.stdio import stdio_clientfrom mcp import ClientSession, StdioServerParametersasync def run_mcp_stdio_new_agent_example (): mcp_server_path = Path(__file__).parent / "mcp_math_server_stdio.py" server_params = StdioServerParameters( command="python3" , args=[str (mcp_server_path)], ) 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) llm = ChatOpenAI(model="deepseek-v3" , temperature=0 ) graph = create_agent( model=llm, tools=tools, system_prompt="你是一个可以使用工具的得力助手。 தயவுசெய்து கருவிகளைப் பயன்படுத்தவும்." , ) print ("正在调用 agent 回答一个数学问题..." ) inputs = {"messages" : [{"role" : "user" , "content" : "123 + 456 等于多少?" }]} async for chunk in graph.astream(inputs, stream_mode="updates" ): print (chunk) if __name__ == "__main__" : asyncio.run(run_mcp_stdio_new_agent_example())