MCP Python SDK 发布流程全解:从依赖升级、双发布线管理到 PyPI 发布与回滚
2026/9/20 11:48:53 网站建设 项目流程
  • 人工智能
  • MCP 服务
  • MCP Clients

【免费下载链接】python-sdk

The official Python SDK for Model Context Protocol servers and clients

项目地址:https://gitcode.com/gh_mirrors/pythonsd/python-sdk
点击查看免费下载

本篇技术指南以本仓库根目录的 RELEASE.md 为核心骨架,系统讲解 Model Context Protocol(MCP)官方 Python SDK 的完整发布流程:如何按 DEPENDENCY_POLICY.md 的约束升级依赖并重新生成锁文件、mainv1.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上的标签会构建并发布两个发行包(mcpmcp-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 如何操作:改声明 → 重新生成锁文件

具体操作分两步:

  1. 修改 pyproject.toml 中的依赖版本。注意根mcp项目的运行时依赖是动态的,位于[tool.hatch.metadata.hooks.uv-dynamic-versioning].dependencies块中(即上文展示的那一段),而不是常规的静态[project.dependencies]

  2. 重新生成锁文件

    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 发布标志
当前稳定版mainv2.X.Y非预发布;成为Latest
维护版(上一大版本)v1.xv1.X.Y非预发布;不是Latest
预发布mainv2.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发布时,如果四个上传文件(mcpmcp-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

完整步骤:

  1. 确认发布提交上完整测试矩阵全绿。发布工作流会重跑同样的检查并阻塞发布直到通过,所以若某条腿红了,应在发布 run 上重跑失败的任务——但正确的做法是在创建发布之前就确认全绿,而不是等标签已经存在后再发现红。

  2. 从该提交冻结main直到标签存在:发布用显式--target创建,期间不应再有其他提交落地。

  3. 以非预发布方式创建发布,并把已验证提交传给--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会被忽略。重新创建发布前,务必先删除旧标签,并仔细核对新标签指向哪里。

  4. 精心编写发布说明:亮点、已知不完整之处、指向文档和迁移指南的链接,放在## What's Changed列表之上。生成该列表可以用发布 UI 的 "Generate release notes"——但必须手工把 Previous tag 设为该发布线(line)上的上一个发布,因为自动选中的基线是最新标签,它可能位于另一条发布线(比如 v1.x)上;也可以直接把整个正文写进传给--notes-file的文件。正文中请使用绝对 URL(相对链接在 GitHub 发布正文中无法解析)。

  5. 如果稳定版发布后发现坏了:在 PyPI 上 yank 它,然后把修复作为下一个补丁版本发布。绝不要从 PyPI 删除发布——版本号不能复用。mcpmcp-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参数才能主动安装预发布版。

步骤:

  1. 预发布阶段 README 和文档会钉住精确的预发布版本,所以先更新这些示例(用 grep 搜索旧版本号——钉住的版本位于 README 的 Installation 章节、docs/index.md、docs/get-started/installation.md 和 docs/get-started/real-host.md),保证被标签的提交——也就是 PyPI 发布的 README——写的是正在发布的版本。进入新阶段(alpha → beta → rc → stable)时还要更新横幅措辞;进入稳定阶段则去掉钉住的版本。

  2. 同样确认发布提交上完整测试矩阵全绿。

  3. 以预发布方式创建发布,并把已验证提交传给--target。预发布标志会让 GitHub 的 "Latest" 徽章和/releases/latest继续停留在最新的稳定版上:

    gh release create v2.X.YbN --prerelease --title v2.X.YbN --target <commit-sha>
  4. 编写发布说明:自上一个预发布以来改了什么、已知不完整之处、安装命令(pip install mcp==2.X.YbN)、指向迁移指南的链接,使用绝对 URL。

  5. 如果预发布坏了:在 PyPI 上同时 yankmcpmcp-types,然后切下一个预发布版本,并把 yank 原因和 GitHub 发布说明指向替代版本。

七、贯穿始终的保障机制:CI 与发布检查

整个发布流程的正确性依赖 .github/workflows/main.yml 与 .github/workflows/shared.yml 提供的"发布前全绿"保障:

  • CI 在mainv1.x分支和v*.*.*标签上运行(main.yml 的on段),发布工作流通过needs: [checks]复用同一套shared.yml检查,检查不过就不允许发布
  • shared.yml 中除了上文提到的双解析矩阵测试外,还包含 pre-commit 全量检查、README 代码片段一致性检查(scripts/update_readme_snippets.py --check)、以及mcp-types在空环境中独立安装并 import 的验证,确保线类型包不隐式依赖 SDK 栈。
  • 发布工作流本身在构建mcpmcp-types之后,通过 trusted publishing(id-token: write)上传到 PyPI 的releaseenvironment,skip-existing: true支持部分失败后的幂等重跑。

这也解释了 RELEASE.md 为何反复强调"在创建发布前验证全绿":标签一旦创建,元数据、工作流选择、PyPI 长描述就全部由该提交决定,事后修正的成本远高于事前检查。

八、一张图看懂三种发布的决策要点

决策点稳定版 v2.X.Y维护版 v1.X.Y预发布 v2.X.YbN
源分支mainv1.xmain
--target已验证的 main 提交v1.x 分支的已验证提交已验证的 main 提交
--prerelease不传不传
--latest默认 Latest--latest=false自动保持非 Latest
Previous tag本线上一稳定版上一v1.*上一预发布
发布产物mcp+mcp-typesmcpmcp+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

项目地址:https://gitcode.com/gh_mirrors/pythonsd/python-sdk
点击查看免费下载

相关推荐

上一篇:终极指南:如何使用Kronos开源AI模型实现85%准确率的股票预测
下一篇:【亲测免费】CabloyJS 全栈框架常见问题解决方案:从入门到精通的终极指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询