MCP 协议深度解析(一):MCP 协议概览与架构设计

🔧 MCP 协议深度解析(一):MCP 协议概览与架构设计


📋 目录

  • [1. 引言:为什么需要 MCP 协议?](#1. 引言:为什么需要 MCP 协议?)
    • [1.1 Function Calling 的局限性](#1.1 Function Calling 的局限性)
    • [1.2 Plugin 系统的问题](#1.2 Plugin 系统的问题)
    • [1.3 工具生态碎片化的挑战](#1.3 工具生态碎片化的挑战)
  • [2. MCP 协议的核心设计理念与目标](#2. MCP 协议的核心设计理念与目标)
    • [2.1 标准化工具接口](#2.1 标准化工具接口)
    • [2.2 一次编写,处处运行](#2.2 一次编写,处处运行)
    • [2.3 安全与隔离](#2.3 安全与隔离)
  • [3. MCP 架构全景:Host ↔ Client ↔ Server 三元架构](#3. MCP 架构全景:Host ↔ Client ↔ Server 三元架构)
    • [3.1 Host:承载 AI 的应用](#3.1 Host:承载 AI 的应用)
    • [3.2 Client:Host 内的 MCP 客户端](#3.2 Client:Host 内的 MCP 客户端)
    • [3.3 Server:提供工具能力的服务端](#3.3 Server:提供工具能力的服务端)
    • [3.4 三者之间的通信关系](#3.4 三者之间的通信关系)
  • [4. MCP 与 Function Calling、Plugin 系统的深度对比](#4. MCP 与 Function Calling、Plugin 系统的深度对比)
    • [4.1 技术架构对比表](#4.1 技术架构对比表)
    • [4.2 适用场景对比](#4.2 适用场景对比)
    • [4.3 优缺点分析](#4.3 优缺点分析)
  • [5. MCP 生态现状](#5. MCP 生态现状)
    • [5.1 官方 SDK](#5.1 官方 SDK)
    • [5.2 支持的客户端](#5.2 支持的客户端)
    • [5.3 社区工具生态](#5.3 社区工具生态)
  • [6. 快速体验:5 分钟上手第一个 MCP Server](#6. 快速体验:5 分钟上手第一个 MCP Server)
    • [6.1 环境准备](#6.1 环境准备)
    • [6.2 安装依赖](#6.2 安装依赖)
    • [6.3 编写简单的计算器 Server](#6.3 编写简单的计算器 Server)
    • [6.4 配置 Claude Desktop](#6.4 配置 Claude Desktop)
    • [6.5 测试运行](#6.5 测试运行)
  • [7. MCP 的应用场景与最佳实践](#7. MCP 的应用场景与最佳实践)
    • [7.1 文件系统访问](#7.1 文件系统访问)
    • [7.2 数据库查询](#7.2 数据库查询)
    • [7.3 API 调用](#7.3 API 调用)
    • [7.4 代码执行](#7.4 代码执行)
    • [7.5 最佳实践与反模式](#7.5 最佳实践与反模式)
  • [8. 常见问题 FAQ](#8. 常见问题 FAQ)
  • [9. 参考文献与延伸阅读](#9. 参考文献与延伸阅读)

1. 引言:为什么需要 MCP 协议?

在 AI 应用蓬勃发展的今天,大型语言模型(LLM)的能力边界正在不断扩展。然而,模型本身的知识是静态的、有限的,要让 AI 真正具备与外部世界交互的能力,就必须引入**工具调用(Tool Calling)**机制。

但传统的工具调用方案存在诸多痛点,MCP(Model Context Protocol,模型上下文协议)正是为了解决这些问题而诞生的。

1.1 Function Calling 的局限性

Function Calling 是 OpenAI 率先提出的一种让 LLM 调用外部函数的标准方式。虽然它极大地扩展了 AI 的能力,但在实际应用中存在明显局限:

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    Function Calling 架构                      │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────┐      ┌──────────────┐      ┌─────────────┐   │
│   │  LLM    │ ───▶ │  解析函数    │ ───▶ │  本地代码   │   │
│   │  模型   │      │  调用意图    │      │  执行函数   │   │
│   └─────────┘      └──────────────┘      └─────────────┘   │
│                                                             │
│   问题:                                                      │
│   ❌ 每个应用需要单独实现工具逻辑                                │
│   ❌ 工具定义格式不统一(JSON Schema 各家略有不同)               │
│   ❌ 工具与模型紧耦合,难以复用                                  │
│   ❌ 缺乏标准化的错误处理机制                                    │
│                                                             │
└─────────────────────────────────────────────────────────────┘

核心痛点:

  1. 重复造轮子:每个 AI 应用都需要自己实现工具调用逻辑,从参数解析到结果处理
  2. 格式碎片化:虽然都基于 JSON Schema,但各家实现细节不同,迁移成本高
  3. 生态封闭:为 ChatGPT 开发的工具无法直接在 Claude 或 Gemini 中使用
  4. 调试困难:缺乏统一的调试和监控标准

1.2 Plugin 系统的问题

ChatGPT Plugins 是 OpenAI 推出的插件系统,试图解决工具扩展问题,但仍存在根本缺陷:

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    Plugin 系统架构                           │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   ┌─────────┐      ┌──────────────┐      ┌─────────────┐   │
│   │ ChatGPT │ ───▶ │  Plugin      │ ───▶ │  第三方     │   │
│   │  平台   │      │  Store       │      │  服务       │   │
│   └─────────┘      └──────────────┘      └─────────────┘   │
│                                                             │
│   问题:                                                      │
│   ❌ 平台锁定:Plugin 只能在特定平台使用(ChatGPT)              │
│   ❌ 审核门槛:需要平台审核才能上架                              │
│   ❌ 技术栈限制:通常需要 HTTP API + OpenAPI 描述               │
│   ❌ 用户体验割裂:Plugin 之间无法协同工作                       │
│                                                             │
└─────────────────────────────────────────────────────────────┘

核心痛点:

  1. 平台锁定:Plugin 与特定平台深度绑定,无法跨平台复用
  2. 开发门槛:需要遵循平台的特定规范,学习成本高
  3. 审核依赖:工具上架受平台审核流程制约
  4. 生态割裂:不同平台的 Plugin 互不兼容

1.3 工具生态碎片化的挑战

当前 AI 工具生态呈现出严重的碎片化状态:

平台/框架 工具调用方式 协议标准 生态开放性
OpenAI Function Calling 自有标准 封闭
Anthropic Tool Use 自有标准 封闭
Google Gemini Function Calling 自有标准 封闭
LangChain Tools 框架特定 半开放
AutoGPT Plugins 自有标准 半开放

这种碎片化的后果是:

  • 开发者负担重:为多个平台重复开发相同功能
  • 用户选择受限:工具与平台绑定,无法自由组合
  • 创新受阻:小团队难以支持多平台,生态难以繁荣

MCP 协议的诞生正是为了解决这些根本性问题。


2. MCP 协议的核心设计理念与目标

MCP(Model Context Protocol)由 Anthropic 于 2024 年 11 月开源发布,旨在建立一个开放、标准化、可移植的 AI 工具协议。

2.1 标准化工具接口

MCP 定义了一套统一的接口规范,让工具开发者只需实现一次,即可在所有支持 MCP 的客户端中运行。

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                     MCP 标准化接口设计                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   ┌─────────────────────────────────────────────────────────────┐  │
│   │                    MCP 协议层                                │  │
│   │  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐        │  │
│   │  │ Tools   │  │Resources│  │ Prompts │  │  Roots  │        │  │
│   │  │ 工具    │  │ 资源    │  │ 提示词  │  │ 根目录  │        │  │
│   │  └─────────┘  └─────────┘  └─────────┘  └─────────┘        │  │
│   └─────────────────────────────────────────────────────────────┘  │
│                              │                                      │
│   ┌──────────────────────────┼──────────────────────────────────┐  │
│   │                    传输层  │                                   │  │
│   │  ┌─────────┐  ┌─────────┐▼┌─────────┐  ┌─────────┐          │  │
│   │  │stdio    │  │HTTP/SSE │ │WebSocket│  │  其他   │          │  │
│   │  │标准输入输出│  │  服务器  │ │         │  │         │          │  │
│   │  └─────────┘  └─────────┘ └─────────┘  └─────────┘          │  │
│   └─────────────────────────────────────────────────────────────┘  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

四大核心原语:

  1. Tools(工具):可被 AI 调用的功能,如计算器、文件读取、API 请求
  2. Resources(资源):可被 AI 读取的数据,如文件内容、数据库记录
  3. Prompts(提示词):预定义的提示模板,帮助用户快速启动任务
  4. Roots(根目录):定义 Server 可访问的目录范围,用于安全隔离

2.2 一次编写,处处运行

MCP 的核心价值主张是**"Write Once, Run Anywhere"**。

这意味着:

  • 工具开发者:只需关注业务逻辑,无需适配不同平台
  • AI 应用开发者:可复用社区丰富的 MCP Server
  • 终端用户:自由组合工具,打造个性化 AI 工作流

2.3 安全与隔离

MCP 从设计之初就将安全性作为首要考量:

安全机制:

  1. 明确授权:用户必须显式授权每个 Server 的权限
  2. Roots 隔离:通过根目录限制 Server 的文件访问范围
  3. 进程隔离:每个 Server 运行在独立进程中,崩溃不影响 Host
  4. 传输安全:支持 stdio、HTTP/SSE 等多种传输方式,可加密通信
  5. 能力声明:Server 必须声明自己提供的工具和资源,Host 据此控制访问

3. MCP 架构全景:Host ↔ Client ↔ Server 三元架构

MCP 采用经典的三元架构设计,清晰划分了各个组件的职责边界。

3.1 Host:承载 AI 的应用

Host 是最终用户直接交互的 AI 应用程序,负责:

  • 提供用户界面(聊天界面、IDE 等)
  • 管理 LLM 对话上下文
  • 协调多个 MCP Client 的生命周期
  • 处理用户授权和安全策略

典型 Host 示例:

Host 应用 类型 特点
Claude Desktop 桌面应用 Anthropic 官方,功能完整
Cursor IDE 代码编辑器集成
Zed 代码编辑器 高性能 Rust 实现
Windsurf IDE Cascade 工作流
Continue VS Code 插件 开源,可扩展

3.2 Client:Host 内的 MCP 客户端

Client 是 Host 内部与 MCP Server 通信的组件:

  • 维护与 Server 的连接(stdio、HTTP 等)
  • 处理协议消息的序列化和反序列化
  • 管理工具调用的请求-响应生命周期
  • 向 Host 暴露统一的工具接口

Client 的核心职责:

复制代码
┌─────────────────────────────────────────────────────────────┐
│                      MCP Client 职责                         │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  1. 连接管理                                                 │
│     ├─ 启动 Server 进程(stdio 模式)                         │
│     ├─ 建立 HTTP/SSE 连接(远程模式)                         │
│     └─ 维护连接状态,处理断线重连                              │
│                                                             │
│  2. 协议处理                                                 │
│     ├─ JSON-RPC 消息编码/解码                                │
│     ├─ 请求-响应匹配                                         │
│     └─ 错误处理和超时管理                                     │
│                                                             │
│  3. 能力协商                                                 │
│     ├─ 发送 initialize 请求                                  │
│     ├─ 接收 Server 能力声明                                   │
│     └─ 缓存工具和资源列表                                     │
│                                                             │
│  4. 工具调用                                                 │
│     ├─ 构造 tool call 请求                                   │
│     ├─ 发送请求并等待响应                                     │
│     └─ 将结果返回给 Host                                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

3.3 Server:提供工具能力的服务端

Server 是实现具体工具逻辑的程序,负责:

  • 声明自己提供的工具和资源
  • 实现工具调用的具体逻辑
  • 管理资源的生命周期和更新
  • 处理 Prompt 模板

Server 的生命周期:

复制代码
┌─────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌─────────┐
│  启动   │───▶│ 初始化   │───▶│ 运行中   │───▶│ 关闭     │───▶│  结束   │
└─────────┘    └──────────┘    └──────────┘    └──────────┘    └─────────┘
     │              │              │              │
     │              │              │              │
     ▼              ▼              ▼              ▼
  进程启动      能力协商          处理请求        清理资源
  加载配置      注册工具          响应调用        断开连接
                声明资源

3.4 三者之间的通信关系

复制代码
┌─────────────────────────────────────────────────────────────────────────┐
│                     MCP 三元架构通信关系                                 │
├─────────────────────────────────────────────────────────────────────────┤
│                                                                         │
│   ┌─────────────────────────────────────────────────────────────────┐  │
│   │                           Host                                   │  │
│   │  ┌─────────────────────────────────────────────────────────┐   │  │
│   │  │  LLM 对话上下文                                          │   │  │
│   │  │  ┌─────────┐    ┌─────────┐    ┌─────────┐             │   │  │
│   │  │  │ 用户输入 │───▶│ 模型推理 │───▶│ 生成回复 │             │   │  │
│   │  │  └─────────┘    └────┬────┘    └─────────┘             │   │  │
│   │  │                      │                                   │   │  │
│   │  │                      ▼ 需要工具调用                      │   │  │
│   │  │              ┌─────────────┐                            │   │  │
│   │  │              │ MCP Client  │                            │   │  │
│   │  │              └──────┬──────┘                            │   │  │
│   │  └─────────────────────┼───────────────────────────────────┘   │  │
│   └────────────────────────┼───────────────────────────────────────┘  │
│                            │                                          │
│                            ▼ MCP 协议 (stdio / HTTP / SSE)            │
│                            │                                          │
│   ┌────────────────────────┼───────────────────────────────────────┐  │
│   │                  ┌─────┴─────┐                                  │  │
│   │                  │ MCP Server │                                  │  │
│   │                  │  ┌─────┐  │                                  │  │
│   │                  │  │Tools│  │                                  │  │
│   │                  │  └─────┘  │                                  │  │
│   │                  │  ┌─────┐  │                                  │  │
│   │                  │  │Resources│                                  │  │
│   │                  │  └─────┘  │                                  │  │
│   │                  └───────────┘                                  │  │
│   └─────────────────────────────────────────────────────────────────┘  │
│                                                                         │
└─────────────────────────────────────────────────────────────────────────┘

通信流程:

  1. 初始化阶段

    • Host 启动 Server 进程
    • Client 发送 initialize 请求
    • Server 返回能力声明(工具列表、资源列表等)
  2. 运行阶段

    • Host 将用户输入发送给 LLM
    • LLM 判断需要调用工具
    • Host 通过 Client 发送 tools/call 请求
    • Server 执行工具逻辑并返回结果
    • Host 将结果注入 LLM 上下文,继续生成回复
  3. 关闭阶段

    • Host 发送 shutdown 请求
    • Server 清理资源并退出

4. MCP 与 Function Calling、Plugin 系统的深度对比

4.1 技术架构对比表

特性 MCP Function Calling Plugin 系统
协议标准 开放标准 厂商特定 平台特定
跨平台支持 ✅ 是 ❌ 否 ❌ 否
传输方式 stdio / HTTP / SSE HTTP API HTTP API
进程模型 独立进程 内嵌/远程 远程服务
安全隔离 进程级 + 权限控制 依赖实现 依赖平台
工具发现 动态协商 静态定义 静态配置
资源访问 原生支持 Resources 需额外实现 需额外实现
Prompt 模板 原生支持 需额外实现 需额外实现
实时更新 ✅ 支持 ❌ 不支持 ⚠️ 部分支持
离线运行 ✅ stdio 模式 ⚠️ 依赖实现 ❌ 需联网

4.2 适用场景对比

复制代码
┌─────────────────────────────────────────────────────────────────────┐
│                     适用场景决策树                                   │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│   是否需要跨平台复用?                                               │
│   ├─ 是 ──▶ 选择 MCP                                               │
│   └─ 否 ──▶ 是否需要深度集成特定平台?                                │
│             ├─ 是 ──▶ 选择该平台原生方案                              │
│             └─ 否 ──▶ 是否需要开放生态?                              │
│                       ├─ 是 ──▶ 选择 MCP                             │
│                       └─ 否 ──▶ 根据团队技术栈选择                     │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

MCP 最佳适用场景:

  • 需要为多个 AI 客户端提供工具支持
  • 希望工具可被社区复用
  • 需要本地文件系统访问
  • 重视安全隔离

Function Calling 最佳适用场景:

  • 仅需支持单一 LLM 平台
  • 已有成熟的内部 API 体系
  • 需要最小化架构复杂度

Plugin 系统最佳适用场景:

  • 目标用户集中在特定平台
  • 需要通过平台审核获得信任背书
  • 依赖平台的用户流量分发

4.3 优缺点分析

MCP 的优势:

优势 说明
🌐 开放生态 不绑定特定厂商,社区驱动发展
🔧 一次编写 工具可跨平台复用,降低维护成本
🛡️ 安全隔离 进程级隔离 + 显式权限控制
📦 丰富原语 原生支持 Tools、Resources、Prompts
🔌 灵活传输 支持 stdio、HTTP、SSE 多种方式
🚀 实时更新 支持资源订阅和增量更新

MCP 的劣势:

劣势 说明
🆕 生态较新 相比 Function Calling 成熟度较低
📚 学习成本 需要理解新的协议概念
🔧 调试复杂 多进程架构增加调试难度
📊 监控困难 缺乏统一的监控和日志标准

5. MCP 生态现状

5.1 官方 SDK

Anthropic 提供了官方 SDK,支持主流编程语言:

TypeScript SDK:

bash 复制代码
# 安装
npm install @modelcontextprotocol/sdk

# 快速开始
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

const server = new Server({
  name: "my-server",
  version: "1.0.0",
}, {
  capabilities: {
    tools: {},
    resources: {},
  },
});

const transport = new StdioServerTransport();
await server.connect(transport);

Python SDK:

bash 复制代码
# 安装
pip install mcp

# 快速开始
from mcp.server import Server
from mcp.server.stdio import stdio_server

app = Server("my-server")

@app.call_tool()
async def handle_tool(name: str, arguments: dict):
    # 处理工具调用
    pass

async with stdio_server() as streams:
    await app.run(
        streams[0],
        streams[1],
        app.create_initialization_options(),
    )

SDK 功能对比:

功能 TypeScript SDK Python SDK
Server 开发 ✅ 完整支持 ✅ 完整支持
Client 开发 ✅ 完整支持 ✅ 完整支持
stdio 传输 ✅ 支持 ✅ 支持
HTTP/SSE 传输 ✅ 支持 ✅ 支持
类型安全 ✅ TypeScript 原生 ✅ Pydantic
异步支持 ✅ 原生 async/await ✅ asyncio

5.2 支持的客户端

客户端 类型 MCP 支持状态 特点
Claude Desktop 桌面应用 ✅ 官方支持 功能最完整
Cursor IDE ✅ 支持 代码编辑集成
Zed 代码编辑器 ✅ 支持 高性能 Rust
Windsurf IDE ✅ 支持 Cascade 工作流
Continue VS Code 插件 ✅ 支持 开源可扩展
Cline VS Code 插件 ✅ 支持 自主编码代理
OpenClaw 开发框架 ✅ 支持 多模型支持

5.3 社区工具生态

MCP 社区正在快速发展,已涌现大量开源 Server:

官方示例 Server:

Server 功能 语言
filesystem 文件系统访问 TypeScript
sqlite SQLite 数据库操作 TypeScript
fetch HTTP 请求 TypeScript
git Git 操作 TypeScript
postgres PostgreSQL 数据库 TypeScript

热门社区 Server:

Server 功能 链接
mcp-server-browser 浏览器自动化 github.com/...
mcp-server-github GitHub API 操作 github.com/...
mcp-server-slack Slack 集成 github.com/...
mcp-server-notion Notion API github.com/...
mcp-server-puppeteer 网页截图/PDF github.com/...

6. 快速体验:5 分钟上手第一个 MCP Server

6.1 环境准备

系统要求:

  • Node.js 18+ 或 Python 3.10+
  • Claude Desktop(或其他 MCP Host)

检查环境:

bash 复制代码
# 检查 Node.js 版本
node --version  # 需要 v18+

# 或检查 Python 版本
python --version  # 需要 3.10+

6.2 安装依赖

TypeScript 版本:

bash 复制代码
# 创建项目目录
mkdir mcp-calculator
cd mcp-calculator

# 初始化项目
npm init -y

# 安装 MCP SDK
npm install @modelcontextprotocol/sdk

# 安装 TypeScript 依赖
npm install -D typescript @types/node

# 初始化 TypeScript
npx tsc --init

Python 版本:

bash 复制代码
# 创建项目目录
mkdir mcp-calculator
cd mcp-calculator

# 创建虚拟环境
python -m venv venv
source venv/bin/activate  # Linux/Mac
# 或 venv\Scripts\activate  # Windows

# 安装 MCP SDK
pip install mcp

6.3 编写简单的计算器 Server

TypeScript 实现:

typescript 复制代码
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";

// 创建 Server 实例
const server = new Server(
  {
    name: "calculator-server",
    version: "1.0.0",
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// 定义可用工具
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      {
        name: "add",
        description: "计算两个数的和",
        inputSchema: {
          type: "object",
          properties: {
            a: { type: "number", description: "第一个数" },
            b: { type: "number", description: "第二个数" },
          },
          required: ["a", "b"],
        },
      },
      {
        name: "subtract",
        description: "计算两个数的差",
        inputSchema: {
          type: "object",
          properties: {
            a: { type: "number", description: "被减数" },
            b: { type: "number", description: "减数" },
          },
          required: ["a", "b"],
        },
      },
      {
        name: "multiply",
        description: "计算两个数的积",
        inputSchema: {
          type: "object",
          properties: {
            a: { type: "number", description: "第一个数" },
            b: { type: "number", description: "第二个数" },
          },
          required: ["a", "b"],
        },
      },
      {
        name: "divide",
        description: "计算两个数的商",
        inputSchema: {
          type: "object",
          properties: {
            a: { type: "number", description: "被除数" },
            b: { type: "number", description: "除数" },
          },
          required: ["a", "b"],
        },
      },
    ],
  };
});

// 处理工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  switch (name) {
    case "add": {
      const result = (args.a as number) + (args.b as number);
      return {
        content: [{ type: "text", text: String(result) }],
      };
    }
    case "subtract": {
      const result = (args.a as number) - (args.b as number);
      return {
        content: [{ type: "text", text: String(result) }],
      };
    }
    case "multiply": {
      const result = (args.a as number) * (args.b as number);
      return {
        content: [{ type: "text", text: String(result) }],
      };
    }
    case "divide": {
      if (args.b === 0) {
        return {
          content: [{ type: "text", text: "错误:除数不能为零" }],
          isError: true,
        };
      }
      const result = (args.a as number) / (args.b as number);
      return {
        content: [{ type: "text", text: String(result) }],
      };
    }
    default:
      throw new Error(`未知工具: ${name}`);
  }
});

// 启动 Server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error("Calculator MCP Server 已启动");
}

main().catch(console.error);

Python 实现:

python 复制代码
# calculator_server.py
import asyncio
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import TextContent, Tool

# 创建 Server 实例
app = Server("calculator-server")

# 定义可用工具
@app.list_tools()
async def list_tools() -> list[Tool]:
    return [
        Tool(
            name="add",
            description="计算两个数的和",
            inputSchema={
                "type": "object",
                "properties": {
                    "a": {"type": "number", "description": "第一个数"},
                    "b": {"type": "number", "description": "第二个数"},
                },
                "required": ["a", "b"],
            },
        ),
        Tool(
            name="subtract",
            description="计算两个数的差",
            inputSchema={
                "type": "object",
                "properties": {
                    "a": {"type": "number", "description": "被减数"},
                    "b": {"type": "number", "description": "减数"},
                },
                "required": ["a", "b"],
            },
        ),
        Tool(
            name="multiply",
            description="计算两个数的积",
            inputSchema={
                "type": "object",
                "properties": {
                    "a": {"type": "number", "description": "第一个数"},
                    "b": {"type": "number", "description": "第二个数"},
                },
                "required": ["a", "b"],
            },
        ),
        Tool(
            name="divide",
            description="计算两个数的商",
            inputSchema={
                "type": "object",
                "properties": {
                    "a": {"type": "number", "description": "被除数"},
                    "b": {"type": "number", "description": "除数"},
                },
                "required": ["a", "b"],
            },
        ),
    ]

# 处理工具调用
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
    if name == "add":
        result = arguments["a"] + arguments["b"]
        return [TextContent(type="text", text=str(result))]
    
    elif name == "subtract":
        result = arguments["a"] - arguments["b"]
        return [TextContent(type="text", text=str(result))]
    
    elif name == "multiply":
        result = arguments["a"] * arguments["b"]
        return [TextContent(type="text", text=str(result))]
    
    elif name == "divide":
        if arguments["b"] == 0:
            return [TextContent(type="text", text="错误:除数不能为零")]
        result = arguments["a"] / arguments["b"]
        return [TextContent(type="text", text=str(result))]
    
    else:
        raise ValueError(f"未知工具: {name}")

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

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

编译 TypeScript:

bash 复制代码
# 编译
npx tsc

# 编译后的文件在 dist/index.js

6.4 配置 Claude Desktop

编辑 Claude Desktop 的配置文件:

macOS:

bash 复制代码
# 打开配置文件
open ~/Library/Application\ Support/Claude/claude_desktop_config.json

Windows:

powershell 复制代码
# 打开配置文件
notepad $env:AppData\Claude\claude_desktop_config.json

添加 Server 配置:

json 复制代码
{
  "mcpServers": {
    "calculator": {
      "command": "node",
      "args": ["/path/to/mcp-calculator/dist/index.js"]
    }
  }
}

Python 版本配置:

json 复制代码
{
  "mcpServers": {
    "calculator": {
      "command": "python",
      "args": ["/path/to/mcp-calculator/calculator_server.py"]
    }
  }
}

6.5 测试运行

  1. 重启 Claude Desktop 以加载新的 MCP Server

  2. 查看工具列表 :在 Claude Desktop 中,点击输入框的 🔧 图标,应该能看到 addsubtractmultiplydivide 四个工具

  3. 测试对话

    用户:帮我计算 123 + 456

    Claude:我来帮你计算 123 + 456。
    [Claude 调用 add 工具,参数: {"a": 123, "b": 456}]

    结果是 579。

    用户:计算 (100 - 50) * 3 / 5

    Claude:我来分步计算:

    1. 先计算 100 - 50 = 50
      [调用 subtract]
    2. 然后 50 * 3 = 150
      [调用 multiply]
    3. 最后 150 / 5 = 30
      [调用 divide]

    最终结果是 30。


7. MCP 的应用场景与最佳实践

7.1 文件系统访问

文件系统访问是 MCP 最常见的应用场景之一。

典型用例:

  • 读取项目代码文件进行分析
  • 批量重命名文件
  • 搜索文件内容
  • 生成项目文档

代码示例:

typescript 复制代码
// 文件读取工具示例
{
  name: "read_file",
  description: "读取指定文件的内容",
  inputSchema: {
    type: "object",
    properties: {
      path: { 
        type: "string", 
        description: "文件路径(相对于工作目录)" 
      },
      encoding: { 
        type: "string", 
        enum: ["utf-8", "base64"],
        default: "utf-8",
        description: "文件编码"
      },
    },
    required: ["path"],
  },
}

最佳实践:

  • ✅ 使用 Roots 限制可访问的目录范围
  • ✅ 对路径进行校验,防止目录遍历攻击
  • ✅ 对大文件进行分块读取
  • ❌ 不要直接暴露系统敏感目录
  • ❌ 不要允许任意路径写入

7.2 数据库查询

MCP Server 可以作为 AI 访问数据库的安全网关。

典型用例:

  • 自然语言查询数据库
  • 生成数据分析报告
  • 数据库结构探索
  • 数据迁移和转换

代码示例:

typescript 复制代码
// SQL 查询工具示例
{
  name: "query_database",
  description: "执行安全的只读 SQL 查询",
  inputSchema: {
    type: "object",
    properties: {
      query: { 
        type: "string", 
        description: "SQL 查询语句(仅支持 SELECT)" 
      },
      limit: { 
        type: "number", 
        default: 100,
        description: "返回结果数量限制"
      },
    },
    required: ["query"],
  },
}

最佳实践:

  • ✅ 使用只读连接,防止误操作
  • ✅ 限制返回结果数量,避免内存溢出
  • ✅ 对 SQL 进行白名单校验
  • ✅ 记录所有查询日志
  • ❌ 不要暴露写权限,除非必要
  • ❌ 不要返回敏感字段(如密码哈希)

7.3 API 调用

MCP Server 可以封装外部 API,让 AI 安全地访问第三方服务。

典型用例:

  • 调用 GitHub API 管理仓库
  • 查询天气、新闻等实时信息
  • 发送 Slack/邮件通知
  • 操作云服务资源

代码示例:

typescript 复制代码
// HTTP 请求工具示例
{
  name: "http_request",
  description: "发送 HTTP 请求",
  inputSchema: {
    type: "object",
    properties: {
      method: { 
        type: "string", 
        enum: ["GET", "POST", "PUT", "DELETE"],
        description: "HTTP 方法"
      },
      url: { 
        type: "string", 
        description: "请求 URL"
      },
      headers: { 
        type: "object", 
        description: "请求头"
      },
      body: { 
        type: "string", 
        description: "请求体"
      },
    },
    required: ["method", "url"],
  },
}

最佳实践:

  • ✅ 使用 API Key 管理器安全存储凭证
  • ✅ 设置请求超时和重试机制
  • ✅ 限制可访问的域名白名单
  • ✅ 对响应进行大小限制
  • ❌ 不要在代码中硬编码 API Key
  • ❌ 不要允许访问内部网络资源

7.4 代码执行

代码执行是最强大的 MCP 能力,也是风险最高的场景。

典型用例:

  • 运行测试脚本
  • 执行数据分析代码
  • 编译和构建项目
  • 自动化运维任务

代码示例:

typescript 复制代码
// Python 代码执行工具示例
{
  name: "execute_python",
  description: "在沙箱环境中执行 Python 代码",
  inputSchema: {
    type: "object",
    properties: {
      code: { 
        type: "string", 
        description: "Python 代码"
      },
      timeout: { 
        type: "number", 
        default: 30,
        description: "执行超时时间(秒)"
      },
    },
    required: ["code"],
  },
}

最佳实践:

  • ✅ 在沙箱环境中执行代码(Docker、VM)
  • ✅ 设置严格的资源限制(CPU、内存、时间)
  • ✅ 禁用危险操作(网络访问、文件系统写入)
  • ✅ 记录所有执行的代码
  • ❌ 不要在生产环境直接执行用户输入的代码
  • ❌ 不要允许访问系统命令

7.5 最佳实践与反模式

✅ 最佳实践:

实践 说明
清晰的工具描述 使用详细的描述帮助 LLM 理解工具用途
合理的参数设计 参数要有明确的类型和约束
错误处理 返回友好的错误信息,帮助 LLM 修正
结果格式化 根据内容类型返回结构化数据
日志记录 记录工具调用日志,便于调试和审计
性能优化 对耗时操作使用异步和缓存

❌ 反模式:

反模式 问题 解决方案
工具过于宽泛 LLM 难以选择正确的工具 拆分为更具体的工具
参数过于复杂 增加 LLM 理解和出错概率 简化参数,提供默认值
返回结果过大 超出 LLM 上下文限制 分页返回,提供摘要
缺乏错误处理 导致对话中断 返回结构化错误信息
硬编码配置 无法适应不同环境 使用环境变量或配置文件
阻塞操作 影响用户体验 使用异步处理

8. 常见问题 FAQ

Q1: MCP 和 Function Calling 有什么区别?

A: MCP 是一个开放协议,定义了 AI 工具的标准接口;Function Calling 是特定 LLM(如 OpenAI)的工具调用机制。MCP Server 可以在任何支持 MCP 的 Host 中运行,而 Function Calling 的工具通常与特定平台绑定。

Q2: 我需要为每个 Host 单独开发 MCP Server 吗?

A: 不需要。这是 MCP 的核心价值------一次编写,处处运行。只要 Host 支持 MCP 协议,你的 Server 就可以在其中运行。

Q3: MCP Server 的安全性如何保障?

A: MCP 提供多层安全机制:

  • 进程隔离:每个 Server 运行在独立进程中
  • 权限控制:用户需显式授权 Server 的能力
  • Roots 限制:限制 Server 的文件访问范围
  • 传输安全:支持加密通信

Q4: 如何调试 MCP Server?

A: 推荐以下调试方法:

  1. 日志输出 :使用 console.error() 输出调试信息
  2. Inspector:使用 MCP Inspector 工具进行交互式调试
  3. 单元测试:编写测试用例验证工具逻辑
  4. 日志文件:配置 Host 输出详细的 MCP 通信日志

Q5: MCP 支持哪些编程语言?

A: 官方提供 TypeScript 和 Python SDK。社区还有以下实现:

  • Go: mcp-go
  • Rust: rust-mcp
  • Java: mcp-java

理论上,任何支持 JSON-RPC 和 stdio/HTTP 通信的语言都可以实现 MCP Server。

Q6: 一个 MCP Server 可以包含多少个工具?

A: 没有硬性限制,但建议遵循以下原则:

  • 相关工具放在同一个 Server 中
  • 单个 Server 工具数量建议控制在 20 个以内
  • 过于庞大的 Server 可考虑拆分

Q7: MCP 支持远程 Server 吗?

A: 支持。MCP 支持多种传输方式:

  • stdio:本地进程通信(最常用)
  • HTTP/SSE:远程服务器通信
  • WebSocket:实时双向通信

Q8: 如何处理 MCP Server 的版本更新?

A: 建议:

  • 在 Server 名称中包含版本号(如 my-server-v2
  • 保持向后兼容的 API 变更
  • 在工具描述中注明版本信息
  • 使用语义化版本管理

9. 参考文献与延伸阅读

官方资源

  1. MCP 官方文档

    https://modelcontextprotocol.io/

    Anthropic 官方 MCP 文档,包含完整的协议规范和教程

  2. MCP 协议规范

    https://spec.modelcontextprotocol.io/

    详细的协议规范文档,适合深度开发者

  3. MCP TypeScript SDK

    https://github.com/modelcontextprotocol/typescript-sdk

    官方 TypeScript SDK 源码和示例

  4. MCP Python SDK

    https://github.com/modelcontextprotocol/python-sdk

    官方 Python SDK 源码和示例

  5. MCP 示例 Servers

    https://github.com/modelcontextprotocol/servers

    官方维护的示例 Server 集合

社区资源

  1. Awesome MCP

    https://github.com/appcypher/awesome-mcp

    社区整理的 MCP 资源大全

  2. MCP 中文文档

    https://github.com/.../mcp-docs-zh

    社区翻译的中文文档(如有)

相关技术

  1. JSON-RPC 2.0 规范

    https://www.jsonrpc.org/specification

    MCP 底层使用的通信协议

  2. JSON Schema

    https://json-schema.org/

    工具参数定义使用的 schema 标准

  3. Claude Desktop 文档

    https://claude.ai/docs

    Claude Desktop 的使用和配置文档


📝 总结

MCP 协议代表了 AI 工具生态的重要演进方向:从封闭走向开放,从碎片化走向标准化

通过本文的学习,你应该已经掌握了:

✅ MCP 协议的设计背景和核心价值

✅ MCP 三元架构的工作原理

✅ MCP 与传统工具调用方案的对比

✅ 如何开发自己的 MCP Server

✅ MCP 的最佳实践和常见陷阱

下一步建议:

  1. 动手实践:按照第 6 节的教程,创建你的第一个 MCP Server
  2. 深入阅读:研读 MCP 官方协议规范,理解底层细节
  3. 探索生态:浏览 Awesome MCP,发现社区的优秀 Server
  4. 贡献社区:将你的 Server 开源,回馈社区

MCP 生态正在快速发展,现在正是加入的最佳时机。期待看到你的 MCP 作品!


💡 系列预告

下一篇我们将深入探讨 MCP 协议底层通信机制,包括:

  • JSON-RPC 消息格式详解
  • stdio vs HTTP 传输方式对比
  • 生命周期管理和错误处理
  • 高级特性:资源订阅和增量更新

敬请期待!


相关推荐
Light602 小时前
SPARK View:从“AI手工作坊”到“软件工业革命
大数据·人工智能·spark
愚公搬代码2 小时前
【愚公系列】《剪映+DeepSeek+即梦:短视频制作》005-初识剪映:快速打开短视频制作的大门(AI创作初体验:零门槛生成第一条视频)
人工智能
灵机一物2 小时前
灵机一物AI智能电商小程序(已上线)-用 AI Agent 替代真人客服做砍价:一套 LLM + 规则混合驱动的智能议价产品方案
人工智能
2301_764441332 小时前
MiroFish:多智能体技术的开源AI推演预测引擎
人工智能·深度学习·语言模型·自然语言处理·数据挖掘·数据分析·开源
新缸中之脑2 小时前
Nano Banana 终极提示指南
人工智能·计算机视觉
卢锡荣2 小时前
LDR6500|超小封装 Type‑C DRP PD 控制芯片:边充边传,一芯极简,全能适配
开发语言·网络·人工智能·计算机外设·电脑
头疼的程序员2 小时前
计算机网络:自顶向下方法(第七版)第四章 学习分享(一)
网络·学习·计算机网络
信道者2 小时前
中国收紧AI“缰绳”:OpenClaw遭银行及政府机构限制使用
人工智能
知无不研2 小时前
Linux主函数的参数含义
linux·运维·服务器·主函数的参数