内容
# polarion-mcp
MCP 服务器通过 [模型上下文协议](https://modelcontextprotocol.io) 将 Polarion ALM 的 REST API 公开给 AI 编码代理。
与将每个 Polarion 端点映射到其自己的 MCP 工具不同,服务器公开了一个代码模式接口:代理通过 `search` 发现操作,然后在单个 `code` 执行中自由组合调用。这保持了公共工具表面较小,同时生成的 Polarion 操作覆盖范围保持广泛。
背景信息:
- [Cloudflare 代码模式文章](https://blog.cloudflare.com/code-mode/)
- [`@cloudflare/codemode`](https://www.npmjs.com/package/@cloudflare/codemode) 包(在此项目中使用)
## 工作原理
服务器公开了三个 MCP 工具:
- **`search`** — 对可调用的 Polarion 操作目录进行模糊查找。使用它来发现函数名称、参数形状和返回类型。
- **`code`** — 在内部 `codemode.*` 接口上执行 JavaScript。
- **`read_attachment`** — 读取由 `code` 找到的特定 Polarion 附件。它接受附件 `links.content` URL 或 `resourceType` 加上完整的 JSON:API 附件 `id`,并返回支持的图像或 UTF-8 文本内容。
典型的代理流程:
1. 调用 `search` 找到正确操作及其签名。
2. 调用 `code` 并附上使用 `codemode.<operationId>(...)` 的脚本。
3. 在脚本返回附件元数据且其内容应被检查时,调用 `read_attachment`。
```js
(async () => {
return await codemode.getProjects({});
})();
```
更多示例:
```js
codemode.getWorkItems({ projectId: "PRJ", query: "type:requirement" })
codemode.patchWorkItem({ projectId: "PRJ", workItemId: "REQ-1", body: { ... } })
```
内部 `codemode.*` 操作从检查的 Polarion OpenAPI 规范中生成。操作名称与上游 `operationId` 匹配。允许列表控制哪些操作被公开 - 有关完整清单,请参见 [docs/allowlist.md](docs/allowlist.md)。
### 设计笔记
- 生成的列表操作获取所有 Polarion 页面并返回完整集合。
- 请求形状针对脚本进行了调整:路径参数和查询参数位于顶级;请求有效载荷位于 `body` 下。
- 生成的读取返回稳定的顶级信封:集合使用 `{ kind: "collection", items, ... }`,单个资源使用 `{ kind: "resource", item, ... }`,而 `204` 写入归一化为 `{ ok: true }`。
- 只有返回给 MCP 客户端的最终 `code` 结果可能会被截断。
- 附件内容路由在 `codemode` 之外;`read_attachment` 验证 Polarion 附件内容 URL,将 PNG 和 JPEG 附件转码为无损 WebP,仅当序列化 MCP 结果适合配置的内联预算时才返回内联图像。
- 身份验证保留在主机侧 - 沙盒代码路径从不接收凭证。
## 客户端配置
配置您的 MCP 客户端或代理程序以连接到服务器。
### stdio
```json
{
"mcpServers": {
"polarion": {
"type": "stdio",
"command": "deno",
"args": ["task", "start:stdio"],
"env": {
"POLARION_BASE_URL": "https://polarion.example.com/polarion/rest/v1",
"POLARION_ACCESS_TOKEN": "your-token"
}
}
}
}
```
### 流式 HTTP
```json
{
"mcpServers": {
"polarion": {
"type": "streamable-http",
"url": "http://localhost:8080/mcp",
"headers": {
"Authorization": "Bearer your-token"
}
}
}
}
```
HTTP 端点是无状态的,直接返回 JSON-RPC 响应。它不发出或要求 `Mcp-Session-Id`;对 `/mcp` 的 `GET` 和 `DELETE` 请求返回 `405 Method Not Allowed`。
## 运行服务器
### 设置
```bash
nix develop # 可选 - 设置 Deno 工具链
cp .env.example .env
# 填写本地默认值,或在 shell/container UI 中设置相同的变量
```
### 环境
| 变量 | 必需 | 描述 |
| ----------------------------------------- | ---------- | --------------------------------------------------------------------- |
| `POLARION_BASE_URL` | 是 | 完整的基本 URL,例如 `https://polarion.example.com/polarion/rest/v1` |
| `POLARION_ACCESS_TOKEN` | 仅限 stdio | stdio 模式下的 Bearer 令牌 |
| `PORT` | 否 | HTTP 监听端口(默认 `8080`) |
| `REST_PAGE_SIZE` | 否 | 生成的集合读取的页面大小;Polarion 默认值(未设置时) |
| `FETCH_CONCURRENCY_COUNT` | 否 | 生成的集合读取的并发页面获取(默认 `1`) |
| `READ_ATTACHMENT_INLINE_RESULT_MAX_BYTES` | 否 | 序列化的内联图像结果预算(默认 `1000000`) |
### 传输
在 HTTP 模式下启动:
```bash
deno task start
```
在 stdio 模式下启动:
```bash
deno task start:stdio
```
HTTP 模式在 `/mcp` 处提供 MCP 端点,并在 `GET /healthz` 和 `GET /readyz` 处提供未经身份验证的健康检查。调用者使用 `Authorization: Bearer <token>` 头对每个 MCP 请求进行身份验证。在 stdio 模式下,服务器从环境中读取 `POLARION_ACCESS_TOKEN`。
## 部署
使用 Docker Compose 构建并运行容器:
```bash
docker compose up -d --build
```
通过 Compose 环境提供 `POLARION_BASE_URL`。`PORT`、`REST_PAGE_SIZE` 和 `FETCH_CONCURRENCY_COUNT` 是可选的。使用 `GET /healthz` 或 `GET /readyz` 进行容器或负载均衡器探测。
## 代码生成
生成器从 [polarionrest.json](polarionrest.json) 读取完整的上游规范,修剪它并写入:
- [generated/polarion.trimmed.json](generated/polarion.trimmed.json) — 修剪后的 OpenAPI 规范
- [generated/polarion.ts](generated/polarion.ts) — TypeScript 客户端
- [src/generated/operations.ts](src/generated/operations.ts) — 操作注册表
- [docs/allowlist.md](docs/allowlist.md) — 允许-vs-阻止清单
重新生成:
```bash
deno task generate
```
## 开发
```bash
deno task fmt:check # 格式化
deno task lint # 校验
deno task test # 测试
deno task check # 类型检查
```
## 许可证
MIT