What is the Model Context Protocol (MCP)? - Model Context Protocol
stdio(标准输入输出,本地子进程)
- 工作方式:客户端(Cursor/Claude Desktop)把MCP服务作为本地子进程启动,通过进程的标准输入(stdin)、标准输出(stdout)收发JSON‑RPC报文。
- 网络:不走TCP网络、没有端口,纯本机进程间通信。
- 适用:本地运行的MCP服务(绝大多数日常开发场景)
- 优点:最简单,零端口,不用处理HTTP、CORS;官方客户端原生支持。
- 缺点:只能本机调用,不能给别的机器远程访问;不能多客户端共享同一个服务实例。
- 配置示例:
"mcpServers": {
"demo": {
"command": "python",
"args": ["server_stdio.py"]
}
}
cherry studio 中配置
{
"mcpServers": {
"mcp-helloworld": {
"command": "C:\\Users\\zg.cai\\Envs\\frida16-1-3\\Scripts\\python.exe",
"args": [
"D:\\czg\\czgAsFwgs\\Swkj\\frida-agent-example\\mcp‑helloworld\\server_STDIO.py"
],
"env": {}
}
}
}
添加情况

mcp-helloworldp 添加到cherry studio
完整源码(已经跑通的版本)
#!/usr/bin/env python3
import asyncio
import json
from mcp.server.mcpserver import MCPServer
# 创建服务实例
mcp = MCPServer("mcp-helloworld-stdio")
@mcp.tool()
async def say_hello(username: str = "匿名用户") -> str:
"""输出一条 hello world 问候消息
Args:
username: 需要问候的用户名
"""
return f"👋 Hello World! 你好,{username}。来自 python版 mcp‑helloworld MCP服务"
@mcp.tool()
async def get_server_info() -> str:
"""获取当前mcp‑helloworld服务信息"""
info = {
"serviceName": "mcp‑helloworld",
"version": "1.0.0",
"status": "running ok"
}
return json.dumps(info, ensure_ascii=False, indent=2)
if __name__ == "__main__":
# stdio 模式,供 Cherry‑Studio 调用
mcp.run(transport="stdio")
逐段深度讲解(mcp‑2.x)
1.导入模块
import asyncio
import json
from mcp.server.mcpserver import MCPServer
-
asyncio:Python异步库。MCP服务底层全部是异步IO。 -
json:用来序列化字典为JSON字符串(get_server_info返回) -
MCPServer:2.x新版高级封装类,就是以前1.x版本的FastMCP,改了名字。
MCPServer = 高级封装,帮你自动处理所有 JSON‑RPC 底层报文,不用手动写
tools/list、tools/call回调。
2.实例化MCP服务
mcp = MCPServer("mcp-helloworld")
-
"mcp‑helloworld":你的MCP服务名称标识,客户端(Cherry‑Studio)会看到这个名字。 -
mcp对象就是你整个服务的管理器,所有工具都注册到它身上。
3.第一个工具函数 say_hello
@mcp.tool()
async def say_hello(username: str = "匿名用户") -> str:
"""输出一条 hello world 问候消息
Args:
username: 需要问候的用户名
"""
return f"👋 Hello World! 你好,{username}。来自 python版 mcp‑helloworld MCP服务"
@mcp.tool() 装饰器(最核心)
等价于告诉MCP框架:把下面这个函数注册成一个可供AI调用的工具。
底层自动帮你完成三件大事:
- 生成工具名称:函数名
say_hello - 生成工具描述:读取函数的文档字符串(三个引号里面的文字)
- 自动解析函数参数
username,自动生成工具的input_schemaJSON结构。
async
MCP框架要求所有工具函数必须是异步 async 函数。
参数 username: str = "匿名用户"
-
username:对外暴露给AI的入参 -
str:参数类型 -
"匿名用户":默认值,AI不传这个参数的时候就用它
文档字符串规范
"""输出一条 hello world 问候消息
Args:
username: 需要问候的用户名
"""
- 第一行 = 工具的简短描述
- Args区块 = 每个参数的说明
MCPServer会自动解析这段文字,生成完整工具元数据,Cherry‑Studio/AI就能看懂每个参数干什么用。
return
返回字符串,就是工具执行完成后返回给大模型的结果。
4.第二个工具 get_server_info
@mcp.tool()
async def get_server_info() -> str:
"""获取当前mcp‑helloworld服务信息"""
info = {
"serviceName": "mcp‑helloworld",
"version": "1.0.0",
"status": "running ok"
}
return json.dumps(info, ensure_ascii=False, indent=2)
-
json.dumps:字典转漂亮格式化JSON字符串 -
ensure_ascii=False:支持中文不乱码 -
indent=2:换行缩进,输出美观
5.程序入口,启动服务
if __name__ == "__main__":
mcp.run(transport="stdio")
-
if __name__ == "__main__":只有直接运行python server.py的时候才执行启动代码,被别的文件import导入时不会启动服务。 -
transport="stdio":传输模式,标准输入输出- MCP客户端(Cherry‑Studio)启动你的python进程
- 客户端通过标准输入(stdin) 给你发JSON‑RPC请求(比如:列出工具、调用工具)
- 你的Python程序通过标准输出(stdout) 返回结果给客户端
这就是为什么你在IDEA直接运行,控制台一片空白:stdio模式不会打印日志,所有通信流量都走后台stdin/stdout通道。
MCP 整体工作流程(客户端 ↔ 你的server.py)
- Cherry‑Studio启动
python server.py子进程 - 客户端发送
tools/list请求 → MCPServer自动扫描你所有@mcp.tool()装饰的函数,返回工具列表 - AI决定调用某个工具,客户端发送
tools/call请求(携带工具名+参数) - MCPServer框架自动路由,执行你对应的 async 函数
- 函数return结果 → MCPServer封装成JSON‑RPC响应发回Cherry‑Studio → 交给大模型
你以后新增工具,只需要照抄模板即可
@mcp.tool()
async def my_new_tool(param1: str) -> str:
"""这里写工具描述
Args:
param1: 参数说明
"""
# 你的业务逻辑
result = "xxx"
return result
不需要修改启动代码、不需要手动注册回调。
容易踩坑的知识点总结
- 工具函数必须 async,不能写普通def同步函数
- 描述、参数说明必须写在函数文档字符串里,框架自动读取,不要写注释
-
transport="stdio"不要改成别的,Cherry‑Studio只支持stdio模式 - 不要在代码里随便print!print会污染stdout数据流,导致JSON‑RPC报文出错,MCP通信崩溃。
如果需要打印调试日志,要用
print("xxx", file=sys.stderr),输出到stderr(错误流),不会干扰通信。
运行&调试方式
方式1:直接命令行运行(直接运行不会看到交互,stdio等待父进程)
python server_STDIO.py
执行后屏幕空白,不是卡死!它在等待父进程发送MCP JSON‑RPC报文,不能直接手动输入文字。
方式2:用 MCP‑Inspector 调试(推荐)
Inspector 充当父进程,fork这个python子进程:
npx @modelcontextprotocol/inspector@latest python server_STDIO.py
(frida16-1-3) PS D:\czg\czgAsFwgs\Swkj\frida-agent-example\mcp‑helloworld\mcp_STDIO方式> npx @modelcontextprotocol/inspector@latest python server_STDIO.py
Starting MCP inspector...
Sandbox: port 6275 in use; falling back to an OS-assigned port. The MCP Apps tab will work locally, but the sandbox is no longer on a predictable port — set MCP_SANDBOX_PORT to a free one if you need to forward it (container / SSH tunnel / reverse proxy).
App origin: port 6278 in use; falling back to an OS-assigned port. Apps declaring _meta.ui.domain will still render, but the origin they are served from is no longer predictable — set MCP_APP_ORIGIN_PORT to a free one if your app's backend allowlists it.
MCP Inspector PORT IS IN USE at http://127.0.0.1:6274
(frida16-1-3) PS D:\czg\czgAsFwgs\Swkj\frida-agent-example\mcp‑helloworld\mcp_STDIO方式>
浏览器打开 inspector UI,Transport自动是stdio,直接点Connect,即可看到两个工具,调用测试。

npx运行情况mcp调试工具.png
Cherry‑Studio / Cursor 配置(stdio模式)
{
"mcpServers": {
"mcp-helloworld-stdio": {
"command": "C:\\Users\\zg.cai\\Envs\\frida16-1-3\\Scripts\\python.exe",
"args": [
"D:\\czg\\czgAsFwgs\\Swkj\\frida-agent-example\\mcp_helloworld\\mcp_STDIO方式\\server_STDIO.py"
],
"env": {}
}
}
}
claude 客户端中配置

image.png

claude 配置mcp

claude 客户端中配置

image.png