> **摘要:** 2026年,MCP(Model Context Protocol)已经成为AI应用开发的事实标准。它让大模型不再是一个"聊天框",而是能连接数据库、操作文件、调用API、控制设备的真正智能体。本文从零带你理解MCP的核心原理,并手把手教你开发自己的MCP Server。

---

## 一、为什么需要 MCP?

### 1.1 大模型的"断联"困境

想象一下:你有一个超级聪明的助手,但他被关在一间没有窗户、没有网络、没有电话的房间里。他能思考、能推理、能写文章,但他**看不到外面的世界,也做不了任何事情**。

这就是2024年之前大模型的处境:

```

┌──────────────────────────────────────┐

│            大模型(LLM)              │

│                                      │

│  ✅ 能理解自然语言                    │

│  ✅ 能推理和生成                      │

│  ❌ 不能访问你的数据库                │

│  ❌ 不能读取你的文件                  │

│  ❌ 不能调用外部API                   │

│  ❌ 不能操作你的电脑                  │

│  ❌ 每次对话都是孤立的                │

└──────────────────────────────────────┘

```

### 1.2 Function Calling 的局限

有人说:"不是有 Function Calling 吗?"

没错,Function Calling 确实让模型能调用函数。但问题是:

| 痛点 | 具体表现 |

|------|----------|

| **碎片化** | 每个平台的FC实现不同(OpenAI、Anthropic、Google各一套) |

| **不可复用** | 为ChatGPT写的插件,Claude用不了 |

| **维护成本高** | 每接入一个新服务,都要写胶水代码 |

| **缺乏标准** | 没有统一的工具描述、权限管理、错误处理规范 |

### 1.3 MCP 的诞生

2024年11月,**Anthropic** 发布了 MCP(Model Context Protocol)——一个开放的、标准化的协议,让AI模型能以统一的方式连接外部世界。

```

MCP 之前:                          MCP 之后:

                                   

LLM ←→ 专用插件A                   LLM ←→ MCP Client ←→ MCP Server A (数据库)

LLM ←→ 专用插件B                              ↕         ←→ MCP Server B (文件系统)

LLM ←→ 专用插件C                              ↕         ←→ MCP Server C (GitHub)

  (每个都要单独开发)                           ↕         ←→ MCP Server D (Slack)

                                               ↕         ←→ MCP Server E (...)

                                          (统一协议,即插即用)

```

---

## 二、MCP 核心架构详解

### 2.1 整体架构

MCP 采用 **Client-Server** 架构,但和传统的 Client-Server 有所不同:

```

┌─────────────────────────────────────────────────┐

│                  AI 应用层                        │

│  ┌──────────────┐  ┌──────────────┐              │

│  │  Claude Code  │  │    Cursor    │  ...         │

│  │ (MCP Client)  │  │ (MCP Client) │              │

│  └──────┬───────┘  └──────┬───────┘              │

│         │                  │                      │

│  ───────┴──────────────────┴───────────────────  │

│              MCP 协议层(JSON-RPC 2.0)           │

│  ───────┬──────────┬──────────┬───────────────  │

│         │          │          │                   │

│  ┌──────┴───┐ ┌────┴────┐ ┌──┴───────┐          │

│  │ MCP      │ │ MCP     │ │ MCP      │          │

│  │ Server A │ │ Server B│ │ Server C │          │

│  │ (GitHub) │ │ (DB)    │ │ (File)   │          │

│  └──────────┘ └─────────┘ └──────────┘          │

│                                                   │

│              MCP Server 层                        │

└─────────────────────────────────────────────────┘

```

### 2.2 三大核心能力

MCP Server 可以向 AI 客户端暴露三种类型的能力:

#### ① Resources(资源)

Resources 是**数据源**,让AI能"看到"外部信息:

```json

{

  "uri": "file:///home/user/project/README.md",

  "name": "项目README",

  "description": "项目的说明文档",

  "mimeType": "text/markdown"

}

```

