开发者从零构建 MCP Server 连接 AI 客户端与外部工具的架构示意图

从 0 开发一个 MCP Server:手把手教你构建 AI 工具调用能力

大模型再聪明,也无法直接查你的数据库、调用内部 API 或读取本地文件——这不是模型「不够聪明」,而是缺少标准化的工具调用通道Model Context Protocol(MCP) 正是 Anthropic 开源的解决方案:让 Claude、Cursor、GPT 通过统一协议访问外部能力。读完本文,你将能独立开发、调试并部署一个生产可用的 MCP Server,涵盖 Tools、Resources、Prompts 三大核心能力与 HTTP 远程传输。

1. 三大痛点:为什么 AI 需要 MCP Server

在写第一行代码前,先对齐你要解决的实际问题:

  1. 工具孤岛:Function Calling、Plugins、LangChain Tools 各写各的格式,换一个模型供应商就要重写集成层——典型的 N×M 困境
  2. 数据不可达:模型训练数据有截止日期,无法读取你的实时配置、内部文档或数据库状态。
  3. 动作不可执行:纯对话 AI 不能替你发 HTTP 请求、写文件或跑 SQL——除非通过标准化工具层暴露这些能力。

若你已读过《MCP 为什么会成为 AI 时代的 HTTP 协议》,本文不再重复协议选型论证,而是直接进入代码实现。适合人群:有 Python 或 TypeScript 基础的后端 / AI 开发者。

2. 什么是 MCP:协议原理与架构概览

2.1 MCP 的诞生背景

大模型工具调用能力经历了三代演进:Function Calling(OpenAI 私有格式)→ Plugins(ChatGPT 生态封闭)→ MCP(2024 年 11 月 Anthropic 开源的开放协议)。MCP 解决的核心问题是:标准化 AI 与外部工具之间的通信,一次实现、多客户端复用。

2.2 协议架构:Client ↔ Server ↔ 三大能力

┌────────────────────┐         ┌─────────────────────┐
│   MCP Client       │ ◄─────► │   MCP Server        │
│  (Claude / Cursor) │  JSON   │  (你要开发的部分)    │
│                    │  -RPC   │                     │
└────────────────────┘         └─────────────────────┘
                                        │
                          ┌─────────────┼─────────────┐
                          ▼             ▼             ▼
                       Tools       Resources      Prompts
                    (工具调用)    (资源读取)    (提示词模板)
  • Client:AI 模型侧——Claude Desktop、Cursor、VS Code、自定义 Agent。
  • Server:你开发的能力提供方,暴露 Tools / Resources / Prompts。
  • Tools:AI 可调用的函数(搜索、计算、数据库查询、写文件)。
  • Resources:AI 可读取的资源(文件、URL、配置流),通过 URI 寻址。
  • Prompts:预定义的提示词模板,支持动态参数注入。

2.3 通信机制

MCP 基于 JSON-RPC 2.0。传输方式有两种:

  • stdio:本地子进程,Client 启动 Server 并通过标准输入/输出通信,延迟极低。
  • HTTP + SSE / Streamable HTTP:远程服务,支持多客户端并发连接。

生命周期:初始化握手能力协商(tools/list、resources/list)→ 请求/响应(tools/call)→ 关闭

2.4 MCP 与其他方案对比

对比维度 MCP OpenAI Function Calling LangChain Tools
标准化程度 开放协议标准 厂商私有 框架绑定
传输方式 stdio / HTTP HTTP HTTP
跨模型支持 是(Claude、GPT、Gemini 等) 部分
Resources / Prompts 原生支持 不支持 不支持
生态规模(2026) 10,000+ Server,AAIF 治理 成熟但封闭 成熟但绑定 Python

3. 开发环境准备与项目结构

3.1 选择开发语言

  • Python(本文主语言):官方 SDK mcpFastMCP 装饰器简洁易上手。
  • TypeScript(对照):官方 SDK @modelcontextprotocol/sdk,适合 Node/全栈开发者。

3.2 环境搭建

