Model Context Protocol (MCP) 技术详解文档

1. 核心概念:什么是 MCP?

Model Context Protocol (MCP) 是由 Anthropic (Claude 的母公司) 在 2024 年推出的一个开放标准。

1.1 痛点分析 (The “Why”)

在 MCP 出现之前,如果你想让 AI (如 Claude, ChatGPT) 连接你的本地数据(数据库、文件、Slack 消息),你需要为每一个 AI 模型单独写一个“插件”或“适配器”。这就像早期的硬件设备,鼠标要装鼠标驱动,键盘要装键盘驱动,且不同操作系统还不兼容。

1.2 MCP 的解决方案

MCP 相当于 AI 时代的 USB 协议

  • 标准化: 任何数据源(本地文件、Postgres、Git)只要实现了 MCP Server 标准,就可以被任何支持 MCP 的 AI 客户端(Claude Desktop, Cursor, IDEs)直接使用。
  • 解耦: 模型不需要知道底层是 SQL 还是 NoSQL,它只管调用 MCP 暴露出来的 Tools(工具)或读取 Resources(资源)。

2. 架构设计 (Architecture)

MCP 采用经典的 Client-Host-Server 架构(但在简单场景下,通常简化为 Client-Server)。

  1. MCP Host (宿主应用):
    • 通常是 AI 应用程序本身,如 Claude DesktopCursor
    • 它负责运行 LLM(大模型),并将用户的自然语言转化为对 MCP Server 的调用指令。
  2. MCP Client (客户端):
    • Host 内部实现协议通信的模块。它负责与 Server 建立连接(通常是 1:1 连接)。
  3. MCP Server (服务端):
    • 这是我们要开发的部分。它是一个轻量级的服务,负责连接实际的数据源,并暴露功能给 Client。

3. 通信协议与传输层

3.1 协议层 (Application Layer)

基于 JSON-RPC 2.0

  • 无状态、轻量级。
  • 主要消息类型:
    • Request (有 id,需要响应): 如 tools/call
    • Notification (无 id,不需要响应): 如 notifications/initialized,或者 Server 主动推送的日志。
    • Result (响应): 包含执行结果。

3.2 传输层 (Transport Layer)

MCP 定义了两种主要的传输方式:

  1. Stdio (标准输入输出流):
    • 场景: 本地运行。Host 直接启动 Server 进程(作为子进程)。
    • 优势: 安全(父子进程天然信任)、简单(无需网络配置)、零延迟。
    • 实现: Client 写入 Server 的 stdin,读取 Server 的 stdoutstderr 用于打印日志。
  2. SSE (Server-Sent Events) over HTTP:
    • 场景: 远程运行。Server 部署在另一台服务器上。
    • 优势: 支持网络调用。Client 通过 HTTP Post 发送请求,Server 通过 SSE 推送结果。

4. MCP Server 的三大核心能力

作为开发者,你在写 Server 时主要定义这三样东西:

  1. Resources (资源):
    • 类比: GET 请求 / 文件读取。
    • 作用: 被动的数据读取。例如:读取一个文本文件,读取数据库的一行记录。
    • 特点: AI 只能读,不能改。
  2. Prompts (提示词模板):
    • 类比: 预制菜 / 存储过程。
    • 作用: Server 预定义好的 Prompt 模板。用户点击一下,就会把复杂的上下文填入 Prompt 发送给 LLM。
  3. Tools (工具) —— 最重要:
    • 类比: POST 请求 / 函数调用 (RPC)。
    • 作用: 可执行的函数。例如:write_file, execute_sql, search_google
    • 特点: 能够改变系统状态,或执行复杂逻辑。

实战案例:Python 版 MCP Client & Server

为了彻底搞懂,我们不使用 Claude Desktop,而是手写一个 Python Client 来模拟 AI,去调用我们手写的一个 Python Server

场景: 这是一个简单的“数学计算服务”。Server 提供加法和乘法工具,Client 连接并调用它。

环境准备

# 安装官方 SDK
uv pip install mcp
# 或者 pip install mcp

1. 服务端代码 (server.py)

利用 FastMCP 快速构建。

from mcp.server.fastmcp import FastMCP

# 1. 创建 Server 实例
# 这里的名字会在握手时告诉 Client
mcp = FastMCP("Math-Server")

# 2. 定义工具:加法
# 注意:类型注解 (int) 和 文档注释 (docstring) 非常重要!
# MCP 会自动把它们转换成 JSON Schema 告诉 Client。
@mcp.tool()
def add(a: int, b: int) -> int:
    """
    计算两个整数的和。
    """
    return a + b

# 3. 定义工具:乘法
@mcp.tool()
def multiply(a: int, b: int) -> int:
    """
    计算两个整数的乘积。
    """
    return a * b

# 4. 定义资源:获取服务器状态
# resources://app/status
@mcp.resource("resources://app/status")
def get_status() -> str:
    """获取服务器当前的运行状态"""
    return "Running smoothly, ready for math!"

