使用python开发mcp server
上一篇文章介绍了UV工具的使用,有了uv 的基础,本篇我们来看一下如何使用python开发mcp server,目前主流的 mcp 分为 stdio 和 sse,stdio 为标准输入输出,通过调用工具获取工具的输出来交互,比如你在终端输入 ping host 命令,返回ping host 的输出,SSE 稍微复杂一些,通过http 接口,返回一个sse长连接,之后工具调用输入输出遵循JSONRPC规范,通过http 调用,但是结果通过SSE长连接返回,实现起来稍微复杂一些,但是调用工具和工具配置sse会更简单一些,本篇先介绍开发简单的 stdio 类型的 mcp server。工具为调用高德地图的天气查询接口返回某地的天气情况。
初始化项目¶
使用uv 创建一个package 类型的项目
这个项目需要使用的mcp,所以通过uv 进行安装
编写代码¶
编写工具函数¶
在 src\gaodeweather_mcp_server
目录下创建 server.py 文件
写入mcp 服务代码
FastMCP 类是高层的封装,如果没有什么特殊的需求,使用FastMCP即可,省去很多开发量,开发者只需要关注工具的具体实现即可,当然 mcp 也提供了底层的实现,这个适用于额外需求的服务开发,本文使用FastMCP开发。以后再扩展 mcp.server.lowlevel 中的Server 。
使用
初始化一个 FastMCP 对象,之后使用 @mcp.tool
装饰器装饰在具体的工具函数上, 工具具体的实现就不展开了,就是通过高德地图的天气查询接口返回对应的天气信息,但是注意由于调用高德地图的接口需求一个apikey,之后如果我们将mcp发布到公网上,需要用户使用自己的key,所以这里我并没有将apikey 固定,而是通过环境变量传入。
如果用户没有设置环境变量,则返回"请先设置GAODE_KEY环境变量"。 具体环境变量如何设置,后面再介绍。
我们也可以定义多个工具函数,只需要使用 @mcp.tool
装饰起来即可。
之后定义了一个 run 函数
run 函数为启动FastMCP对象,启动方式为 stdio, 这种是标准的输入输出的方式,后面再介绍sse的方式。
最后在server.py中添加启动函数,这主要是用于之后的本地调试。
修改启动函数¶
此时 pyproject.toml 文件中脚本定义为
这意味着当运行 uvx gaodeweather-mcp-server
时会调用 gaodeweather_mcp_server
下的main 函数。转换成代码应该为
而此时 src\gaodeweather_mcp_server\__init__.py
中还是uv 默认生成的内容
这里我们修改一下
以上我们就完成了一个简单的stdio类型的mcp server 的开发,接下来我们本地调试一下。
本地调试¶
mcp 官方提供了一个本地调试工具 inspector, https://github.com/modelcontextprotocol/inspector , 我们先使用它来进行调试。
安装 mcp[cli]
启动调试命令
这里注意,在windows 下路径中需要使用 /
, 或者 \\
, 不要写成 src\gaodeweather_mcp_server\server.py
使用浏览器打开 http://localhost:5173
此时还没有连接这个mcp 工具,点击 Connect 按钮进行连接。当连接成功以后,会显示 Connected
连接成功以后,点击右侧导航中的Tools,再点击下面的 List Tools 按钮
显示在该mcp server 中定义的工具, 上面只定义了一个工具,这里只显示 "高德天气查询助手"。
点击工具名称,右侧会展示该工具的调试窗口
这里的输入参数是真实的调用工具时的参数,并不是用户与大模型交互时的对话,如我们和大模型交互时会问:“北京明天的天气怎么样?”,大模型会根据mcp 工具的参数定义解析出工具的入参,city="北京"
, 但是这个调试界面,我们不能输入 "北京明天的天气怎么样?", 而是输入真正调用工具函数时的输入参数:"北京",也就是说,这个 Inspector 调试工具,只是调试工具函数本身的输入输出,并不能调试大模型的交互。
这里输入 "北京" 来测试一下。
不出意外的话会报错,由于在上面的工具实现中有定义,如果在环境变量中未设置 GAODE_KEY 变量,将返回失败。我们来设置一下这个环境变量。
点击 Environment Variables 按钮
拉到最下面,点击 Add Environment Variable 按钮,添加环境变量
再点击 Connect 按钮,重新连接一下。之后再点击右侧的 Run Tool 按钮,即可获得工具的输出了。
我们通过使用 Inspector 来观察工具的输出,进而修改工具的实现。
如何定义工具说明¶
和function call 或者 tool call 类似,大模型是需要了解函数能做什么以及它需要哪些参数,才能从自然语言中分析解析出要调用哪个工具函数以及参数是什么,如果开发人员没有写清楚函数的作用和参数的定义,那么再牛的大模型也不能很好的分析出来,在前面的代码中我是这样定义函数说明和参数定义的
这里使用了两种书写工具说明的方式
第一种将工具的定义以及描述信息通过 @mcp.tool
装饰器的 name 和 description 参数传入。name 和description 说明该工具能做什么,再工具函数的实现上,async def query_logistics(city: str = Field(description="要查询天气的城市名称"))
通过pydantic.Field 来定义参数的说明。
第二种通过书写工具函数的注释。这种就没有什么规则可言,完全凭开发人员的习惯,当mcp.tool
装饰器中未定义工具名称和描述时,会使用工具的注释。
就我个人而言,更加倾向于第一种方式,因为可以很明确的说明工具的作用以及参数的描述,单纯的靠函数注释的方式编写则更加考验大模型的分析解析能力。
client 调试¶
上面使用 Inspector 工具只是调试了工具函数本身,而对于mcp server 的调试,应该更加关注与大模型应用的交互调用,目前有很多工具(在mcp 规范里叫 host)已经支持了MCP的调用,下面以 Cline 和 cherry studio 为例,演示如何接入本地 mcp 。
cherry studio¶
先复制在 Inspector 中启动的命令行
uv run --with mcp mcp run src/gaodeweather_mcp_server/server.py
点击 cherry studio 中添加服务器按钮
在弹出的对话框中填写相应的信息
这里的名称和描述随便写的,并不是mcp server 本身的名称和描述,只是方便使用者查看的。
类型选择STDIO
命令填写 uv
参数这里比较重要,将之前 Inspector 中复制的命令参数填到这里
run --with mcp mcp run src/gaodeweather_mcp_server/server.py
然后将每个参数另起一行,再添加上脚本本身的目录,最终参数填写为
环境变量那里需要设置GAODE_KEY 变量,点击确认填加mcp 服务。
返回助手页面,设置一个支持函数调用的模型,这里我选择 qwen-plus,如果模型不支持function call, 则在对话框中是不显示mcp是否开启的图标的。
之后在对话框中将刚刚添加的mcp 开启
然后问一个查询天气相关的问题,如 “我明天要去上海出差,我应该穿什么衣服?” 虽然没有直接问天气,但是大模型也是可以分析出要调用天气接口来回答问题的。
Cline¶
Cline 是 vs code 的插件,也支持 mcp 的调用。
在 cherry studio 的MCP 配置界面,点击编辑JSON
复制刚刚测试成功的 gaode_weather json 信息。
打开Cline 的配置,点击 configure MCP servers 按钮
将刚才复制的配置信息填到这里, 注意修改一下路径的分隔符。
然后在Cline 的对话框中再问一下刚才的问题, 当需要调用mcp 时,默认Cline 不会调用,而是询问用户是否调用,这时点击 Approve 进行实际的调用
打包发布¶
上面经过本地调试,功能正常,但是我们注意到,无论是Cherry studio 还是Cline,都需要设置 --directory
参数指定脚本文件位置,如果我们想要让mcp 工具提供给别人使用,不可能把将原文件发给每个人,然后使用者配置复杂的json,所以需要将mcp server 发布到pypi 中,让用户可以使用uvx 直接运行。
将本地写的mcp工具发布成功以后,就可以很简单的配置了
cherry studio¶
将命令改为 uvx, uvx 是 uv tool run 的简称,参数只需要改为 gaodeweather-mcp-server, 这个是在 project.scripts
中定义的命令,
uvx 会从pypi 中自动下载安装对应的包,用户不用在配置目录信息。
问答效果和之前一样。
Cline¶
编辑 Cline 中的mcp json 配置
可以看到,命令行简单了很多。
总结¶
本文介绍了使用python 开发一个stdio 类型的mcp server, 主要的步骤如下
- 使用
uv init --package
初始化 package 类型的项目 - 使用FastMCP编写简单的 mcp 工具
- 使用 Inspector 进行工具本身的调试
- 使用cherry studio 或者 Cline 进行本地大模型交互测试
- 打包上传 pypi
- 重新配置 cherry studio 和 Cline,使用uvx 运行 mcp 服务
除了stdio 还有另外一种mcp 服务 SSE,sse 类型的mcp 在使用和配置上会更加简单,下一篇文章再做详细介绍,敬请期待!
