MCP 协议完全指南:从原理到自己动手构建 AI 工具服务器
教程资源教程入门20 分钟阅读
学习路径:AI 编程入门

MCP 协议完全指南:从原理到自己动手构建 AI 工具服务器

MCP(Model Context Protocol)是 Anthropic 推出的开放协议,让 AI 模型能连接任何工具和数据源。本指南从架构原理到代码实现,教你构建自己的 MCP 服务器。

MCP 协议正在改变 AI 的使用方式

2024 年底,Anthropic 发布了 MCP(Model Context Protocol)。当时大多数人没当回事。

现在 MCP 已经成为 AI 工具链的核心协议——Claude Desktop、Cursor、Windsurf、Cline 全都支持了。OpenAI 也宣布支持 MCP。

这意味着什么?意味着 MCP 正在成为 AI 连接外部世界的"USB 接口"。

这篇教程会从零开始,带你理解 MCP 协议、搭建 MCP 服务器、集成到你的工作流中。

MCP 是什么?用一句话说清楚

MCP 是一个标准化协议,让 AI 应用(如 Claude、Cursor)能够与外部工具和数据源通信。

没有 MCP 的世界:每个 AI 工具都要单独为每个外部服务写集成代码。N x M 的复杂度。

有 MCP 的世界:每个外部服务实现一次 MCP 服务器,所有 AI 工具都能用。N + M 的复杂度。

传统方式:
Claude → [GitHub集成] [数据库集成] [文件系统集成]
Cursor → [GitHub集成] [数据库集成] [文件系统集成]
每个 AI 工具 × 每个服务 = N×M 个集成

MCP 方式:
Claude ──┐
Cursor ──┼── [MCP 协议] ──┬── GitHub MCP Server
Windsurf ┘                ├── Database MCP Server
                          └── Filesystem MCP Server

MCP 架构:三个核心角色

MCP 协议定义了三个角色:

Host(宿主):AI 应用本身,比如 Claude Desktop、Cursor。

Client(客户端):Host 内部的 MCP 客户端,负责与 Server 通信。每个 Server 对应一个 Client。

Server(服务端):提供工具、资源、提示词的外部服务。

┌──────────────────────┐
│   Host (Claude App)  │
│  ┌───────┐ ┌───────┐│
│  │Client1│ │Client2││
│  └───┬───┘ └───┬───┘│
└──────┼─────────┼────┘
       │ stdio   │ stdio
  ┌────▼────┐ ┌──▼────────┐
  │ GitHub  │ │Database   │
  │ Server  │ │ Server    │
  └─────────┘ └───────────┘

通信方式有两种:

  • stdio:本地进程通信(最常用)
  • SSE(Server-Sent Events):远程服务通信

Server 能提供什么?

一个 MCP Server 可以提供三类能力:

1. Tools(工具)——AI 可以调用的函数

{
  "name": "query_database",
  "description": "执行 SQL 查询并返回结果",
  "inputSchema": {
    "type": "object",
    "properties": {
      "sql": { "type": "string", "description": "SQL 查询语句" },
      "limit": { "type": "number", "default": 100 }
    },
    "required": ["sql"]
  }
}

2. Resources(资源)——AI 可以读取的数据

{
  "uri": "file:///project/README.md",
  "name": "项目说明文档",
  "mimeType": "text/markdown"
}

3. Prompts(提示词模板)——预定义的提示词

{
  "name": "code_review",
  "description": "代码审查提示词模板",
  "arguments": [
    { "name": "language", "required": true },
    { "name": "focus_area", "required": false }
  ]
}

从零搭建一个 MCP Server

我们来构建一个实用的"项目助手" MCP Server,提供文件搜索、代码统计和 Git 信息查询功能。

Step 1:初始化项目

mkdir my-project-mcp && cd my-project-mcp
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript @types/node

Step 2:编写 Server

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { execSync } from "child_process";

const server = new McpServer({ name: "project-assistant", version: "1.0.0" });

// Tool 1: 搜索代码
server.tool(
  "search_code",
  "在项目中搜索代码内容",
  { pattern: z.string(), file_glob: z.string().optional(), max_results: z.number().default(20) },
  async ({ pattern, file_glob, max_results }) => {
    const globOpt = file_glob ? `--include="${file_glob}"` : "";
    const cmd = `grep -rn ${globOpt} -E "${pattern}" . | head -${max_results}`;
    try {
      const result = execSync(cmd, { encoding: "utf-8" });
      return { content: [{ type: "text", text: result || "没有匹配结果" }] };
    } catch { return { content: [{ type: "text", text: "没有匹配结果" }] }; }
  }
);

