开发实战 2026-06-16

从 0 开发
MCP Server

大模型再聪明,没有外部工具也只能「纸上谈兵」——查不了实时股价、改不了本地文件、连不上内网数据库。Model Context Protocol(MCP) 把「AI 能调什么」写成标准协议,让你写一次 Server、多 Host 复用。本文面向全栈开发者与 Agent 工程师,从环境搭建到生产部署,覆盖 Tools / Resources / Prompts 全实现MCP 对比 Function Calling 决策表ChromaDB 知识库实战,以及五步 Mac 隔离开发验收清单

2026 年从零开发 MCP Server 构建 AI 工具调用能力架构与 FastMCP 实战示意

01 · 引言:AI 缺工具,MCP 来补

2026 年的 Agent 已经能写代码、做推理、规划多步任务,但没有外部工具就仍是封闭系统:它不知道你 Git 仓库里最新的 PR 状态,无法替你执行 SELECT * FROM orders WHERE status='pending',更不能在 Slack 里 @同事。传统做法是每家模型宿主各自实现 Function Calling,每个 SaaS 又要为 Claude、GPT、Gemini 写一套适配器——集成成本随 N×M 线性爆炸。

MCP(Model Context Protocol) 由 Anthropic 于 2024 年 11 月开源,定位是「大模型与外部世界的 USB-C 插头」:你实现一个符合规范的 Server,Cursor、Claude Desktop、OpenClaw 等 Host 都能加载,无需重复写胶水。若你已读过站内 MCP 为何成为 AI 时代的 HTTP 协议,本文是它的动手版——从 pip install mcp 到 Docker 上线,全程可跟做。

本文结构:三大开发痛点MCP 架构与 JSON-RPC 生命周期对比 OpenAI FC / LangChain 决策表Hello World → Tools → Resources → Prompts 递进实现HTTP+SSE 部署ChromaDB 知识库实战Mac 隔离开发验收

02 · 三大开发痛点

1. 每家宿主一套工具方言。 OpenAI 的 tools 数组、Anthropic 的 tool_use 块、Google 的 Function Declaration——Schema 字段名、错误回传格式各不相同。把同一个「查订单」能力接到三个宿主,往往要写三份包装层。MCP 把工具注册、能力描述、调用语义统一到 JSON-RPC,Write Once, Run Everywhere

2. 本地凭证与权限边界模糊。 MCP Server 常需读文件系统、调内网 API、持有 OAuth Token。在主力笔记本混装十几个 Server 与多款 IDE,一次误配就可能把生产 Key 写进测试 cron。与 OpenClaw MCP 接入与安全配置 同理,需要可丢弃的沙箱环境先验收再上线。

3. 调试链路长、错误难定位。 从 Host 发起到 Server 执行,中间经过 Client 转发、STDIO 管道或 HTTP 长连接——任何一环配置错误都表现为「工具不可用」或「Connection closed」。没有 Inspector 与单元测试,排查往往靠猜。

03 · 什么是 MCP:架构与演进

从 Function Calling 到 MCP 的三段演进

第一阶段(2023):Function Calling。 OpenAI 在 GPT-4 中引入工具调用,模型输出 JSON 指定函数名与参数,由应用层执行。问题是 Schema 嵌在 Prompt 或闭源 SDK,无法跨宿主复用

第二阶段(2024 初):Plugins / Actions。 ChatGPT Plugins、GPT Actions 把 HTTP 端点包装成工具,降低了接入门槛,但仍是宿主私有生态,且依赖 OpenAPI 静态描述,Agent 无法在运行时动态发现新 Server。

第三阶段(2024 11 月至今):MCP。 Anthropic 发布开放规范 + 参考 SDK,Host / Client / Server 三层解耦,10,000+ 社区 Server 在 18 个月内涌现,OpenAI、Google、Microsoft 于 2026 年全线跟进。

Client-Server 架构与三大能力

