MCP 深入理解:协议原理与自定义开发


导语

Agent 要干活,得连接外部世界——读文件、查数据库、调 API。以前每个工具都要单独写适配代码,10 个工具写 10 套,换个模型再写一遍。

MCP(Model Context Protocol) 的出现改变了这一切。它是 AI 领域的"USB-C 接口"——一个协议接所有工具。Anthropic 发起,OpenAI 和 Google 都宣布支持。三个死对头在技术标准上达成一致——这种事在互联网历史上每次发生都不是小事。


一、MCP 是什么:Agent 的"万能插头"

1.1 解决的核心问题

没有 MCP 之前,M 个 AI 应用要对接 N 个工具,需要 M×N 个集成:

Before MCP:                    After MCP:
App1 ──┬── Tool1              App1 ──┐
       ├── Tool2              App2 ──┤     ┌── Tool1
       └── Tool3              App3 ──┼─MCP─┤── Tool2
App2 ──┬── Tool1                     │     └── Tool3
       ├── Tool2              M + N 个连接
       └── Tool3
App3 ──┬── Tool1
       ├── Tool2
       └── Tool3
M × N 个连接

1.2 MCP 发展历程

时间事件
2024.11Anthropic 发布 MCP 规范
2025.03OpenAI 宣布支持 MCP
2025.04Google Gemini 支持 MCP
2025.06MCP 生态爆发,社区 Server 超过 1000+
2026.01MCP 成为 Agent 工具集成的事实标准

二、MCP 协议规范详解

2.1 架构

┌────────────┐         ┌─────────────┐         ┌──────────────┐
│   MCP Host  │         │  MCP Client  │         │  MCP Server   │
│ (如 Claude   │ ──包含─→ │ (协议客户端)  │ ──通信──→ │ (提供工具/资源) │
│  Code/IDE)  │         │              │         │              │
└────────────┘         └─────────────┘         └──────────────┘
                                                       │
                                                       ▼
                                              ┌──────────────┐
                                              │   外部服务     │
                                              │  DB/API/文件   │
                                              └──────────────┘
  • Host:用户侧应用(Claude Code、Cursor、VS Code 等)
  • Client:Host 内部的 MCP 协议客户端,负责与 Server 通信
  • Server:提供工具和资源的服务端程序

2.2 传输层

传输方式适用场景特点
stdio本地 Server最简单,通过标准输入输出通信
HTTP + SSE远程 ServerServer-Sent Events,兼容性好
Streamable HTTP远程 Server(新)更灵活,支持双向流

2.3 三大核心原语

MCP 定义了三种能力原语:

原语用途谁控制类比
Tools可执行的操作模型决定调用函数/API
Resources可读的数据应用决定读取文件/数据库记录
Prompts可复用的提示模板用户选择使用预设 Prompt

Tools(最常用):

{
  "name": "query_database",
  "description": "查询 PostgreSQL 数据库",
  "inputSchema": {
    "type": "object",
    "properties": {
      "sql": {"type": "string", "description": "SQL 查询语句"},
      "database": {"type": "string", "description": "数据库名"}
    },
    "required": ["sql"]
  }
}

Resources

{
  "uri": "file:///project/config.yaml",
  "name": "项目配置文件",
  "description": "项目的配置信息",
  "mimeType": "text/yaml"
}

Prompts

{
  "name": "code_review",
  "description": "代码审查专家模板",
  "arguments": [
    {"name": "language", "description": "编程语言", "required": true},
    {"name": "code", "description": "待审查的代码", "required": true}
  ]
}

三、MCP 生态全景

3.1 热门 MCP Server

Server功能适用场景
@modelcontextprotocol/server-filesystem文件读写本地文件操作
@modelcontextprotocol/server-githubGitHub API代码管理、PR、Issues
@modelcontextprotocol/server-postgresPostgreSQL数据库操作
@modelcontextprotocol/server-slackSlack团队沟通
@modelcontextprotocol/server-brave-search网页搜索信息检索
@modelcontextprotocol/server-memory知识图谱记忆Agent 长期记忆

3.2 MCP Client 支持

Client支持情况特点
Claude Code完整支持Anthropic 官方,支持最全
Cursor完整支持IDE 集成
Windsurf完整支持IDE 集成
VS Code (Copilot)支持微软生态
Continue.dev支持开源 IDE 插件

四、实战:开发你的第一个 MCP Server

4.1 Python 版完整示例

# weather_server.py
import json
import httpx
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent, Resource

# 创建 MCP Server
server = Server("weather-server")

