跳到主要内容

MCP知识体系与实战指南

生成日期:2026-05-09
资料口径:联网核对官方来源后整理。MCP 官方规范当前最新版本为 2025-11-25。优先采用 Model Context Protocol 官方站点、官方 GitHub SDK、Anthropic/OpenAI 官方文档。

阅读目标:先建立 MCP 的完整认知框架,再能独立写一个本地 MCP Server、接入客户端、调试、做安全评审,并判断什么时候该做本地 stdio、什么时候该做远程 Streamable HTTP。


1. 一句话理解 MCP​

MCP(Model Context Protocol)是一个开放协议,用标准方式把 LLM 应用连接到外部数据、工具和工作流。

它解决的问题不是“怎么调用某个模型”,而是:

  • LLM 应用如何发现外部能力。
  • 外部系统如何声明可用工具、资源、提示词。
  • 工具参数、返回值、错误、权限、生命周期如何标准化。
  • 本地工具和远程服务如何用统一协议接入不同 AI 客户端。

可以把 MCP 理解为 AI 应用生态里的“上下文与工具连接协议”。类似 LSP 统一编辑器和语言服务的连接方式,MCP 统一 LLM Host 和外部能力的连接方式。


2. 先把术语讲清楚​

2.1 三个核心角色​

用户
|
v
Host:AI 应用,例如 Claude Desktop、IDE、ChatGPT、内部 Agent 平台
|
| 一个 Host 可以管理多个 MCP Client 连接
v
Client:Host 内部的连接器,每个 Client 通常对应一个 Server 会话
|
| JSON-RPC 2.0 over stdio / Streamable HTTP
v
Server:暴露工具、资源、提示词等能力的程序或远程服务
  • Host:用户实际使用的 AI 产品或 Agent 容器,负责 UI、用户授权、模型调用、连接生命周期。
  • Client:Host 内部实现 MCP 协议的一端,负责与一个 MCP Server 通信。
  • Server:提供能力的一端,可以是本地进程,也可以是远程 HTTP 服务。

2.2 MCP Server 能暴露什么​

Server 主要暴露三类能力:

能力控制方用途例子
Tools模型可发起,Host 应要求用户确认高风险动作执行动作、查询 API、计算search_docs、create_ticket、query_db
Resources应用/用户/模型按实现选择读取给模型补上下文文件、数据库 schema、文档片段、日志
Prompts用户显式选择更合理可复用提示词模板代码审查模板、SQL 诊断模板

Client 也可以暴露能力给 Server:

能力方向用途
RootsClient -> Server告诉 Server 可访问的工作区边界
SamplingServer -> Client -> LLMServer 请求 Client 代为调用模型
ElicitationServer -> Client -> 用户Server 通过 Client 向用户要额外信息

3. MCP 的分层知识体系​

3.1 Base Protocol​

MCP 基于 JSON-RPC 2.0:

  • Request:有 id,期待 Response。
  • Response:同一个 id 返回 result 或 error。
  • Notification:没有 id,不期待响应。
  • 消息必须 UTF-8 编码。
  • MCP 的 id 不能是 null,同一会话内请求方不能复用请求 ID。

MCP 还规定了生命周期:

  1. Client 建立传输连接。
  2. Client 发送 initialize,声明协议版本、客户端信息、能力。
  3. Server 返回协议版本、服务端信息、能力。
  4. Client 发送 initialized 通知。
  5. 双方进入正常交互阶段。
  6. 结束连接,释放资源。

3.2 Capability Negotiation​

MCP 的能力必须协商。不要假设对方支持某功能。

常见能力:

  • Server:tools、resources、prompts、logging、completions、tasks。
  • Client:roots、sampling、elicitation、tasks。

工程原则:

  • Server 没声明 tools,Client 不该调用 tools/list。
  • Client 没声明 sampling,Server 不该发 sampling/createMessage。
  • 支持 listChanged 才发送列表变更通知。
  • 支持 tasks 才做异步任务增强请求。

3.3 Schema​

MCP 大量使用 JSON Schema:

  • 工具输入:inputSchema。
  • 工具结构化输出:outputSchema。
  • elicitation 表单:受限制的 JSON Schema 子集。
  • 默认 schema dialect:JSON Schema 2020-12。
  • 显式 $schema 可以指定别的 dialect,但实现至少应支持 2020-12。