```json

{

  "uri": "postgres://localhost/mydb/users",

  "name": "用户表",

  "description": "系统中的所有用户数据",

  "mimeType": "application/json"

}

```

**类比:** Resources 就像给AI开了"窗户",让它能看到外面的世界。

#### ② Tools(工具)

Tools 是**可执行的操作**,让AI能"做事":

```json

{

  "name": "query_database",

  "description": "执行SQL查询并返回结果",

  "inputSchema": {

    "type": "object",

    "properties": {

      "sql": {

        "type": "string",

        "description": "要执行的SQL语句"

      },

      "database": {

        "type": "string",

        "description": "目标数据库名"

      }

    },

    "required": ["sql"]

  }

}

```

**类比:** Tools 就像给AI提供了"手",让它能操作外部系统。

#### ③ Prompts(提示模板)

Prompts 是**预定义的交互模板**,让AI能更好地完成特定任务:

```json

{

  "name": "code_review",

  "description": "代码审查模板",

  "arguments": [

    {

      "name": "language",

      "description": "编程语言",

      "required": true

    },

    {

      "name": "code",

      "description": "要审查的代码",

      "required": true

    }

  ]

}

```

### 2.3 通信协议

MCP 底层使用 **JSON-RPC 2.0** 协议,支持两种传输方式:

| 传输方式 | 适用场景 | 特点 |

|----------|----------|------|

| **stdio** | 本地工具 | 简单、低延迟、无需网络 |

| **SSE (Server-Sent Events)** | 远程服务 | 支持远程部署、可扩展 |

**stdio 模式示例(本地通信):**

```

Client → Server: {"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"read_file","arguments":{"path":"/tmp/test.txt"}}}

Server → Client: {"jsonrpc":"2.0","id":1,"result":{"content":[{"type":"text","text":"Hello, World!"}]}}

```

---

## 三、实战:从零开发一个 MCP Server

### 3.1 开发环境准备

```bash

# 创建项目

mkdir mcp-server-demo && cd mcp-server-demo

npm init -y

# 安装 MCP SDK

npm install @modelcontextprotocol/sdk zod

# 安装开发依赖

npm install -D typescript @types/node tsx

# 初始化 TypeScript

npx tsc --init

```

**tsconfig.json:**

```json

{

  "compilerOptions": {

    "target": "ES2022",

    "module": "ESNext",

    "moduleResolution": "bundler",

    "strict": true,

    "outDir": "./dist",

    "rootDir": "./src"

  },

  "include": ["src/**/*"]

}

```

### 3.2 实现一个实用的 MCP Server

我们来做一个**代码统计 MCP Server**,它能分析项目代码的各种指标:

**src/index.ts:**

