Metadata-Version: 2.4
Name: zentao-bugfix-mcp
Version: 0.1.0
Summary: 禅道 Bug MCP 服务 —— 在 Cursor 等客户端中查询待处理缺陷与 Bug 详情
Project-URL: Homepage, https://git.xhkjedu.com/xh/zentao_bugfix_mcp
Project-URL: Repository, https://git.xhkjedu.com/xh/zentao_bugfix_mcp
Author-email: wangguangxue <18837135595@163.com>
License-Expression: MIT
License-File: LICENSE
Keywords: bugfix,mcp,zentao
Classifier: Development Status :: 3 - Alpha
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Software Development :: Bug Tracking
Requires-Python: >=3.10
Requires-Dist: fastmcp>=2.3.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: requests>=2.31.0
Requires-Dist: starlette>=0.37.0
Requires-Dist: uvicorn>=0.30.0
Description-Content-Type: text/markdown

# 禅道 Bug MCP 服务

在 Cursor 里通过 MCP 查禅道「指派给我的 Bug」、详情与截图。本服务**只对接禅道 API**；修复方案与改代码仍在 Cursor 同一对话中完成。

**团队可选用两种 Cursor 接入方式（可同时存在）：**

| 方式 | MCP 跑在哪里 | Cursor 配置要点 |
|------|--------------|-----------------|
| **A. 远程 HTTP** | 公司服务器（Docker / 裸机） | `url` + `headers`（`X-Zentao-*`） |
| **B. PyPI + `uvx`（stdio）** | 每人本机子进程 | `command: uvx` + `env`（`ZENTAO_*`、`MCP_TRANSPORT=stdio`） |

```
方式 A：  禅道 API ←── MCP（服务器, streamable-http） ←── Cursor（url + headers）
方式 B：  禅道 API ←── MCP（本机 uvx, stdio）        ←── Cursor（command + env）
```

- **方式 A**：适合统一运维、内网 HTTPS、集中 `MCP_AUTH_TOKEN`。  
- **方式 B**：适合发布到 **PyPI** 后一条 `uvx` 命令接入，无需自建服务（禅道凭据在本机环境变量）。  

详细发版与核对清单见：[docs/PYPI发布与双模式接入计划.md](docs/PYPI发布与双模式接入计划.md)。  
示例配置（勿直接提交密码）：[docs/cursor-mcp.uvx.example.json](docs/cursor-mcp.uvx.example.json)、[docs/cursor-mcp.http.example.json](docs/cursor-mcp.http.example.json)。

## 提供的工具

| 工具 | 功能 | 参数 |
|------|------|------|
| `list_my_bugs` | 查询指派给我的待处理 Bug | `product_id`（可选） |
| `get_bug_detail` | Bug 文字详情（含步骤、附件链接） | `bug_id` |
| `get_bug_detail_with_images` | 同上 + 禅道 Token 拉取图片，供 Cursor 看图分析 | `bug_id` |

---

## 服务端部署

### 方式一：Docker（推荐）

```bash
# 1. 克隆代码
git clone <repo-url> && cd zentao-bugfix-mcp

# 2. 配置环境变量
cp .env.example .env
# 编辑 .env，填写认证令牌与禅道默认值（禅道也可仅由客户端 headers 传入）

# 3. 启动
docker compose up -d


# 4. 构建失败重新构建
# 防止镜像内容和实际内容不对称
docker compose build --no-cache

docker compose up -d
```

docker compose build --no-cache

服务默认监听 `http://<服务器IP>:8000/mcp`。

### 方式二：裸 Python

```bash
pip install .
cp .env.example .env    # 编辑 .env
zentao-bugfix-mcp       # 启动
```

### 服务端环境变量