实战建议:

  • 工具参数 schema 要严格,尽量 additionalProperties: false。
  • 不要把自然语言描述当校验逻辑。
  • 对外部输入做二次校验,schema 只是第一层。
  • 返回结构化数据时同时提供 structuredContent 和可读 content,兼容旧客户端。

4. 传输层:stdio 与 Streamable HTTP​

4.1 stdio​

stdio 是本地 MCP Server 最常见的传输方式。

机制:

  • Host/Client 启动 Server 子进程。
  • Client 写 Server 的 stdin。
  • Server 写 stdout。
  • 每行是一条 JSON-RPC 消息。
  • 日志只能写 stderr 或文件,不能写 stdout。

适用场景:

  • 本地文件系统工具。
  • 本地 Git/代码库工具。
  • 只给单个用户本机使用的工具。
  • IDE、桌面应用、CLI Agent。

关键禁忌:

  • Python 不要 print() 到 stdout,除非明确输出 MCP JSON-RPC。
  • TypeScript 不要 console.log() 到 stdout。
  • 日志用 stderr、标准 logging、文件日志。

4.2 Streamable HTTP​

Streamable HTTP 是远程/生产部署更重要的传输方式。官方规范中它取代了早期的 HTTP+SSE 传输。

机制:

  • Server 提供一个 MCP endpoint,例如 /mcp。
  • Client 用 HTTP POST 发送 JSON-RPC 消息。
  • Server 可以返回 JSON,也可以返回 SSE 流。
  • Client 可以 GET endpoint 来接收 Server 主动消息。
  • 支持 session、恢复、重连、轮询式 SSE。

适用场景:

  • 多用户远程 MCP 服务。
  • 企业内统一工具平台。
  • SaaS 给 AI Host 提供官方 MCP Server。
  • ChatGPT/Claude API 等远程连接。

生产要求:

  • 必须校验 Origin,防 DNS rebinding。
  • 本地 HTTP Server 默认绑定 127.0.0.1,不要裸绑 0.0.0.0。
  • 远程 Server 必须做认证授权。
  • 浏览器客户端要正确设置 CORS,并暴露 Mcp-Session-Id。

5. Server Features:Tools、Resources、Prompts​

5.1 Tools​

Tools 是 MCP 最常用、也最危险的能力。它让模型能调用外部函数。

工具定义包含:

  • name:唯一名称,建议只用 ASCII 字母、数字、_、-、.。
  • title:给 UI 展示的人类可读名称。
  • description:功能说明,会影响模型是否调用。
  • inputSchema:参数 JSON Schema。
  • outputSchema:可选,结构化输出 schema。
  • annotations:可选的行为描述,不应被无条件信任。
  • execution.taskSupport:是否支持 task-augmented execution。

常用协议方法:

  • tools/list:列工具。
  • tools/call:调用工具。
  • notifications/tools/list_changed:工具列表变更通知。

工具错误分两类:

  • Protocol Error:未知工具、请求结构错误、协议级错误。
  • Tool Execution Error:业务错误、输入不合法、外部 API 失败,返回 isError: true,模型可能据此自我修正后重试。

设计工具的核心原则:

  • 小而准:一个工具只做一个明确动作。
  • 参数强约束:枚举、格式、范围、必填字段都写进 schema。
  • 描述写“何时使用/何时不用”,不要只写“调用某 API”。
  • 高风险写操作必须让 Host/用户可确认。
  • read 与 write 分开,不要一个工具既查又改。
  • 不要把密钥、内部路径、系统提示词塞进 tool description。

5.2 Resources​

Resources 是 Server 暴露给 Client 的上下文数据。每个 resource 用 URI 唯一标识。

典型资源:

  • file:///repo/README.md
  • git://repo/commit/abc123
  • db://analytics/schema/orders
  • docs://product/api/auth

常用协议方法:

  • resources/list:列资源。
  • resources/read:读资源内容。
  • resources/templates/list:列参数化 URI 模板。
  • resources/subscribe:订阅资源变更。
  • notifications/resources/updated:资源更新。
  • notifications/resources/list_changed:资源列表更新。

