MCP 2026:AI Agent 互联协议的范式革命——从工具调用到生产级基础设施的深度解析
引言:AI Agent 互联的「USB-C 时刻」
2026年,AI Agent 领域最值得关注的变革,不是某个新模型的发布,不是某个新框架的上线,而是一个底层协议的演进——Model Context Protocol(MCP)在2026年7月28日发布了史上最大规模的修订版。
MCP 不是什么新概念。它由 Anthropic 在2024年提出,定位是「让大模型连接外部工具和数据源的开放标准」。如果说2024年它还只是一个让 Claude 能够「调用工具」的连接协议,那么2026年的今天,它正在成为可规模部署、全链路可治理、调用全流程可追溯的生产级智能体基础设施。
理解这其中的转变,对每一个关注 AI Agent 发展的开发者来说,都至关重要。它关乎我们如何设计 AI 应用、如何构建 Agent 系统、如何在生产环境中安全可控地运行 AI。这不只是协议层面的改进,它在重新定义「AI 应用」和「外部世界」之间的边界。
本文将从协议架构、2026-07-28 核心变更、生产级工程实践、性能与安全四大维度,深度解析这场变革。
一、背景:为什么 AI Agent 需要标准化互联协议
1.1 从「能聊」到「能做事」:Agent 的本质跃迁
2023-2024年,大语言模型的突破让 AI 从「聊天机器人」进化为「能执行任务的智能体」。但真正让 Agent 变得有用的,不是模型的对话能力,而是它能触达外部世界的能力——读文件、发邮件、查数据库、调用 API、控制智能家居……
然而,当开发者想让同一个 Agent 连接不同的外部工具时,问题就来了:
没有统一协议的时代,每个工具都要单独适配。
你要让 Claude 调用 GitHub API,需要写一套定制代码;让同样的 Claude 调用内部知识库,需要再写一套。数据格式不同、认证方式不同、错误处理不同——每增加一个工具,就增加一层定制化开发成本。
MCP 的核心愿景,就是解决这个问题:为 AI 和外部工具之间建立统一的「语言」。
就像 USB-C 接口统一了设备与计算机的连接方式,MCP 试图统一 AI 应用与外部工具的连接方式。一旦协议标准化,开发者就可以:
- 一次实现,到处运行:一个 MCP Server 实现,可以被任何兼容 MCP 的客户端使用
- 工具可插拔:像搭积木一样组合不同工具,而不需要修改核心应用代码
- 生态互联:Anthropic 的 Claude、Cursor、Cline,Vercel AI SDK,LangChain,LlamaIndex……所有支持 MCP 的工具共享同一套工具生态
1.2 MCP 的核心定位
MCP 的全称是 Model Context Protocol(模型上下文协议),它由 Anthropic 于2024年正式提出并开源。与其名字中的「Context」所暗示的不止于「上下文管理」,MCP 的实际能力远超过传统意义的上下文窗口扩展:
- 工具调用(Tools):让 AI 执行外部函数调用
- 资源访问(Resources):让 AI 读取外部数据
- 提示模板(Prompts):标准化复用的高质量提示词
- 采样(Sampling):让服务器反向调用 AI(用于 AI 驱动的工具回调)
MCP 采用 Client-Server 架构:AI 应用(如 Claude Desktop、Cursor)充当 MCP Client,外部工具和数据源以 MCP Server 的形式暴露能力。Client 和 Server 之间通过 JSON-RPC 2.0 协议通信,支持 stdio(本地进程)和 Streamable HTTP(远程连接)两种传输方式。
1.3 现有生态一览
截至2026年7月,MCP 生态已相当丰富:
官方/知名 MCP Servers:
github— 操作 GitHub 仓库、PR、Issuesfilesystem— 访问本地文件系统brave-search— 网页搜索slack— 消息发送和读取postgres— PostgreSQL 数据库查询- AWS MCP Servers — 连接 AWS 各服务
国内 MCP 生态(2026年爆发):
- 企查查 MCP:企业工商、股权、司法数据
- 天眼查 MCP:商业数据查询
- MasterGo Magic MCP:设计稿 AI 分析
- 哔哩哔哩 MCP:视频内容搜索
开发框架支持:
- LangChain MCP Adapters
- LlamaIndex MCP Integration
- Microsoft Agent Framework MCP Integration
- Spring AI 2.0(Java 生态)
二、协议架构深度解析:MCP 如何让 AI 与外部世界对话
2.1 协议分层架构
MCP 协议可以理解为四层架构,每一层都有明确的职责:
┌─────────────────────────────────────────┐
│ MCP Client(AI 应用层) │
│ Claude Desktop / Cursor / Cline 等 │
├─────────────────────────────────────────┤
│ MCP Client SDK │
│ 连接管理 / 请求路由 / 响应解析 │
├─────────────────────────────────────────┤
│ Transport Layer(传输层) │
│ stdio / Streamable HTTP / SSE │
├─────────────────────────────────────────┤
│ MCP Server(工具服务层) │
│ 工具暴露 / 资源管理 / 权限控制 │
└─────────────────────────────────────────┘
2.2 通信协议:JSON-RPC 2.0 的精妙应用
MCP 使用 JSON-RPC 2.0 作为应用层协议。这是一个轻量级的远程过程调用协议,其设计哲学与 MCP 的需求高度契合:简单、宽松、可扩展。
协议消息类型:
// 请求示例:调用 GitHub 创建 Issue
{
"jsonrpc": "2.0",
"id": "req-001",
"method": "tools/call",
"params": {
"name": "create_issue",
"arguments": {
"owner": "anthropics",
"repo": "mcp",
"title": "Bug: Token refresh fails",
"body": "Steps to reproduce..."
}
}
}
// 成功响应
{
"jsonrpc": "2.0",
"id": "req-001",
"result": {
"content": [
{
"type": "text",
"text": "Issue #42 created successfully"
}
],
"isError": false
}
}
// 错误响应
{
"jsonrpc": "2.0",
"id": "req-001",
"error": {
"code": -32602,
"message": "Invalid params: 'body' exceeds maximum length",
"data": {
"field": "body",
"max_length": 65536
}
}
}
2.3 三类核心能力:Tools、Resources、Prompts
MCP 的核心抽象围绕三类能力展开:
(1)Tools(工具)—— AI 可以执行的动作
Tools 是 MCP 最核心的能力。它让 AI 能够「动手做事」,而不只是「动嘴说话」。
// MCP Server 暴露的工具定义示例
const server = new McpServer({
name: "enterprise-db",
version: "1.0.0"
});
// 定义一个查询工具
server.tool(
"query_orders",
"查询企业订单数据,支持时间范围和状态过滤",
{
customer_id: Schema.string("客户ID"),
start_date: Schema.string("开始日期 YYYY-MM-DD"),
end_date: Schema.string("结束日期 YYYY-MM-DD"),
status: Schema.enum(["pending", "paid", "shipped", "completed"])
},
async ({ customer_id, start_date, end_date, status }) => {
const orders = await db.queryOrders({
customerId: customer_id,
startDate: new Date(start_date),
endDate: new Date(end_date),
status
});
return {
content: [
{
type: "text",
text: JSON.stringify({
total: orders.length,
data: orders
}, null, 2)
}
]
};
}
);
(2)Resources(资源)—— AI 可以读取的数据
Resources 是只读数据源。它们与 Tools 的本质区别在于:Tools 执行动作(可能产生副作用),Resources 只提供数据(幂等、可缓存)。
// 暴露企业内部知识库
server.resource(
"kb://policies/returns",
"退货政策文档",
async (uri) => {
const policy = await knowledgeBase.getPolicy("returns");
return {
contents: [{
uri: uri.toString(),
mimeType: "text/markdown",
text: policy.content
}]
};
}
);
// 暴露数据库 schema 文档
server.resource(
"db://schema/orders",
"订单表结构文档",
async (uri) => {
const schema = await db.getTableSchema("orders");
return {
contents: [{
uri: uri.toString(),
mimeType: "application/json",
text: JSON.stringify(schema, null, 2)
}]
};
}
);
(3)Prompts(提示模板)—— 标准化的高质量提示
Prompts 允许 MCP Server 定义可复用的提示模板,确保 AI 在特定场景下使用最优的提示策略。
// 定义一个代码审查提示模板
server.prompt(
"security-code-review",
"执行安全相关的代码审查",
{
language: Schema.string("编程语言"),
focus_area: Schema.enum([
"sql-injection",
"xss",
"auth-bypass",
"data-exposure"
])
},
({ language, focus_area }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `请对以下 ${language} 代码进行安全审查,重点关注 ${focus_area} 相关漏洞。\n\n代码:\n${code}`
}
}]
})
);
2.4 传输层:stdio 与 Streamable HTTP
MCP 支持两种传输方式,各有适用场景:
stdio 模式(本地进程):
AI Client <---> MCP Server (同一台机器,通过 stdin/stdout 通信)
这种模式适合:
- 本地工具集成(如 Claude Desktop 连接本地文件系统、Git 仓库)
- 开发调试阶段
- 不需要网络安全的场景
Streamable HTTP 模式(远程连接):
AI Client <--HTTP/SSE--> MCP Gateway <---> MCP Server 集群
这种模式适合:
- 企业级部署(连接远程服务、数据库、内部系统)
- 需要负载均衡、高可用的场景
- 微服务架构中的工具服务化
2026-07-28 版本的重大更新之一,就是在 HTTP 传输模式上引入了无状态核心架构,这是从「会话绑定」到「请求自包含」的根本性转变。
三、2026-07-28 核心变更:从工具调用协议到生产级基础设施
3.1 变更总览:MCP 历史上最大的版本迭代
2026年5月,MCP 官方发布了 2026-07-28 规范候选版,官方将其定位为「协议推出以来规模最大的一次系统性修订」。这次更新涵盖无状态核心、能力发现、结构化交付、全链路追踪四大核心模块,配以授权安全、扩展插件、任务协作等配套体系。
这次升级的核心目标:推动 MCP 从「让 AI 会调工具」的连接协议,走向可规模运行、可治理、可追踪、可扩展的生产级基础设施。
3.2 变更一:无状态核心架构——消除会话绑定
旧版的问题:
旧版 MCP(尤其是远程 HTTP 模式)的协议设计中,Client 和 Server 之间需要维护一个会话(Session)。整个通信流程如下:
1. Client 发送 initialize 请求,Server 返回 Session ID
2. Client 在后续所有请求中携带 Mcp-Session-Id header
3. Server 依赖 Session 维护协议状态和上下文
这个设计在本地 stdio 模式下工作良好,但在远程部署中遇到了根本性问题:
- 水平扩展困难:所有请求必须路由到同一台服务器,因为服务器维护了会话状态
- 负载均衡受限:无法使用标准的 HTTP 负载均衡器(它们不理解 MCP Session)
- 故障恢复复杂:服务器重启会导致所有会话失效,Client 需要重新建立连接
- 部署不灵活:无法在 Kubernetes 等容器编排平台上弹性扩缩容
新版解决方案:
2026-07-28 版本彻底取消协议层的 Session 机制。每个请求都是自包含的——它携带完成处理所需的全部信息,不依赖任何服务器端状态。
# 旧版(会话绑定):每个请求携带 Session ID
# 请求头
headers = {
"Mcp-Session-Id": "sess-abc123",
"Content-Type": "application/json"
}
# 请求体
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {"name": "query_db", "arguments": {...}}
}
# 新版(无状态):请求完全自包含,无需 Session
headers = {
"Content-Type": "application/json"
# 不再需要 Mcp-Session-Id
}
# 请求体(携带完整上下文)
{
"jsonrpc": "2.0",
"id": 42,
"method": "tools/call",
"params": {
"name": "query_db",
"arguments": {...}
}
# 无需额外会话上下文,服务器完全无状态
}
工程含义:
无状态架构的引入,让 MCP Server 可以像普通的无状态 HTTP 服务一样部署和扩缩容:
# Kubernetes 部署示例:无状态 MCP Server
apiVersion: apps/v1
kind: Deployment
metadata:
name: enterprise-mcp-server
spec:
replicas: 10 # 可根据负载弹性调整
template:
spec:
containers:
- name: mcp-server
image: enterprise/mcp-server:latest
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: enterprise-mcp-server-svc
spec:
selector:
app: enterprise-mcp-server
ports:
- port: 80
targetPort: 8080
type: LoadBalancer # 标准云负载均衡器
---
# 使用 Kubernetes HPA 实现自动扩缩容
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: enterprise-mcp-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: enterprise-mcp-server
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
这样一来,MCP Server 可以:
- 任意水平扩展:新增 Pod 即可增加吞吐,不需要共享状态
- 零停机部署:滚动更新时,新旧版本可以同时运行
- 故障自动恢复:Pod 崩溃时,Kubernetes 自动重建,请求自动路由到健康实例
- 复用现有基础设施:不再需要自定义的会话亲和路由
3.3 变更二:能力发现与治理——从「列清单」到「可管控」
旧版的困境:
在旧版协议中,Client 获取工具列表的方式非常原始——Server 暴露一个固定的工具清单,Client 一次性拿到,然后自己决定用哪个。
当一个 MCP Server 只有5个工具时,这不是问题。但当 Server 扩展到50个、100个甚至更多工具时,问题就出现了:
- 工具选择不透明:Client 不理解每个工具的语义和边界
- 无缓存机制:每次请求都要重新获取工具清单
- 无治理能力:无法对工具进行分类、限流、权限控制
- 工具描述模糊:工具的定义往往是简短的自然语言描述,AI 难以准确理解使用边界
新版的能力发现体系:
2026-07-28 引入了完整的能力发现、路由和缓存语义体系:
// 新版 Server Capabilities 响应示例
{
"capabilities": {
"tools": {
"listChanged": true,
"supportsDynamicRegistration": true
},
"resources": {
"subscribe": true,
"listChanged": true
},
"discovery": {
"server_info": {
"name": "enterprise-data-mcp",
"version": "2.1.0",
"vendor": "enterprise-corp"
},
"capability_categories": [
{
"category": "customer_data",
"description": "客户数据查询",
"tools": ["query_customer", "get_customer_history", "list_customers"],
"cache_ttl_ms": 30000
},
{
"category": "order_management",
"description": "订单管理",
"tools": ["query_orders", "create_order", "update_order_status"],
"cache_ttl_ms": 10000
},
{
"category": "risk_analysis",
"description": "风险分析(需高级权限)",
"tools": ["calculate_risk_score", "run_fraud_detection"],
"required_scope": "risk_analysis",
"cache_ttl_ms": 5000
}
]
}
}
}
关键改进:
能力分类:工具不再只是平铺的清单,而是按业务领域分类。AI 可以理解「这个工具属于哪个业务范畴」。
语义缓存:每个能力类别有明确的 TTL(缓存时间)。在 TTL 内,Client 不需要重新获取工具清单,减少网络往返。
限流与权限:通过
required_scope字段声明工具所需的权限级别,Client 和网关可以在调用前就知道是否有权访问。变更通知:Server 可以通知 Client 工具集发生了变化(
listChanged: true),Client 自动刷新工具清单。
网关层的治理能力:
# MCP Gateway 层面的工具治理示例
class MCPToolGateway:
def __init__(self):
self.tool_registry = ToolRegistry()
self.rate_limiter = TokenBucketRateLimiter(rate=100, capacity=200)
self.access_control = RBACEngine()
async def handle_tool_call(self, request: ToolCallRequest) -> ToolCallResponse:
# 1. 能力发现:验证工具是否存在
tool = self.tool_registry.get(request.tool_name)
if not tool:
raise ToolNotFoundError(request.tool_name)
# 2. 权限检查
if not self.access_control.can_access(request.caller_id, tool):
raise AccessDeniedError(f"Caller {request.caller_id} lacks access to {tool.name}")
# 3. 限流检查
if not self.rate_limiter.allow(request.caller_id):
raise RateLimitExceededError(f"Rate limit exceeded for {request.caller_id}")
# 4. 审计日志
await self.audit_log.record(
caller=request.caller_id,
tool=request.tool_name,
arguments=request.arguments,
timestamp=datetime.utcnow()
)
# 5. 执行工具
result = await tool.execute(request.arguments)
# 6. 结果结构化 + 追踪上下文
return ToolCallResponse(
result=result,
trace_id=self.audit_log.current_trace_id,
trace_context=W3CTraceContext.extract()
)
3.4 变更三:结构化交付——从「文字答案」到「可验证数据」
旧版的结果交付方式:
旧版 MCP 的工具返回结果以自然语言文本为主:
{
"content": [
{
"type": "text",
"text": "客户 A 公司有 3 条未处理的订单,总金额 ¥125,000。最近一次下单是 2026-07-15。"
}
]
}
这种方式有两个严重问题:
- 下游系统无法自动处理:业务系统无法解析这段自然语言文本
- 无法验证 AI 的解读是否正确:同样的数据,不同的 AI 可能给出不同的解读
新版完整 JSON Schema 2020-12 支持:
2026-07-28 版本将 Tool 的输入和输出 Schema 升级到完整的 JSON Schema 2020-12 规范,允许更完整地表达组合、条件和引用关系。
// 新版结构化输出示例:订单查询结果
{
"schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"query_info": {
"type": "object",
"description": "查询元信息",
"properties": {
"customer_id": { "type": "string", "description": "客户标识" },
"query_time": { "type": "string", "format": "date-time" },
"data_time_range": {
"type": "object",
"properties": {
"start": { "type": "string", "format": "date" },
"end": { "type": "string", "format": "date" }
}
}
},
"required": ["customer_id", "query_time"]
},
"summary": {
"type": "object",
"properties": {
"total_orders": { "type": "integer", "description": "订单总数" },
"pending_orders": { "type": "integer" },
"total_amount": {
"type": "number",
"format": "currency",
"description": "总金额(元)"
}
}
},
"orders": {
"type": "array",
"items": {
"type": "object",
"properties": {
"order_id": { "type": "string" },
"status": {
"type": "string",
"enum": ["pending", "paid", "shipped", "completed", "cancelled"]
},
"amount": { "type": "number", "format": "currency" },
"created_at": { "type": "string", "format": "date-time" },
"items": {
"type": "array",
"items": {
"type": "object",
"properties": {
"product_id": { "type": "string" },
"product_name": { "type": "string" },
"quantity": { "type": "integer" },
"unit_price": { "type": "number" }
}
}
}
},
"required": ["order_id", "status", "amount", "created_at"]
}
}
}
}
这意味着工具返回的数据现在有了完整的类型定义。下游业务系统可以:
- 自动校验:验证返回的数据结构是否符合预期
- 类型安全:在强类型语言中自动生成对应的数据结构
- 文档生成:从 Schema 自动生成 API 文档
- Mock 数据:从 Schema 自动生成测试数据
3.5 变更四:全链路追踪——让 AI 结论可溯源
企业级 MCP 的核心挑战:
在企业环境中,AI 给出的结论必须能够被审计和追责。当一个 AI Agent 通过 MCP 调用了多个工具并给出最终建议时,这个建议的形成路径是什么?使用了哪些数据?调用的工具顺序是什么?
旧版 MCP 在这方面几乎是空白——只返回一个自然语言结果,没有追踪上下文。
新版 W3C Trace Context 集成:
2026-07-28 版本明确了 W3C Trace Context 规范的传播方式,实现了从 AI 应用到 MCP Server 再到下游数据服务的完整调用链追踪。
import logging
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# 初始化 OpenTelemetry 追踪
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter(
endpoint="http://telemetry.internal:4317"
)))
trace.set_tracer_provider(provider)
tracer = trace.get_tracer(__name__)
class MCPToolWithTracing:
"""带全链路追踪的 MCP 工具包装器"""
def __init__(self, tool_name: str, original_handler):
self.tool_name = tool_name
self.original_handler = original_handler
async def execute(self, arguments: dict, trace_context: dict) -> dict:
# 从 W3C Trace Context 提取追踪上下文
tracer.inject_context({
"traceparent": trace_context.get("traceparent"),
"tracestate": trace_context.get("tracestate", {})
})
with tracer.start_as_current_span(
f"mcp.tool.{self.tool_name}",
attributes={
"mcp.tool.name": self.tool_name,
"mcp.tool.arguments": arguments,
"mcp.call.timestamp": datetime.utcnow().isoformat()
}
) as span:
try:
result = await self.original_handler(arguments)
span.set_attribute("mcp.result.success", True)
span.set_attribute("mcp.result.item_count", len(result.get("orders", [])))
span.add_event("Tool execution completed", {
"result_size": len(str(result))
})
# 在结果中注入追踪上下文,供下游服务使用
result["_trace"] = {
"trace_id": span.get_span_context().trace_id,
"span_id": span.get_span_context().span_id,
"tool": self.tool_name,
"executed_at": datetime.utcnow().isoformat()
}
return result
except Exception as e:
span.set_attribute("mcp.result.success", False)
span.set_attribute("mcp.error.type", type(e).__name__)
span.set_attribute("mcp.error.message", str(e))
span.record_exception(e)
raise
# 使用示例
async def enterprise_task_pipeline():
trace_context = extract_w3c_trace_context(request.headers)
# 步骤1:查询客户信息
customer_result = await tools["query_customer"].execute(
{"customer_id": "CUST-12345"},
trace_context
)
# 步骤2:查询订单历史
orders_result = await tools["query_orders"].execute(
{"customer_id": "CUST-12345", "start_date": "2026-01-01"},
trace_context # 追踪上下文在步骤间传递
)
# 步骤3:执行风险评估
risk_result = await tools["calculate_risk_score"].execute(
{
"customer_id": "CUST-12345",
"total_orders": orders_result["summary"]["total_orders"],
"total_amount": orders_result["summary"]["total_amount"]
},
trace_context
)
# 最终结果包含完整追踪链
return {
"customer": customer_result,
"orders": orders_result,
"risk_assessment": risk_result,
"_full_trace": build_trace_tree(trace_context) # 可追溯的完整调用链
}
通过这套追踪体系,当业务人员质疑 AI 给出的某个风险评分时,工程师可以回溯:
Trace ID: 4bf92f3577b34da6a3ce929d0e0e4736
└── Span: enterprise_task_pipeline (Root)
├── Span: mcp.tool.query_customer
│ ├── DB Query: SELECT * FROM customers WHERE id = 'CUST-12345'
│ └── Response time: 23ms
├── Span: mcp.tool.query_orders
│ ├── DB Query: SELECT * FROM orders WHERE customer_id = 'CUST-12345'
│ └── Found 47 orders, filtered to 12 (2026-01-01 onward)
└── Span: mcp.tool.calculate_risk_score
├── Input: total_orders=12, total_amount=¥386,500
├── Model: RiskAssessment-v2.1
└── Output: risk_level=LOW, score=0.23
3.6 扩展能力:Tasks 与 MCP Apps
长任务支持(Tasks):
旧版 MCP 的工具调用模型本质上是同步的——请求-响应,完成。但在企业场景中,许多任务是异步的:
- 批量数据扫描:可能需要扫描数千条记录
- 大文档解析:处理 PDF 报表可能耗时数分钟
- 多维度尽调:需要协调多个数据源
2026-07-28 引入了 Tasks 机制,让这些长周期任务有了标准化的协议位置:
# 启动一个长任务
async def start_batch_risk_scan(customer_ids: list[str]) -> str:
task_id = await mcp_server.tasks.create(
TaskDefinition(
name="batch_risk_scan",
description=f"批量扫描 {len(customer_ids)} 家企业的风险",
estimated_duration_ms=300000, # 预估5分钟
parameters={
"customer_ids": customer_ids,
"risk_dimensions": ["judicial", "credit", "operational"]
}
)
)
# 任务在后台异步执行
asyncio.create_task(execute_batch_scan(task_id, customer_ids))
return task_id # 返回任务 ID,Client 可通过 polling 或 WebSocket 获取进度
# Client 端轮询任务状态
async def monitor_task(task_id: str):
while True:
status = await mcp_server.tasks.get_status(task_id)
if status.state == "completed":
result = await mcp_server.tasks.get_result(task_id)
return result
elif status.state == "failed":
raise TaskFailedError(status.error)
else:
# 进度更新
print(f"Progress: {status.progress}% - {status.message}")
await asyncio.sleep(5)
MCP Apps(交互式界面):
新版还引入了 MCP Apps 的概念,为复杂任务提供标准化的交互界面支持:
- 用户确认节点:当 AI 需要用户确认关键决策时,可以通过 MCP App 展示确认对话框
- 候选选项展示:当 AI 识别到多个可能的答案时,可以通过 MCP App 展示选项卡片
- 任务进度可视化:长时间运行的任务可以通过 MCP App 展示进度条和状态摘要
这些能力的存在意义,不在于让所有 MCP 产品都立即实现完整的 UI 交互,而在于为过去需要各家自行设计的确认、异步任务和交互流程,提供了更标准的协议位置,降低了生态碎片化的风险。
四、生产级工程实践:构建企业级 MCP 服务
4.1 典型的企业 MCP 架构
以企业数据 MCP 为例,一个生产级的 MCP 服务架构如下:
┌──────────────────────────────────┐
│ API Gateway / MCP │
│ Client SDK │
│ (Claude Code / Cursor / │
│ QClaw / WorkBuddy 等) │
└──────────────┬───────────────────┘
│ HTTPS + OAuth2
┌──────────────▼───────────────────┐
│ MCP Gateway │
│ ┌────────────────────────────┐ │
│ │ · 认证鉴权 │ │
│ │ · 能力发现与缓存 │ │
│ │ · 限流与配额管理 │ │
│ │ · 审计日志 │ │
│ │ · 追踪上下文注入 │ │
│ └────────────────────────────┘ │
└──────────────┬───────────────────┘
┌──────────────┬──────────┼───────────────────┐
│ │ │ │
┌──────▼──────┐ ┌─────▼─────┐ ┌─▼──────────┐ ┌──────▼─────┐
│ 企业数据 MCP │ │ 法律数据 │ │ 文档解析 │ │ 风控 MCP │
│ Server │ │ MCP │ │ MCP │ │ Server │
│ (6 Servers) │ │ (2 Srv) │ │ (1 Srv) │ │ (按需) │
└──────┬───────┘ └─────┬─────┘ └─────┬──────┘ └──────┬─────┘
│ │ │ │
┌──────────┼───────────────┼─────────────┼───────────────┼──────────┐
│ │ │ │ │ │
┌────▼────┐ ┌──▼───┐ ┌────▼────┐ ┌───▼────┐ ┌────▼────┐ ┌───▼────┐
│工商数据库│ │股权库│ │法律知识库│ │文档解析│ │风控模型│ │外部数据│
│ │ │ │ │ │ │服务 │ │服务 │ │源 API │
└─────────┘ └──────┘ └─────────┘ └────────┘ └─────────┘ └────────┘
4.2 Python SDK 实现生产级 MCP Server
"""
企业级 MCP Server 实现示例
展示了无状态架构、能力发现、资源管理和全链路追踪的最佳实践
"""
import asyncio
import logging
from datetime import datetime, timezone
from typing import Any, AsyncIterator
from dataclasses import dataclass, field
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import (
Tool, Resource, GetPromptResult, PromptMessage,
TextContent, ImageContent, EmbeddedResource
)
from pydantic import BaseModel, Field
# ==================== 配置与数据模型 ====================
class QueryOrdersParams(BaseModel):
customer_id: str = Field(description="客户唯一标识")
start_date: str = Field(description="开始日期 YYYY-MM-DD")
end_date: str = Field(description="结束日期 YYYY-MM-DD")
status: list[str] | None = Field(
default=None,
description="订单状态过滤,不指定则返回全部"
)
limit: int = Field(default=100, ge=1, le=1000)
class OrderResult(BaseModel):
order_id: str
status: str
amount: float
currency: str = "CNY"
created_at: str
updated_at: str
items: list[dict] = field(default_factory=list)
@dataclass
class QueryResponse:
"""结构化查询响应"""
query_info: dict
summary: dict
orders: list[OrderResult]
warnings: list[str] = field(default_factory=list)
def to_mcp_content(self) -> list[TextContent]:
import json
return [TextContent(
type="text",
text=json.dumps(self.model_dump(), ensure_ascii=False, indent=2)
)]
# ==================== 追踪与审计 ====================
class TracingContext:
"""W3C Trace Context 追踪上下文"""
def __init__(self, traceparent: str | None = None):
self.trace_id = self._extract_trace_id(traceparent)
self.span_id = self._extract_span_id(traceparent)
@staticmethod
def _extract_trace_id(parent: str | None) -> str:
if not parent:
import uuid
return uuid.uuid4().hex[:32]
# W3C traceparent 格式: 00-{trace-id}-{span-id}-{flags}
parts = parent.split("-")
return parts[1] if len(parts) >= 2 else uuid.uuid4().hex[:32]
@staticmethod
def _extract_span_id(parent: str | None) -> str:
if not parent:
import uuid
return uuid.uuid4().hex[:16]
parts = parent.split("-")
return parts[2] if len(parts) >= 3 else uuid.uuid4().hex[:16]
class AuditLogger:
"""审计日志记录器"""
def __init__(self, log_file: str = "/var/log/mcp/audit.log"):
self.logger = logging.getLogger("mcp.audit")
self.logger.setLevel(logging.INFO)
handler = logging.FileHandler(log_file)
handler.setFormatter(
logging.Formatter('%(asctime)s %(message)s')
)
self.logger.addHandler(handler)
async def log_tool_call(
self,
tool_name: str,
arguments: dict,
caller_id: str,
trace_context: TracingContext,
result_size: int | None = None
):
"""记录工具调用审计日志"""
self.logger.info(
f"TOOL_CALL | trace_id={trace_context.trace_id} | "
f"caller={caller_id} | tool={tool_name} | "
f"args_hash={hash(str(arguments))} | "
f"result_size={result_size}"
)
async def log_access_denied(
self, caller_id: str, tool_name: str, reason: str,
trace_context: TracingContext
):
self.logger.warning(
f"ACCESS_DENIED | trace_id={trace_context.trace_id} | "
f"caller={caller_id} | tool={tool_name} | reason={reason}"
)
# ==================== 核心业务逻辑 ====================
class EnterpriseDB:
"""企业数据库访问层(模拟)"""
async def query_orders(
self,
customer_id: str,
start_date: str,
end_date: str,
status_filter: list[str] | None = None
) -> tuple[list[OrderResult], dict]:
# 实际生产中这里连接真实数据库
# 这里用模拟数据演示
import random
from datetime import datetime, timedelta
orders = []
start = datetime.strptime(start_date, "%Y-%m-%d")
end = datetime.strptime(end_date, "%Y-%m-%d")
delta = end - start
num_orders = random.randint(3, 20)
statuses = ["pending", "paid", "shipped", "completed"]
for i in range(num_orders):
order_date = start + timedelta(
days=random.randint(0, delta.days)
)
order_status = random.choice(statuses)
if status_filter and order_status not in status_filter:
continue
orders.append(OrderResult(
order_id=f"ORD-{customer_id}-{i+1:04d}",
status=order_status,
amount=round(random.uniform(100, 50000), 2),
created_at=order_date.isoformat(),
updated_at=order_date.isoformat(),
items=[{
"product_id": f"PROD-{random.randint(1000, 9999)}",
"product_name": f"企业产品-{random.randint(1, 100)}",
"quantity": random.randint(1, 10),
"unit_price": round(random.uniform(50, 5000), 2)
}]
))
# 计算汇总统计
summary = {
"total_orders": len(orders),
"pending_orders": sum(1 for o in orders if o.status == "pending"),
"total_amount": round(sum(o.amount for o in orders), 2),
"avg_order_value": round(
sum(o.amount for o in orders) / len(orders), 2
) if orders else 0
}
return orders, summary
# ==================== MCP Server 实现 ====================
@dataclass
class MCPServerConfig:
name: str = "enterprise-orders-mcp"
version: str = "2.1.0"
vendor: str = "enterprise-corp"
rate_limit_per_minute: int = 100
max_concurrent_requests: int = 50
class EnterpriseMCPServer:
def __init__(self, config: MCPServerConfig):
self.config = config
self.server = Server(config.name)
self.db = EnterpriseDB()
self.audit = AuditLogger()
self._register_handlers()
self._register_capabilities()
def _register_capabilities(self):
"""注册 MCP Server 能力(新版能力发现支持)"""
self.server.capabilities = {
"tools": {
"listChanged": True,
"supportsDynamicRegistration": True
},
"resources": {
"subscribe": True,
"listChanged": True
},
"prompts": {
"listChanged": False
},
"discovery": {
"server_info": {
"name": self.config.name,
"version": self.config.version,
"vendor": self.config.vendor
}
}
}
def _register_handlers(self):
"""注册所有 MCP 协议处理器"""
# 工具列表定义
@self.server.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="query_orders",
description