```typescript

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";

import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";

import { z } from "zod";

import * as fs from "fs/promises";

import * as path from "path";

// 创建 MCP Server 实例

const server = new McpServer({

  name: "code-stats",

  version: "1.0.0",

  description: "代码统计分析工具",

});

// ============ Tool 1: 统计文件行数 ============

server.tool(

  "count_lines",

  "统计指定目录下代码文件的行数",

  {

    directory: z.string().description("要统计的目录路径"),

    extensions: z

      .array(z.string())

      .optional()

      .description("文件扩展名过滤,如 ['.ts', '.js']"),

  },

  async ({ directory, extensions }) => {

    const result = await countLines(directory, extensions || []);

    return {

      content: [

        {

          type: "text",

          text: JSON.stringify(result, null, 2),

        },

      ],

    };

  }

);

// ============ Tool 2: 分析代码复杂度 ============

server.tool(

  "analyze_complexity",

  "分析指定文件的代码复杂度(函数数量、平均函数长度、嵌套深度等)",

  {

    file_path: z.string().description("要分析的文件路径"),

  },

  async ({ file_path }) => {

    const content = await fs.readFile(file_path, "utf-8");

    const analysis = analyzeComplexity(content);

    return {

      content: [

        {

          type: "text",

          text: JSON.stringify(analysis, null, 2),

        },

      ],

    };

  }

);

// ============ Tool 3: 查找重复代码 ============

server.tool(

  "find_duplicates",

  "查找项目中的重复代码片段",

  {

    directory: z.string().description("要扫描的目录路径"),

    min_lines: z

      .number()

      .optional()

      .default(5)

      .description("最小重复行数"),

  },

  async ({ directory, min_lines }) => {

    const duplicates = await findDuplicates(directory, min_lines);

    return {

      content: [

        {

          type: "text",

          text: JSON.stringify(duplicates, null, 2),

        },

      ],

    };

  }

);

// ============ Resource: 项目概览 ============

server.resource(

  "project-overview",

  "stats://project/overview",

  async (uri) => {

    const overview = await getProjectOverview(".");

    return {

      contents: [

        {

          uri: uri.href,

          mimeType: "application/json",

          text: JSON.stringify(overview, null, 2),

        },

      ],

    };

  }

);

// ============ 辅助函数 ============

interface LineCountResult {

  totalFiles: number;

  totalLines: number;

  byExtension: Record<string, { files: number; lines: number }>;

  details: Array<{ file: string; lines: number }>;

}

async function countLines(

  dir: string,

  extensions: string[]

): Promise<LineCountResult> {

  const result: LineCountResult = {

    totalFiles: 0,

    totalLines: 0,

    byExtension: {},

    details: [],

  };

  async function walk(currentDir: string) {

    const entries = await fs.readdir(currentDir, { withFileTypes: true });

    for (const entry of entries) {

      const fullPath = path.join(currentDir, entry.name);

      if (entry.isDirectory()) {

        if (!["node_modules", ".git", "dist", "build"].includes(entry.name)) {

          await walk(fullPath);

        }

        continue;

      }

      const ext = path.extname(entry.name);

      if (extensions.length > 0 && !extensions.includes(ext)) continue;

      const content = await fs.readFile(fullPath, "utf-8");

      const lines = content.split("\n").length;

      result.totalFiles++;

      result.totalLines += lines;

      result.details.push({ file: fullPath, lines });

      if (!result.byExtension[ext]) {

        result.byExtension[ext] = { files: 0, lines: 0 };

      }

      result.byExtension[ext].files++;

      result.byExtension[ext].lines += lines;

    }

  }

  await walk(dir);

  result.details.sort((a, b) => b.lines - a.lines);

  return result;

}

function analyzeComplexity(content: string) {

  const lines = content.split("\n");

  const functions: Array<{ name: string; lines: number; nesting: number }> = [];

  let currentFunction: string | null = null;

  let functionStart = 0;

  let maxNesting = 0;

  let currentNesting = 0;

  for (let i = 0; i < lines.length; i++) {

    const line = lines[i];

    // 检测函数定义

    const funcMatch = line.match(

      /(?:function|const|let|var)\s+(\w+)\s*(?:=\s*(?:async\s*)?\(|[\s]*\()/

    );

    if (funcMatch) {

      currentFunction = funcMatch[1];

      functionStart = i;

    }

    // 统计嵌套深度

    const openBraces = (line.match(/{/g) || []).length;

    const closeBraces = (line.match(/}/g) || []).length;

    currentNesting += openBraces - closeBraces;

    maxNesting = Math.max(maxNesting, currentNesting);

    // 函数结束

    if (currentFunction && currentNesting === 0 && line.includes("}")) {

      functions.push({

        name: currentFunction,

        lines: i - functionStart + 1,

        nesting: maxNesting,

      });

      currentFunction = null;

      maxNesting = 0;

    }

  }

  const totalLines = lines.length;

  const blankLines = lines.filter((l) => l.trim() === "").length;

  const commentLines = lines.filter((l) =>

    l.trim().startsWith("//") || l.trim().startsWith("*") || l.trim().startsWith("/*")

  ).length;

  return {

    totalLines,

    blankLines,

    commentLines,

    codeLines: totalLines - blankLines - commentLines,

    functionCount: functions.length,

    avgFunctionLength:

      functions.length > 0

        ? Math.round(

            functions.reduce((sum, f) => sum + f.lines, 0) / functions.length

          )

        : 0,

    maxFunctionLength: Math.max(...functions.map((f) => f.lines), 0),

    functions,

  };

}

async function findDuplicates(dir: string, minLines: number) {

  const files: Array<{ path: string; lines: string[] }> = [];

  async function walk(currentDir: string) {

    const entries = await fs.readdir(currentDir, { withFileTypes: true });

    for (const entry of entries) {

      const fullPath = path.join(currentDir, entry.name);

      if (entry.isDirectory()) {

        if (!["node_modules", ".git", "dist"].includes(entry.name)) {

          await walk(fullPath);

        }

      } else if (/\.(ts|js|tsx|jsx)$/.test(entry.name)) {

        const content = await fs.readFile(fullPath, "utf-8");

        files.push({ path: fullPath, lines: content.split("\n") });

      }

    }

  }

  await walk(dir);

  const duplicates: Array<{

    snippet: string;

    locations: Array<{ file: string; startLine: number }>;

  }> = [];

  // 简单的滑动窗口检测

  const snippetMap = new Map<string, Array<{ file: string; startLine: number }>>();

  for (const file of files) {

    for (let i = 0; i <= file.lines.length - minLines; i++) {

      const snippet = file.lines

        .slice(i, i + minLines)

        .map((l) => l.trim())

        .filter((l) => l.length > 0)

        .join("\n");

      if (snippet.length < 20) continue;

      if (!snippetMap.has(snippet)) {

        snippetMap.set(snippet, []);

      }

      snippetMap.get(snippet)!.push({ file: file.path, startLine: i + 1 });

    }

  }

  for (const [snippet, locations] of snippetMap) {

    const uniqueFiles = new Set(locations.map((l) => l.file));

    if (uniqueFiles.size >= 2) {

      duplicates.push({ snippet: snippet.substring(0, 200), locations });

    }

  }

  return {

    duplicateCount: duplicates.length,

    duplicates: duplicates.slice(0, 20),

  };

}

async function getProjectOverview(dir: string) {

  const pkgPath = path.join(dir, "package.json");

  let pkg: any = {};

  try {

    pkg = JSON.parse(await fs.readFile(pkgPath, "utf-8"));

  } catch {}

  const lineStats = await countLines(dir, []);

  return {

    name: pkg.name || "unknown",

    version: pkg.version || "unknown",

    description: pkg.description || "",

    totalFiles: lineStats.totalFiles,

    totalLines: lineStats.totalLines,

    languages: lineStats.byExtension,

    dependencies: Object.keys(pkg.dependencies || {}),

    devDependencies: Object.keys(pkg.devDependencies || {}),

  };

}

// ============ 启动服务 ============

async function main() {

  const transport = new StdioServerTransport();

  await server.connect(transport);

  console.error("Code Stats MCP Server 已启动");

}

main().catch(console.error);

```