Resource 内容可以是:

  • text:文本。
  • blob:base64 二进制。

实战建议:

  • 大文档不要一次塞完整,优先暴露搜索工具 + fetch 工具。
  • URI 要稳定,便于缓存和引用。
  • MIME type 要准确,例如 text/markdown、application/json。
  • 私有资源必须按用户身份过滤。
  • 不要让 Resource 绕过 Tool 的权限控制。

5.3 Prompts​

Prompts 是 Server 提供的可复用提示词模板,通常由用户显式选择。

常用协议方法:

  • prompts/list:列模板。
  • prompts/get:按参数生成 prompt messages。
  • notifications/prompts/list_changed:模板列表变更。

适用场景:

  • 固化高质量工作流,例如“代码审查”“生成迁移方案”“事故复盘”。
  • 把团队内部方法论封装为可选择模板。
  • 将 Resource 嵌入 Prompt,形成可靠上下文。

Prompt 设计建议:

  • 模板参数要少,参数名明确。
  • 输出格式要求写清楚。
  • 不要把敏感策略或密钥写进 prompt。
  • 让用户能看见并选择,而不是暗中自动注入。

6. Client Features:Roots、Sampling、Elicitation​

6.1 Roots​

Roots 是 Client 告诉 Server 的文件系统边界。

作用:

  • Server 可以知道当前工作区有哪些目录。
  • Server 应只在这些边界内读写。
  • Roots 变更时,Client 可通知 Server。

实战建议:

  • 本地文件工具必须把 roots 当权限边界,而不是 UI 提示。
  • 路径要 canonicalize,防 ..、symlink、大小写绕过。
  • 默认最小权限,只暴露当前项目,不暴露整个 home 目录。

6.2 Sampling​

Sampling 允许 Server 请求 Client 代为调用 LLM。

典型用途:

  • Server 内部需要模型判断,但不想持有模型 API key。
  • Server 想把部分推理交给 Host 控制的模型。
  • Server 实现复杂 agentic workflow。

安全原则:

  • 用户应能查看和拒绝 sampling 请求。
  • 用户应能查看/编辑即将发给模型的 prompt。
  • Server 不应假设可以访问任意模型。
  • Client 应控制模型选择、token、权限和可见上下文。

最新规范点:

  • 2025-11-25 增强了 sampling 的 tool calling 支持。
  • includeContext: "thisServer" / "allServers" 属于 soft-deprecated,用时要谨慎。

6.3 Elicitation​

Elicitation 允许 Server 通过 Client 向用户索取额外信息。

两种模式:

  • Form mode:Client 展示表单,收集结构化非敏感信息。
  • URL mode:跳转到外部 URL,处理敏感凭据、OAuth、支付等流程。

重点:

  • Form mode 不能索要密码、API key、access token、支付凭据。
  • 敏感信息必须走 URL mode,且用户要看到目标域名并授权跳转。
  • Server 不能只靠 session ID 绑定敏感状态,应绑定真实用户身份或授权上下文。

7. 2025-11-25 规范重点变化​

这一版相对 2025-06-18 的关键变化:

  • 增强授权服务器发现,支持 OpenID Connect Discovery。
  • tools/resources/prompts/resource templates 增加 icons 元数据。
  • 授权流增加基于 WWW-Authenticate 的增量 scope consent。
  • 明确工具命名建议。
  • Elicitation enum/schema 更贴近标准 JSON Schema。
  • 新增 URL mode elicitation。
  • Sampling 支持 tool calling。
  • 新增 OAuth Client ID Metadata Documents,作为推荐 client registration 机制之一。
  • 新增实验性 Tasks,用于持久请求、轮询和延迟结果获取。
  • JSON Schema 2020-12 成为默认 dialect。
  • Streamable HTTP 的 Origin 校验、SSE 轮询/恢复说明更明确。
  • 安全最佳实践更新。

8. Tasks:异步和长任务​

Tasks 是 2025-11-25 新增的实验能力,适合耗时任务。

适用场景:

  • 大文件索引。
  • 批量数据导入。
  • 长时间报表计算。
  • 异步外部 API workflow。

