EP09. "MCP 基础:不用自己写全套工具集成"
🔒 登录后可标记已读- 想让 Claude 操作 GitHub,光是 repositories、pull requests、issues、projects 这几块就要写一大堆 tool schema 和函数,要写、要测、要维护——MCP(Model Context Protocol) 就是让你不用全部自己来
- MCP 把「定义工具、执行工具」这个负担从你自己的 server 转移到专门的 MCP Server——它包了一层外部服务,提供 Claude 能直接用的现成工具,谁都能写一个 MCP Server(很多服务商会自己出官方实现)
- MCP 跟 tool use 是互补关系,不是同一件事:tool use 讲的是「Claude 怎么调用函数」,MCP 讲的是「这些函数是谁写的」——现成的还是你自己写的
- MCP Client 是沟通桥梁,负责把消息在你的程序和 MCP Server 之间传来传去,处理协议细节,通信方式跟具体走哪种传输协议无关(可以是标准输入输出、HTTP、WebSocket)
- 前置知识:EP04/EP05 的 tool use 基础(ToolUse/ToolResult 结构、schema 写法)
重点内容
MCP 解决什么问题
设想要让 Claude 操作 GitHub 的每一项功能——repositories、pull requests、issues、projects 等等——如果不用 MCP,就要自己写一大堆 tool schema 和对应函数,代码量可观,还要写测试、长期维护。
MCP 怎么运作
MCP 把「定义工具、执行工具」的负担从你的 server 转移给专门的 MCP Server。不用自己从零构建 GitHub 集成,直接接一个现成的 GitHub MCP Server 就行。
📌 MCP Server 本质上是外部服务的一层包装,提供一批 Claude 能直接使用的现成工具。
常见问题
谁在写 MCP Server? 任何人都可以实现一个 MCP Server,很多服务商自己会出官方实现。
这跟直接调 API 有什么不同? 直接调 API 还是得自己写 tool schema 和函数实现;MCP Server 已经把这些预先定义好了。
MCP 是不是跟 tool use 是同一回事? 不是。MCP Server 和 tool use 是互补但不同的概念——tool use 是 Claude 调用函数这件事本身;MCP 关心的是这些函数由谁提供——预先实现好的,而不是自己写的。
MCP Client:通信桥梁
协议本身跟传输方式无关(transport agnostic)。最常见的做法是 client 和 server 跑在同一台机器上,用标准输入输出通信;其他可选传输方式包括 HTTP、WebSocket 等网络协议。
Client 和 Server 之间交换的消息类型(MCP 规范里定义):
- ListToolsRequest / ListToolsResult:Client 询问有哪些可用工具,Server 回传完整的工具清单
- CallToolRequest / CallToolResult:Client 要求 Server 执行某个指定工具、带上指定参数,拿到执行结果
完整流程范例:查询 GitHub Repositories
用户问「我有哪些 repositories?」,完整流程走十一步:
- 用户把问题发给你的 server
- Server 透过
ListToolsRequest向 MCP client 询问有哪些可用工具 - Server 把用户问题 + 工具列表一起发给 Claude
- Claude 分析工具列表,请求执行某个特定工具
- Server 透过
CallToolRequest请 MCP client 执行这个工具 - MCP server 联系外部服务(GitHub)拿数据
- GitHub 回传 repository 信息
- MCP server 把回应包进
CallToolResult - MCP client 把工具执行结果传回 server
- Server 把结果发给 Claude,作为后续消息的一部分
- Claude 整理出最终回答给用户
📌 每个组件的职责都很清楚:MCP client 把复杂的通信细节都抽象掉了,你的 server 不用操心底层协议怎么跑。
动手项目:CLI 聊天机器人
课程接下来用一个实战项目串起 MCP 的 client 端和 server 端——一个命令行界面的聊天机器人,功能包括:
- 命令行聊天界面
- Claude 能读写文档
- 用
@doc_name语法「提及」某份文档 - 用
/command_name语法执行命令 - 一批存在内存里的假文档集合
三个主要组件:
- MCP Client:负责用户交互和聊天界面
- MCP Server:提供文档操作相关的工具
- Document Storage:内存里存的各类文件(PDF、表格、文本、markdown)
Server 实现两个核心工具:读文档内容、更新文档内容。所有文档都存在内存里,不落地磁盘。
📌 实务上通常只会实现 client 或 server 其中一边,这个项目两边都做只是为了教学目的,方便看清楚 client 和 server 之间到底怎么互动。
用 MCP Python SDK 定义工具
MCP 官方的 Python SDK 好处:用极少的样板代码就能建起 MCP server;能从 Python 函数签名自动生成 JSON schema,不用自己手写;用装饰器(decorator)简化工具定义;自动处理类型校验和错误处理。
建立 Server:
from mcp.server.fastmcp import FastMCP
from pydantic import Field
mcp = FastMCP("DocumentMCP", log_level="ERROR")
docs = {
"deposition.md": "This deposition covers the testimony of Angela Smith, P.E.",
"report.pdf": "The report details the state of a 20m condenser tower.",
"financials.docx": "These financials outline the project's budget and expenditures",
"outlook.pdf": "This document presents the projected future performance of the system",
"plan.md": "The plan outlines the steps for the project's implementation.",
"spec.txt": "These specifications define the technical requirements for the equipment"
}
读文档工具:
@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]
这个工具具备:有描述性的名字、说明功能的 description、带描述的有类型参数、对无效 ID 的错误处理。
编辑文档工具:
@mcp.tool(
name="edit_document",
description="Edit a document by replacing a string in the documents content with a new string."
)
def edit_document(
doc_id: str = Field(description="Id of the document that will be edited"),
old_str: str = Field(description="The text to replace. Must match exactly, including whitespace."),
new_str: str = Field(description="The new text to insert in place of the old text.")
):
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)
接收三个参数(文档 ID、要找的文字、替换的新文字),用 Python 内建的 replace() 方法做替换。
要记住的几个要点:
- 要用
Field(来自pydantic)写参数描述 - 用类型注解(type hints)指定参数类型
- 边界情况要有错误处理
- 工具名字和描述要写清楚、有描述性
- MCP Python SDK 会自动把函数签名转成合规的 JSON schema
⚠️ 注意跟 Claude Agent SDK 的差异:Claude Agent SDK 提供的是另一个独立的 @tool 装饰器,需要显式传 input_schema 参数(配合 pydantic Field 注解),跟这里 MCP Python SDK 的写法不一样,两者不要混淆。
用 Server Inspector 调试
写 MCP server 时,不想每次都接一整套完整应用才能测试——Python MCP SDK 内建一个基于浏览器的 inspector,能实时调试和测试 server。
启动方式:先激活项目的 Python 环境(具体做法看项目的 README),再跑:
mcp dev mcp_server.py
这会启动一个开发服务器,提供一个本地网址(6277 端口),在浏览器打开就是 inspector 界面。
💡 Inspector 还在持续开发中,界面之后可能会变,但核心功能是稳定的。
打开后先点左侧的 Connect 按钮初始化 MCP server、加载可用工具。连上之后导航栏会显示 Resources、Prompts、Tools 几个区块,进 Tools 区、点 List Tools 看到所有可用工具,选中某个工具会在右侧出现测试表单。
测试读文档工具:选 read_doc_contents → 填文档 ID(例如 "deposition.md")→ 点 Run Tool → inspector 执行并显示结果(状态和返回数据)。
测试编辑文档工具:切到 edit_document → 填文档 ID、要替换的旧文字、新文字 → 跑一次确认成功 → 再用读文档工具确认改动真的生效。
💡 Inspector 左侧会保留调用历史,方便追踪测过什么、重跑之前的操作。开发循环变成:改 server 代码 → 重启 inspector → 立刻测试工具 → 确认结果——不用为了简单测试就搭一整套完整应用。
实作 MCP Client
MCP 项目通常只实现 client 或 server 其中一边,课程两边都做。Client 端由两个部分组成:
- MCP Client:自己写的一个类,用来简化 session 的用法
- Client Session:真正的服务器连接(来自 MCP Python SDK)
Client session 负责底层通信,但关闭时需要小心地做资源清理——包一层自定义类可以自动处理这个清理流程。
核心功能:
async def list_tools(self) -> list[types.Tool]:
result = await self.session().list_tools()
return result.tools
async def call_tool(
self, tool_name: str, tool_input: dict
) -> types.CallToolResult | None:
return await self.session().call_tool(tool_name, tool_input)
复杂的通信细节都交给 session() 处理。
测试 Client:
uv run mcp_client.py
连上 MCP server,打印出所有可用工具(名字、描述、input schema)。
⚠️ MCP 的工具定义格式跟 Claude 预期的格式有点不一样——core/bedrock.py 里的 to_bedrock_tools 函数会自动把 MCP 工具定义转换成 Bedrock 能用的格式,不用自己手动转。
跟 Claude 一起测试:
uv run main.py
问「What is the contents of the report.pdf document?」——Claude 拿到可用工具列表后,会选中 read_doc_contents 工具,透过 client 执行它,再拿文档内容回答用户。
常见错误
- ❌ 把 MCP 当成 tool use 的替代品——MCP 是互补概念,讲的是工具从哪里来;实际调用工具、处理 ToolUse/ToolResult 还是走 EP04/EP05 那套 tool use 流程
- ❌ 用 MCP Python SDK 定义工具时,跟 Claude Agent SDK 的
@tool装饰器写法搞混——两者参数要求不一样,@tool要显式传input_schema - ❌ 以为 MCP 工具定义能直接塞给 Bedrock 用——两边格式有差异,要经过
to_bedrock_tools这类转换函数 - ❌ 为了测一个工具能不能跑,就去搭一整套完整应用——先用
mcp dev起 inspector 快速验证,省下大量来回调试的时间
Sources
官方文档:
- Claude with Amazon Bedrock(Claude Academy 课程)— https://academy.claude.com/courses/claude-with-amazon-bedrock