如何使用LangChain创建MCP客户端服务器

如何使用LangChain创建MCP客户端服务器

人工智能和大型语言模型 (LLM) 的世界瞬息万变。整合外部工具和实时数据对于构建真正强大的应用程序至关重要。模型上下文协议(MCP)提供了弥合这一差距的标准方法。本教学指南为使用 LangChain 创建 MCP 客户端服务器提供了清晰易懂的新手指南。了解 MCP 客户端服务器架构有助于构建强大的人工智能代理。我们将介绍一些基本知识,包括什么是 MCP 服务器功能,并提供一个使用 LangChain 的实用 MCP 客户端服务器示例。

了解模型上下文协议(MCP)

模型上下文协议(MCP)

Source: Link

那么,MCP 服务器和客户端交互是怎么回事?模型上下文协议(MCP)是一个开放标准系统。Anthropic 开发该系统是为了将 LLM 与外部工具和数据源有效连接起来。它采用结构化和可重复使用的方法。MCP 可帮助人工智能模型与不同系统对话。这使它们能够访问当前信息,并完成超出其初始训练的任务。将其视为人工智能与外部世界之间的通用翻译器,构成了 MCP 客户端服务器架构的核心。

MCP的主要特点

MCP 具有以下几个重要特点:

  1. 标准化集成:MCP 提供了一种单一、一致的方式,将 LLM 与许多工具和数据源连接起来。这样就不需要为每个连接编写独特的代码。它简化了使用 LangChain 设置 MCP 客户端服务器的过程。
  2. 上下文管理:该协议可确保人工智能模型在多个步骤中跟踪对话上下文。这可以防止在任务需要多次交互时丢失重要信息。
  3. 安全和隔离:MCP 包括强大的安全措施。它严格控制访问权限,并使用权限边界将服务器连接分开。这确保了客户端和服务器之间的安全通信。

MCP在基于LLM的应用中的作用

LLM 应用程序经常需要外部数据。它们可能需要查询数据库、获取文档或使用网络 API。MCP 是一个重要的中间层。它能让模型与这些外部资源顺利交互,而无需手动操作。使用 LangChain 的 MCP 客户端服务器,开发人员可以构建更智能的人工智能代理。这些代理能力更强、工作速度更快,并能在定义明确的 MCP 客户端服务器架构内安全运行。这种设置是高级人工智能助手的基础。现在,让我们来看看实施部分。

设置环境

在使用 LangChain 构建 MCP 客户端服务器之前,我们先来准备一下环境。您需要这些物品:

  • Python 3.11 或更新版本。
  • 设置新的虚拟环境(可选)
  • 一个 API 密钥(例如 OpenAI 或 Groq,取决于您选择的模式)。
  • 特定的 Python 库:langchain-mcp-adapterslanggraph 和您选择的 LLM 库(如 langchain-openai langchain groq)。

使用 pip 安装所需的库。打开终端或命令提示符并运行:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
pip install langchain-mcp-adapters langgraph langchain-groq # Or langchain-openai
pip install langchain-mcp-adapters langgraph langchain-groq # Or langchain-openai
pip install langchain-mcp-adapters langgraph langchain-groq # Or langchain-openai

确保已准备好正确的 Python 版本和必要的密钥。

构建MCP服务器

MCP 服务器的任务是提供客户端可以使用的工具。在使用 langchain 的 MCP 客户端服务器示例中,我们将构建一个简单的服务器。该服务器将处理基本的数学运算以及复杂的天气 api,以获取城市的天气详细信息。从这里开始了解 MCP 服务器的功能。

创建一个名为 mcp_server.py 的 Python 文件:

1. 让我们导入所需的库

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
import math
import requests
from mcp.server.fastmcp import FastMCP
import math import requests from mcp.server.fastmcp import FastMCP
import math
import requests
from mcp.server.fastmcp import FastMCP

2. 初始化 FastMCP 对象

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mcp= FastMCP("Math")
mcp= FastMCP("Math")
mcp= FastMCP("Math")