// Tool 2: 代码统计
server.tool(
  "code_stats",
  "统计代码行数和文件数",
  { directory: z.string().default(".") },
  async ({ directory }) => {
    const cmd = `find ${directory} -type f \( -name '*.ts' -o -name '*.py' -o -name '*.js' \`;
    try {
      const result = execSync(cmd, { encoding: "utf-8" });
      return { content: [{ type: "text", text: result }] };
    } catch { return { content: [{ type: "text", text: "统计失败" }] }; }
  }
);

// 启动服务器
const transport = new StdioServerTransport();
await server.connect(transport);

Step 3:配置到 Cursor

// .cursor/mcp.json
{
  "mcpServers": {
    "project-assistant": {
      "command": "node",
      "args": ["/path/to/my-project-mcp/dist/index.js"]
    }
  }
}

重启 Cursor 后,Agent 模式就能使用你定义的工具了。esult || "无内容" }] };\n } catch (error) {\n return { content: [{ type: "text", text: "Git 命令执行失败,请确认当前目录是 Git 仓库" }] };\n }\n }\n);\n\n// 启动 Server\nconst transport = new StdioServerTransport();\nawait server.connect(transport);\n\n\n**Step 3:编译和配置**\n\nbash\nnpx tsc\n\n\n然后在 Claude Desktop 或 Cursor 中配置:\n\njson\n{\n "mcpServers": {\n "project-assistant": {\n "command": "node",\n "args": ["/path/to/my-project-mcp/dist/index.js"]\n }\n }\n}\n\n\n配置文件位置:\n- Claude Desktop: `~/Library/Application Support/Claude/claude_desktop_config.json`(Mac)\n- Cursor: `.cursor/mcp.json`(项目目录下)\n\n## Python 版本:用 FastMCP 快速开发\n\n如果你更喜欢 Python,官方提供了 FastMCP 库:\n\nbash\npip install fastmcp\n\n\npython\n# server.py\nfrom fastmcp import FastMCP\nimport httpx\nimport json\n\nmcp = FastMCP("weather-assistant")\n\n@mcp.tool()\nasync def get_weather(city: str) -> str:\n """查询指定城市的当前天气"""\n async with httpx.AsyncClient() as client:\n response = await client.get(\n f"https://api.open-meteo.com/v1/forecast\",\n params={\n "latitude": get_lat(city),\n "longitude": get_lon(city),\n "current_weather": "true"\n }\n )\n data = response.json()\n weather = data["current_weather"]\n return json.dumps({\n "city": city,\n "temperature": weather["temperature"],\n "windspeed": weather["windspeed"],\n "time": weather["time"]\n }, ensure_ascii=False)\n\n@mcp.resource("config://app")\ndef get_config() -> str:\n """暴露应用配置作为资源"""\n return json.dumps({"version": "1.0.0"})\n\nif name == "main":\n mcp.run()\n\n\n## 调试技巧\n\n开发 MCP Server 时,调试是个痛点。推荐两个方法:\n\n**方法 1:使用 MCP Inspector**\n\nbash\nnpx @modelcontextprotocol/inspector python server.py\n\n\n会启动一个网页界面,可以测试每个 Tool、查看 Resources、调试 Prompts。\n\n**方法 2:日志调试**\n\npython\nimport logging\nlogging.basicConfig(level=logging.DEBUG)\n\n\n## 安全注意事项\n\n1. **输入验证**:所有 Tool 参数必须验证,防止注入攻击\n2. **权限控制**:Server 应该最小权限原则,只暴露必要的操作\n3. **敏感数据**:不要通过 Resources 暴露密码、密钥等敏感信息\n4. **网络隔离**:远程 MCP Server 应该做好认证,使用 SSE 时建议加 API Key\n\n## 实战案例:构建客服知识库 MCP\n\n把公司内部知识库接入 AI,让客服团队能直接用 Claude 查询产品信息。\n\npython\nfrom fastmcp import FastMCP\nimport chromadb\nfrom sentence_transformers import SentenceTransformer\n\nmcp = FastMCP("knowledge-base")\nembedder = SentenceTransformer("BAAI/bge-m3")\nclient = chromadb.PersistentClient(path="./kb_db")\ncollection = client.get_or_create_collection("products")\n\n@mcp.tool()\nasync def search_knowledge_base(query: str, category: str = None) -> str:\n """搜索产品知识库"""\n query_vec = embedder.encode(query).tolist()\n results = collection.query(query_embeddings=[query_vec], n_results=5)\n return "\n\n---\n\n".join(results["documents"][0])\n\nif name == "main":\n mcp.run()\n```\n\n## 总结\n\nMCP 是 AI 工具链的基础设施层,掌握它能让你:\n\n1. 把任何数据源接入 AI(数据库、API、文件系统)\n2. 构建自定义工具链,让 AI 精确完成特定任务\n3. 一次开发,所有支持 MCP 的 AI 应用都能用\n\n建议从简单的文件搜索 Server 开始,逐步构建更复杂的工具链。\n\n---\n\n本文基于 MCP SDK 1.x 版本编写。MCP 协议仍在快速发展中,建议关注 modelcontextprotocol.io 获取最新规范。