Back to Blog
MCPProtocolAnthropic

MCP Protocol Complete Guide: Connecting AI Agents to Everything

2026-04-2012 min

Model Context Protocol(MCP)是 Anthropic 于 2024 年底推出的一项开放协议,旨在为 AI 模型与外部工具、数据源之间建立标准化的通信桥梁。本文将深入解析 MCP 的设计理念、技术架构和实践方法。

什么是 MCP

问题背景

在 MCP 出现之前,每个 AI 应用都需要为每种工具和数据源编写专用的集成代码。这意味着:

  • N×M 问题:N 个 AI 应用 × M 个工具 = N×M 个集成
  • 碎片化生态:每个框架都有自己的工具定义方式
  • 安全不一致:没有统一的权限和安全模型
  • MCP 将这个问题简化为 N+M——每个 AI 应用只需实现一个 MCP 客户端,每个工具只需实现一个 MCP 服务器。

    核心理念

    MCP 基于一个简单但强大的理念:工具应该像 USB 设备一样即插即用。你不需要为每个应用重新编写驱动程序——只要遵循标准协议,任何设备都能在任何系统上工作。

    MCP 架构详解

    整体架构

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

    │ MCP Host (AI 应用) │

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

    │ │ MCP Client │ │

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

    │ │ │Session 1 │ │Session 2 │ │Session 3 │ │ │

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

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

    │ │ │ │ │

    └──────────┼─────────────┼─────────────┼───────────────────┘

    │ │ │

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

    │MCP Server│ │MCP Server│ │MCP Server│

    │ (文件系统) │ │ (GitHub) │ │ (数据库) │

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

    MCP 基于 JSON-RPC 2.0 协议,支持两种通信模式:

    | 通信模式 | 传输方式 | 适用场景 |
    |---------|---------|---------|
    | stdio | 标准输入/输出 | 本地进程,最简单 |
    | HTTP+SSE | HTTP + Server-Sent Events | 远程服务,可扩展 |

    MCP 的四大核心概念

    #### 1. Resources(资源)

    Resources 允许服务器向客户端暴露数据。这些数据可以来自文件、数据库、API 等。

    // 服务器端定义资源
    

    server.setRequestHandler(ListResourcesRequestSchema, async () => {

    return {

    resources: [

    {

    uri: "file:///project/src/main.ts",

    name: "Main Entry Point",

    mimeType: "text/typescript",

    description: "应用程序的主入口文件"

    },

    {

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

    name: "Users Table",

    mimeType: "application/json",

    description: "用户表数据"

    }

    ]

    };

    });

    // 读取资源

    server.setRequestHandler(ReadResourceRequestSchema, async (request) => {

    const { uri } = request.params;

    const content = await readResource(uri);

    return {

    contents: [{ uri, mimeType: "text/plain", text: content }]

    };

    });

    #### 2. Tools(工具)

    Tools 允许服务器暴露可执行的函数,AI 模型可以调用这些函数执行操作。

    // 定义工具
    

    server.setRequestHandler(ListToolsRequestSchema, async () => {

    return {

    tools: [

    {

    name: "create_issue",

    description: "在 GitHub 上创建新的 Issue",

    inputSchema: {

    type: "object",

    properties: {

    title: { type: "string", description: "Issue 标题" },

    body: { type: "string", description: "Issue 内容" },

    labels: {

    type: "array",

    items: { type: "string" },

    description: "标签列表"

    }

    },

    required: ["title", "body"]

    }

    }

    ]

    };

    });

    // 执行工具

    server.setRequestHandler(CallToolRequestSchema, async (request) => {

    const { name, arguments: args } = request.params;

    if (name === "create_issue") {

    const issue = await github.createIssue(args);

    return {

    content: [{ type: "text", text: Issue #${issue.number} 已创建 }]

    };

    }

    throw new Error(未知工具: ${name});

    });

    #### 3. Prompts(提示模板)

    Prompts 允许服务器提供预定义的提示模板,帮助用户完成常见任务。

    server.setRequestHandler(ListPromptsRequestSchema, async () => {
    

    return {

    prompts: [

    {

    name: "review_code",

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

    arguments: [

    {

    name: "file_path",

    description: "要审查的文件路径",

    required: true

    }

    ]

    }

    ]

    };

    });

    server.setRequestHandler(GetPromptRequestSchema, async (request) => {

    const { name, arguments: args } = request.params;

    if (name === "review_code") {

    const code = await readFile(args.file_path);

    return {

    messages: [

    {

    role: "user",

    content: {

    type: "text",

    text: 请审查以下代码,关注安全性、性能和可维护性:\n\n\\\\n${code}\n\\\`

    }

    }

    ]

    };

    }

    });

    #### 4. Sampling(采样)

    Sampling 允许服务器请求 AI 模型进行推理,实现服务器端的智能处理。

    // 服务器请求客户端调用 AI 模型
    

    const result = await client.request(

    {

    method: "sampling/createMessage",

    params: {

    messages: [

    {

    role: "user",

    content: {

    type: "text",

    text: "分析这段日志中的异常模式"

    }

    }

    ],

    maxTokens: 1000

    }

    },

    CreateMessageResultSchema

    );

    构建 MCP 服务器实战

    环境准备

    初始化项目

    mkdir my-mcp-server && cd my-mcp-server

    npm init -y

    npm install @modelcontextprotocol/sdk zod

    TypeScript 配置

    npm install -D typescript @types/node

    完整的 MCP 服务器示例

    以下是一个完整的数据库查询 MCP 服务器实现:

    // src/server.ts
    

    import { Server } from "@modelcontextprotocol/sdk/server/index.js";

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

    import {

    CallToolRequestSchema,

    ListToolsRequestSchema,

    ListResourcesRequestSchema,

    ReadResourceRequestSchema,

    } from "@modelcontextprotocol/sdk/types.js";

    import { Pool } from "pg";

    import { z } from "zod";

    // 数据库连接池

    const pool = new Pool({

    connectionString: process.env.DATABASE_URL,

    });

    // 定义工具的输入 Schema

    const QuerySchema = z.object({

    sql: z.string().describe("SQL 查询语句"),

    params: z.array(z.string()).optional().describe("查询参数"),

    });

    const CreateTableSchema = z.object({

    name: z.string().describe("表名"),

    columns: z.array(z.object({

    name: z.string(),

    type: z.string(),

    nullable: z.boolean().default(true),

    })).describe("列定义"),

    });

    // 创建服务器实例

    const server = new Server(

    { name: "postgres-mcp", version: "1.0.0" },

    { capabilities: { tools: {}, resources: {} } }

    );

    // 注册工具列表

    server.setRequestHandler(ListToolsRequestSchema, async () => ({

    tools: [

    {

    name: "query",

    description: "执行只读 SQL 查询(SELECT 语句)",

    inputSchema: QuerySchema,

    },

    {

    name: "get_schema",

    description: "获取数据库表结构信息",

    inputSchema: z.object({

    table: z.string().optional().describe("指定表名,不填则返回所有表"),

    }),

    },

    {

    name: "explain_query",

    description: "分析 SQL 查询的执行计划",

    inputSchema: QuerySchema,

    },

    ],

    }));

    // 注册工具执行

    server.setRequestHandler(CallToolRequestSchema, async (request) => {

    const { name, arguments: args } = request.params;

    switch (name) {

    case "query": {

    const { sql, params } = QuerySchema.parse(args);

    // 安全检查:只允许 SELECT 语句

    if (!sql.trim().toUpperCase().startsWith("SELECT")) {

    throw new Error("安全限制:只允许执行 SELECT 查询");

    }

    const result = await pool.query(sql, params);

    return {

    content: [{

    type: "text",

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

    }],

    };

    }

    case "get_schema": {

    const table = args?.table;

    let sql =

    SELECT table_name, column_name, data_type, is_nullable

    FROM information_schema.columns

    WHERE table_schema = 'public'

    ;

    if (table) sql += AND table_name = $1;

    sql += ORDER BY table_name, ordinal_position;

    const result = await pool.query(sql, table ? [table] : []);

    return {

    content: [{

    type: "text",

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

    }],

    };

    }

    case "explain_query": {

    const { sql, params } = QuerySchema.parse(args);

    const result = await pool.query(EXPLAIN (FORMAT JSON) ${sql}, params);

    return {

    content: [{

    type: "text",

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

    }],

    };

    }

    default:

    throw new Error(未知工具: ${name});

    }

    });

    // 注册资源列表

    server.setRequestHandler(ListResourcesRequestSchema, async () => ({

    resources: [

    {

    uri: "postgres://schema",

    name: "数据库 Schema",

    mimeType: "application/json",

    description: "当前数据库的完整表结构",

    },

    ],

    }));

    // 注册资源读取

    server.setRequestHandler(ReadResourceRequestSchema, async (request) => {

    const { uri } = request.params;

    if (uri === "postgres://schema") {

    const result = await pool.query(

    SELECT table_name, column_name, data_type, column_default, is_nullable

    FROM information_schema.columns

    WHERE table_schema = 'public'

    ORDER BY table_name, ordinal_position

    );

    return {

    contents: [{

    uri,

    mimeType: "application/json",

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

    }],

    };

    }

    throw new Error(未知资源: ${uri});

    });

    // 启动服务器

    async function main() {

    const transport = new StdioServerTransport();

    await server.connect(transport);

    console.error("PostgreSQL MCP 服务器已启动");

    }

    main().catch(console.error);

    客户端配置

    在 Claude Desktop 或其他 MCP 客户端中配置服务器:

    {
    

    "mcpServers": {

    "postgres": {

    "command": "node",

    "args": ["dist/server.js"],

    "env": {

    "DATABASE_URL": "postgresql://user:pass@localhost:5432/mydb"

    }

    }

    }

    }

    MCP vs Function Calling 对比

    | 维度 | MCP | Function Calling |
    |------|-----|------------------|
    | 标准化 | 开放协议,厂商中立 | 各厂商私有实现 |
    | 发现能力 | 运行时动态发现工具 | 静态定义,调用时已知 |
    | 资源暴露 | 原生支持 | 不支持 |
    | 双向通信 | 支持(Sampling) | 单向 |
    | 可组合性 | 多个服务器可同时连接 | 每次调用独立 |
    | 传输层 | stdio / HTTP+SSE | 内置于 API |
    | 适用场景 | 复杂工具生态 | 简单工具调用 |

    MCP 并非要取代 Function Calling,而是提供更高层次的抽象。实际上,许多 MCP 客户端在底层仍然使用 Function Calling 来实现工具调用。

    真实世界应用场景

    场景 1:企业知识库助手

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

    │ Claude Desktop │

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

    │ │ MCP Client │ │

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

    │ │ │ │ │

    └─────────┼──────┼──────┼──────────────────┘

    │ │ │

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

    │Conflu│ │Slack │ │Jira │

    │ence │ │ │ │ │

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

    用户可以自然地提问:"上周张三在 Confluence 上更新了哪些文档?" Claude 通过 MCP 自动查询 Confluence 和相关系统。

    场景 2:全栈开发助手

    {
    

    "mcpServers": {

    "github": { "command": "npx", "args": ["-y", "@anthropic/github-mcp"] },

    "filesystem": { "command": "npx", "args": ["-y", "@anthropic/filesystem-mcp", "/home/user/project"] },

    "postgres": { "command": "node", "args": ["./servers/postgres/dist/index.js"] },

    "docker": { "command": "npx", "args": ["-y", "@anthropic/docker-mcp"] }

    }

    }

    Claude 可以:读取代码 → 查询数据库结构 → 分析依赖关系 → 提交修复 PR,全部通过 MCP 自动完成。

    场景 3:数据分析工作流

    MCP 服务器可以封装复杂的数据处理逻辑:

    server.tool(
    

    "run_analysis",

    {

    dataset: z.string(),

    analysis_type: z.enum(["correlation", "regression", "clustering"]),

    parameters: z.record(z.any()).optional(),

    },

    async ({ dataset, analysis_type, parameters }) => {

    // 执行数据分析并返回结果

    const result = await executeAnalysis(dataset, analysis_type, parameters);

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

    }

    );

    最佳实践

    1. 工具设计原则

  • 单一职责:每个工具只做一件事
  • 幂等性:相同输入应产生相同结果(对于查询类工具)
  • 描述清晰:工具描述应该让 AI 准确理解何时使用
  • 参数验证:使用 Zod 等库严格验证输入
  • 2. 安全考虑

    // 始终验证和限制用户输入
    

    server.tool("query", QuerySchema, async ({ sql }) => {

    // 防止 SQL 注入

    if (containsDangerousPatterns(sql)) {

    throw new Error("检测到潜在的危险 SQL 模式");

    }

    // 限制结果集大小

    const limitedSql = ${sql} LIMIT 1000;

    // ...执行查询

    });

    3. 错误处理

    try {
    

    const result = await executeOperation();

    return { content: [{ type: "text", text: result }] };

    } catch (error) {

    // 返回结构化错误信息,帮助 AI 理解问题

    return {

    content: [{

    type: "text",

    text: 操作失败: ${error.message}\n建议: 检查数据库连接或 SQL 语法`,

    }],

    isError: true,

    };

    }

    总结

    MCP 正在成为 AI Agent 生态系统的"USB 标准"。它解决了工具集成的碎片化问题,为 AI 应用提供了一个统一、可扩展的工具接入框架。

    对于开发者来说,MCP 的价值在于:

  • 降低集成成本:一次实现,到处可用
  • 提升可发现性:工具可以在运行时动态发现
  • 标准化安全模型:统一的权限控制和审计
  • 促进生态繁荣:开源的服务器实现越来越多
  • 随着 Anthropic、OpenAI 等主要 AI 厂商对 MCP 的支持,这一协议正在成为行业标准。现在是开始学习和使用 MCP 的最佳时机。