Model Context Protocol (MCP) 是一个开源标准,用于连接 AI 应用和外部系统。就像 USB-C 为电子设备提供统一接口,MCP 为 AI 应用提供统一的外部系统连接方式。
"MCP is an open-source standard for connecting AI applications to external systems. Think of MCP like a USB-C port for AI applications."
假设你要让 Claude 访问 GitHub 数据。没有 MCP,你需要自己编写所有 GitHub 功能的 tool schema 和调用函数,涵盖 repositories、pull requests、issues、projects 等海量功能。
"Without MCP, you'd need to create an incredible number of tool schemas and functions to handle all of GitHub's features. That's a lot of effort and ongoing maintenance burden."
MCP 的解决方案:把工具定义和执行的负担从你的服务器转移到专门的 MCP Server。GitHub MCP Server 已经封装好所有功能,你只需连接即可。
"MCP servers provide tool schemas and functions already defined for you, while tool use is about how Claude actually calls those tools. The key difference is who does the work."
MCP 是开放协议,支持广泛的客户端和服务器。Claude、ChatGPT、VS Code、Cursor 等都支持 MCP,实现了 build once, integrate everywhere。
MCP 架构由三个角色组成:Host、Client、Server。理解它们的关系是掌握 MCP 的基础。
| 角色 | 说明 | 示例 |
|---|---|---|
| MCP Host | AI 应用本身 | Claude Desktop, VS Code, IDE |
| MCP Client | Host 内部的通信桥梁,每个 Server 对应一个 | SDK 提供的 ClientSession |
| MCP Server | 暴露工具/资源/提示词的程序 | GitHub Server, 文件系统 Server |
"The MCP client serves as the communication bridge between your server and MCP servers. It's your access point to all the tools that an MCP server provides."
MCP 是 transport agnostic(传输无关)的,客户端和服务器可以通过不同协议通信:
| 协议 | 适用场景 | 机制 |
|---|---|---|
| stdio | 本地,同一台机器 | 客户端启动服务器作为子进程,通过 stdin/stdout 通信,换行分隔 JSON-RPC |
| Streamable HTTP | 远程连接 | 单个 MCP endpoint,POST 发请求,GET 开 SSE 流接收服务器推送 |
MCP-Session-Id header 管理Last-Event-ID 断线重连MCP-Protocol-Version: 2025-11-25Origin header 防止 DNS rebinding 攻击| 消息 | 方向 | 用途 |
|---|---|---|
ListToolsRequest/Result | Client → Server | 询问服务器有哪些工具 |
CallToolRequest/Result | Client → Server | 执行指定工具 |
ReadResourceRequest/Result | Client → Server | 读取资源数据 |
GetPromptRequest/Result | Client → Server | 获取预构建提示词 |
用户问 "What repositories do I have?" 时的 12 步流程:
"Yes, this flow involves many steps, but each component has a clear responsibility. The MCP client abstracts away the complexity of server communication."
使用官方 Python SDK,通过装饰器定义工具,SDK 自动处理 JSON schema 生成。
"Instead of writing complex JSON schemas by hand, you can define tools with decorators and let the SDK handle the heavy lifting."
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("DocumentMCP", log_level="ERROR")
用 @mcp.tool 装饰器定义工具。SDK 根据 Python 类型提示和 Field 描述自动生成工具 schema:
@mcp.tool(
name="read_doc_contents",
description="Read the contents of a document and return it as a string."
)
def read_document(
doc_id: str = Field(description="Id of the document to read")
):
if doc_id not in docs:
raise ValueError(f"Doc with id {doc_id} not found")
return docs[doc_id]
@mcp.tool(
name="edit_document",
description="Edit a document by replacing a string."
)
def edit_document(
doc_id: str = Field(description="Id of the document"),
old_str: str = Field(description="The text to replace. Must match exactly."),
new_str: str = Field(description="The new text to insert.")
):
if doc_id not in docs:
raise ValueError(f"Doc with id {doc_id} not found")
docs[doc_id] = docs[doc_id].replace(old_str, new_str)
"The Python MCP SDK includes a built-in browser-based inspector that lets you debug and test your server in real-time."
mcp dev mcp_server.py
启动后在浏览器打开 http://127.0.0.1:6274,可以:
| 字段 | 说明 |
|---|---|
name | 1-128 字符,区分大小写,允许 A-Z a-z 0-9 _ - . |
title | 人类可读的显示名称 |
description | 工具的功能描述 |
inputSchema | JSON Schema(默认 2020-12),定义参数 |
outputSchema | 可选,声明返回值的 JSON Schema |
annotations | 附加元信息(如 audience、priority) |
taskSupport | forbidden / optional / required,控制长时间运行 |
工具结果支持多种类型:text、image (base64)、audio (base64)、resource_link、embedded resource、structuredContent。
Resources 让你向客户端暴露只读数据,类似 HTTP 服务器的 GET 请求处理器。它们由应用代码控制,而非模型。
"Resources in MCP servers allow you to expose data to clients, similar to GET request handlers in a typical HTTP server."
静态 URI,不需要参数:
@mcp.resource(
"docs://documents",
mime_type="application/json"
)
def list_docs() -> list[str]:
return list(docs.keys())
URI 中包含参数,SDK 自动解析并传递给函数:
@mcp.resource(
"docs://documents/{doc_id}",
mime_type="text/plain"
)
def fetch_doc(doc_id: str) -> str:
if doc_id not in docs:
raise ValueError(f"Doc with id {doc_id} not found")
return docs[doc_id]
| 类型 | 用途 |
|---|---|
application/json | 结构化数据 |
text/plain | 纯文本 |
application/pdf | 二进制文件 |
SDK 自动序列化返回值,不需要手动转 JSON。
async def read_resource(self, uri: str) -> Any:
result = await self.session().read_resource(AnyUrl(uri))
resource = result.contents[0]
if isinstance(resource, types.TextResourceContents):
if resource.mimeType == "application/json":
return json.loads(resource.text)
return resource.text
响应包含 MIME 类型,客户端据此决定如何解析内容。
"When a user mentions a document, your system automatically injects the document's contents into the prompt sent to Claude, eliminating the need for Claude to use tools to fetch the information."
用户输入 @document_name 时,系统自动将文档内容注入到 prompt 中,无需 Claude 额外调用工具。
服务器可以声明 subscribe 能力,客户端通过 resources/subscribe 监听资源变化:
notifications/resources/updated:某个资源内容变化notifications/resources/list_changed:可用资源列表变化Resource 还支持 annotations(audience、priority、lastModified)和 icons 字段。
Prompts 让你定义精心编写的指令模板,用户通过 slash 命令触发。比用户自己写的提示词更可靠。
"Users can already ask Claude to do most tasks directly. But they'll get much better results if you provide a thoroughly tested, specialized prompt that handles edge cases and follows best practices."
@mcp.prompt(
name="format",
description="Rewrites the document in Markdown format."
)
def format_document(
doc_id: str = Field(description="Id of the document to format")
) -> list[base.Message]:
prompt = f"""
Your goal is to reformat a document to be written with markdown syntax.
The id of the document you need to reformat is:
<document_id>
{doc_id}
</document_id>
Add in headers, bullet points, tables, etc as necessary.
Use the 'edit_document' tool to edit the document.
"""
return [base.UserMessage(prompt)]
async def list_prompts(self) -> list[types.Prompt]:
result = await self.session().list_prompts()
return result.prompts
async def get_prompt(self, prompt_name, args: dict[str, str]):
result = await self.session().get_prompt(prompt_name, args)
return result.messages
用户输入 /format plan.md,系统获取 prompt 消息列表,直接发送给 Claude 处理。
"Prompts work best when they're specialized for your MCP server's domain. The goal is to provide prompts that are so well-crafted that users prefer them over writing their own instructions."
Tools、Resources、Prompts 各由不同层级控制。选对原语是设计好 MCP 系统的关键。
"The key insight is that each primitive is controlled by a different part of your application stack."
| 原语 | 控制者 | 触发方式 | 数据方向 | 适用场景 |
|---|---|---|---|---|
| Tools | AI 模型 (Claude) | Claude 自主决定 | 双向(读写) | 搜索、计算、API 调用、文件操作 |
| Resources | 应用代码 | App 代码触发 | 只读 | 自动补全、上下文注入、UI 数据源 |
| Prompts | 用户 | 用户操作(slash/按钮) | 输入到模型 | 格式化、审查、报告等工作流 |
"You can see all three primitives in action in Claude's official interface. The workflow buttons demonstrate prompts, the Google Drive integration shows resources in action, and when Claude executes code, it's using tools."
| 能力 | 声明 | 可选特性 |
|---|---|---|
| Tools | capabilities.tools | listChanged 工具列表变化通知 |
| Resources | capabilities.resources | subscribe 订阅变化、listChanged |
| Prompts | capabilities.prompts | listChanged 提示词列表变化通知 |
客户端也有自己的原语:Sampling(让服务器请求 LLM 生成)、Elicitation(请求用户输入)、Logging(结构化日志)。
课程覆盖了 MCP 的核心概念和实战技能。以下是最值得记住的要点。
mcp = FastMCP("name")@mcp.tool,Field 描述每个参数mcp dev server.py,不需要写测试脚本list_tools() 和 call_tool()| 考点 | 关键答案 |
|---|---|
| MCP 的核心类比 | USB-C,统一的 AI 应用连接标准 |
| 三个角色 | Host (AI App) → Client (Bridge) → Server (Tools) |
| 两种传输 | stdio (本地) / Streamable HTTP (远程) |
| Tools 的控制者 | 模型 (Claude 自主决定调用) |
| Resources 的控制者 | 应用代码 (App 决定获取) |
| Prompts 的控制者 | 用户 (用户触发工作流) |
| MCP vs Tool Use | 互补:MCP 提供工具定义,Tool Use 是调用机制 |
| FastMCP 的优势 | 装饰器 + 类型提示 → 自动生成 JSON schema |
| MCP Inspector 命令 | mcp dev server.py |
| Resource URI 类型 | Direct (静态) vs Templated (含参数) |