基本模型:

  1. 请求方在原请求参数里加 task。
  2. 接收方立即返回 taskId 和状态。
  3. 请求方用 tasks/get 查状态。
  4. 完成后用 tasks/result 取结果。
  5. 可选 notifications/tasks/status 主动通知状态变化。
  6. 可用 tasks/cancel 取消。

状态:

  • working
  • input_required
  • completed
  • failed
  • cancelled

安全要求:

  • taskId 必须不可预测。
  • 有授权上下文时,task 必须绑定用户/客户端身份。
  • tasks/list 只能返回当前请求方有权访问的任务。
  • 没有身份绑定能力的服务,不建议声明 tasks.list。
  • 设置 TTL、并发上限、轮询限流、审计日志。

9. 授权与安全体系​

9.1 授权​

MCP Authorization 主要针对 HTTP-based transport。stdio 不走这套授权,通常从环境变量或本地配置取凭据。

HTTP MCP 中:

  • MCP Server 作为 OAuth Resource Server。
  • MCP Client 作为 OAuth Client。
  • Authorization Server 负责用户认证和发 token。
  • 规范基于 OAuth 2.1、RFC 8414、RFC 7591、RFC 9728、OAuth Client ID Metadata Documents 等标准子集。

生产建议:

  • 远程 MCP Server 默认要求 HTTPS。
  • token audience 必须绑定到 MCP Server。
  • 不要做 token passthrough。
  • scope 最小化。
  • 每个用户、每个客户端、每个下游 API 单独记录授权关系。

9.2 高风险攻击面​

风险解释防护
Prompt Injection外部网页/邮件/文档夹带恶意指令,诱导模型调用工具泄露数据工具最小权限、写操作确认、敏感数据隔离、输出过滤
Confused DeputyMCP proxy 代用户访问第三方 API 时,被恶意 client 借权per-client consent、严格 redirect URI、CSRF state、scope 展示
Token PassthroughServer 接受不是发给自己的 token 并转发禁止;校验 issuer/audience/scope
SSRF恶意 Server 让 Client 拉内网/metadata URLHTTPS、私网 IP 阻断、redirect 校验、egress proxy
Session Hijacking攻击者拿到 session ID 后冒用session 不当认证凭据;绑定用户;安全随机;过期轮换
Local Server Compromise一键安装/启动本地恶意命令展示完整命令、用户确认、危险命令警告、沙箱
Tool Definition Abuse工具描述或 annotation 欺骗 Host/模型不信任未知 Server 的 annotations;用户确认高风险操作

9.3 安全评审清单​

上线前逐项检查:

  • Server 来源可信,依赖包可信。
  • 本地 stdio Server 没有向 stdout 写日志。
  • HTTP Server 校验 Origin。
  • 本地 HTTP Server 只绑定 127.0.0.1。
  • 远程 HTTP Server 只走 HTTPS。
  • 每个 tool 都有严格 inputSchema。
  • 写操作 tool 独立命名,且明显可识别。
  • destructive 操作需要用户确认。
  • 不在 tool description/resource/prompt 中暴露密钥。
  • 不接受未发给本 MCP Server 的 token。
  • token 校验 issuer、audience、scope、expiry。
  • task、session、resource 都绑定用户授权上下文。
  • SSRF 防护覆盖 OAuth metadata discovery 和 redirect。
  • 日志脱敏,避免记录 access token、API key、用户隐私。
  • 对外部 API 设置 timeout、重试、限流、熔断。
  • 有审计日志:谁在什么时候调用了什么 tool,输入输出摘要是什么。

10. 实战一:Python 写一个本地 MCP Server​

目标:写一个本地知识库工具,暴露两个工具:

  • search_notes(keyword):搜索当前目录下 .md 文件名和内容。
  • read_note(path):读取指定 Markdown 文件。

10.1 创建项目​

uv init mcp-notes-server
cd mcp-notes-server
uv add "mcp[cli]"

10.2 写 server.py​

from pathlib import Path
from typing import Any

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("notes-server")

ROOT = Path.cwd().resolve()


def safe_path(path: str) -> Path:
candidate = (ROOT / path).resolve()
if ROOT not in candidate.parents and candidate != ROOT:
raise ValueError("path is outside the allowed workspace")
return candidate


