🔌 MCP 详解

"世界上有一种协议叫MCP,它让AI Agent之间可以互相传递情报"

🌙 午夜档:MCP的诞生

2025年9月20日,凌晨3点46分,Anthropic的一名工程师在提交了一个PR。

这个PR定义了一个协议,叫做Model Context Protocol

没人知道,这个协议将彻底改变AI Agent的连接方式。就像USB统一了设备接口,MCP统一了AI模型的工具箱。

到2026年7月,MCP生态已经:

  • 🚀 19,900+ MCP服务器
  • 📥 97M+ 月度SDK下载
  • 376K+ GitHub Stars
  • 📱 72,000+ ClawHub Skills

💡 核心定义

MCP(Model Context Protocol,模型上下文协议)是由Anthropic提出的开放标准协议,定义了AI模型如何与外部工具、数据源和上下文服务进行交互。

你可以把它理解为AI Agent的USB协议——标准化的插拔接口,让各种工具可以即插即用。

⏰ MCP无状态化倒计时:26天(截止2026-07-28)

🚨 重大倒计时!所有MCP服务器必须在2026-07-28前完成无状态化迁移

OpenClaw已于2026年6月发布MCP无状态化迁移指南,所有依赖状态的MCP实现必须在截止日期前完成改造。

什么是无状态化? MCP服务器不再维护内部状态,每次请求都必须包含所有必要的上下文信息。

⚙️ MCP的工作原理

1. 核心架构

MCP采用客户端-服务器架构:

┌─────────────────┐         ┌──────────────────┐
│                 │         │                  │
│   AI Model      │ ◄─────► │   MCP Server     │
│   (Client)      │  MCP    │   (Tools/Data)   │
│                 │ 协议     │                  │
└─────────────────┘         └──────────────────┘
        │                           │
        │ 工具调用                   │ 提供能力
        ▼                           ▼
┌─────────────────┐         ┌──────────────────┐
│   Skills/Agents │         │  Database / API  │
│                 │         │  / File System   │
└─────────────────┘         └──────────────────┘

2. 通信过程

  1. 能力发现:Client向Server查询可用工具列表
  2. 工具选择:Client根据任务选择合适的工具
  3. 参数传递:Client将参数通过MCP协议发送给Server
  4. 工具执行:Server执行工具,返回结果
  5. 无状态保证:所有上下文在请求中包含,Server不维护状态

3. MCP vs 传统API

特性 MCP 传统API
协议标准 统一标准 各写各的
能力发现 自动发现 需要文档
参数格式 标准化 自定义
无状态化 ✅ 是(2026-07-28后强制) ❌ 不一定
扩展性 即插即用 需要适配
安全 内置安全检查 需要自行实现

🎯 实战案例:MCP在妙趣AI中的应用

场景:妙趣AI需要访问多个数据源生成日报

MCP实现

  • 📡 MCP Server 1:RSS聚合器(获取OpenClaw Blog + HN)
  • 📡 MCP Server 2:GitHub API(获取Trending仓库)
  • 📡 MCP Server 3:内容生成器(调用LLM生成日报文案)
  • 📡 MCP Server 4:Feishu通知器(发送飞书消息)

通过MCP统一调度,妙趣AI可以自由组合这些Server

🔄 MCP无状态化迁移指南

为什么必须无状态化?

  • 伸缩性:无状态Server可以水平扩展
  • 可靠性:任何Server实例都可以处理任何请求
  • 安全性:不保存敏感用户数据
  • 简单性:简化故障恢复

迁移步骤

# 改造前:有状态MCP Server(❌ 不兼容)
class MyMCPServer:
    def __init__(self):
        self.session_state = {}  # 维护状态
    
    def handle_request(self, request):
        user_id = request.user_id
        # 依赖之前保存的状态
        prev_context = self.session_state.get(user_id, {})
        result = process_with_context(request, prev_context)
        self.session_state[user_id] = result.context  # 更新状态
        return result

# 改造后:无状态MCP Server(✅ 兼容)
class MyStatelessMCPServer:
    def handle_request(self, request):
        # 所有上下文都在请求中
        context = request.context  # 由Client传递
        result = process_with_context(request.data, context)
        # 返回新的上下文给Client
        return {
            "result": result.value,
            "next_context": result.next_context  # Client保存
        }

OpenClaw中的MCP配置

# openclaw/config.yaml 中的MCP配置

mcp_servers:
  # RSS聚合器
  rss_aggregator:
    type: "mcp"
    endpoint: "http://localhost:3100/mcp/rss"
    timeout: 30s
    stateless: true  # 无状态化
    capabilities:
      - fetch_blog
      - fetch_news
      - fetch_trending
  
  # 内容生成器  
  content_generator:
    type: "mcp"
    endpoint: "http://localhost:3101/mcp/content"
    timeout: 60s
    stateless: true
    capabilities:
      - generate_daily_report
      - generate_glossary
  
  # 通知服务
  notifier:
    type: "mcp"
    endpoint: "http://localhost:3102/mcp/notify"
    timeout: 10s
    stateless: true
    capabilities:
      - send_feishu_message
      - send_discord_message

# Skill通过MCP调用
skills:
  rss_aggregation:
    mcp_server: "rss_aggregator"
    tools: ["fetch_blog", "fetch_news"]
  
  report_generation:
    mcp_server: "content_generator"
    tools: ["generate_daily_report"]

💻 MCP实战:构建自定义MCP Server

示例1:简单的MCP Server(Python)

"""
妙趣AI - 自定义MCP Server示例
实现了无状态的RSS聚合工具
"""

from datetime import datetime
from typing import Dict, Any
import json, httpx

