在当前AI工程化快速发展的背景下,多Agent协作系统(Multi-Agent System, MAS) 已成为企业级AI应用的核心架构。而要让这些智能体真正具备“感知-决策-执行”的闭环能力,MCP(Model Communication Protocol)协议扮演着至关重要的角色——它统一了大模型与外部工具、数据源之间的通信标准。
尤其当我们在集成第三方流式API(如OpenAI GPT、DeepSeek等支持SSE流输出的模型)到MCP Server时,既要保证低延迟的实时交互体验,又要确保协议兼容性和错误处理机制健全。本文将手把手带你完成这一关键集成,并附上可运行的代码示例,助你迈出构建商业级多Agent系统的坚实一步。
一、为什么需要流式接入MCP?
传统同步调用LLM API存在明显瓶颈:用户需等待完整响应后才能看到结果,体验割裂。而流式输出(Streaming) 能逐字返回token,实现“边思考边输出”,极大提升交互流畅度。
但在MCP架构中,Agent通过MCP Server调用外部工具或模型,若直接使用非流式接口,会阻塞整个协作流程。因此,将流式API正确封装为MCP工具,是实现高性能多Agent系统的关键。
核心目标:让MCP Server能接收流式LLM响应,并将其透传给调用Agent,同时保持协议一致性与错误恢复能力。
二、技术前提:MCP协议简述
MCP是一种轻量级、基于JSON-RPC的通信协议,定义了LLM如何发现、调用和接收外部工具的响应。一个典型的MCP工具注册如下:
{
"name": "streaming_llm_chat",
"description": "调用支持流式的LLM进行对话",
"parameters": {
"type": "object",
"properties": {
"messages": { "type": "array" },
"model": { "type": "string" }
}
}
}
MCP Server需暴露 /mcp 端点供LLM调用,并按规范返回 result 或 error。
三、流式API接入MCP的三大挑战
- 协议不匹配:MCP默认为请求-响应模型,而流式API是长连接。
- 上下文管理:如何将流式chunk拼接成完整逻辑单元?
- 错误重试与超时:网络中断或token限流时如何优雅降级?
四、解决方案与代码示例(基于FastAPI + OpenAI SDK)
我们以 OpenAI 的 chat.completions.create(stream=True) 为例,将其封装为MCP工具。
步骤1:初始化FastAPI项目并安装依赖
pip install fastapi uvicorn openai pydantic python-dotenv
步骤2:创建MCP Server端点(支持流式透传)
注意:MCP本身不原生支持流,但我们可通过“模拟流”方式——将每个chunk立即推送给前端(或内部Agent消息队列),并在MCP响应中标记为“流开始/中/结束”。
# mcp_server.py
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
import asyncio
from openai import AsyncOpenAI
import os
from dotenv import load_dotenv
load_dotenv()
app = FastAPI()
client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))
@app.post("/mcp/streaming_llm")
async def mcp_streaming_llm(request: Request):
data = await request.json()
messages = data.get("messages", [])
model = data.get("model", "gpt-4o")
async def event_stream():
try:
stream = await client.chat.completions.create(
model=model,
messages=messages,
stream=True
)
async for chunk in stream:
content = chunk.choices[0].delta.content
if content:
# 模拟MCP流式事件格式
yield f"data: {content}\n\n"
yield "data: [DONE]\n\n"
except Exception as e:
yield f"data: {{\"error\": \"{str(e)}\"}}\n\n"
return StreamingResponse(event_stream(), media_type="text/event-stream")
步骤3:在Agent中调用该MCP工具
假设你的Agent框架支持自定义工具调用(如LangChain或自研调度器),注册工具如下:
tools = [
{
"type": "function",
"function": {
"name": "streaming_llm_chat",
"description": "流式调用LLM进行对话",
"parameters": {"messages": [...], "model": "gpt-4o"}
}
}
]
Agent在ReAct循环中触发此工具,MCP Server返回SSE流,前端或下游Agent实时渲染。
五、关键注意事项
- 不要阻塞事件循环:务必使用 AsyncOpenAI 和 async/await。
- 设置超时与重试:在生产环境中加入 timeout=30s 和指数退避重试。
- 日志与监控:记录每个流会话ID,便于追踪问题。
- 前端配合:使用 EventSource 或 WebSocket 接收流数据。
// 前端示例(浏览器)
const eventSource = new EventSource("/mcp/streaming_llm");
eventSource.onmessage = (e) => {
if (e.data === "[DONE]") return;
document.getElementById("output").innerText += e.data;
};
上面的示例成功打通了“流式LLM → MCP Server → Agent”的链路。
但现实中的多Agent系统远不止于此:
- 如何让多个Agent通过 A2A(Agent-to-Agent)协议 自主协商任务?
- 如何将 Jina.ai 向量搜索、Browser-Use 浏览器自动化、Code Interpreter 等工具统一注册到MCP?
- 如何设计可插拔的工具网关,支持动态加载新能力?
- 如何用 DDD(领域驱动设计) 管理复杂的Agent业务逻辑?
- 如何将整套系统打包为一个可演示、可交付的产品?
如果你正站在“能跑Demo”和“能交付产品”的分岔路口,那么,这些问题都是你需要思考的。
希望本文为你打开了第一扇门。而门后的世界,你继续探索。
共同学习,写下你的评论
评论加载中...
作者其他优质文章