┌─────────────────────────────────────────────────────────────┐
│  Host(Cursor / Claude Desktop / OpenClaw)                  │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐          │
│  │ MCP Client  │  │ MCP Client  │  │ MCP Client  │          │
│  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘          │
└─────────┼────────────────┼────────────────┼─────────────────┘
          │ JSON-RPC       │ JSON-RPC       │ JSON-RPC
          ▼                ▼                ▼
   ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
   │ MCP Server A │ │ MCP Server B │ │ MCP Server C │
   │ Tools        │ │ Resources    │ │ Prompts      │
   │ Resources    │ │ Tools        │ │ Tools        │
   └──────────────┘ └──────────────┘ └──────────────┘
  • Tools(工具):模型可主动调用的函数,如 read_filequery_databasesend_http_request。带 JSON Schema 输入描述,返回结构化或文本结果。
  • Resources(资源):模型可被动读取的上下文,如配置文件、日志片段、数据库 schema 快照。通过 URI 标识(file:///project/README.md),由 Client 按需拉取。
  • Prompts(提示模板):预置的多轮对话模板,如「代码审查」「SQL 生成」,Host 可一键注入,减少重复 Prompt 工程。

JSON-RPC 2.0 与传输层

所有 MCP 消息统一为 JSON-RPC 2.0。常见方法包括 initializetools/listtools/callresources/listresources/readprompts/listprompts/get

// 连接生命周期:initialize → initialized → 业务调用 → 关闭

// 1. Client 发起握手
{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": { "protocolVersion": "2024-11-05", "capabilities": {}, "clientInfo": { "name": "cursor", "version": "1.0" } } }

// 2. Server 响应能力集
{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2024-11-05", "capabilities": { "tools": {} }, "serverInfo": { "name": "my-server", "version": "0.1.0" } } }

// 3. 调用工具
{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
  "params": { "name": "say_hello", "arguments": { "name": "MacDate" } } }

传输层两种主流模式:STDIO(Host 以子进程拉起 Server,stdin/stdout 传 JSON-RPC,适合本地开发)与 HTTP + SSE(远程 Server、多租户网关,Client 通过 SSE 收 Server 推送)。2026 年规范还引入了 Streamable HTTP,进一步简化双向流式通信。

04 · MCP vs OpenAI FC vs LangChain 对比表

选型时常见疑问:「我已有 OpenAI Function Calling,还要 MCP 吗?」「LangChain Tool 够不够用?」下表从架构师视角对比三者:

维度 OpenAI Function Calling LangChain Tools MCP
定位 单模型宿主内置能力 Python 框架层工具抽象 跨宿主开放协议
发现机制 静态 Schema 嵌入请求 代码内注册,运行时枚举 运行时 tools/list(机读)
跨 Host 复用 仅 OpenAI API / ChatGPT 需重写各宿主适配器 一次实现,多 Host 加载
Resources / Prompts 无原生支持 通过 Retriever / Template 模拟 协议级一等公民
传输 HTTP API 内嵌 进程内调用 STDIO / HTTP+SSE / Streamable HTTP
生态规模(2026 中) 宿主私有 数千 PyPI 集成 10,000+ Server
适用场景 纯 OpenAI 栈快速验证 自研 Agent 框架内编排 多 Host、企业 Catalog、长期维护

硬核数据快照: 采用 MCP 统一工具层的团队,报告集成成本下降 38%–55%;同一 Server 接到 Cursor 与 Claude Desktop 的重复开发工作量减少约 70%;公网扫描显示未授权暴露的 MCP Server 约 1,000+——部署前必须在隔离环境验收权限边界。

05 · 开发环境搭建

Python vs TypeScript 选型

官方 SDK 覆盖 Python(mcp)TypeScript(@modelcontextprotocol/sdk)。Python 侧 FastMCP 装饰器语法简洁,适合数据工程与 AI 脚本;TypeScript 适合 Node 生态与前端团队。本文以 Python + FastMCP 为主,TS 读者可对照 SDK 文档平移概念。

虚拟环境与项目结构

mkdir my-mcp-server && cd my-mcp-server
python3 -m venv .venv
source .venv/bin/activate
pip install "mcp[cli]" pydantic httpx chromadb

推荐目录结构:

my-mcp-server/
├── server.py # FastMCP 入口
├── tools/ # 各工具模块
│ ├── calculator.py
│ ├── filesystem.py
│ ├── http_client.py
│ ├── database.py
│ └── datetime_tool.py
├── resources/ # Resource 处理器
├── prompts/ # Prompt 模板
├── tests/ # pytest 单元测试
├── pyproject.toml
└── Dockerfile

MCP Inspector、Cursor 与 Claude Desktop

MCP Inspector 是官方调试 UI,可独立连接 STDIO 或 HTTP Server,可视化 tools/listtools/call

npx @modelcontextprotocol/inspector python server.py

Cursor~/.cursor/mcp.json(或项目级 .cursor/mcp.json)注册 Server。Claude Desktop 使用 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)。二者格式类似,下文 Hello World 节给出完整示例。

06 · Hello World:第一个 MCP Server

用 FastMCP 实现最小可运行 Server,包含一个 say_hello 工具:

# server.py
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("hello-server")

@mcp.tool()
def say_hello(name: str = "World") -> str:
    """向指定名称打招呼。"""
    return f"Hello, {name}! MCP Server is running."

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

本地启动与 Inspector 验证:

python server.py
# 另开终端
npx @modelcontextprotocol/inspector python server.py

在 Inspector 中点击 ConnectList Tools → 调用 say_hello 并传入 {"name": "MacDate"},应返回问候语。

Cursor 配置示例

// ~/.cursor/mcp.json
{
  "mcpServers": {
    "hello-server": {
      "command": "/path/to/my-mcp-server/.venv/bin/python",
      "args": ["/path/to/my-mcp-server/server.py"]
    }
  }
}

Claude Desktop 配置结构相同,路径改为上述 macOS 配置文件。重启 Host 后,在对话中应能看到 say_hello 工具可用。若你同时在 OpenClaw 网关侧管理 MCP,请对照 OpenClaw MCP 接入与安全配置 统一审批模板。

07 · Tools:五种典型工具实现

Tool 结构与 Pydantic 输入校验

FastMCP 用 Python 类型注解自动生成 JSON Schema。复杂参数可用 Pydantic BaseModel

from pydantic import BaseModel, Field

class CalcInput(BaseModel):
    expression: str = Field(description="数学表达式,如 2+3*4")

@mcp.tool()
def calculator(input: CalcInput) -> str:
    """安全计算器,仅允许数字与四则运算。"""
    import re
    if not re.match(r'^[\d\s+\-*/().]+$', input.expression):
        raise ValueError("非法字符")
    return str(eval(input.expression))

五种工具一览

工具名 用途 关键实现
calculator 安全四则运算 正则白名单 + eval 沙箱
read_file 读取工作区文件 路径规范化 + 根目录约束
http_get 代理 HTTP 请求 httpx 异步 + 超时/域名白名单
query_db 只读 SQL 查询 sqlite3 / asyncpg + 参数化
current_time 返回指定时区时间 zoneinfo + ISO 8601 格式

文件工具示例

from pathlib import Path

WORKSPACE = Path("/safe/workspace").resolve()

@mcp.tool()
def read_file(path: str) -> str:
    """读取工作区内文件内容。"""
    target = (WORKSPACE / path).resolve()
    if not str(target).startswith(str(WORKSPACE)):
        raise ValueError("路径越界")
    return target.read_text(encoding="utf-8")

异步工具与错误处理

IO 密集型工具应使用 async def,FastMCP 会自动调度:

@mcp.tool()
async def http_get(url: str) -> str:
    """GET 请求,5 秒超时。"""
    import httpx
    async with httpx.AsyncClient(timeout=5.0) as client:
        try:
            resp = await client.get(url)
            resp.raise_for_status()
            return resp.text[:8000]
        except httpx.HTTPError as e:
            return f"HTTP 错误: {e}"

错误应返回可读文本而非裸抛异常(除非参数校验失败),便于模型在对话中向用户解释并重试。

08 · Resources:只读上下文

Resource vs Tool 的分工

Tool 是模型主动决策调用的动作(副作用:写文件、发 HTTP、改数据库)。Resource 是模型按需读取的上下文(无副作用:配置文件、schema 文档、日志 tail)。Host 可在对话开始时预拉 Resource,减少 Token 浪费。

URI Scheme 与静态/动态 Resource

  • 静态 Resource:固定 URI,如 config://app/settings.json,内容相对固定。
  • 动态 Resource:URI 带参数或使用 Resource Template,如 log://app/{date},内容随请求变化。
  • 文件系统 Server:官方 @modelcontextprotocol/server-filesystem 将目录映射为 file:// Resource,适合只读暴露项目文档。
@mcp.resource("config://app/settings")
def get_settings() -> str:
    """返回应用配置 JSON。"""
    import json
    return json.dumps({"env": "production", "debug": False})

@mcp.resource("schema://db/{table_name}")
def get_table_schema(table_name: str) -> str:
    """动态返回指定表的 DDL。"""
    return f"CREATE TABLE {table_name} (...);"

09 · Prompts:可复用对话模板

Prompts 让 Host 一键注入多轮对话结构,减少重复 Prompt 工程。与 Cursor 的 Agent Skill 互补:Skill 编排「何时用什么能力」,MCP Prompt 提供「标准对话骨架」。

@mcp.prompt()
def code_review_prompt(language: str = "Python") -> str:
    """生成代码审查 Prompt 模板。"""
    return f"""你是一位资深 {language} 代码审查专家。请按以下结构审查用户提交的代码:
1. 安全漏洞(SQL 注入、路径遍历、密钥硬编码)
2. 性能问题(N+1 查询、阻塞 IO)
3. 可读性与命名
4. 测试覆盖建议
请用中文输出,每条发现附带行号与修复建议。"""

多轮 Prompt 可通过返回多条 Message 实现:FastMCP 支持 list[PromptMessage],第一条设 system 角色,后续设 user 角色,Host 按序注入对话历史。

10 · HTTP 传输与安全

STDIO vs HTTP+SSE 对比

维度 STDIO HTTP + SSE Streamable HTTP(2026)
部署位置 本地子进程 远程服务器 / 容器 远程,单端点双向流
多 Client 共享 每 Host 独立进程 多 Client 连同一 Server 同左,连接管理更简
认证 进程级(谁启动谁负责) Bearer Token / mTLS / OAuth 同 HTTP+SSE
适用场景 桌面 Host、敏感本地工具 企业内网、SaaS 网关 新部署首选
负载均衡 不适用 需会话粘性 改进中

HTTP Server 启动示例(FastMCP):

# 生产环境用 uvicorn 或 mcp 内置 HTTP 模式
mcp run server.py --transport streamable-http --port 8080

安全要点: 公网暴露的 MCP Server 必须启用认证(Bearer Token 或 OAuth 2.1);工具层实施域名白名单、路径沙箱、SQL 只读;审计日志记录每次 tools/call 的参数与调用方。2026 年扫描显示 1,000+ 未授权 Server 裸奔——切勿把内网 API Key 直接写进无鉴权的 HTTP Server。

11 · 调试测试与常见错误

MCP Inspector 工作流

  1. Connect:选择 STDIO 命令或 HTTP URL,确认 initialize 握手成功。
  2. List Tools / Resources / Prompts:核对能力集与 JSON Schema 是否符合预期。
  3. Call Tool:手动传入参数,观察返回与错误信息。
  4. Notifications:若 Server 支持进度推送,在此面板查看。
  5. Export Log:导出 JSON-RPC transcript 供团队复盘。

pytest 单元测试示例

# tests/test_tools.py
import pytest
from server import calculator

def test_calculator_basic():
    from server import CalcInput
    result = calculator(CalcInput(expression="2+3*4"))
    assert result == "14"

def test_calculator_rejects_injection():
    with pytest.raises(ValueError):
        calculator(CalcInput(expression="__import__('os')"))

常见错误对照表

现象 可能原因 排查步骤
Host 看不到工具 配置路径错误、Python 非 venv 检查 mcp.json 绝对路径;Inspector 先验证
Connection closed Server 启动崩溃、stderr 污染 stdout 单独运行 python server.py 看 traceback
tools/call 超时 同步阻塞 IO、无超时设置 改 async + httpx timeout;数据库加 statement_timeout
HTTP 401 Token 缺失或过期 核对 Authorization 头;轮换 Key
Schema 校验失败 Pydantic 字段名与模型输出不匹配 Inspector 查看 tools/list 的 inputSchema

12 · 生产部署

Docker 打包

# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY pyproject.toml .
RUN pip install --no-cache-dir .
COPY . .
EXPOSE 8080
CMD ["mcp", "run", "server.py", "--transport", "streamable-http", "--port", "8080"]

云平台选型

  • Railway / Render:零配置容器部署,适合 MVP 与 PoC,按用量计费。
  • AWS Lambda / Google Cloud Run:无服务器,冷启动需优化 Server 体积;Cloud Run 支持 SSE 长连接更友好。
  • VPS(DigitalOcean / Hetzner):完全控制,适合 mTLS 内网网关;需自建监控与日志。

监控与版本化:serverInfo.version 中语义化版本(SemVer);接入 Prometheus 或云厂商 APM 记录 tools/call 延迟 P99;灰度发布时新旧 Server 并行注册到 Host Catalog,对比错误率后再切换。

13 · 知识库实战:ChromaDB / Qdrant

企业 Agent 最常见的 MCP Server 场景是向量知识库:把内部文档 embedding 后供模型检索。以下以 ChromaDB 为例(Qdrant 接口类似,换客户端即可)。

import chromadb
from chromadb.utils import embedding_functions

client = chromadb.PersistentClient(path="./chroma_data")
ef = embedding_functions.DefaultEmbeddingFunction()
collection = client.get_or_create_collection("docs", embedding_function=ef)

@mcp.tool()
def index_document(doc_id: str, text: str) -> str:
    """写入文档到向量库。"""
    collection.upsert(ids=[doc_id], documents=[text])
    return f"已索引: {doc_id}"

@mcp.tool()
def search_knowledge(query: str, top_k: int = 5) -> str:
    """语义检索知识库。"""
    results = collection.query(query_texts=[query], n_results=top_k)
    docs = results["documents"][0]
    return "\n---\n".join(docs or ["无结果"])

Embedding 模型可选 OpenAI text-embedding-3-small(1536 维)或本地 sentence-transformers。ChromaDB 默认使用 all-MiniLM-L6-v2(384 维),单条 512 token 切片是常见实践;索引 10 万页文档约需 2–4 GB 磁盘与 8 GB 内存。生产环境建议 Qdrant 集群 + 副本,ChromaDB 适合单机 PoC。

14 · 生态与学习路径

推荐社区 Server

  • @modelcontextprotocol/server-filesystem — 文件读写与 Resource
  • @modelcontextprotocol/server-postgres — 只读 SQL 查询
  • @modelcontextprotocol/server-slack — Slack 消息与频道
  • @modelcontextprotocol/server-github — Issue / PR / 代码搜索
  • mcp-server-fetch — HTTP 抓取与 HTML 转 Markdown

2026 趋势与学习路径

趋势: Streamable HTTP 取代纯 SSE 成为新部署默认;OAuth 2.1 设备流进入主流 Host;企业 Catalog 与 Server 签名/审计成为合规标配;MCP 与 A2A(Agent-to-Agent)在同一栈分层共存。

建议学习路径(约 2 周):

  1. 阅读 MCP 协议架构解析,理解 Host / Client / Server 三层。
  2. 跟做本文 Hello World → Tools 五件套,Inspector 验收。
  3. 接入 Cursor,跑通真实业务场景(读 README + 查库 + HTTP)。
  4. 实现 ChromaDB 知识库 Server,对比检索准确率。
  5. Docker + HTTP 部署到 Railway,配置 Bearer 认证。
  6. 在隔离 Mac 节点做 Catalog 彩排,写入 ADR 后推进生产。

15 · 结语:在隔离 Mac 上练熟再上线

虽然你可以在 Windows WSL、Linux 容器或主力 Mac 上直接开发 MCP Server,但主力机混装 OAuth、生产 API Key 与多款 Host 全局配置,一次误配就可能让 tools/call 在后台 cron 里访问内网;WSL 文件系统权限与 macOS Seatbelt 沙箱体验也不等价。公网扫描已发现 1,000+ 未授权暴露的 Server——在污染生产凭证之前,用隔离环境验证「哪些 Server 值得进白名单」是更稳妥的工程纪律。

MCP 让你写一次 Server、多 Host 复用,但开发体验同样重要:Cursor 与 Claude Desktop 的 MCP 配置路径、STDIO 子进程行为、Keychain 凭证存储都是 macOS 原生体验。若你需要可审计的「多 Server × 多 Host 对照实测」证据,又与 Xcode / Apple 工具链同周期协作,在独立 macOS 租用节点完成 1–3 天 MCP 开发彩排再推进企业 Catalog,通常比直接在办公笔记本上叠装 Server 更轻、比裸容器更接近真实桌面 Host 行为。

五步 Mac 隔离 MCP 开发验收(HowTo)

  1. 租用隔离 macOS:Mac mini M4 起,SSH 接入;本地用户、Apple ID 与 OAuth 与主力机完全隔离。套餐见 M 系列算力定价
  2. 部署开发环境:安装 Python 3.12、Node(Inspector)、Cursor;创建独立 venv,不共享主力机 ~/.config
  3. 并行开发多个 Server:在同一节点实现 Hello World、Tools 五件套与 ChromaDB 知识库,Inspector 导出 tools/list 快照。
  4. Cursor / Claude Desktop 联调:注册 STDIO Server,跑固定任务包(读文件、查库、语义检索),记录延迟与越权拦截。
  5. 导出 ADR 并释放:将 Server 白名单、OAuth 范围与数据分级写入架构决策记录,吊销测试 Key、退租擦盘。