@mcp.tool()
def search_notes(keyword: str, limit: int = 20) -> list[dict[str, Any]]:
"""Search markdown notes in the current workspace by keyword."""
if not keyword.strip():
raise ValueError("keyword must not be empty")

results: list[dict[str, Any]] = []
for file in ROOT.rglob("*.md"):
if len(results) >= limit:
break
try:
text = file.read_text(encoding="utf-8", errors="ignore")
except OSError:
continue
if keyword.lower() in file.name.lower() or keyword.lower() in text.lower():
results.append(
{
"path": str(file.relative_to(ROOT)),
"title": file.stem,
"preview": text[:300],
}
)
return results


@mcp.tool()
def read_note(path: str) -> str:
"""Read a markdown note by relative path within the workspace."""
file = safe_path(path)
if file.suffix.lower() != ".md":
raise ValueError("only markdown files are allowed")
if not file.exists() or not file.is_file():
raise FileNotFoundError("file not found")
return file.read_text(encoding="utf-8", errors="ignore")


@mcp.resource("notes://index")
def notes_index() -> str:
"""List markdown files in the workspace."""
files = sorted(str(p.relative_to(ROOT)) for p in ROOT.rglob("*.md"))
return "\n".join(files)


@mcp.prompt()
def summarize_note(path: str) -> str:
return (
"请阅读这篇笔记,输出:核心观点、关键概念、可行动清单、"
f"未解决问题。笔记路径:{path}"
)


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

10.3 本地运行​

uv run server.py

stdio Server 直接运行后会等待 MCP JSON-RPC 输入,不会像普通 Web 服务那样输出提示信息。

10.4 用 MCP Inspector 调试​

npx @modelcontextprotocol/inspector uv --directory /ABSOLUTE/PATH/mcp-notes-server run server.py

在 Inspector 里检查:

  • Tools tab 是否出现 search_notes、read_note。
  • Resource tab 是否出现 notes://index。
  • Prompt tab 是否出现 summarize_note。
  • 调用 search_notes 是否返回结构清晰结果。
  • 输入非法路径,例如 ../../.ssh/id_rsa,是否被拒绝。

10.5 接入 Claude Desktop​

macOS 配置文件:

~/Library/Application Support/Claude/claude_desktop_config.json

Windows 配置文件:

%APPDATA%\Claude\claude_desktop_config.json

示例:

{
"mcpServers": {
"notes": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/mcp-notes-server",
"run",
"server.py"
]
}
}
}

重启 Claude Desktop 后,让它搜索某个关键词或读取某篇笔记。


11. 实战二:TypeScript 写一个 MCP Server​

适用:Node.js 生态、npm 分发、前端/平台团队更熟悉 TypeScript 的情况。

版本注意:TypeScript SDK 官方仓库的 main README 已经展示 v2 分包 API,并明确说明 v2 仍处于 pre-alpha;同时仓库 release 页显示 v1.x 仍是生产推荐线。下面示例按当前官方 README 的 v2 分包 API 编写,用于学习最新结构;生产项目应根据目标 Host 和 SDK 稳定性,优先 pin 官方推荐的稳定 v1.x,或在评估后再使用 v2。

11.1 创建项目​

mkdir mcp-notes-ts
cd mcp-notes-ts
npm init -y
npm install @modelcontextprotocol/server zod@4
npm install -D typescript @types/node

package.json:

{
"type": "module",
"scripts": {
"build": "tsc"
}
}

tsconfig.json:

{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true,
"skipLibCheck": true
},
"include": ["src/**/*.ts"]
}

11.2 写 src/index.ts​

import { McpServer } from "@modelcontextprotocol/server";
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
import { readFile, readdir } from "node:fs/promises";
import { resolve, relative, join } from "node:path";
import * as z from "zod/v4";

const root = process.cwd();

function safePath(input: string): string {
const candidate = resolve(root, input);
const rel = relative(root, candidate);
if (rel.startsWith("..") || rel === ".." || rel.startsWith("/")) {
throw new Error("path is outside the allowed workspace");
}
return candidate;
}