# Python 环境
python -m venv .venv
source .venv/bin/activate   # Windows: .venv\Scripts\activate
pip install mcp httpx pydantic

# TypeScript 环境(对照)
npm init -y
npm install @modelcontextprotocol/sdk

3.3 推荐项目结构

my-mcp-server/
├── server.py            # 主服务入口
├── tools/
│   ├── __init__.py
│   ├── calculator.py
│   └── web_search.py
├── resources/
│   └── file_reader.py
├── prompts/
│   └── templates.py
├── tests/
│   └── test_tools.py
├── pyproject.toml
└── README.md

3.4 调试工具

  • MCP Inspector:官方调试 UI,可视化测试 Tools / Resources / Prompts。
  • Claude Desktop:编辑 claude_desktop_config.json 联调。
  • Cursor:在 Settings → MCP 或项目 .cursor/mcp.json 中配置。

4. 第一个 MCP Server:Hello World

4.1 最简 Server 代码

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-first-server")

@mcp.tool()
def say_hello(name: str) -> str:
    """向指定的人打招呼"""
    return f"Hello, {name}! 这是你的第一个 MCP 工具。"

if __name__ == "__main__":
    mcp.run()

4.2 运行与验证

python server.py
# 或使用 MCP Inspector 调试
npx @modelcontextprotocol/inspector python server.py

Inspector 启动后,在浏览器中查看 tools/list 是否返回 say_hello,并用 tools/call 传入 {"name": "开发者"} 验证返回。

4.3 在 Cursor / Claude Desktop 中接入

Cursor.cursor/mcp.json):

{
  "mcpServers": {
    "my-first-server": {
      "command": "python",
      "args": ["/absolute/path/to/server.py"]
    }
  }
}

Claude Desktop(macOS ~/Library/Application Support/Claude/claude_desktop_config.json):结构相同。重启客户端后,在 Agent 对话中应能看到 say_hello 工具出现在上下文中。

5. Tools:开发可被 AI 调用的工具

5.1 工具基本结构

函数签名即文档:参数类型、返回类型、docstring 会被自动转为 JSON Schema 供 AI 理解。命名建议用 snake_case,动词开头(search_webread_file)。

5.2 输入参数类型(Pydantic)

from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    query: str = Field(description="搜索关键词")
    max_results: int = Field(default=5, description="最多返回结果数")
    language: str = Field(default="zh", description="结果语言")

@mcp.tool()
def web_search(input: SearchInput) -> list[dict]:
    """执行网络搜索,返回相关结果列表"""
    # 实现搜索逻辑
    ...

5.3 五个实用工具实战

  1. 计算器eval 安全子集或 ast.literal_eval,处理数学表达式。
  2. 文件读写:限定白名单目录,防止路径穿越。
  3. HTTP 请求:用 httpx 调用外部 API,返回 JSON 或文本。
  4. 数据库查询:只读 SQL + 参数化查询,禁止 DDL。
  5. 时间工具datetime.now(timezone.utc) 与时区转换。

5.4 异步工具

import httpx

@mcp.tool()
async def fetch_url(url: str) -> str:
    """获取指定 URL 的内容"""
    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.get(url)
        response.raise_for_status()
        return response.text

5.5 错误处理最佳实践

  • 业务错误返回结构化 JSON({"error": "...", "code": 404}),而非裸抛异常。
  • 所有外部调用设置超时(建议 30s 以内)。
  • 文件/数据库操作做权限校验,最小权限原则。

6. Resources:让 AI 读取动态内容

6.1 Resource 与 Tool 的区别

Resource 是数据提供者,Tool 是动作执行者。 AI 通过 URI 读取 Resource 内容,不会触发副作用。

6.2 静态与动态资源

import json

@mcp.resource("config://app-settings")
def get_app_settings() -> str:
    """返回应用配置"""
    return json.dumps({"version": "1.0", "env": "production"})

