在构建基于大语言模型(LLM)的复杂应用时,开发者常常面临一个核心挑战:如何高效、可靠地管理不断增长的对话或文档上下文?传统的上下文拼接方法不仅容易触及模型的令牌限制,还可能导致关键信息丢失或成本激增。Model Context Protocol (MCP) 的出现,为解决这一难题提供了标准化的思路。而当 MCP 遇上强大的 AI 应用编排框架 LangChain 时,又能碰撞出怎样的火花?本文将带你从零开始,深入探索 LangChain 接入 MCP 的完整流程。
什么是 MCP?为何需要它?
MCP (Model Context Protocol) 是一个开放的协议,旨在为大语言模型应用提供标准化的上下文管理接口。它的核心思想是将“上下文管理”作为一个独立的服务层,与具体的模型推理逻辑解耦。
MCP 的核心优势:
- 标准化:为不同的模型提供商(如 OpenAI, Anthropic, Cohere)提供统一的上下文操作接口。
- 高效性:通过智能的上下文压缩、摘要、优先级排序和向量检索等技术,在有限的令牌窗口内保留最相关的信息。
- 可观测性:提供对上下文使用情况的清晰洞察,便于调试和优化。
- 成本控制:通过减少不必要的令牌使用,直接降低 API 调用成本。
对于 LangChain 开发者而言,集成 MCP 意味着可以将繁琐的上下文窗口管理、历史消息处理等“脏活累活”外包给专业的 MCP 服务器,从而更专注于应用本身的业务逻辑和链式编排。
LangChain 与 MCP 集成的典型场景
在实际项目中,LangChain + MCP 的组合大有用武之地:
- 长文档问答系统:处理远超模型上下文长度的 PDF、研究报告,MCP 可以动态检索最相关的片段供 LLM 参考。
- 多轮复杂对话助手:在持续的对话中,智能地维护对话历史,总结过往回合,确保模型始终拥有“记忆”。
- Agent 的长期记忆:为 LangChain Agent 提供持久的、可查询的记忆存储,使其在多次运行中都能记住关键信息。
- 降低 API 调用成本:通过压缩冗余或次要的上下文,确保每次请求的令牌数都在最优范围内。
实战:一步步将 MCP 接入 LangChain
下面我们将通过一个完整的示例,演示如何搭建一个简单的 MCP 服务器,并在 LangChain 链中使用它。
步骤 1:环境准备与依赖安装
首先,确保你已安装 Python 3.8+。然后安装必要的库。我们将使用 mcp 库来创建服务器,并使用 LangChain 的社区集成包。
pip install langchain langchain-community mcp openai
步骤 2:创建一个简单的 MCP 服务器
MCP 服务器负责实际的上下文管理逻辑。我们创建一个名为 simple_mcp_server.py 的文件。
# simple_mcp_server.py
import asyncio
from typing import List, Optional
from mcp import Server, ClientSession
from mcp.shared.models import ContextItem, ListContextItemsResult
class SimpleContextManager:
"""一个简单的内存上下文管理器示例"""
def __init__(self):
self.contexts: List[ContextItem] = []
async def list_items(self) -> ListContextItemsResult:
"""列出所有上下文项"""
return ListContextItemsResult(items=self.contexts)
async def add_item(self, item: ContextItem):
"""添加上下文项(这里实现简单的去重)"""
# 简单示例:如果存在同名的项,则替换内容
for i, ctx in enumerate(self.contexts):
if ctx.name == item.name:
self.contexts[i] = item
return
self.contexts.append(item)
async def get_relevant_context(self, query: str, limit: int = 2) -> List[ContextItem]:
"""根据查询返回最相关的上下文(这里实现简单的关键词匹配)"""
# 这是一个非常简化的“检索”逻辑。生产环境应使用向量数据库。
relevant = []
query_lower = query.lower()
for ctx in self.contexts:
if query_lower in ctx.content.lower():
relevant.append(ctx)
if len(relevant) >= limit:
break
return relevant
# 创建 MCP 服务器实例
server = Server()
context_manager = SimpleContextManager()
@server.list_context_items()
async def handle_list_items(session: ClientSession) -> ListContextItemsResult:
return await context_manager.list_items()
@server.add_context_item()
async def handle_add_item(session: ClientSession, item: ContextItem) -> None:
await context_manager.add_item(item)
@server.get_context()
async def handle_get_context(session: ClientSession, query: str) -> List[ContextItem]:
# 在实际协议中,可能需要更复杂的请求体,这里做了简化
return await context_manager.get_relevant_context(query)
async def main():
# 启动服务器,监听本地端口 8000
async with await server.run_tcp_server("localhost", 8000) as server_handle:
print("MCP 服务器已在 localhost:8000 启动")
await server_handle.serve_forever()
if __name__ == "__main__":
asyncio.run(main())
步骤 3:在 LangChain 中创建 MCP 工具并集成到链中
现在,我们在另一个文件中创建 LangChain 应用,并通过 MCPClient 连接到我们刚创建的服务器。
# langchain_mcp_client.py
import asyncio
from langchain.agents import AgentExecutor, create_tool_calling_agent
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
from langchain_community.tools.mcp import MCPClient, create_mcp_tool
async def main():
# 1. 初始化 MCP 客户端,连接到我们的服务器
# 注意:`langchain-community` 中的 MCP 集成可能仍在演进,以下为示例性代码。
# 实际使用时请查阅最新文档。
async with MCPClient(server_url="http://localhost:8000") as client:
# 2. 基于 MCP 客户端的能力创建 LangChain Tool
# 假设我们的服务器提供了 `add_context` 和 `query_context` 工具
tools = []
# 创建“添加上下文”的工具
add_context_tool = create_mcp_tool(
client,
tool_name="add_knowledge",
description="添加一段知识或信息到上下文库中。输入应为要存储的文本内容。"
)
tools.append(add_context_tool)
# 创建“查询上下文”的工具
query_context_tool = create_mcp_tool(
client,
tool_name="search_knowledge",
description="从上下文库中搜索与问题相关的知识。输入应为你的问题。"
)
tools.append(query_context_tool)
# 3. 初始化 LLM
llm = ChatOpenAI(model="gpt-4o", temperature=0)
# 4. 创建提示词模板
prompt = ChatPromptTemplate.from_messages([
("system", "你是一个拥有外部知识库的助手。你可以使用工具来存储或查找信息。在回答用户问题时,请先尝试从知识库中搜索相关信息。"),
("placeholder", "{chat_history}"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
# 5. 创建 Agent 和执行器
agent = create_tool_calling_agent(llm=llm, tools=tools, prompt=prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
# 6. 运行示例对话
print("=== 示例 1:存储信息 ===")
result1 = await agent_executor.ainvoke({
"input": "请记住,我们公司的产品‘AI助手’的核心优势是实时翻译和代码生成。",
"chat_history": []
})
print(f"结果: {result1['output']}\n")
print("=== 示例 2:基于存储的信息回答问题 ===")
result2 = await agent_executor.ainvoke({
"input": "你们公司的‘AI助手’有什么特点?",
"chat_history": [] # 在实际多轮对话中,这里应包含历史消息
})
print(f"结果: {result2['output']}")
if __name__ == "__main__":
asyncio.run(main())
运行步骤:
- 在终端 A 运行
python simple_mcp_server.py,启动 MCP 服务器。 - 在终端 B 运行
python langchain_mcp_client.py,启动 LangChain 客户端并与之交互。
常见问题与解决方案
- 连接失败:确保 MCP 服务器地址和端口正确,且防火墙未阻止连接。检查
langchain-community中MCPClient的实际参数。 - 协议不匹配:MCP 协议本身可能更新。确保你使用的
mcp库和 LangChain 集成包的版本兼容。关注 LangChain 官方文档和langchain-community的更新。 - 性能瓶颈:示例中的内存存储和简单关键词检索不适合生产环境。对于生产级应用,应将 MCP 服务器中的
SimpleContextManager替换为使用向量数据库(如 Chroma, Pinecone, Weaviate) 的检索器,并实现更智能的上下文压缩算法。 - 错误处理:在生产代码中,务必为 MCP 客户端的调用添加完善的错误处理(try-catch)和重试逻辑。
最佳实践建议
- 生产级 MCP 服务器:使用成熟的框架(如 FastMCP)或云服务来部署高性能、可扩展的 MCP 服务器,而不是自建简易版本。
- 上下文策略:在 MCP 服务器中定义清晰的上下文管理策略,例如:不同来源(对话历史、文档、网络搜索)的优先级、摘要的触发条件、过期信息的清理规则。
- 与 LangChain 生态结合:除了创建 Tool,还可以探索将 MCP 作为
BaseRetriever或BaseMemory的实现,使其能更无缝地融入现有的 LangChain 链(RAG)或 Agent 模式中。 - 监控与评估:记录每次上下文检索的结果和使用的令牌数,评估 MCP 策略的有效性,并持续优化。
总结
通过本文的探索,我们看到了 LangChain 与 MCP 结合的巨大潜力。MCP 将上下文管理这一复杂任务标准化和外部化,而 LangChain 则以其强大的编排能力,轻松地将这种标准化服务集成到复杂的 AI 应用流水线中。从简单的内存服务器到基于向量数据库的智能检索,MCP 的灵活性为开发者提供了从原型到生产的不同选择。
尽管目前 LangChain 对 MCP 的原生支持仍在社区集成阶段,但其代表的方向非常明确:专业化分工和标准化接口是构建复杂、可靠 AI 应用的未来。现在就开始尝试将 MCP 接入你的下一个 LangChain 项目,为你的大语言模型应用装上高效、智能的“记忆中枢”吧。