MCP(Model Context Protocol)
不用 ,用亲手写的小型 和 一条条跟着看 消息,再把它连接到 ,看看设置保存在哪里。
什么是 MCP
()是把 应用连接到外部和的。没有 MCP 的时候,每个 AI 应用都要为每个工具单独做连接。有了 MCP,你只要做一次,任何支持 MCP 的应用——、、 或你自己写的——都能使用它。
MCP 由开发 的公司 创建。官方文档:https://claude.com/docs/connectors/building/mcp
MCP 客户端与 MCP 服务器
MCP 由两方对话。
- MCP = :挑选并使用工具的一方。Claude Code、Codex 这样的 AI 智能体充当 MCP 客户端,连接到服务器。
- = 提供自身功能的一方:把自己能做的事(功能)通过 MCP 提供给智能体使用的程序。
- :规范里的叫法,指装着智能体的 AI 应用。在这个应用里,每连接一个服务器,就有一个 MCP 客户端连接。
例子:WebMCP
WebMCP 是网站像 MCP 那样把自己提供出来的方法。它是网页提供的 ,让网站把自己的功能作为 AI 智能体可以使用的工具提供出来。网站开发者在自己网站的里加入 registerTool(),注册“搜索商品”“加入购物车”这样的功能后,智能体就不必看着屏幕一个个点按钮,而是直接这些工具。
- 智能体(MCP 客户端):被要求“在这家网店找一把伞并加入购物车”的 AI。
- 网站(MCP 服务器角色):把自己的功能作为工具提供出来,智能体调用时执行并返回结果。网页浏览器是连接两者的窗口。
也就是说,成为 MCP 服务器就是“把自己提供给智能体使用”。它和其他浏览器 MCP 的区别,在“使用 MCP”标签页里看。
MCP 服务器提供的三样东西
服务器可以提供三类东西:
- 工具(Tools):AI 可以调用的函数,比如“搜索笔记”或“添加一行”。
- :应用可以读取的数据,比如一个文件或一条记录,每个都有自己的地址()。
- (Prompts):用户可以挑选的现成消息。
轻松理解
- 可以这样想
- MCP 就像 AI 应用的 USB 。有 USB 之前,每台打印机和键盘都需要自己的插头;现在任何带 USB 插头的设备都能插进任何电脑。MCP 服务器是设备,AI 应用是电脑,因为插头形状相同,所以你只要做一次服务器,所有 MCP 应用都能用。
- 例子
- strange-add 服务器提供一个工具:把两个数相加,再加上一个 1 到 100 之间的随机数。
- 你用一条把它连接到 Claude Code。
- 你说“用 strange-add 把 2 和 3 相加”:AI 读工具描述,征求你的批准,然后客户端在服务器上调用 strange-add。答案不是 5——这证明工具真的运行了。
- 常见错误
- 找到什么 MCP 服务器就装什么。服务器会用你的在你的电脑上运行代码。先读一读,或者选一个可信的,并且只给它需要的文件夹或。
把 MCP 服务器连接到智能体
要连接到上才能用。连接( · codex add)、范围和确认方法每个都不一样,所以分别写在各个工具页面的 MCP 单元里,各写一次。
WebMCP vs Chrome DevTools MCP vs Playwright MCP
三者都让智能体在网页里工作。不同的是由谁来准备,以及智能体怎么工作。WebMCP 是网站一方声明“我的网站可以使用这些功能”的浏览器 ;另外两个是安装在智能体一方、在任何网站上都直接操作浏览器的 MCP 服务器。
| 项目 | WebMCP | Chrome DevTools MCP | Playwright MCP |
|---|---|---|---|
| 是什么 | 网站使用的浏览器 API——仍处于提案阶段的网页标准(Web 社区组草案) | 安装在智能体一方的 MCP 服务器(Google 团队) | 安装在智能体一方的 MCP 服务器(Microsoft) |
| 由谁准备 | 网站开发者——在自己网站的里加入 registerTool() 来注册工具 | 使用智能体的人——把添加到自己的智能体 | 使用智能体的人——把服务器添加到自己的智能体 |
| 智能体怎么工作 | 按名字网站注册的工具,不需要读屏幕去猜。 | 通过 操作并查看真正的 Chrome——点击、输入、。 | 读取页面的无障碍树(页面结构)来点击和输入——看的是结构,不是。 |
| 擅长的事 | 准确、快速地使用这个网站的功能,直接用我已登录的 | ——性能记录、请求、控制台错误 | 与测试——、、WebKit 多种浏览器 |
| 局限 | 只能在网站注册了工具的地方使用。它是新标准,支持的浏览器和网站还很少。 | 为 Chrome(和 Chrome for )打造。页面一变,就要重新找。 | 页面结构一变,就要重新找。它靠一个个按钮工作,而不是靠网站定义的功能。 |
入门代码
// WebMCP: the website registers its own feature as a tool
// (first explainer / Chrome preview: navigator.modelContext,
// spec draft 2026-10-27: document.modelContext)
const modelContext = document.modelContext ?? navigator.modelContext;
modelContext.registerTool({
name: "search-products",
description: "Search this shop's products by keyword",
inputSchema: {
type: "object",
properties: { query: { type: "string" } },
required: ["query"],
},
async execute({ query }) {
const response = await fetch("/api/products?q=" + encodeURIComponent(query));
return await response.json(); // the agent gets this result
},
});
# Chrome DevTools MCP: add the server to your agent (Claude Code)
claude mcp add chrome-devtools -- npx -y chrome-devtools-mcp@latest
# Playwright MCP: add the server to your agent (Claude Code)
claude mcp add playwright -- npx @playwright/mcp@latest
WebMCP 写在网站的 里,另外两个写在你电脑的里。WebMCP 最初的说明和 Chrome 预览版用 navigator.modelContext,2026-10-27 的规范草案用 document.modelContext——规范还在变化中。
打个比方——挂出菜单的店和跑腿机器人
WebMCP = 店家挂出的点单窗口和菜单
- 店家(网站)事先在门口挂出写着“请在这个窗口点单”的菜单。
- 菜单上写着能点什么(工具名)和怎么填点单表(输入 )。
- 机器人(智能体)只要读菜单、把点单表递进窗口就行——不用在店里到处走。
- 不过只有设了窗口的店,才能这样点单。
Chrome DevTools MCP · Playwright MCP = 顾客派出的跑腿机器人
- 顾客(使用智能体的人)把跑腿机器人派进店里。店家什么都不用准备。
- 机器人自己在店里转,读货架、拿商品、按收银台的按钮。
- 哪家店都能进,但货架一换就得重新找,所以可能很慢,还会迷路。
- Chrome DevTools MCP 机器人是连店里的线路和电表都要查看的检修师傅(性能、网络、控制台)。
- Playwright MCP 机器人是在好几家店(浏览器)里一模一样地重复规定购物路线的购物机器人。
总之,在有窗口的店里,用窗口点单又快又准;在没有窗口的店里,机器人只能自己转着找。所以三者不是互相替代,而是一起用。
MCP 安全守则
安全:工具是以你的运行的代码,除非服务器可信,否则工具描述也不可信。规范要求主机在调用工具之前征得用户同意。只安装你读过或信任的服务器,只给服务器它所需的最小访问权限,把放在环境变量里而不是代码里,并且要提防( injection)——工具读取的网页或文件里可能藏着针对 的指令。
消息与传输方式
消息采用 2.0——像 (“你能做什么?”)和 (“用这些做这件事”)这样的小 对象。它们通过两种标准之一来往:stdio(在同一台电脑上把作为启动,双方通过标准对话)或 (服务器运行在一个网址上,所以很多用户都能访问)。
亲手做的服务器和客户端
服务器(mcp-server.py)只用 ,所以你能看到本身。它从标准输入每行读一条 JSON-RPC 消息,并向标准输出每行写一条回复:
- :客户端带着打招呼。服务器用同一个回答,说明自己有,并报出自己的名字。
- tools/list:服务器返回它唯一的工具 strange-add,附带描述和输入模式(a 和 b 是数字)。
- tools/call:服务器运行 strange-add,并把结果作为文本返回。
- 没有 id 的消息是通知(比如 /initialized),所以服务器不回复。其他任何请求(比如 ping)都会得到一个空结果。
strange-add 会在 a + b 上再加一个 1 到 100 之间的随机数。自己算不出这个值,所以 2 + 3 的答案不是 5,就证明工具真的运行了。stdout 只协议消息——混进一个多余的 () 就会破坏对话,所以要写到 stderr。print(..., =True) 会把每条回复立刻发出去。
客户端(mcp-client.sh)是一个不需要任何 就能扮演主机角色的 脚本。它启动服务器,发送整个(initialize、initialized 通知、tools/list、tools/call、ping),逐条检查回复,并打印 PASS 或 FAIL。退出码 0 表示全部通过。在把服务器连接到之前,先这样测试它。在真正的客户端里,模型会加入这个循环:
- 把用户的问题和工具列表发给模型;
- 当模型要求使用某个工具时,客户端用 tools/call 在服务器上它;
- 把结果发回去,模型写出最终的回答。
这个手写的服务器使用以 initialize 开始的方式(协议版本 2025-06-18), 等客户端仍然接受这种方式。(2026-07-28)不再用 initialize ,而是在每个请求里带上版本。做真正的服务时,请使用官方 (Python MCPServer、),它们会替你遵循规范。
"""
mcp-server.py: the smallest MCP server.
One tool, plain Python (standard library only), no SDK.
Who is who
MCP server This program. It offers tools (functions the AI
may use).
Host The app the user talks to (Claude Code, Codex).
It runs one MCP client for each connected server.
MCP client The part of the host that talks to this server
with JSON-RPC messages (here over stdio: one JSON
message per line).
Model The LLM (Claude Opus, GPT, ...). It never talks to
the server directly. It only talks to the host.
Flow
1. Discover tools
The client asks for the tools (tools/list). The server replies
with each tool's name, description and input schema.
2. Offer tools
The host sends the user's message to the model, together
with the tool list.
3. Model decides
The model answers directly, or asks for a tool call
(tool name + arguments). It never runs the tool itself.
4. Call the tool
The client sends the request to the server (tools/call).
5. Run the tool
The server runs the function and returns the result.
6. Model continues
The host gives the result back to the model. The model may
call more tools (3-6 again) or write the final answer.
Model Host (MCP client) MCP server
| | 1. tools/list ------> |
| | <------ tool list |
| <-- 2. message + tool list |
| 3. tool call --> | |
| | 4. tools/call ------> |
| | <------ 5. result |
| <-- 6. result | |
Rule for stdio servers: stdout carries protocol messages only.
Never print() anything else there. Write logs to stderr.
"""
import json
import random
import sys
SERVER_INFO = {"name": "strange-add-mcp", "version": "1.0.0"}
# The tool. The model reads the description to decide when to use it.
STRANGE_ADD = {
"name": "strange-add",
"description": "Add two numbers with a strange number.",
"inputSchema": {
"type": "object",
"properties": {
"a": {"type": "number"},
"b": {"type": "number"},
},
"required": ["a", "b"],
},
}
def strange_add(a, b):
"""Add a + b and a random number from 1 to 100 (always > a + b).
The model cannot guess the answer, so a right answer proves
that the tool was really called.
"""
return a + b + random.randint(1, 100)
def handle(method, params):
"""Return the result for one request. Others (like ping) get {}."""
if method == "initialize":
# Use the client's protocol version and say "I have tools".
return {
"protocolVersion": params["protocolVersion"],
"capabilities": {"tools": {}},
"serverInfo": SERVER_INFO,
}
if method == "tools/list":
return {"tools": [STRANGE_ADD]}
if method == "tools/call":
args = params["arguments"]
total = strange_add(args["a"], args["b"])
return {"content": [{"type": "text", "text": str(total)}]}
return {}
def main():
# One JSON-RPC message per line comes in, one reply per line goes out.
for line in sys.stdin:
request = json.loads(line)
# No id means a notification: send no reply.
if "id" not in request:
continue
result = handle(request["method"], request.get("params", {}))
reply = {"jsonrpc": "2.0", "id": request["id"], "result": result}
# flush=True sends the reply at once.
print(json.dumps(reply), flush=True)
if __name__ == "__main__":
main()
#!/bin/sh
# mcp-client.sh: the simplest MCP client, a shell script.
# It starts mcp-server.py, talks to it over stdio (one JSON-RPC
# message per line) and checks every reply.
# Exit code 0 means every check passed.
SERVER="python3 $(dirname "$0")/mcp-server.py"
# 1. Send the whole session at once and keep the replies.
# id 1 initialize agree on a version
# (no id) notifications/initialized "ready" (no reply)
# id 2 tools/list which tools are there?
# id 3 tools/call run strange-add(2, 3)
# id 4 ping is the server alive?
replies=$(
$SERVER <<'EOF'
{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"protocolVersion": "2025-06-18", "capabilities": {}, "clientInfo": {"name": "shell-mcp-client", "version": "1.0.0"}}}
{"jsonrpc": "2.0", "method": "notifications/initialized"}
{"jsonrpc": "2.0", "id": 2, "method": "tools/list"}
{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "strange-add", "arguments": {"a": 2, "b": 3}}}
{"jsonrpc": "2.0", "id": 4, "method": "ping"}
EOF
)
echo "--- Server replies ---"
echo "$replies"
echo "--- Checks ---"
failed=0
# 2. check <label> <reply id> <text the reply must contain>
check() {
reply=$(echo "$replies" | grep -F "\"id\": $2,")
if echo "$reply" | grep -qF "$3"; then
echo "PASS $1"
else
echo "FAIL $1 (expected: $3)"
failed=1
fi
}
check "initialize: protocol version" 1 '"protocolVersion": "2025-06-18"'
check "initialize: server info" 1 '"serverInfo": {'
check "initialize: has tools" 1 '"capabilities": {"tools": {}}'
check "tools/list: strange-add" 2 '"name": "strange-add"'
check "ping: empty result" 4 '"result": {}'
# 3. strange-add adds a random 0 to 100,
# so the answer only has to be >= 2 + 3.
total=$(echo "$replies" | grep -F '"id": 3,' |
sed 's/.*"text": "\([0-9]*\)".*/\1/')
if [ "$total" -ge 5 ] 2>/dev/null; then
echo "PASS tools/call: strange-add(2, 3) >= 5 (got $total)"
else
echo "FAIL tools/call: strange-add(2, 3) >= 5 (got $total)"
failed=1
fi
exit $failed
# put the two files above into one folder
mkdir -p ~/tmp/mcp && cd ~/tmp/mcp
# mcp-server.py mcp-client.sh
# 1) test the server without any AI
sh mcp-client.sh # -> 6 x PASS, exit code 0
# 2) connect it to Claude Code (no --scope: the "local" scope)
claude mcp add strange-add -- python3 ~/tmp/mcp/mcp-server.py
claude mcp list # strange-add: ... - Connected
claude mcp get strange-add # Scope: Local config
# 3) where it was saved: NOT in this folder (no new file here)
# ~/.claude.json -> projects -> "<this folder>" -> mcpServers
jq '.projects["'"$PWD"'"].mcpServers' ~/.claude.json
# 4) use it: start Claude Code in THIS folder
claude # "Use strange-add to add 2 and 3"
# -> not 5 (e.g. 61): the tool ran
claude mcp remove strange-add -s local
这些在你自己的电脑或服务器的里运行,而不是在这个页面上。运行前请逐行读一遍。