- 人工智能
- MCP 服务
- MCP Clients
【免费下载链接】python-sdk
The official Python SDK for Model Context Protocol servers and clients
本篇技术指南以本仓库根目录的 RELEASE.md 为核心骨架,系统讲解 Model Context Protocol(MCP)官方 Python SDK 的完整发布流程:如何按 DEPENDENCY_POLICY.md 的约束升级依赖并重新生成锁文件、main与v1.x两条发布线如何协作、稳定版 / 维护版 / 预发布版三种发布如何用ghCLI 正确创建,以及发布出错时如何在 PyPI 上安全回滚。读完本文,你将掌握一套可复制的、以 git 标签驱动版本、以 GitHub Release 触发自动发布的生产级发布 SOP,并能理解每一步背后的设计动机。
一、前置知识:版本号从哪来,发布由谁触发
在进入操作步骤之前,先建立两个关键认知,它们贯穿整个发布流程。
1.1 版本号来自 git 标签(uv-dynamic-versioning)
本仓库的包版本号不写入任何源码文件,而是由 git 标签动态推导。根目录 pyproject.toml 中的配置说明了这一点:
[project] name = "mcp" dynamic = ["version", "dependencies"] [build-system] requires = ["hatchling", "uv-dynamic-versioning"] build-backend = "hatchling.build" [tool.hatch.version] source = "uv-dynamic-versioning" [tool.uv-dynamic-versioning] vcs = "git" style = "pep440" bump = true也就是说:打什么标签,构建出的包就是什么版本。PEP 440 风格的语义化版本由uv-dynamic-versioning从 git 标签推导(详细语义见 VERSIONING.md)。因此,发布流程的核心操作本质上就是"在正确的提交上创建正确的标签"。
1.2 发布由 GitHub Release 触发,且从"被标签的提交"运行
发布动作由 .github/workflows/publish-pypi.yml 完成,该工作流监听release事件中的published类型:
on: release: types: [published]RELEASE.md 中特别强调:该工作流从被标签的提交运行。这意味着触发的工作流是标签所在分支自己的版本——main上的标签会构建并发布两个发行包(mcp与mcp-types,两者通过Requires-Dist: mcp-types=={{ version }}锁步发布),而v1.x上的标签只构建并发布mcp。
从 pyproject.toml 可以看到锁步约束的实际写法,位于动态依赖块中:
[tool.hatch.metadata.hooks.uv-dynamic-versioning] dependencies = [ # ... "mcp-types=={{ version }}", # ... ]{{ version }}模板会在构建时被当前标签推导出的版本号替换,从而保证mcp的每个发行版恰好依赖同版本的mcp-types(即"wire-types 包",见 DEPENDENCY_POLICY.md 中关于它是 SDK 另一半的说明)。
二、升级依赖的正确姿势(Bumping Dependencies)
RELEASE.md 将依赖升级明确拆成两层:
- 何时应该移动依赖下限(when)→ 由 DEPENDENCY_POLICY.md 规定;
- 如何操作(mechanics)→ 由 RELEASE.md 本节规定。
2.1 何时升级:遵守依赖政策
DEPENDENCY_POLICY.md 的核心规则是:mcp作为运行在他人环境里的库,所有运行时依赖都声明为>=下限,且只有当 SDK 开始使用某版本才首次提供的新功能或修复时才提升下限——不会仅仅因为上游发布了安全公告就提升。唯一例外是mcp-types:它是与mcp锁步发布的线类型包,每个mcp发行版要求恰好匹配自己的版本,属于 SDK 的另一半而非独立约束。
2.2 如何操作:改声明 → 重新生成锁文件
具体操作分两步:
修改 pyproject.toml 中的依赖版本。注意根
mcp项目的运行时依赖是动态的,位于[tool.hatch.metadata.hooks.uv-dynamic-versioning].dependencies块中(即上文展示的那一段),而不是常规的静态[project.dependencies]。重新生成锁文件:
uv lock # 只想移动某一个包时: uv lock --upgrade-package <package>
RELEASE.md 补充了一个容易混淆的细节:提交到仓库的uv.lock是默认策略(default-strategy)的解析结果;而用于证明依赖下限(floors)仍然成立的lowest-direct解析只在 CI 矩阵中的对应分支于测试时应用,从不提交。
这一点在 .github/workflows/shared.yml 的测试矩阵中有直接印证——每个 Python 版本(3.10 至 3.14)都会跑两种依赖解析:
dep-resolution: - name: lowest-direct install-flags: "--upgrade --resolution lowest-direct" - name: locked install-flags: "--frozen"lowest-direct用--resolution lowest-direct把所有直接依赖解析到声明的下限版本,专门验证>=下限是否仍然成立;locked则用--frozen严格按提交的锁文件安装。此外 DEPENDENCY_POLICY.md 还提到 Dependabot 每月分组自动升级uv锁文件与 GitHub Actions,但这只刷新开发/测试所依赖的版本,发布到 PyPI 的声明约束只按上述规则移动。
三、双发布线(Release Lines):main 与 v1.x
RELEASE.md 明确:两条分支持续发布,版本号来自 git 标签。核心表格如下:
| 发布线 | 分支 | 标签 | GitHub 发布标志 |
|---|---|---|---|
| 当前稳定版 | main | v2.X.Y | 非预发布;成为Latest |
| 维护版(上一大版本) | v1.x | v1.X.Y | 非预发布;不是Latest |
| 预发布 | main | v2.X.YaN/bN/rcN | 勾选Pre-release;永远不是 Latest |
几个贯穿全流程的要点:
- 两个 pyproject.toml(根项目与
src/mcp-types工作区包)中的Development Statusclassifier永久保持5 - Production/Stable,不随任何发布改动——即使发布预发布版本也不改。 mcp-types这个 PyPI 项目与mcp共用同一个 trusted publisher(同一仓库、同一工作流publish-pypi.yml、同一 GitHub environmentrelease)。- 从
main发布时,如果四个上传文件(mcp与mcp-types的 wheel + sdist)只成功上传了一部分,修复原因后直接重跑发布任务即可——publish-pypi.yml 的pypi-publish步骤设置了skip-existing: true,会跳过已在 PyPI 上的文件、只补传缺失部分。v1.x工作流只发布单个发行包,因此没有这个设置。
四、从 main 发布稳定版(v2.X.Y)
稳定版发布线有一个重要特点:README 和文档不钉版本号(pip install "mcp[cli]"永远安装最新的稳定版),所以常规的稳定版发布不需要一次"翻转版本钉"的提交;唯一的例外是新大版本的第一个稳定版——届时预发布横幅和钉住的版本号会通过那次翻转替换掉。
同时要牢记:被标签提交处的 README.md 就是 PyPI 的长描述,所以任何 README 修复都必须在打标签前合并进main。
完整步骤:
确认发布提交上完整测试矩阵全绿。发布工作流会重跑同样的检查并阻塞发布直到通过,所以若某条腿红了,应在发布 run 上重跑失败的任务——但正确的做法是在创建发布之前就确认全绿,而不是等标签已经存在后再发现红。
从该提交冻结
main直到标签存在:发布用显式--target创建,期间不应再有其他提交落地。以非预发布方式创建发布,并把已验证提交传给
--target(否则标签会落在那时main的 HEAD 上)。它成为 GitHub 的 "Latest",PyPI 上默认的pip install mcp也会切换到该版本。被标签的提交决定发布的一切——运行哪些工作流、发布哪些包元数据(README、classifiers)——所以它必须包含当前的发布工具链,而不只是通过测试。gh release create v2.X.Y --title v2.X.Y --target <commit-sha> --notes-file <notes.md>注意:如果标签已存在,
--target会被忽略。重新创建发布前,务必先删除旧标签,并仔细核对新标签指向哪里。精心编写发布说明:亮点、已知不完整之处、指向文档和迁移指南的链接,放在
## What's Changed列表之上。生成该列表可以用发布 UI 的 "Generate release notes"——但必须手工把 Previous tag 设为该发布线(line)上的上一个发布,因为自动选中的基线是最新标签,它可能位于另一条发布线(比如 v1.x)上;也可以直接把整个正文写进传给--notes-file的文件。正文中请使用绝对 URL(相对链接在 GitHub 发布正文中无法解析)。如果稳定版发布后发现坏了:在 PyPI 上 yank 它,然后把修复作为下一个补丁版本发布。绝不要从 PyPI 删除发布——版本号不能复用。
mcp和mcp-types要一起 yank(它们是一次发布),并把 yank 原因和 GitHub 发布说明都指向替代版本——因为 yank 并不能阻止==精确钉住版本的用户安装到那个坏版本。
五、从 v1.x 发布维护版(v1.X.Y)
维护版流程的第一步是把带[v1.x]前缀的 backport PR 合并进v1.x分支(以及任何 README 横幅更新——那是该版本在 PyPI 上展示的 README),确认分支尖端全绿,然后按与稳定版相同的方式创建发布,但有两点关键差异:
标签的目标是
v1.x分支上已验证的提交。UI 和 CLI 默认把 target 指向main,那是 v2 代码库——在main上创建的 v1 标签会把 v2 代码当作 v1 稳定版发布出去!同样出于 HEAD 会移动的原因,请传上一步已验证全绿的确切 commit,而不是分支名。gh release create v1.X.Y --title v1.X.Y --target <commit-sha> --latest=false --notes-file <notes.md>绝不能把 "Latest" 从 2.x 线抢走。UI 默认会给最新的非预发布版本勾选 "Set as the latest release";请取消勾选,或传
--latest=false,并在之后确认/releases/latest仍然指向最新的 v2 标签。如果失手了,用gh release edit v1.X.Y --latest=false修复——这只会修改发布元数据,不需要重新切发布。
生成说明时同样要手工把Previous tag设为上一个v1.*发布(理由同前)。最后,请另一个人 review 这次发布。
这一节与 VERSIONING.md 的支持策略互相印证:仓库同时维护 2.x(main,接收缺陷修复、安全修复和新功能)与 1.x(v1.x分支,只接收关键缺陷修复和安全修复),且每条线只有最新版本获得修复。
六、从 main 发布预发布版(Pre-releases)
下一个版本的预发布同样从main切出,使用 PEP 440 预发布标签:aN表示 alpha,后续用bN/rcN表示 beta 和 release candidate。PEP 440 后缀正是pip install mcp停留在稳定版的原因——只要存在满足普通mcp需求的最终版,安装器就不会选择预发布版;用户必须通过精确钉版本、指定预发布版本的 specifier,或--pre参数才能主动安装预发布版。
步骤:
预发布阶段 README 和文档会钉住精确的预发布版本,所以先更新这些示例(用 grep 搜索旧版本号——钉住的版本位于 README 的 Installation 章节、docs/index.md、docs/get-started/installation.md 和 docs/get-started/real-host.md),保证被标签的提交——也就是 PyPI 发布的 README——写的是正在发布的版本。进入新阶段(alpha → beta → rc → stable)时还要更新横幅措辞;进入稳定阶段则去掉钉住的版本。
同样确认发布提交上完整测试矩阵全绿。
以预发布方式创建发布,并把已验证提交传给
--target。预发布标志会让 GitHub 的 "Latest" 徽章和/releases/latest继续停留在最新的稳定版上:gh release create v2.X.YbN --prerelease --title v2.X.YbN --target <commit-sha>编写发布说明:自上一个预发布以来改了什么、已知不完整之处、安装命令(
pip install mcp==2.X.YbN)、指向迁移指南的链接,使用绝对 URL。如果预发布坏了:在 PyPI 上同时 yank
mcp和mcp-types,然后切下一个预发布版本,并把 yank 原因和 GitHub 发布说明指向替代版本。
七、贯穿始终的保障机制:CI 与发布检查
整个发布流程的正确性依赖 .github/workflows/main.yml 与 .github/workflows/shared.yml 提供的"发布前全绿"保障:
- CI 在
main、v1.x分支和v*.*.*标签上运行(main.yml 的on段),发布工作流通过needs: [checks]复用同一套shared.yml检查,检查不过就不允许发布。 - shared.yml 中除了上文提到的双解析矩阵测试外,还包含 pre-commit 全量检查、README 代码片段一致性检查(
scripts/update_readme_snippets.py --check)、以及mcp-types在空环境中独立安装并 import 的验证,确保线类型包不隐式依赖 SDK 栈。 - 发布工作流本身在构建
mcp与mcp-types之后,通过 trusted publishing(id-token: write)上传到 PyPI 的releaseenvironment,skip-existing: true支持部分失败后的幂等重跑。
这也解释了 RELEASE.md 为何反复强调"在创建发布前验证全绿":标签一旦创建,元数据、工作流选择、PyPI 长描述就全部由该提交决定,事后修正的成本远高于事前检查。
八、一张图看懂三种发布的决策要点
| 决策点 | 稳定版 v2.X.Y | 维护版 v1.X.Y | 预发布 v2.X.YbN |
|---|---|---|---|
| 源分支 | main | v1.x | main |
--target | 已验证的 main 提交 | v1.x 分支的已验证提交 | 已验证的 main 提交 |
--prerelease | 不传 | 不传 | 传 |
--latest | 默认 Latest | --latest=false | 自动保持非 Latest |
| Previous tag | 本线上一稳定版 | 上一v1.* | 上一预发布 |
| 发布产物 | mcp+mcp-types | 仅mcp | mcp+mcp-types |
| 出错处理 | 双包 yank,下个补丁版 | 同左 | 双包 yank,下个预发布 |
结语
MCP Python SDK 的发布体系把"不可变"原则贯彻到底:版本号锁定在 git 标签上、发布工作流从被标签的提交运行、PyPI 版本号不可复用、README 即 PyPI 长描述。对维护者而言,掌握本文的依赖升级纪律、双发布线隔离和gh release create的--target/--latest/--prerelease三组标志,就能安全地完成从日常补丁到大版本切换的全部发布场景;对 SDK 使用者而言,理解这套流程则能解释"为什么pip install mcp停在稳定版"、"为什么 v1.x 仍能收到关键修复"以及"为什么版本号永远不会倒退"等实际问题。
相关文档与源码索引:RELEASE.md(发布流程)、DEPENDENCY_POLICY.md(依赖下限政策)、VERSIONING.md(版本语义与支持策略)、pyproject.toml(动态版本与动态依赖)、.github/workflows/publish-pypi.yml(发布工作流)、.github/workflows/shared.yml(发布前检查矩阵)、docs/migration.md(跨大版本迁移指南)。
- 人工智能
- MCP 服务
- MCP Clients
【免费下载链接】python-sdk
The official Python SDK for Model Context Protocol servers and clients
相关推荐
Composio Python 包发布全流程指南:从 bump.py 版本管理到 PyPI 发布
Composio Python 包发布全流程指南:从 bump.py 版本管理到 PyPI 发布 本文以 Composio 开源仓库的 python/docs/
人工智能AI Agent工具调用MCP 服务MCP ClientsHydra 发布流程全解析:从版本号管理到 PyPI 发布与文档归档
Hydra 发布流程全解析:从版本号管理到 PyPI 发布与文档归档 本篇技术指南以 Hydra 项目的官方发布流程文档为主体,系统梳理从版本号更新、变更日志生
开发工具后端CLIGenkit Python SDK 版本发布全流程实战指南:从 RC 候选版到 PyPI 稳定发布
Genkit Python SDK 版本发布全流程实战指南:从 RC 候选版到 PyPI 稳定发布 导读 本文围绕 Genkit 开源仓库中 Python 发布
人工智能大模型后端AI AgentRAG工具调用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考