if __name__ == "__main__":
    # 默认使用 Stdio 模式运行
    mcp.run()

2. 客户端代码 (client.py)

这个脚本扮演了 Claude Desktop 的角色。它负责启动 Server 进程,并发送指令。

import asyncio
import sys
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client

# 配置 Server 的启动参数
# 我们要启动刚才写的 server.py
# 必须使用当前环境的 python 解释器
server_params = StdioServerParameters(
    command=sys.executable, # 获取当前 python 路径
    args=["server.py"],     # 脚本路径
    env=None                # 环境变量
)

async def run_client():
    print("🔌 Client: 正在启动 MCP Server 子进程...")
    
    # 使用上下文管理器建立 Stdio 连接
    async with stdio_client(server_params) as (read, write):
        # 创建 MCP 会话
        async with ClientSession(read, write) as session:
            
            # Step 1: 握手 (Initialize)
            # SDK 会自动帮我们处理 jsonrpc 版本和 capabilities 协商
            await session.initialize()
            print("✅ Client: 握手成功!连接已建立。")

            # Step 2: 列出可用工具 (List Tools)
            # 相当于发送 tools/list
            tools = await session.list_tools()
            print(f"\n🛠️  Server 提供了以下工具:")
            for tool in tools.tools:
                print(f"   - {tool.name}: {tool.description}")

            # Step 3: 列出可用资源 (List Resources)
            resources = await session.list_resources()
            print(f"\n📂 Server 提供了以下资源:")
            for res in resources.resources:
                print(f"   - {res.uri}")

            # Step 4: 读取资源 (Read Resource)
            print(f"\n📖 Client: 正在读取资源 resources://app/status ...")
            resource_content = await session.read_resource("resources://app/status")
            print(f"   资源内容: {resource_content.contents[0].text}")

            # Step 5: 调用工具 (Call Tool)
            print(f"\n🧮 Client: 正在请求计算 10 + 20 ...")
            # 相当于发送 tools/call
            result_add = await session.call_tool(
                name="add",
                arguments={"a": 10, "b": 20}
            )
            print(f"   计算结果: {result_add.content[0].text}")

            print(f"\n✖️ Client: 正在请求计算 5 * 9 ...")
            result_mul = await session.call_tool(
                name="multiply",
                arguments={"a": 5, "b": 9}
            )
            print(f"   计算结果: {result_mul.content[0].text}")

if __name__ == "__main__":
    # 运行异步主程序
    asyncio.run(run_client())

3. 如何运行与结果

确保 server.pyclient.py 在同一目录下。

在终端执行:

python client.py

预期输出:

🔌 Client: 正在启动 MCP Server 子进程...
✅ Client: 握手成功!连接已建立。

🛠️  Server 提供了以下工具:
   - add: 计算两个整数的和。
   - multiply: 计算两个整数的乘积。

📂 Server 提供了以下资源:
   - resources://app/status

📖 Client: 正在读取资源 resources://app/status ...
   资源内容: Running smoothly, ready for math!

🧮 Client: 正在请求计算 10 + 20 ...
   计算结果: 30

✖️ Client: 正在请求计算 5 * 9 ...
   计算结果: 45

4. 深度解析:这其中发生了什么?

虽然你运行的是 client.py,但底层发生了完整的 进程间通信 (IPC)

  1. 启动进程: client.py 使用 subprocess 启动了 python server.py。此时 server.py 在后台静默运行,监听它的 stdin
  2. 握手: Client 发送 JSON {"method": "initialize", ...} 给 Server。
  3. Schema 生成: Server 收到 list_tools 请求时,Python 的 mcp 库利用 反射 (Reflection) 技术,读取了 add 函数的 a: int, b: int 类型提示,自动生成了如下 JSON Schema 返回给 Client:
    {
      "name": "add",
      "inputSchema": {
        "type": "object",
        "properties": {
          "a": {"type": "integer"},
          "b": {"type": "integer"}
        },
        "required": ["a", "b"]
      }
    }
    
  4. 调用: 当 Client 调用 call_tool 时,Server 接收参数,执行 Python 函数 add(10, 20),并将返回值 30 包装成 TextContent 返回。

5. 总结

对于您(后端开发者)来说,MCP 并没有引入什么“黑科技”,它只是把我们熟悉的后端技术做了一个标准化封装

  • Server 就是一个 JSON-RPC API 服务
  • Stdio 就是 API 网关(只不过走的是管道不是 TCP)。
  • LLM (AI) 就是 API 调用方(它根据你提供的 API 文档/Schema,决定何时调用哪个接口)。

掌握了这个模式,您就可以用 Python 写任何逻辑(操作数据库、调用第三方 API、爬虫),封装成 MCP Server,让 Claude 瞬间拥有处理复杂业务的能力。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