@mcp.resource("user://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
    """根据用户 ID 返回用户资料"""
    user = db.query_user(user_id)
    return json.dumps(user)

URI 方案支持 file://http://custom:// 等自定义前缀。

6.3 资源类型

  • 文本text/plainapplication/json
  • 二进制:图片、PDF(Base64 或 Blob URI)
  • 流式:实时数据推送(SSE 订阅)

6.4 文件系统资源服务器

实战模式:列出目录 → 读取文件内容 → 可选监听文件变化(watchfiles)触发资源更新通知。务必配置允许访问的根目录白名单,避免 AI 读取敏感路径。

7. Prompts:定义可复用的提示词模板

7.1 什么是 MCP Prompt

预定义的提示词片段,AI 客户端可直接复用,支持动态参数注入,提升团队一致性与可维护性。

7.2 创建提示词模板

from mcp.types import PromptMessage, TextContent

@mcp.prompt()
def code_review_prompt(language: str, code: str) -> list[PromptMessage]:
    """代码审查提示词模板"""
    return [
        PromptMessage(
            role="user",
            content=TextContent(
                type="text",
                text=f"""请对以下 {language} 代码进行审查,重点关注:
1. 代码质量和可读性
2. 潜在的 Bug 和安全隐患
3. 性能优化建议

代码内容:
```{language}
{code}
```"""
            )
        )
    ]

7.3 多轮对话提示词

可定义包含 userassistant 的多轮模板,适用于面试模拟、代码调试助手等场景。每条 PromptMessage 指定 rolecontent,Client 按序注入对话上下文。

8. HTTP 传输模式:远程 MCP Server

8.1 stdio vs HTTP + SSE

特性 stdio HTTP + SSE
部署方式 本地子进程 远程服务器
延迟 极低(<1ms) 依赖网络(10–200ms)
多客户端 不支持 支持
适用场景 本地开发、个人工具 SaaS、团队共享、7×24 服务

8.2 实现 HTTP 传输

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("remote-server", transport="streamable-http")

if __name__ == "__main__":
    mcp.run(host="0.0.0.0", port=8000)

8.3 认证与安全

  • Bearer Token:Client 请求头携带 Authorization: Bearer <token>
  • API Key 中间件:校验密钥 + IP 白名单。
  • CORS:仅允许可信 Origin。
  • 频率限制:防止工具被滥用(如每秒 10 次 tools/call)。

9. 调试、测试与常见错误

9.1 MCP Inspector 调试流程

  1. 启动:npx @modelcontextprotocol/inspector python server.py
  2. 在 UI 中查看 Tools / Resources / Prompts 列表。
  3. 手动触发 tools/call,检查请求/响应 JSON。
  4. 模拟错误场景(超时、非法参数)验证错误处理。

9.2 单元测试示例

import pytest
from mcp.client.session import ClientSession
from mcp.client.stdio import StdioServerParameters, stdio_client

@pytest.mark.asyncio
async def test_calculator_tool():
    server_params = StdioServerParameters(
        command="python",
        args=["server.py"]
    )
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool("calculate", {"expression": "2 + 2"})
            assert result.content[0].text == "4"

9.3 常见错误排查

错误现象 常见原因 解决方案
工具未出现在 AI 中 配置路径错误、Client 未重启 检查 config.json 绝对路径,重启 Cursor/Claude
JSON 序列化失败 返回类型不支持(如 datetime 对象) 转为字符串或 dict
超时断开 工具执行超过 Client 默认超时 改用 async + 设置 timeout,或拆分长任务
权限拒绝 文件路径超出白名单 配置允许访问的目录根路径

10. 生产部署:Docker、云服务与监控

10.1 Docker 容器化

FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "server.py"]

10.2 云服务选型(2026 参考)

  • Railway / Render:一键部署,适合个人项目(月费约 $5–20)。
  • AWS Lambda / Google Cloud Run:Serverless,按调用计费。
  • 自建 VPS / 远程 Mac:配合 Nginx 反向代理 + launchd 守护,适合需要 Apple 生态或长期 7×24 运行的 Agent 工具链。

10.3 监控与可观测性

  • 结构化日志:每次 tools/call 记录 tool 名、耗时、状态码。
  • Prometheus 指标:调用次数、P99 延迟、错误率。
  • Sentry:未捕获异常告警。
  • 健康检查GET /health 返回 200 + 协议版本号。