### 3.3 配置和运行

**package.json:**

```json

{

  "name": "mcp-code-stats",

  "version": "1.0.0",

  "type": "module",

  "scripts": {

    "build": "tsc",

    "start": "node dist/index.js",

    "dev": "tsx src/index.ts"

  },

  "dependencies": {

    "@modelcontextprotocol/sdk": "^1.0.0",

    "zod": "^3.22.0"

  }

}

```

**在 Claude Code 中使用:**

编辑 `~/.claude/settings.json`:

```json

{

  "mcpServers": {

    "code-stats": {

      "command": "node",

      "args": ["/path/to/mcp-code-stats/dist/index.js"]

    }

  }

}

```

**在 Cursor 中使用:**

编辑 `.cursor/mcp.json`:

```json

{

  "mcpServers": {

    "code-stats": {

      "command": "npx",

      "args": ["tsx", "/path/to/mcp-code-stats/src/index.ts"]

    }

  }

}

```

### 3.4 使用效果

配置完成后,在 Claude Code 中可以直接使用:

```

你:帮我统计一下这个项目有多少行代码,按语言分类

Claude:(调用 count_lines 工具)

项目代码统计结果:

- TypeScript: 45 个文件, 12,340 行

- JavaScript: 12 个文件, 3,200 行

- CSS: 8 个文件, 1,560 行

- 总计: 65 个文件, 17,100 行

你:分析一下 src/index.ts 的代码复杂度

Claude:(调用 analyze_complexity 工具)

代码复杂度分析:

- 总行数: 245 行

- 代码行: 198 行(80.8%)

- 注释行: 32 行(13.1%)

- 空行: 15 行(6.1%)

- 函数数量: 8 个

- 平均函数长度: 24.7 行

- 最长函数: processData (67行) ⚠️ 建议拆分

```

