使用 uv + Python 开发一个 MCP 服务从部署到发布全流程
1. MCP 概念简述
MCP(Model Context Protocol),模型上下文协议,定义了一个模型与外界工具交互的标准。
一个本地的 MCP 服务,如果想要使用,整体来说有三个角色:
- MCP 客户端(如 Cursor、CherryStudio)这些支持 MCP 的工具,当然也可以自己写代码
- MCP 服务端,一般是通过 uvx 或者 npx 启动在本地的一个服务
- LLM
大概流程:
- MCP 客户端添加上 MCP 服务,获取 MCP 服务的工具列表数据
- 用户和 LLM 对话,Cursor 将工具列表信息和用户信息组合发送给 LLM
- LLM 判断是否需要调用工具,比如说判断出来需要调用查询天气预报工具,就生成天气预报工具的入参返回给 Cursor
- Cursor 用 LLM 给的参数,调用对应 MCP 服务,获取调用结果,将调用结果返回给 LLM
- LLM 根据返回信息进行总结,返回给用户,比如说:根据查询到的结果,北京明天的气温在 35 度,天气晴
2. Hello MCP
2.1 开发
我们使用 uv 来构建项目、管理依赖和创建虚拟环境:
# 1.创建项目文件夹
mkdir mcp_start
# 2.进入项目文件夹
cd mcp_start
# 3.初始化项目
uv init -p 3.11
# 4.添加依赖 twine 用于发布包到 pypi
uv add "mcp[cli]==1.9.2"
uv add twine --group dev
创建 hello.py ,写入以下内容:
from mcp.server import FastMCP
app = FastMCP("hello-world")
@app.tool()
async def hello(name: str) -> str:
"""给对方欢迎提示语
Args:
name (str): 任何人的名字,当然,不是名字也行
Returns:
str: 欢迎提示语
"""
return f"hello,{name}!"
def main():
app.run(transport="stdio")
if __name__ == "__main__":
main()
关键点:
- 创建一个 FastMCP 实例 app,后续用此实例对象来定义工具和启动 MCP 服务
- 使用装饰器定义工具
@app.tool() - 给函数完整的注释,注释要准确描述该函数的作用,包括参数、返回值;因为后续这些说明是要发给 LLM 的,如果描述不清晰,LLM 就不知道怎么用这个工具,如何传参等等
- 定义传输方式:
app.run(transport="stdio"),最常用的就是标准输入输出(本地运行的话),也可以用 SSE,放到服务器上运行
现在写完这个文件了,如何启动?
可以使用 mcp 命令来启动服务:
mcp dev hello.py
会自动跳出来一个调试的页面,如下图所示,地址是http://localhost:6274/#resources
注意:需要从命令行把Session token: 后面的 token 粘贴到 configuration 中的 Proxy Session Token 中,点击 Connect,即可连接

连接成功之后,点击 Tools ,再点击 ListTools,点击 hello,然后输入 name 进行工具调试工作:

可以看到工具可以正常的请求和响应,现在可以准备发布工作了!
2.2 发布
2.2.1 获取 pypi token
先准备 pypi 的 token:https://pypi.org/manage/account/
登录之后滑到最下面,token 就是在这里创建:

2.2.2 配置 twine
twine 可以很方便的发布包到 pypi 上
# 创建配置文件
vim ~/.pypirc
# 写入以下内容
[distutils]
index-servers =
pypi
[pypi]
repository = https://upload.pypi.org/legacy/
username = __token__
password = ****
里面的 password 字段后面写上刚刚申请的 token 即可
2.2.3 项目配置文件
项目配置文件,我们要配置项目的入口mcp-start = "hello:main":
mcp-start运行的命令名称,安装这个包之后,就可以在命令行运行这个 mcp-start 来执行hello:main是 模块名:函数名,就是我们在命令行运行mcp-start命令时,这个函数就会被执行
[project]
name = "mcp-start"
version = "0.1.6"
description = "Add your description here"
readme = "README.md"
requires-python = ">=3.11"
dependencies = ["mcp[cli]==1.9.2"]
[dependency-groups]
dev = [
"twine>=6.1.0",
]
[project.scripts]
mcp-start = "hello:main"
2.2.4 打包
直接在命令行运行 uv build 命令即可,运行之后会出现一个 dist 文件夹
.
├── __pycache__
│ └── hello.cpython-311.pyc
├── dist
│ ├── mcp_start-0.1.6-py3-none-any.whl
│ └── mcp_start-0.1.6.tar.gz
├── hello.json
├── hello.py
├── mcp_start.egg-info
│ ├── dependency_links.txt
│ ├── entry_points.txt
│ ├── PKG-INFO
│ ├── requires.txt
│ ├── SOURCES.txt
│ └── top_level.txt
├── pyproject.toml
├── README.md
├── release.json
└── uv.lock
2.2.5 发布
发布使用 twine upload dist/* --verbose ,—verbose 是展示更多的发布信息
(mcp_start) ➜ mcp_start git:(master) ✗ twine upload dist/* --verbose
INFO Using configuration from /Users/powercheng/.pypirc
Uploading distributions to https://upload.pypi.org/legacy/
INFO dist/mcp_start-0.1.6-py3-none-any.whl (1.7 KB)
INFO dist/mcp_start-0.1.6.tar.gz (1.3 KB)
INFO username set by command options
INFO password set from config file
INFO username: __token__
INFO password: <hidden>
Uploading mcp_start-0.1.6-py3-none-any.whl
100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.5/3.5 kB • 00:00 • ?
...
...
View at:
https://pypi.org/project/mcp-start/0.1.6/
3. 验证及使用
3.1 验证
直接看发布完之后的日志,最底下有一个地址,就是我们的包地址:https://pypi.org/project/mcp-start/0.1.6/
访问即可查看:

3.2 使用
我们先自己写一个 json,就是装 mcp 的时候那个 json:
遵循下面的格式就好,我们使用 uvx 运行 mcp-start 程序!
{
"mcpServers": {
"hello": {
"command": "uvx",
"args": [
"mcp-start"
]
}
}
}
在 cursor 中安装:在 cursor 中找到 Tools 这个菜单,然后点击新增 MCP Server,把上面的 json 粘进去,然后保存就好

在 Agent 模式下,触发 MCP 调用:

至此,完成 MCP 服务从开发到发布全流程~