模型上下文协议(MCP)实践指南
python SDK :https://github.com/modelcontextprotocol/python-sdk/tree/main?tab=readme-ov-file
编写mcp 服务
# server.py
from mcp.server.fastmcp import FastMCP# Create an MCP server
mcp = FastMCP("Demo")# Add an addition tool
@mcp.tool()
def add(a: int, b: int) -> int:"""Add two numbers"""return a + b@mcp.tool()
def mul(a: int, b: int) -> int:"""Mul two numbers"""return a * b# Add a dynamic greeting resource
@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:"""Get a personalized greeting"""return f"Hello, {name}!"
环境依赖安装(首次开发时需要)
- step1 : 安装mcp
pip install "mcp[cli]"
要求python 大于3.10.
- step2 测试demo
mcp dev server.py
出现下面的错误,
[06/10/25 20:14:37] ERROR npx not found. Please ensure Node.js and npm are properly installed and added to your system PATH. You may need to restart your terminal after installation. cli.py:308
解决办法是安装相应的依赖
sudo apt install nodejs npm
这一步会安装很多很多依赖,需要谨慎操作。
安装完这些依赖后再运行, 还需要安装一个工具@modelcontextprotocol/inspector, 不过这个是自动安装的
Need to install the following packages:@modelcontextprotocol/inspector
Ok to proceed? (y) y
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: '@modelcontextprotocol/sdk@1.12.1',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'concurrently@9.1.2',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'open@10.1.2',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'typescript@5.8.3',
npm WARN EBADENGINE required: { node: '>=14.17' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'commander@13.1.0',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'pkce-challenge@4.1.0',
npm WARN EBADENGINE required: { node: '>=16.20.0' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'express@5.1.0',
npm WARN EBADENGINE required: { node: '>= 18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'eventsource@3.0.7',
npm WARN EBADENGINE required: { node: '>=18.0.0' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'express-rate-limit@7.5.0',
npm WARN EBADENGINE required: { node: '>= 16' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'pkce-challenge@5.0.0',
npm WARN EBADENGINE required: { node: '>=16.20.0' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'eventsource-parser@3.0.2',
npm WARN EBADENGINE required: { node: '>=18.0.0' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'body-parser@2.2.0',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'merge-descriptors@2.0.0',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'router@2.2.0',
npm WARN EBADENGINE required: { node: '>= 18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'send@1.2.0',
npm WARN EBADENGINE required: { node: '>= 18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'serve-static@2.2.0',
npm WARN EBADENGINE required: { node: '>= 18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'default-browser@5.2.1',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'is-inside-container@1.0.0',
npm WARN EBADENGINE required: { node: '>=14.16' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'is-wsl@3.1.0',
npm WARN EBADENGINE required: { node: '>=16' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'bundle-name@4.1.0',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'default-browser-id@5.0.0',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'run-applescript@7.0.0',
npm WARN EBADENGINE required: { node: '>=18' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE package: 'path-to-regexp@8.2.0',
npm WARN EBADENGINE required: { node: '>=16' },
npm WARN EBADENGINE current: { node: 'v12.22.9', npm: '8.5.1' }
npm WARN EBADENGINE }
file:///home/pinefield/.npm/_npx/5a9d879542beca3a/node_modules/@modelcontextprotocol/inspector/cli/build/cli.js:30const CLIENT_PORT = process.env.CLIENT_PORT ?? "6274";^SyntaxError: Unexpected token '?'at Loader.moduleStrategy (internal/modules/esm/translators.js:133:18)at async link (internal/modules/esm/module_job.js:42:21)
[06/10/25 20:17:54] ERROR Dev server failed
自动安装完后会有一个检查, 上面的检查结果表明刚才安装的依赖的版本都不符合要求, 并且最终程序出错了。
解决办法, 升级node和npm版本, 有2种方式:
1种方式是直接升级:
# Remove old version
sudo apt remove nodejs npm# Install latest LTS
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -
sudo apt-get install -y nodejs
但是通常会遇到网络问题无法完成
另一种方式是使用 Node Version Manager (推荐):
# For Linux/macOS
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
# Restart terminal, then:
nvm install --lts
nvm use --lts
成功运行结果如下:
(leo_py311) pinefield@edge-gpu-01:/data/joyiot/leo/codes/mcp_tutorial$ mcp dev server.py
Starting MCP inspector...
⚙️ Proxy server listening on port 6277
🔍 MCP Inspector is up and running at http://127.0.0.1:6274 🚀
打开这个页面, 显示如下:
在Claude app 中使用
上面的环境安装是linux环境的。 但是Claude app目前只有Winddows和mac的版本, 没有linux版本。 因此要想在Claude app中使用, 需要在windows上安装环境。 python环境的安装是一样的, 只是nodejs 和npm 的安装不同。 直接在官网下载安装包即可完成安装。
如果想要在Claude app中使用刚才写好的mcp server, 需要执行安装
mcp install server.py
安装成功会有如下提示:
然后重启Claude app, 查看mcp设置:
点Edit Config 可以直接打开配置文件。
配置文件如下:
{"mcpServers": {"Demo": {"command": "E:\\anaconda3\\Scripts\\uv.EXE","args": ["run","--with","mcp[cli]","mcp","run","E:\\work\\LLM\\codes\\mcp_tutorial\\server.py"]}}
}
如果一切正常的话, 可以在Claude app首页看到这样的图标, 这表明mcp server已经被添加好了。
如果电脑上设置了网络代理,可能出现mcp server disconnect 的问题, 这时需要关闭掉代理。 但是如果没有网络代理, 在大陆地区使用不了Claude app, 需要注意设置代理模式。
使用:
当在Claude app中进行对话时, 会自动识别是否需要调用相应服务, 首次使用时会有确认的提示:
之后再调用时, 可能不会再有提示, 但可以通过服务名称查看是否调用了想用了mcp 服务。
如上, 回答中没有显式说明调用了mcp 服务, 但会显示调用的服务名称。
也可以通过mcp 服务的日志查看调用记录:
2025-06-11T03:15:27.221Z [info] [Demo] Message from client: {"method":"tools/call","params":{"name":"add","arguments":{"a":44,"b":45}},"jsonrpc":"2.0","id":18}
2025-06-11T03:15:27.224Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":18,"result":{"content":[{"type":"text","text":"89"}],"isError":false}}
2025-06-11T03:24:01.129Z [info] [Demo] Message from client: {"method":"tools/call","params":{"name":"add","arguments":{"a":44,"b":45}},"jsonrpc":"2.0","id":19}
2025-06-11T03:24:01.134Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":19,"result":{"content":[{"type":"text","text":"89"}],"isError":false}}
2025-06-11T03:24:25.949Z [info] [Demo] Message from client: {"method":"tools/call","params":{"name":"add","arguments":{"a":44,"b":45}},"jsonrpc":"2.0","id":20}
2025-06-11T03:24:25.954Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":20,"result":{"content":[{"type":"text","text":"89"}],"isError":false}}
2025-06-11T03:24:59.271Z [info] [Demo] Message from client: {"method":"tools/call","params":{"name":"add","arguments":{"a":44,"b":45}},"jsonrpc":"2.0","id":21}
2025-06-11T03:24:59.275Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":21,"result":{"content":[{"type":"text","text":"89"}],"isError":false}}
2025-06-11T03:25:18.461Z [info] [Demo] Message from client: {"method":"tools/call","params":{"name":"add","arguments":{"a":36,"b":89}},"jsonrpc":"2.0","id":22}
2025-06-11T03:25:18.466Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":22,"result":{"content":[{"type":"text","text":"125"}],"isError":false}}
2025-06-11T03:25:20.390Z [info] [Demo] Message from client: {"method":"resources/list","params":{},"jsonrpc":"2.0","id":23}
2025-06-11T03:25:20.395Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":23,"result":{"resources":[]}}
2025-06-11T03:25:20.401Z [info] [Demo] Message from client: {"method":"prompts/list","params":{},"jsonrpc":"2.0","id":24}
2025-06-11T03:25:20.404Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":24,"result":{"prompts":[]}}
2025-06-11T03:25:35.058Z [info] [Demo] Message from client: {"method":"tools/call","params":{"name":"add","arguments":{"a":44,"b":45}},"jsonrpc":"2.0","id":25}
2025-06-11T03:25:35.062Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":25,"result":{"content":[{"type":"text","text":"89"}],"isError":false}}
2025-06-11T03:26:44.476Z [info] [Demo] Message from client: {"method":"tools/list","params":{},"jsonrpc":"2.0","id":26}
2025-06-11T03:26:44.476Z [info] [Demo] Message from client: {"method":"tools/list","params":{},"jsonrpc":"2.0","id":27}
2025-06-11T03:26:44.476Z [info] [Demo] Message from client: {"method":"resources/list","params":{},"jsonrpc":"2.0","id":28}
2025-06-11T03:26:44.483Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":26,"result":{"tools":[{"name":"add","description":"Add two numbers","inputSchema":{"properties":{"a":{"title":"A","type":"integer"},"b":{"title":"B","type":"integer"}},"required":["a","b"],"title":"addArguments","type":"object"}}]}}
2025-06-11T03:26:44.484Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":27,"result":{"tools":[{"name":"add","description":"Add two numbers","inputSchema":{"properties":{"a":{"title":"A","type":"integer"},"b":{"title":"B","type":"integer"}},"required":["a","b"],"title":"addArguments","type":"object"}}]}}
2025-06-11T03:26:44.485Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":28,"result":{"resources":[]}}
2025-06-11T03:26:44.536Z [info] [Demo] Message from client: {"method":"prompts/list","params":{},"jsonrpc":"2.0","id":29}
2025-06-11T03:26:44.540Z [info] [Demo] Message from server: {"jsonrpc":"2.0","id":29,"result":{"prompts":[]}}
日志文件地址: C:\Users\Administrator\AppData\Roaming\Claude\logs