class MCPServer:
    """MCP Server基础类"""
    
    def __init__(self, name: str, version: str = "1.0.0"):
        self.name = name
        self.version = version
        self.tools = {}  # 注册的工具
    
    def register_tool(self, name: str, handler, description: str, params: list):
        """注册工具"""
        self.tools[name] = {
            "handler": handler,
            "description": description,
            "parameters": params
        }
    
    def discover(self) -> Dict:
        """能力发现接口(Client查询可用工具)"""
        return {
            "server": self.name,
            "version": self.version,
            "tools": {
                name: {
                    "description": info["description"],
                    "parameters": info["parameters"]
                }
                for name, info in self.tools.items()
            }
        }
    
    def handle_request(self, request: Dict) -> Dict:
        """处理MCP请求(无状态)"""
        tool_name = request.get("tool")
        params = request.get("params", {})
        context = request.get("context", {})  # Client传递的上下文
        
        if tool_name not in self.tools:
            return {"error": f"Unknown tool: {tool_name}"}
        
        try:
            result, next_context = self.tools[tool_name]["handler"](params, context)
            return {
                "result": result,
                "next_context": next_context  # 返回给Client
            }
        except Exception as e:
            return {"error": str(e)}


# 创建RSS聚合MCP Server
rss_server = MCPServer("rss-aggregator", "1.0.0")

def fetch_rss(params, context):
    """获取RSS内容(无状态)"""
    sources = params.get("sources", [
        "https://openclaw.ai/blog/feed.xml",
        "https://hnrss.org/frontpage"
    ])
    
    results = []
    for source in sources:
        # 模拟API调用
        results.append({
            "source": source,
            "count": 10,
            "articles": []
        })
    
    # 无状态:返回下次需要的上下文
    next_context = {
        "last_fetch": datetime.now().isoformat(),
        "sources_fetched": sources
    }
    
    return results, next_context

rss_server.register_tool(
    "fetch_rss",
    fetch_rss,
    "聚合多个RSS源的内容",
    [
        {"name": "sources", "type": "array", "required": False},
        {"name": "max_count", "type": "number", "required": False}
    ]
)


# 处理请求示例
def process_mcp_request():
    """完整的MCP请求处理流程"""
    
    # Step 1: 能力发现
    print("🔍 发现能力...")
    capabilities = rss_server.discover()
    print(f"   可用工具: {list(capabilities['tools'].keys())}")
    
    # Step 2: 构造请求(包含上下文)
    print("📤 发送请求...")
    request = {
        "tool": "fetch_rss",
        "params": {
            "sources": ["https://openclaw.ai/blog"],
            "max_count": 5
        },
        "context": {}  # 首次请求,上下文为空
    }
    
    # Step 3: 处理请求
    print("⚙️ 处理中...")
    response = rss_server.handle_request(request)
    
    # Step 4: 处理结果
    print(f"✅ 结果: {response['result']}")
    print(f"📦 下次上下文: {response['next_context']}")
    
    # Step 5: 第二次请求(带上上下文)
    request2 = {
        "tool": "fetch_rss",
        "params": {"sources": ["https://hnrss.org/frontpage"]},
        "context": response['next_context']  # 携带上次的上下文
    }
    
    response2 = rss_server.handle_request(request2)
    print(f"✅ 第二次请求完成")

# 执行
if __name__ == "__main__":
    process_mcp_request()

✅ MCP最佳实践

1. 无状态化设计原则

  • 所有状态在请求中传递:Server不应保存任何会话状态
  • 幂等性:相同请求产生相同结果
  • 上下文携带:Client维护全量上下文
  • 超时处理:设置合理的超时时间(10-60s)

2. 安全最佳实践

  • 参数验证:严格验证所有输入参数
  • 速率限制:防止滥用
  • 审计日志:记录所有请求
  • 敏感数据过滤:不在上下文中传递敏感信息

3. 性能优化

  • 结果缓存:相同参数的请求可以缓存结果
  • 连接复用:复用HTTP连接
  • 批量处理:合并多个小请求

💡 妙趣AI实战技巧

妙趣AI的MCP架构:

  • ✅ 所有MCP Server都是无状态的
  • ✅ 上下文由主Agent统一管理
  • ✅ 每个请求包含完整的上下文
  • ✅ 失败自动重试(最多3次)

倒计时提醒:你的MCP Server迁移了吗?还剩26天!

🔗 相关术语

🏷️ 标签

MCP Model Context Protocol 无状态化 Agent通信 OpenClaw Anthropic

📚 推荐阅读

🔗 MCP Tool Discovery 详解 - MCP工具发现机制 🔗 MCP协议2026:AI Agent的通信革命 🔗 Context Window Optimization(上下文窗口优化) 🔗 MCP (Model Context Protocol) - 模型上下文协议详解 🔗 MCP飞书集成详解 🔗 MCP Client(MCP客户端)是什么?

📚 推荐阅读

这些文章可能对你有帮助

🛠️ MCP集成教程 🛠️ MCP协议深入解析 📖 MCP术语详解 🛠️ MCP无状态迁移 🛠️ 工具库 📖 术语百科

📚 推荐阅读

这些文章可能对你有帮助

🛠️ MCP集成教程 🛠️ MCP协议深入解析 📖 MCP术语详解 🛠️ MCP无状态迁移 🛠️ 工具库 📖 术语百科

📚 推荐阅读

这些文章可能对你有帮助

🛠️ MCP集成教程 🛠️ MCP协议深入解析 📖 MCP术语详解 🛠️ MCP无状态迁移 🛠️ 工具库 📖 术语百科