10.4 版本管理与兼容性

在初始化握手时声明 MCP 协议版本;工具升级采用向后兼容策略——新增可选参数而非删除必填字段。重大变更时并行运行 v1/v2 Server,Client 通过能力协商选择。

11. 实战项目:个人知识库 MCP Server

11.1 项目需求

  • 让 AI 能搜索你的本地 Markdown 笔记。
  • 支持语义搜索(向量检索,而非纯关键词)。
  • 支持创建和更新笔记。

11.2 技术选型

  • 向量数据库:ChromaDB 或 Qdrant(本地嵌入式,零运维)。
  • 嵌入模型text-embedding-3-small(OpenAI)或本地 nomic-embed-text
  • 文件监听watchfiles 自动重建索引。

11.3 核心工具设计

  1. index_notes:扫描笔记目录,分块嵌入并写入向量库。
  2. search_notes:语义搜索,返回 Top-K 片段 + 源文件路径。
  3. write_note:创建或追加 Markdown 文件(白名单目录内)。
  4. notes://{path} Resource:直接读取指定笔记全文。

11.4 效果演示

在 Cursor 中直接问:「我上周记录了什么关于 MCP 的笔记?」—— AI 调用 search_notes 工具,返回相关片段并引用源文件。这比把整库笔记塞进 Context Window 节省 90%+ Token,且支持实时更新。

12. MCP 生态与未来展望

12.1 优质 MCP Server 推荐

  • mcp-server-filesystem:文件系统读写与目录列表。
  • mcp-server-github:GitHub 仓库操作、Issue、PR。
  • mcp-server-brave-search:网络搜索。
  • mcp-server-postgres:PostgreSQL 只读查询。
  • mcp-server-slack:Slack 消息发送与读取。

官方文档:modelcontextprotocol.io;Python SDK:github.com/modelcontextprotocol/python-sdk;TypeScript SDK:github.com/modelcontextprotocol/typescript-sdk

12.2 2026 生态趋势

  • 主流 AI 客户端(Cursor、Claude Desktop、VS Code Copilot、Gemini CLI)均已原生支持 MCP。
  • MCP Marketplace 与 AAIF 治理推动 Server 质量认证。
  • 企业级安全标准:OAuth 2.1、细粒度 Tool 权限、审计日志。

12.3 下一步学习路径

  • 深入学习 MCP 协议规范全文。
  • 开发并发布你的第一个公开 MCP Server 到 GitHub。
  • 探索 MCP + Agent 组合(参考《Cursor Agent Skill》与 OpenClaw MCP 集成)。
  • 向开源生态贡献 Tools 或 Resources 实现。

13. 总结:从本机实验到 7×24 生产节点的决策

本文覆盖了 MCP Server 开发的完整链路:协议原理 → 环境搭建 → Hello World → Tools / Resources / Prompts → HTTP 远程传输 → Inspector 调试 → Docker 部署 → 个人知识库实战。MCP 是 AI 工具化的标准协议,掌握它是 2026 年 AI 工程师的核心竞争力之一。

然而,本机 stdio 模式有明确边界:笔记本合盖即断链、向量库与嵌入模型占用本地内存、多 Server 并发时 CPU 争抢。个人知识库 MCP、HTTP 远程 Server、以及需要 ChromaDB + 嵌入 API 的长时会话,在常在线 Apple Silicon 节点上运行更稳定——统一内存架构对向量检索友好,macOS 原生支持 launchd 守护与 Cursor/Claude 同构工具链。

SFTPMAC 远程 Mac 租赁提供面向 MCP Server 与 AI Agent 工作流的 7×24 Apple Silicon 环境:低延迟 HTTP+SSE 回调、原生 Python/Node 运行时、SFTP/rsync 同步笔记目录与配置,比「家用电脑兼 MCP 宿主」更适合把个人知识库或团队工具层当生产入口。你打算用 MCP 开发什么工具?从 Hello World 开始,今天就能跑起来。