async function listMarkdownFiles(dir: string): Promise<string[]> {
const entries = await readdir(dir, { withFileTypes: true });
const files: string[] = [];

for (const entry of entries) {
const full = join(dir, entry.name);
if (entry.isDirectory()) {
files.push(...(await listMarkdownFiles(full)));
} else if (entry.isFile() && entry.name.endsWith(".md")) {
files.push(full);
}
}

return files;
}

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

server.registerTool(
"read_note",
{
description: "Read a markdown note by relative path inside the current workspace.",
inputSchema: z.object({
path: z.string().min(1),
}),
},
async ({ path }) => {
const full = safePath(path);
if (!full.endsWith(".md")) {
return {
isError: true,
content: [{ type: "text", text: "Only markdown files are allowed." }],
};
}
const text = await readFile(full, "utf8");
return {
content: [{ type: "text", text }],
};
},
);

server.registerTool(
"list_notes",
{
description: "List markdown note paths in the current workspace.",
inputSchema: z.object({}),
},
async () => {
const files = await listMarkdownFiles(root);
const paths = files.map((file) => relative(root, file));
return {
structuredContent: { paths },
content: [{ type: "text", text: JSON.stringify({ paths }, null, 2) }],
};
},
);

const transport = new StdioServerTransport();
await server.connect(transport);

11.3 构建和调试​

npm run build
npx @modelcontextprotocol/inspector node dist/index.js

stdio 模式下不要用 console.log() 打日志;需要日志用 console.error()。


12. 实战三:远程 Streamable HTTP Server​

Python 官方 SDK 支持 Streamable HTTP:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("remote-notes", stateless_http=True, json_response=True)


@mcp.tool()
def ping() -> dict[str, str]:
"""Health check tool."""
return {"status": "ok"}


if __name__ == "__main__":
mcp.run(transport="streamable-http")

默认路径通常是:

http://localhost:8000/mcp

远程上线要补齐:

  • TLS/HTTPS。
  • OAuth 或企业内认证。
  • Origin 校验。
  • CORS 白名单。
  • rate limit。
  • structured logs。
  • health check。
  • per-user authorization。
  • deployment secrets 管理。

13. 实战四:给 OpenAI / Anthropic 这类 Host 使用​

13.1 Anthropic Messages API MCP connector​

Anthropic 官方 Messages API 支持直接连接远程 MCP Server,但有边界:

  • 需要 beta header。
  • 支持远程 URL Server。
  • 目前重点支持 MCP tools。
  • 本地 stdio Server 不能被 API 直接连接。
  • 可配置 allowlist/denylist/per-tool settings。
  • OAuth token 由 API 调用方先获取并传入。

适合:

  • 你有公网 HTTPS MCP Server。
  • 你只需要暴露工具给 Claude API。
  • 不需要 Client 侧 roots、本地文件、prompts/resources 的完整控制。

13.2 OpenAI ChatGPT Apps / Responses API​

OpenAI 官方文档中,远程 MCP Server 可用于 ChatGPT Apps、deep research、API integrations。

典型数据类 MCP Server 需要实现:

  • search:返回候选结果。
  • fetch:按 ID 拉取完整内容和引用。

Responses API 使用 MCP 工具时,核心配置类似:

{
"tools": [
{
"type": "mcp",
"server_label": "docs",
"server_url": "https://example.com/sse/",
"allowed_tools": ["search", "fetch"],
"require_approval": "never"
}
]
}

注意:

  • Deep research/API 场景通常要求远程可访问。
  • 对自定义 MCP Server 要格外关注 prompt injection 和写操作风险。
  • 不要连接未知第三方代理的“某某官方服务 MCP”,优先选择服务商自己托管的官方 Server。

14. MCP Server 设计范式​

14.1 工具粒度​

差设计:

manage_database(query: string)

问题:权限过大、语义不清、不可审计。

好设计:

list_tables()
describe_table(table: enum)
run_readonly_query(sql: string)
create_report(name: string, query_id: string)

优势:

  • Host 能做更清晰的权限和确认。
  • 模型更容易选对工具。
  • 日志和审计更准确。
  • 更容易做 schema 校验。

14.2 Read 与 Write 分离​

只读工具:

  • search_docs
  • get_customer
  • list_orders
  • preview_email

写操作工具:

  • send_email
  • refund_order
  • delete_file
  • create_jira_ticket