3. 让我们来定义数学工具

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@mcp.tool()
def add(a: int, b: int) -> int:
print(f"Server received add request: {a}, {b}")
return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
print(f"Server received multiply request: {a}, {b}")
return a * b
@mcp.tool()
def sine(a: int) -> int:
print(f"Server received sine request: {a}")
return math.sin(a)
@mcp.tool() def add(a: int, b: int) -> int: print(f"Server received add request: {a}, {b}") return a + b @mcp.tool() def multiply(a: int, b: int) -> int: print(f"Server received multiply request: {a}, {b}") return a * b @mcp.tool() def sine(a: int) -> int: print(f"Server received sine request: {a}") return math.sin(a)
@mcp.tool()
def add(a: int, b: int) -> int:
   print(f"Server received add request: {a}, {b}")
   return a + b
@mcp.tool()
def multiply(a: int, b: int) -> int:
   print(f"Server received multiply request: {a}, {b}")
   return a * b
@mcp.tool()
def sine(a: int) -> int:
   print(f"Server received sine request: {a}")
   return math.sin(a)

4. 现在,让我们定义一个天气工具,确保您已从这里获取了 API。

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
WEATHER_API_KEY = "YOUR_API_KEY"
@mcp.tool()
def get_weather(city: str) -> dict:
"""
Fetch current weather for a given city using WeatherAPI.com.
Returns a dictionary with city, temperature (C), and condition.
"""
print(f"Server received weather request: {city}")
url = f"http://api.weatherapi.com/v1/current.json?key={WEATHER_API_KEY}&q={city}"
response = requests.get(url)
if response.status_code != 200:
return {"error": f"Failed to fetch weather for {city}."}
data = response.json()
return {
"city": data["location"]["name"],
"region": data["location"]["region"],
"country": data["location"]["country"],
"temperature_C": data["current"]["temp_c"],
"condition": data["current"]["condition"]["text"]
}
5. Now, instantiate the mcp server
if __name__ =="__main__":
print("Starting MCP Server....")
mcp.run(transport="stdio")
WEATHER_API_KEY = "YOUR_API_KEY" @mcp.tool() def get_weather(city: str) -> dict: """ Fetch current weather for a given city using WeatherAPI.com. Returns a dictionary with city, temperature (C), and condition. """ print(f"Server received weather request: {city}") url = f"http://api.weatherapi.com/v1/current.json?key={WEATHER_API_KEY}&q={city}" response = requests.get(url) if response.status_code != 200: return {"error": f"Failed to fetch weather for {city}."} data = response.json() return { "city": data["location"]["name"], "region": data["location"]["region"], "country": data["location"]["country"], "temperature_C": data["current"]["temp_c"], "condition": data["current"]["condition"]["text"] } 5. Now, instantiate the mcp server if __name__ =="__main__": print("Starting MCP Server....") mcp.run(transport="stdio")
WEATHER_API_KEY = "YOUR_API_KEY"
@mcp.tool()
def get_weather(city: str) -> dict:
   """
   Fetch current weather for a given city using WeatherAPI.com.
   Returns a dictionary with city, temperature (C), and condition.
   """
   print(f"Server received weather request: {city}")
   url = f"http://api.weatherapi.com/v1/current.json?key={WEATHER_API_KEY}&q={city}"
   response = requests.get(url)
   if response.status_code != 200:
       return {"error": f"Failed to fetch weather for {city}."}
   data = response.json()
   return {
       "city": data["location"]["name"],
       "region": data["location"]["region"],
       "country": data["location"]["country"],
       "temperature_C": data["current"]["temp_c"],
       "condition": data["current"]["condition"]["text"]
   }
   5. Now, instantiate the mcp server 
if __name__ =="__main__":
   print("Starting MCP Server....")
   mcp.run(transport="stdio")

说明:

该脚本设置了一个名为“Math”的简单 MCP 服务器。它使用 FastMCP 定义了四个工具:加法、乘法、正弦和由 @mcp.tool() 装饰器标记的 get_weather 。类型提示告诉 MCP 有关预期输入和输出的信息。直接执行时,服务器使用标准输入/输出(stdio)进行通信。以上演示了 MCP 服务器的基本设置。

运行服务器:打开终端,导航到包含 mcp_server.py 的目录。然后运行

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
python mcp_server.py
python mcp_server.py
python mcp_server.py

服务器启动时应无任何警告。该服务器将持续运行,以便客户端访问工具

输出:

mcp服务器输出

构建MCP客户端

客户端连接到服务器,发送请求(如要求代理执行计算并获取实时天气),并处理响应。这演示了使用 LangChain 的 MCP 客户端服务器的客户端。

