Plan: GitHub Actions 自动化发布与 PyPI Token

目标:
- 通过 Git 标签或手动触发自动构建并上传到 PyPI。
- 安全管理 PyPI API Token（初次全局，后续改项目作用域）。
- 提供本地与 CI 统一的构建与验证流程。
- 可选先发布到 TestPyPI 验证。

阶段与步骤:
1. 元数据完善
   - 在 pyproject.toml 添加 [project.urls]: Homepage, Repository, Issues。
   - 增补 classifiers: Operating System :: OS Independent, Programming Language :: Python :: 3 :: Only。
   - 确认 version 来源仅 pyproject（保持单一真源）。
2. 本地初次发布准备（使用 uv）
  - 无需在全局环境安装工具：使用 uv/uvx 临时运行。
  - 构建: uvx --from build python -m build。
  - 校验: uvx twine check dist/*。
  - 可选 TestPyPI 试发: uvx twine upload -r testpypi dist/*。
  - 用全新环境验证安装: uv pip install -i https://test.pypi.org/simple mcp-server-fetch。
3. 生成正式 PyPI API Token
   - 登录 https://pypi.org/。
   - Account → API tokens → Add API token (全局 first publish)。
   - 复制 token (仅显示一次)。
   - 在 GitHub 仓库 Settings → Secrets → New repository secret: PYPI_API_TOKEN。
4. GitHub Actions 工作流（使用 uv）
   - 文件: .github/workflows/publish.yml。
   - 触发: push tags 匹配 v* OR 手动 workflow_dispatch。
  - 步骤: checkout → setup-python (3.10+) → 安装 uv → 使用 uvx 构建与上传（无需 pip 安装依赖）。
   - 环境变量: TWINE_USERNAME='__token__'; TWINE_PASSWORD=secrets.PYPI_API_TOKEN。
   - 可选 matrix: 只需单平台 (ubuntu-latest)。
5. 版本发布流程
   - 更新 pyproject.toml version。
   - Git commit & push。
   - Git tag vX.Y.Z & push tag。
   - Action 自动上传。
   - 在 Releases 编写变更说明 (Changelog)。
6. 安全与健壮性
   - 启用 PyPI 2FA（强制 token 使用）。
   - 后续改为项目作用域 token。
   - 引入 ruff/pyright 在工作流 pre-upload 验证 (可选)。
7. 回滚策略
   - 若上传失败: 删除损坏文件重试（PyPI 不允许覆盖版本，需 bump patch）。
   - 若包内容错误: yanked 该版本，在 PyPI release 页面标记。然后发布修复版。
8. 自动化扩展 (后续)
   - 添加 test step (单元测试 / import check)。
   - Add job for TestPyPI before production (manual approval via environment protection)。

工作流示例 (概念草稿，uv 版):
- name: Publish
  on:
    push:
      tags:
        - 'v*'
    workflow_dispatch: {}
  jobs:
    build-publish:
      runs-on: ubuntu-latest
      steps:
        - uses: actions/checkout@v4
        - uses: actions/setup-python@v5
          with:
            python-version: '3.11'
        - name: Setup uv
          uses: astral-sh/setup-uv@v4
        - name: Build package (uvx)
          run: uvx --from build python -m build
        - name: Check dist (uvx)
          run: uvx twine check dist/*
        - name: Publish to PyPI
          if: startsWith(github.ref, 'refs/tags/v')
          env:
            TWINE_USERNAME: __token__
            TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
          run: uvx twine upload dist/*

本地命令速查（uv 版）:
```
uvx --from build python -m build
uvx twine check dist/*
uvx twine upload dist/*  # 首次或后续发布
```

PyPI Token 申请 Step-by-Step:
1. 打开 https://pypi.org/ 并登录（建议已启用 2FA）。
2. 顶部右上角用户名 → Account。
3. 左侧栏或页面中部找到 “API tokens”。
4. 点击 “Add API token”。
5. 选择作用域 (首次可选 ‘Entire account’)。命名 token（例如 mcp-server-fetch-initial）。
6. 点击 “Create token” 后复制显示的值（只出现一次）。
7. 在 GitHub 仓库: Settings → Secrets and variables → Actions → New repository secret。
8. Name: PYPI_API_TOKEN, Value: 粘贴复制的 token。
9. 保存后本地不再需要 .pypirc；CI 使用 Twine 环境变量发布。
10. 后续改项目作用域: 新建 token 选择 Project: mcp-server-fetch → 更新 GitHub Secret。

回顾要点:
- 只对标签发布，避免普通 push 误发。
- 使用 __token__ 用户名 + Secret 方式。
- 构建与校验分离，失败快速终止。
- 版本不可覆盖，错误时用 yank + 新版本替换。

开放问题(可讨论):
- 是否需要添加 CHANGELOG.md 并在工作流自动附加到 Release。
- 是否需要 pre-release (rc) 发布流程。
- 是否增加 supply chain 安全 (Sigstore, provenance)。