写操作必须:

  • 名称明确。
  • 参数明确。
  • 支持 dry-run 或 preview。
  • 有用户确认。
  • 有幂等键或重复提交保护。

14.3 Search + Fetch 模式​

面向文档、知识库、RAG 的 MCP Server 推荐采用:

  1. search(query, filters):返回短列表,包含 id/title/url/snippet。
  2. fetch(id):返回完整内容、引用、元数据。

好处:

  • 降低上下文浪费。
  • 便于 deep research 类 Host 多轮检索。
  • 结果可引用。
  • 权限更容易按文档粒度控制。

14.4 Structured Output​

如果工具返回数据给后续程序使用,应提供结构化输出:

{
"structuredContent": {
"order_id": "ord_123",
"status": "paid",
"amount": 199.0
},
"content": [
{
"type": "text",
"text": "{\"order_id\":\"ord_123\",\"status\":\"paid\",\"amount\":199.0}"
}
]
}

同时保留 content 是为了兼容旧客户端和模型可读性。


15. 调试方法论​

15.1 先用 Inspector​

npx @modelcontextprotocol/inspector <command> <args>

检查项:

  • initialize 是否成功。
  • capabilities 是否符合预期。
  • tools/resources/prompts 是否能列出来。
  • tool schema 是否正确。
  • 非法输入是否返回 isError: true 或合理协议错误。
  • stdout 是否被日志污染。
  • notifications 是否正常。

15.2 再接真实 Host​

连接真实 Host 前先确认:

  • 绝对路径正确。
  • 运行命令在普通终端能启动。
  • 依赖已安装。
  • 环境变量存在。
  • API key 不写进配置文件。
  • Server 不依赖交互式输入。

15.3 常见问题​

问题可能原因处理
Host 找不到工具Server 未启动、initialize 失败、capability 未声明用 Inspector 看握手
JSON parse errorstdout 混入日志日志改 stderr
tool 调用后无响应外部 API 卡住timeout、错误捕获
路径读取越权未做 canonicalizeresolve 后检查 roots
HTTP 被网页攻击未校验 Origin403 拒绝非法 Origin
Claude/ChatGPT 不调用工具描述不清、schema 太宽、工具名不语义化重写 tool description

16. 学习路线​

阶段 1:基本认知​

  • 搞清 Host / Client / Server。
  • 理解 tools/resources/prompts。
  • 理解 stdio 和 Streamable HTTP。
  • 用 Inspector 连一个现成 filesystem server。

阶段 2:本地实战​

  • 写一个 Python FastMCP Server。
  • 暴露 2 个只读工具。
  • 接入 Claude Desktop 或支持 MCP 的 IDE。
  • 加路径安全检查。

阶段 3:生产化​

  • 改造成 Streamable HTTP。
  • 加 OAuth 或内部认证。
  • 加结构化日志、审计、限流、监控。
  • 做 tool 风险分级。

阶段 4:生态集成​

  • 适配 OpenAI/Anthropic 的远程 MCP 接入。
  • 实现 search/fetch 模式。
  • 发布 server metadata。
  • 设计企业内部 MCP Registry 或聚合层。

17. 权威资料索引​

官方规范与文档:

官方 SDK:

主流平台官方接入文档:


18. 最后给一个判断框架​

当你想做一个 MCP 集成时,先回答这 8 个问题:

  1. 这是本地能力还是远程服务?
  2. 主要是只读数据,还是会执行写操作?
  3. 用 tools、resources、prompts 中的哪一种最自然?
  4. 是否需要 search/fetch 两段式?
  5. 是否需要用户授权、OAuth、scope?
  6. 是否有 prompt injection 后可能造成的数据泄漏或破坏?
  7. 是否有长任务,需要 Tasks?
  8. 目标 Host 支持哪些 MCP 能力?不要只按协议理想状态设计。

最保守的默认方案:

  • 本地个人工具:stdio + 最小 roots + Inspector 调试。
  • 企业内部工具:Streamable HTTP + OAuth/SSO + 审计日志 + allowlist。
  • 文档知识库:search + fetch + read-only tools + 引用元数据。
  • 有写操作的业务系统:read/write 分离 + preview + confirmation + idempotency key。