---

## 四、常用 MCP Server 推荐

### 4.1 官方 & 社区热门 MCP Server

| Server | 功能 | 适用场景 |

|--------|------|----------|

| **@modelcontextprotocol/server-filesystem** | 文件系统操作 | 读写文件、目录管理 |

| **@modelcontextprotocol/server-github** | GitHub API | PR管理、Issue操作、代码搜索 |

| **@modelcontextprotocol/server-postgres** | PostgreSQL | 数据库查询、Schema管理 |

| **@modelcontextprotocol/server-slack** | Slack API | 消息发送、频道管理 |

| **@modelcontextprotocol/server-puppeteer** | 浏览器自动化 | 网页截图、数据抓取 |

| **@modelcontextprotocol/server-memory** | 持久化记忆 | 跨会话记忆管理 |

### 4.2 热门第三方 MCP Server

```bash

# 数据库类

npx @benborber/mcp-server-mysql        # MySQL

npx @mongodb-js/mcp-server-mongodb     # MongoDB

npx @anthropic/mcp-server-redis        # Redis

# 开发工具类

npx @anthropic/mcp-server-docker       # Docker 操作

npx @anthropic/mcp-server-kubernetes   # K8s 管理

npx @anthropic/mcp-server-vercel       # Vercel 部署

# 生产力工具

npx @anthropic/mcp-server-notion       # Notion 文档

npx @anthropic/mcp-server-google-drive # Google Drive

npx @anthropic/mcp-server-linear       # Linear 项目管理

# 搜索类

npx @anthropic/mcp-server-brave-search # Brave 搜索

npx @anthropic/mcp-server-tavily       # Tavily 搜索

```

---

## 五、MCP 高级特性

### 5.1 Sampling(采样)

MCP Server 可以反向请求 Client 端的 LLM 进行推理:

```typescript

server.tool(

  "summarize_file",

  "智能总结文件内容",

  { path: z.string() },

  async ({ path }) => {

    const content = await fs.readFile(path, "utf-8");

    // 通过 Client 请求 LLM 进行总结

    const summary = await server.createMessage({

      messages: [

        {

          role: "user",

          content: {

            type: "text",

            text: `请总结以下代码文件的功能和关键逻辑:\n\n${content}`,

          },

        },

      ],

      maxTokens: 1000,

    });

    return {

      content: [{ type: "text", text: summary.content.text }],

    };

  }

);

```

### 5.2 动态工具注册

根据运行时条件动态注册工具:

```typescript

// 根据数据库类型动态注册不同的查询工具

function registerDatabaseTools(server: McpServer, dbType: string) {

  if (dbType === "postgres") {

    server.tool("query", "执行PostgreSQL查询", schema, handler);

  } else if (dbType === "mysql") {

    server.tool("query", "执行MySQL查询", schema, handler);

  } else if (dbType === "mongodb") {

    server.tool("find", "执行MongoDB查询", schema, handler);

  }

}

```