| 变量                     | 必填 | 默认值            | 说明                                     |
| ------------------------ | ---- | ----------------- | ---------------------------------------- |
| `MCP_AUTH_TOKEN`         | 否   |                   | Bearer 认证令牌（公网部署时必须设置）    |
| `MCP_PORT`               | 否   | `8000`            | 监听端口                                 |
| `MCP_HOST`               | 否   | `0.0.0.0`         | 监听地址                                 |
| `MCP_TRANSPORT`          | 否   | `streamable-http` | 传输模式                                 |
| `ZENTAO_URL`             | 否   |                   | 禅道地址（服务端默认值，可被客户端覆盖） |
| `ZENTAO_ACCOUNT`         | 否   |                   | 禅道账号（服务端默认值，可被客户端覆盖） |
| `ZENTAO_PASSWORD`        | 否   |                   | 禅道密码（服务端默认值，可被客户端覆盖） |
| `ZENTAO_PRODUCT_ID`      | 否   | `0`               | 默认产品 ID（可被客户端覆盖）            |
| `ZENTAO_TOKEN_TIMEOUT`   | 否   | `15`              | 获取 Token 超时（秒）                    |
| `ZENTAO_REQUEST_TIMEOUT` | 否   | `30`              | 禅道 API 请求超时（秒）                  |

> 禅道配置的优先级：**客户端请求头 > 服务端 .env**。
> 如果团队共用同一禅道实例且希望统一管理，可以在服务端 .env 中配置；否则留空，由每个用户通过 headers 传入自己的账号。
>
> **安全**：`X-Zentao-Password` 为明文头，公网场景必须在 MCP 服务前使用 **HTTPS** 终结；生产环境建议配合 `MCP_AUTH_TOKEN`。
>
> HTTP 健康检查：`GET /health`（Docker 镜像默认用此路径做 HEALTHCHECK）。MCP 端点仍为 `GET/POST /mcp`（与 FastMCP 默认 `FASTMCP_STREAMABLE_HTTP_PATH` 一致）。

### 生产部署建议

公网暴露时，在 MCP 服务前加一层 Nginx 做 HTTPS 终结：

```nginx
server {
    listen 443 ssl;
    server_name mcp.yourcompany.com;

    ssl_certificate     /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # 健康检查 / 探活（Docker HEALTHCHECK、K8s、监控同源可复用）
    location /health {
        proxy_pass http://127.0.0.1:8000;
        proxy_set_header Host $host;
    }

    location /mcp {
        proxy_pass http://127.0.0.1:8000;
        proxy_buffering off;
        proxy_read_timeout 300s;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Authorization $http_authorization;
        proxy_set_header X-Zentao-URL $http_x_zentao_url;
        proxy_set_header X-Zentao-Account $http_x_zentao_account;
        proxy_set_header X-Zentao-Password $http_x_zentao_password;
        proxy_set_header X-Zentao-Product-ID $http_x_zentao_product_id;
    }
}
```

---

## 团队接入 · 配置 Cursor MCP

### 方式 A：连接已部署的远程服务（`url` + `headers`）

复制 [docs/cursor-mcp.http.example.json](docs/cursor-mcp.http.example.json) 到项目 `.cursor/mcp.json` 或 `~/.cursor/mcp.json`，把 `url` / `headers` 改成你们环境。

> **headers 说明：** `Authorization` 仅在服务端配置了 `MCP_AUTH_TOKEN` 时需要；`X-Zentao-*` 可在每人配置里不同；若服务端 `.env` 已写死禅道且不设 Bearer，可只填 `url`。

### 方式 B：本机 `uvx`（包发布到 PyPI 后）

1. 按 [docs/PYPI发布与双模式接入计划.md](docs/PYPI发布与双模式接入计划.md) 完成 `twine upload`。  
2. 复制 [docs/cursor-mcp.uvx.example.json](docs/cursor-mcp.uvx.example.json)，将 `env` 中的 `ZENTAO_*` 改为个人禅道信息。  
3. **必须**包含 `MCP_TRANSPORT=stdio`（否则进程会按 HTTP 模式启动，与 Cursor 子进程不兼容）。  
4. 可选固定版本：`"args": ["zentao-bugfix-mcp==0.1.0"]`（与 `pyproject.toml` 的 `version` 一致）。

