首页 / 资讯中心 / 文章详情

从零制作 MCP Server 并发布到 PyPI:用 uv + setup.py 让其他人 pip 安装即用(TaoToken 统一 Key 通道)

从零制作 MCP Server 并发布到 PyPI:用 uv + setup.py 让其他人 pip 安装即用(TaoToken 统一 Key 通道) ★ FEATURED ARTICLE
1. 为什么我要把自研 MCP Server 发到 PyPIMCP Server 说白了就是给 AI 客户端加外挂工具的进程你写一个函数声明成 tool客户端通过 stdio 或 HTTP 调它模型就能读时间、查数据库、调内部接口。问题在于很多人写完只在自己机器上uv run server.py换台电脑、发给同事对方就得克隆仓库、装依赖、改绝对路径体验极差。我试过把脚本直接丢给朋友结果他卡在--directory路径上折腾了半小时。后来想通了既然 Python 生态有 pip那就把 MCP Server 当成一个普通命令行包发布到 PyPI别人pip install mcp-educate-time之后用python -m 包名.server就能启动配置文件里不用写任何本地路径。这才是安装即用。这篇面向的是个人开发者你有一个能跑的 MCP Server想让它被别人一行命令装上。完整链路是 uv 初始化项目 → 写 server.py 工具 → 本地mcp dev测试 → 补__init__.py和setup.py→uv build出包 →twine upload上 PyPI → 别人 pip 安装后写 mcp.json 验证。中间涉及多工具统一调用时我会用 TaoToken 的统一 Key 通道来简化配置避免每个工具各配一套密钥。需要提前说清楚MCP 协议本身、客户端怎么连不是本文重点。本文只解决打包 发布 别人装完能用这一段。如果你连 MCP 是什么都还没概念先去补基础再回来跟着做。2. 用 uv 初始化项目并写第一个 MCP 工具2.1 uv 是什么为什么不用 pip venvuv 可以理解成 pip venv pip-tools 的合体用 Rust 写的装依赖快很多而且它自带 lock 文件别人复现你的环境更稳。对发布包这件事uv 还有个好处uv build直接按 PEP 517 标准出 sdist 和 wheel不用你手写一堆命令。安装 uv 按官网来即可装完验证uv --version有版本号输出就继续。2.2 创建项目骨架uv init mcp_educate_time cd mcp_educate_time uv venv uv add mcp[cli]uv init会生成pyproject.toml和main.pyuv venv建虚拟环境uv add mcp[cli]把 MCP 官方 SDK 和 CLI 工具装进来。装完你的pyproject.toml里会多出dependencies [mcp[cli]]这类声明。目录结构此时大概是这样mcp_educate_time/ ├── .venv/ ├── main.py ├── pyproject.toml └── uv.lock2.3 写 server.py一个 get_time 工具在项目根目录建一个和项目同名的包目录再放server.pymcp_educate_time/ └── mcp_educate_time/ └── server.pyserver.py内容from mcp.server.fastmcp import FastMCP import datetime mcp FastMCP() mcp.tool() def get_time() - str: 获取当前系统时间 return str(datetime.datetime.now()) if __name__ __main__: mcp.run(transportstdio)FastMCP是官方封装mcp.tool()装饰器把函数注册成工具函数签名和 docstring 会变成模型看到的工具描述。transportstdio表示走标准输入输出这是本地客户端最常用的方式。2.4 用 mcp dev 本地测试mcp dev mcp_educate_time/server.py它会起一个本地调试界面点 Connect再点 Tools能看到get_time点调用返回当前时间就说明工具没问题。这一步很关键别跳过——后面打包出问题你至少能确定是打包环节而不是工具逻辑。2.5 先在客户端里跑通再打包拿 Cursor 举例在mcp.json里加{ mcpServers: { get_time: { command: uv, args: [ --directory, D:\\pycharm\\create-pip-tools\\mcp_educate_time\\mcp_educate_time, run, server.py ] } } }注意这里的--directory是绝对路径这正是别人用不了的根源。设置里看到绿灯让 AI 调一次get_time成功就可以进入打包环节了。3. 编写 setup.py 与 pyproject 声明入口点3.1 补init.py在包目录下建__init__.pyfrom .server import get_time这样import mcp_educate_time时能拿到工具函数也方便别人做二次开发。3.2 安装打包依赖uv add setuptools wheel twinesetuptools负责构建wheel出 wheel 包twine负责上传到 PyPI。3.3 setup.py 完整片段from setuptools import setup, find_packages setup( namemcp_educate_time, version0.1.0, descriptionA simple MCP server exposing a get_time tool, long_descriptionopen(README.md, encodingutf-8).read(), long_description_content_typetext/markdown, authorrong, author_emailyour_emailexample.com, urlhttps://github.com/yourname/mcp_educate_time, packagesfind_packages(), install_requires[ mcp[cli], ], classifiers[ Programming Language :: Python :: 3, License :: OSI Approved :: MIT License, ], python_requires3.10, )几个容易踩的点name用下划线但 PyPI 上会规范成连字符所以别人安装时写pip install mcp-educate-timeinstall_requires必须带上mcp[cli]否则别人装完启动会报ModuleNotFoundErrorpython_requires建议写3.10MCP SDK 对版本有要求。3.4 用 pyproject.toml 声明入口点推荐如果你想让别人能直接敲命令启动而不是python -m在pyproject.toml里加[project.scripts] mcp-educate-time mcp_educate_time.server:mcp.run不过mcp.run带参数直接映射会有点别扭更稳的做法是包一层main()def main(): mcp.run(transportstdio)然后[project.scripts] mcp-educate-time mcp_educate_time.server:main这样别人装完直接mcp-educate-time就能起服务mcp.json 里command写这个命令名即可彻底摆脱路径问题。3.5 写 README.mdPyPI 页面会渲染 README至少写清楚这个 Server 提供什么工具、怎么安装、mcp.json 怎么配。示例# mcp_educate_time 一个演示用的 MCP Server提供 get_time 工具。 ## 安装 pip install mcp-educate-time ## 使用 在客户端 mcp.json 中配置 { mcpServers: { get_time: { command: python, args: [-m, mcp_educate_time.server] } } }README 写得好别人装完不用问你。4. 构建发布并用 pip 安装验证4.1 生成发布文件老教程用python setup.py sdist bdist_wheel现在推荐uv build它会在dist/下生成mcp_educate_time-0.1.0.tar.gz和mcp_educate_time-0.1.0-py3-none-any.whl。两个文件都上传pip 会优先选 wheel。4.2 上传到 PyPI先去 PyPI 注册账号并生成 API Token然后uv run twine upload dist/*用户名填__token__密码填你的 Token。上传成功后去 PyPI 搜你的包名能看到页面就对了。4.3 本地 pip 安装验证为了模拟别人新建一个干净目录建个新 venvpython -m venv test_env test_env\Scripts\activate pip install mcp-educate-time装完验证模块能导入python -c import mcp_educate_time; print(ok)再验证能启动python -m mcp_educate_time.server如果卡住不动说明 stdio 服务在等输入这是正常的CtrlC 退出即可。4.4 客户端最终测试在 Cursor 的mcp.json里改成不依赖本地路径的写法{ mcpServers: { get_time: { command: python, args: [-m, mcp_educate_time.server] } } }设置里看到绿灯让 AI 调一次get_time返回时间就说明整条链路通了。别人拿到你的包名照这个配置抄一遍就能用。4.5 多工具统一 Key用 TaoToken 简化配置当你的 MCP Server 不止一个工具还要调外部模型或 API 时每个工具各配一套 Key 会很乱。我一般用 TaoToken 做统一通道在 TaoToken 控制台 生成一个 KeyBase URL 填https://taotoken.net/api模型 ID 按需选。这样你的 Server 里读环境变量就行import os TAOTOKEN_KEY os.environ.get(TAOTOKEN_API_KEY) BASE_URL https://taotoken.net/api发布到 PyPI 的包里不要硬编码 Key让使用者自己配环境变量。想先试模型效果可以去 模型对话 页面点几下确认通道通了再写进代码。长期跑编码类 Agent 的话Coding Plan 更省心。5. 发布 MCP Server 常见报错排查5.1 401 Unauthorizedtwine upload报 401八成是 Token 填错或用户名没写__token__。检查uv run twine upload dist/* -u __token__ -p pypi-你的token如果还是 401去 PyPI 重新生成 Token注意 Token 只在生成时显示一次。5.2 local proxy failed客户端启动 MCP Server 时报local proxy failed或连接失败通常是command找不到。比如你写python但系统里只有python3或者虚拟环境没激活。解决办法在 mcp.json 里写绝对路径的 python或者用uv run包一层。Windows 上尤其注意反斜杠要转义。5.3 reading choices 相关报错如果 Server 内部调模型 API 时报error reading choices或解析响应失败先确认 Base URL 和模型 ID 是否匹配。用 TaoToken 的话Base URL 是https://taotoken.net/api模型 ID 要和 接入文档 里列的一致。响应结构对不上时打印原始返回体最快定位。5.4 OAuth 或鉴权失败有些客户端连远程 MCP Server 会走 OAuth。如果你只做本地 stdio不用管如果做 HTTP transport鉴权头要带对。报 OAuth 错误时先确认 Token 没过期再确认请求头格式是Authorization: Bearer xxx。5.5 别人装完报 ModuleNotFoundError最常见setup.py里install_requires漏了mcp[cli]或者packagesfind_packages()没找到你的包目录。检查包目录里有没有__init__.py以及find_packages()能不能扫到。可以在本地pip install dist/*.whl后python -c import 你的包验证。5.6 版本号重复导致上传失败PyPI 不允许同版本号重复上传。改了代码要发新版把version0.1.0改成0.1.1重新uv build再传。别想着覆盖覆盖不了。6. 装完即用把配置交给使用者走到这里你的 MCP Server 已经在 PyPI 上了。别人拿到包名三步就能用pip install mcp-educate-time在 mcp.json 里写python -m mcp_educate_time.server重启客户端看绿灯。如果你想让配置更统一尤其是 Server 里还要调模型建议在 README 里直接给出带 TaoToken 的示例Base URL 用https://taotoken.net/apiKey 让使用者去 API Keys 页面自己生成模型 ID 按 接入文档 填。这样你的包不绑定任何私有密钥谁都能装、谁都能配。最后提醒一句发布前一定在干净虚拟环境里pip install测一遍别只在自己开发环境跑通就传。我见过太多我这儿能用的包别人装完直接报错。
阅读完成 · 觉得有帮助?
咨询建站