# ===== 定义 Tool =====
@server.list_tools()
async def list_tools():
    return [
        Tool(
            name="get_weather",
            description="获取指定城市的当前天气信息,包括温度、湿度、天气状况。",
            inputSchema={
                "type": "object",
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "城市名称,如 '北京'、'Shanghai'"
                    }
                },
                "required": ["city"]
            }
        ),
        Tool(
            name="get_forecast",
            description="获取指定城市未来 3 天的天气预报。",
            inputSchema={
                "type": "object",
                "properties": {
                    "city": {"type": "string", "description": "城市名称"},
                    "days": {"type": "integer", "description": "预报天数,1-3", "default": 3}
                },
                "required": ["city"]
            }
        )
    ]

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "get_weather":
        city = arguments["city"]
        # 实际项目中调用天气 API
        weather_data = {
            "city": city,
            "temperature": 22,
            "humidity": 65,
            "condition": "晴",
            "wind": "东南风 3级"
        }
        return [TextContent(
            type="text",
            text=json.dumps(weather_data, ensure_ascii=False)
        )]
    
    elif name == "get_forecast":
        city = arguments["city"]
        days = arguments.get("days", 3)
        forecast = [
            {"date": f"Day {i+1}", "high": 22+i, "low": 12+i, "condition": "晴"}
            for i in range(days)
        ]
        return [TextContent(
            type="text",
            text=json.dumps(forecast, ensure_ascii=False)
        )]
    
    raise ValueError(f"未知工具: {name}")

# ===== 定义 Resource =====
@server.list_resources()
async def list_resources():
    return [
        Resource(
            uri="weather://cities",
            name="支持的城市列表",
            description="当前支持查询天气的所有城市",
            mimeType="application/json"
        )
    ]

@server.read_resource()
async def read_resource(uri: str):
    if uri == "weather://cities":
        cities = ["北京", "上海", "广州", "深圳", "杭州", "成都"]
        return json.dumps(cities, ensure_ascii=False)
    raise ValueError(f"未知资源: {uri}")

# ===== 启动 Server =====
async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream)

if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

4.2 配置使用

在 Claude Code 中使用,编辑 ~/.claude/claude_code_config.json

{
  "mcpServers": {
    "weather": {
      "command": "python",
      "args": ["/path/to/weather_server.py"],
      "env": {
        "WEATHER_API_KEY": "your-api-key"
      }
    }
  }
}

五、MCP Server 开发最佳实践

5.1 工具描述设计原则(ACI)

ACI(Agent-Computer Interface)——为 AI 设计接口,和为人类设计 UI 一样重要。

原则说明示例
名称语义化工具名一看就知道干什么search_knowledge_base > search
描述详细说清楚能做什么、不能做什么"查询公司内部文档。不支持外部网页搜索。"
参数有约束枚举、范围、默认值enum: ["pdf", "docx"]
错误信息友好Agent 能理解并决定下一步"文件不存在,请检查路径" > "Error 404"

5.2 安全考量

# 输入验证
import re

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "query_database":
        sql = arguments["sql"]
        
        # 1. SQL 注入防护:只允许 SELECT
        if not sql.strip().upper().startswith("SELECT"):
            return [TextContent(type="text", text="安全限制:只允许 SELECT 查询")]
        
        # 2. 禁止危险关键词
        dangerous = ["DROP", "DELETE", "UPDATE", "INSERT", "ALTER", "EXEC"]
        if any(kw in sql.upper() for kw in dangerous):
            return [TextContent(type="text", text="安全限制:检测到危险操作")]
        
        # 3. 执行查询(使用参数化查询)
        result = await db.fetch(sql)
        return [TextContent(type="text", text=json.dumps(result))]

六、MCP vs Function Calling vs API

维度Function CallingMCP传统 API
标准化各平台不同统一标准HTTP/REST
发现机制需要预定义自动发现需要文档
运行时嵌入应用独立进程独立服务
生态绑定特定平台跨平台复用通用
适用场景简单工具调用Agent 生态服务间通信

什么时候用 MCP:构建 Agent、需要工具复用、希望跨平台兼容 什么时候直接用 FC:简单场景、不需要复用、绑定单一平台


七、职业视角

MCP 正在成为 Agent 开发的基础设施。能开发 MCP Server 是一个重要的差异化技能。

问题核心答案要点
MCP 的架构?Host → Client → Server,三层架构
Tool vs Resource?Tool 是可执行操作(模型控制),Resource 是可读数据(应用控制)
MCP 和 FC 的关系?FC 是能力(模型决定调什么),MCP 是标准化的工具接口协议
为什么三大厂商都支持?统一标准降低整个生态的集成成本,M×N → M+N

总结

  1. MCP 定位:AI 领域的 USB-C,统一 Agent 与工具的集成标准
  2. 三大原语:Tools(可执行操作)、Resources(可读数据)、Prompts(提示模板)
  3. 开发简单:Python/TypeScript SDK 成熟,一个 Server 几十行代码
  4. 安全重要:输入验证、权限控制、SQL 注入防护
  5. 生态繁荣:1000+ 社区 Server,主流 IDE/AI 工具都支持

本站提供的所有下载资源均来自互联网,仅提供学习交流使用,版权归原作者所有。如需商业使用,请联系原作者获得授权。 如您发现有涉嫌侵权的内容,请联系我们 邮箱:alixiixcom@163.com