> **方式 B 注意：** 不使用 `X-Zentao-*` 请求头；stdio 下禅道配置只认环境变量或进程工作目录下的 `.env`（由 `python-dotenv` 加载）。

### 第 2 步（可选）：免确认自动执行

编辑 `~/.cursor/permissions.json`，允许工具自动执行而不弹确认框：

```json
{
  "mcpAllowlist": ["zentao-bugfix:*"]
}
```

### 使用方式

配置完成后，在 Cursor 对话中直接说：

- "帮我看看我的禅道 Bug"
- "分析一下 Bug #123 怎么修"

Cursor 的 AI 会调用 MCP 工具获取禅道数据，并在同一会话中继续完成分析与改代码。

> 如果把 `.cursorrules` 文件放在项目根目录，AI 的工具调用命中率会更高。
> 文件内容见仓库中的 [.cursorrules](.cursorrules)。

---

## 本地开发

在仓库根目录安装 editable 或正式 wheel 后，用 **stdio** 调试（与 **方式 B** 一致的环境变量）：

```bash
pip install -e .
export MCP_TRANSPORT=stdio
export ZENTAO_URL=https://你的禅道
export ZENTAO_ACCOUNT=...
export ZENTAO_PASSWORD=...
zentao-bugfix-mcp
```

**包装未发布、又想试跑 uvx 时：**

```bash
uvx --from . zentao-bugfix-mcp
```

（同样需要上述 `ZENTAO_*` 与 `MCP_TRANSPORT=stdio`，可通过 shell 导出或 Cursor `env`。）

**Cursor 本地 stdio（不经过 PyPI）** 也可使用 `command` + 已安装解释器，例如：

```json
{
  "mcpServers": {
    "zentao-bugfix-dev": {
      "command": "uvx",
      "args": ["--from", "D:/path/to/zentao_bugfix_mcp", "zentao-bugfix-mcp"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "ZENTAO_URL": "https://your-zentao.example.com",
        "ZENTAO_ACCOUNT": "your_account",
        "ZENTAO_PASSWORD": "your_password",
        "ZENTAO_PRODUCT_ID": "21"
      }
    }
  }
}
```

将 `--from` 改为本机克隆路径即可。

## 项目结构

```
├── src/
│   ├── __init__.py
│   ├── __main__.py     # 启动：stdio 或 streamable-http
│   ├── mcp_app.py      # FastMCP + /health + 工具
│   ├── config.py
│   ├── auth.py
│   └── zentao_client.py
├── docs/                   # PyPI 计划、Cursor 配置示例（无密钥）
├── .env.example            # 环境变量模板
├── LICENSE                 # MIT（PyPI 发版建议保留）
├── .cursorrules            # Cursor AI 工具调用引导
├── Dockerfile
├── docker-compose.yml
└── pyproject.toml
```

### 源码阅读顺序（建议）

路径均在 `src/` 下：

1. `mcp_app.py` — 工具与 `/health`
2. `config.py` — 环境与客户端从哪来
3. `auth.py` — HTTP 头如何进 ContextVar
4. `zentao_client.py` — 禅道 API

公开函数、类、以及行为不直观的私有方法在源码里用 **docstring** 标了一行说明；显而易见的 getter/单行逻辑不再重复注释。

### Cursor / VS Code 中 Ctrl+点击无法跳转？

1. 确认已装 **Python** 扩展，语言服务器为 **Pylance**（默认）。
2. **选择解释器**：`Ctrl+Shift+P` → `Python: Select Interpreter` → 选你用来 `pip install .` 的 venv/conda。
3. 仓库已含 `.vscode/settings.json`，为 `src` 配置了 `python.analysis.extraPaths`，刷新窗口后相对导入应能解析。
4. 若仍异常：`pip install .` 装当前项目，再 **Developer: Reload Window**。