### 5.3 错误处理最佳实践

```typescript

server.tool(

  "safe_query",

  "安全的数据库查询",

  { sql: z.string() },

  async ({ sql }) => {

    // 1. SQL注入检测

    if (/;\s*(DROP|DELETE|TRUNCATE|ALTER)/i.test(sql)) {

      return {

        content: [{ type: "text", text: "❌ 检测到危险操作,已拦截" }],

        isError: true,

      };

    }

    try {

      // 2. 执行查询(带超时)

      const result = await Promise.race([

        db.query(sql),

        new Promise((_, reject) =>

          setTimeout(() => reject(new Error("查询超时")), 30000)

        ),

      ]);

      return {

        content: [{ type: "text", text: JSON.stringify(result, null, 2) }],

      };

    } catch (error) {

      // 3. 优雅的错误处理

      return {

        content: [

          {

            type: "text",

            text: `查询失败: ${error instanceof Error ? error.message : "未知错误"}`,

          },

        ],

        isError: true,

      };

    }

  }

);

```

---

## 六、MCP 生态的未来

### 6.1 MCP 正在成为行业标准

截至2026年6月,MCP 已获得广泛支持:

```

支持 MCP 的 AI 应用:

├── Claude Code(Anthropic)     ← 原生支持

├── Cursor                       ← 原生支持

├── Windsurf                     ← 原生支持

├── Continue.dev                 ← 原生支持

├── Zed Editor                   ← 原生支持

├── Cline (VS Code)              ← 原生支持

├── ChatGPT Desktop              ← 实验性支持

└── 更多应用持续接入中...

支持 MCP 的服务:

├── GitHub / GitLab

├── PostgreSQL / MySQL / MongoDB

├── Slack / Discord / Teams

├── AWS / GCP / Azure

├── Notion / Confluence

├── Jira / Linear

└── 200+ 个 MCP Server...

```

### 6.2 MCP vs Function Calling vs Tool Use

| 维度 | Function Calling | MCP |

|------|------------------|-----|

| **标准化** | 各平台各自实现 | 统一开放协议 |

| **可复用性** | 平台绑定 | 跨平台通用 |

| **发现机制** | 手动配置 | 自动发现和注册 |

| **安全模型** | 应用层实现 | 协议层内置 |

| **生态** | 封闭 | 开放社区 |

| **传输** | HTTP为主 | stdio / SSE 灵活选择 |

### 6.3 给开发者的建议

1. **现在就开始学习 MCP**——它将是未来2-3年AI应用开发的基础协议

2. **把常用工具封装为 MCP Server**——一次开发,所有AI应用都能用

3. **关注 MCP 生态的发展**——新的 Server 和 Client 不断涌现

4. **参与开源贡献**——MCP 社区欢迎 PR 和新 Server

---

## 总结

MCP 协议的核心价值在于**标准化**和**连接性**:

- 🔌 **标准化**:统一了AI模型与外部工具的通信方式

- 🌐 **连接性**:让AI真正"触手可及",连接一切数字世界

- 🧩 **可组合**:像乐高积木一样,自由组合各种能力

- 🔒 **安全**:协议层面的权限控制和安全边界

- 🚀 **生态**:200+ 个现成的 MCP Server,即插即用

2026年,不会用 MCP 的 AI 开发者,就像不会用 REST API 的后端开发者一样——你必须掌握它。

**开始构建你的第一个 MCP Server 吧!**

---

> **作者说:** MCP 是我在2026年最看好的技术协议之一。它真正解决了AI应用"最后一公里"的连接问题。如果你对 MCP 有任何疑问,欢迎在评论区讨论!

---

*本文首发于CSDN,转载请注明出处。*

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