创建一个名为 client.py 的 Python 文件:

  1. 首先导入必要的库
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# client.py
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_groq import ChatGroq
from langchain_openai import ChatOpenAI
import asyncio
import os
# client.py from mcp import ClientSession, StdioServerParameters from mcp.client.stdio import stdio_client from langchain_mcp_adapters.tools import load_mcp_tools from langgraph.prebuilt import create_react_agent from langchain_groq import ChatGroq from langchain_openai import ChatOpenAI import asyncio import os
# client.py
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from langchain_groq import ChatGroq
from langchain_openai import ChatOpenAI
import asyncio
import os
  1. 为 LLM(Groq 或 OpenAI)设置 API 密钥,并初始化 LLM 模型
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Set your API key (replace with your actual key or use environment variables)
GROQ_API_KEY = "YOUR_GROQ_API_KEY" # Replace with your key
os.environ["GROQ_API_KEY"] = GROQ_API_KEY
# OPENAI_API_KEY = "YOUR_OPENAI_API_KEY"
# os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
# Initialize the LLM model
model = ChatGroq(model="llama3-8b-8192", temperature=0)
# model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# Set your API key (replace with your actual key or use environment variables) GROQ_API_KEY = "YOUR_GROQ_API_KEY" # Replace with your key os.environ["GROQ_API_KEY"] = GROQ_API_KEY # OPENAI_API_KEY = "YOUR_OPENAI_API_KEY" # os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY # Initialize the LLM model model = ChatGroq(model="llama3-8b-8192", temperature=0) # model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# Set your API key (replace with your actual key or use environment variables)
GROQ_API_KEY = "YOUR_GROQ_API_KEY" # Replace with your key
os.environ["GROQ_API_KEY"] = GROQ_API_KEY
# OPENAI_API_KEY = "YOUR_OPENAI_API_KEY"
# os.environ["OPENAI_API_KEY"] = OPENAI_API_KEY
# Initialize the LLM model
model = ChatGroq(model="llama3-8b-8192", temperature=0)
# model = ChatOpenAI(model="gpt-4o-mini", temperature=0)
  1. 现在,定义参数以启动 MCP 服务器进程。
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
server_params = StdioServerParameters(
command="python", # Command to execute
args=["mcp_server.py"] # Arguments for the command (our server script)
)
server_params = StdioServerParameters( command="python", # Command to execute args=["mcp_server.py"] # Arguments for the command (our server script) )
server_params = StdioServerParameters(
   command="python",      # Command to execute
   args=["mcp_server.py"] # Arguments for the command (our server script)
)
  1. 让我们定义运行代理交互的异步函数
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
async def run_agent():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
print("MCP Session Initialized.")
tools = await load_mcp_tools(session)
print(f"Loaded Tools: {[tool.name for tool in tools]}")
agent = create_react_agent(model, tools)
print("ReAct Agent Created.")
print(f"Invoking agent with query")
response = await agent.ainvoke({
"messages": [("user", "What is (7+9)x17, then give me sine of the output recieved and then tell me What's the weather in Torronto, Canada?")]
})
print("Agent invocation complete.")
# Return the content of the last message (usually the agent's final answer)
return response["messages"][-1].content
async def run_agent(): async with stdio_client(server_params) as (read, write): async with ClientSession(read, write) as session: await session.initialize() print("MCP Session Initialized.") tools = await load_mcp_tools(session) print(f"Loaded Tools: {[tool.name for tool in tools]}") agent = create_react_agent(model, tools) print("ReAct Agent Created.") print(f"Invoking agent with query") response = await agent.ainvoke({ "messages": [("user", "What is (7+9)x17, then give me sine of the output recieved and then tell me What's the weather in Torronto, Canada?")] }) print("Agent invocation complete.") # Return the content of the last message (usually the agent's final answer) return response["messages"][-1].content
async def run_agent():
   async with stdio_client(server_params) as (read, write):
       async with ClientSession(read, write) as session:
           await session.initialize()
           print("MCP Session Initialized.")
           tools = await load_mcp_tools(session)
           print(f"Loaded Tools: {[tool.name for tool in tools]}")
           agent = create_react_agent(model, tools)
           print("ReAct Agent Created.")
           print(f"Invoking agent with query")
           response = await agent.ainvoke({
               "messages": [("user", "What is (7+9)x17, then give me sine of the output recieved and then tell me What's the weather in Torronto, Canada?")]
           })
           print("Agent invocation complete.")
           # Return the content of the last message (usually the agent's final answer)
           return response["messages"][-1].content
  1. 现在,运行此函数并在终端上等待结果
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
# Standard Python entry point check
if __name__ == "__main__":
# Run the asynchronous run_agent function and wait for the result
print("Starting MCP Client...")
result = asyncio.run(run_agent())
print("\nAgent Final Response:")
print(result)
# Standard Python entry point check if __name__ == "__main__": # Run the asynchronous run_agent function and wait for the result print("Starting MCP Client...") result = asyncio.run(run_agent()) print("\nAgent Final Response:") print(result)
# Standard Python entry point check
if __name__ == "__main__":
   # Run the asynchronous run_agent function and wait for the result
   print("Starting MCP Client...")
   result = asyncio.run(run_agent())
   print("\nAgent Final Response:")
   print(result)

说明:

该客户端脚本用于配置 LLM(此处使用 ChatGroq;记得设置 API 密钥)。它使用 StdioServerParameters 定义了如何启动服务器。run_agent 函数通过 stdio_client 连接到服务器,创建一个 ClientSession 并将其初始化。 load_mcp_tool 为 LangChain 获取服务器工具。create_react_agent 使用 LLM 和工具处理用户查询。最后,agent.ainvoke 发送查询,让代理可能使用服务器工具找到答案。下面是一个使用 langchain 的完整 MCP 客户端服务器示例。

运行客户端:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
python client.py
python client.py
python client.py

输出:

mcp客户端输出

我们可以看到,客户端启动服务器进程、初始化连接、加载工具、调用代理并打印通过调用服务器的添加工具(也称为天气 api)和检索实时天气数据计算出的最终答案。

实际应用

使用 LangChain 的 MCP 客户端服务器为创建复杂的人工智能代理提供了多种可能性。一些实际应用包括

  • LLM 独立性:通过使用 Langchain,我们现在可以将任何 LLM 与 MCP 集成。以前我们只能
  • 数据检索:代理可以通过 MCP 连接到数据库服务器,获取实时客户数据或查询内部知识库。
  • 文档处理:代理可以使用 MCP 工具与文档管理系统进行交互,从而可以根据用户请求汇总、提取信息或更新文档。
  • 任务自动化:通过 MCP 服务器与各种业务系统(如客户关系管理系统、日历或项目管理工具)集成,自动执行日常任务,如安排会议或更新销售记录。MCP 客户端服务器架构支持这些复杂的工作流程。

最佳实践

在使用 LangChain 构建 MCP 客户端服务器时,请遵循良好实践,以获得更好的效果:

  • 采用模块化设计,为不同的任务创建特定的工具,并将服务器逻辑与客户端逻辑分开。
  • 在服务器工具和客户端代理中实施强大的错误处理功能,以便系统能从容应对故障。
  • 通过使用 MCP 的访问控制和权限边界等功能,优先考虑安全性,尤其是当服务器处理敏感数据时。
  • 为 MCP 工具提供清晰的说明和文档;这有助于代理了解其目的和用法。

常见陷阱

开发系统时要注意潜在问题。如果代理框架不能正确管理状态,复杂对话中可能会出现上下文丢失,从而导致错误。长期运行的 MCP 服务器资源管理不善可能会导致内存泄漏或性能下降,因此要谨慎处理连接和文件句柄。确保客户端和服务器传输机制的兼容性,因为不匹配(如一个使用 stdio 而另一个期待 HTTP)会阻碍通信。最后,注意工具模式的不匹配,服务器工具的定义与客户端的期望不一致时,会阻碍工具的执行。解决这些问题可以加强使用 LangChain 实现的 MCP 客户端服务器。

小结

利用 LangChain 的模型上下文协议为构建高级人工智能代理提供了一种功能强大的标准化方法。通过使用 LangChain 创建 MCP 客户端服务器,您可以让 LLM 安全有效地与外部工具和数据源进行交互。本指南使用 LangChain 示例了一个基本的 MCP 客户端服务器,概述了 MCP 客户端服务器的核心架构以及 MCP 服务器的功能。这种方法可简化集成、提高代理能力并确保可靠运行,从而为更智能、更有用的人工智能应用铺平道路。

评论留言