内容
# @triparc/xray-mcp
[](https://github.com/TravelEdge/xray-mcp/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/@triparc/xray-mcp)
[](LICENSE)
[](https://nodejs.org/)
用于 [Xray Cloud 测试管理](https://www.getxray.app/) 的生产级 MCP 服务器 — 90 种工具涵盖完整的 API 接口,优化令牌响应。
## 功能
- **10 个领域共 90 种工具** — 测试,测试运行,执行,测试计划,测试集,预条件,文件夹,证据,导入和管理
- **令牌优化对象表示法(TOON)** — 默认响应格式减少 LLM 令牌消耗;按调用切换到 `json` 或 `summary`
- **两种传输模式** — `stdio` 用于本地 IDE 使用,可流式传输的 HTTP 用于服务器部署
- **支持 Docker 和 Helm** — 多阶段 Alpine 镜像和生产 Helm 图表
- **三种凭证模式** — `strict`(个人),`shared-reads`(团队读取),`fully-shared`(内部服务器)
- **四个区域端点** — `global`,`us`,`eu`,`au` — 通过 `XRAY_REGION` 选择
- **每个请求的凭证隔离** 在 HTTP 模式下 — 每个 `POST /mcp` 从请求头解析其自己的凭证
- **零额外依赖** — 原生 Node.js 22 `fetch` 用于所有 HTTP;无需 `graphql-request`,无需 `axios`
## 先决条件
- Node.js >= 22
- Xray Cloud API 凭证 — 在 **Xray Cloud > API Keys** 生成(参见 [Xray 身份验证文档](https://docs.getxray.app/display/XRAYCLOUD/Authentication+-+REST+v2))
## 快速入门
```bash
export XRAY_CLIENT_ID=your-client-id
export XRAY_CLIENT_SECRET=your-client-secret
npx -y @triparc/xray-mcp
```
服务器在 stdio 模式下启动,准备好与支持 MCP 的 IDE 连接。
## IDE 设置
### Claude Desktop
配置文件:`~/Library/Application Support/Claude/claude_desktop_config.json`(macOS)或 `%APPDATA%\Claude\claude_desktop_config.json`(Windows)
**stdio(推荐用于个人使用)**
```json
{
"mcpServers": {
"xray": {
"command": "npx",
"args": ["-y", "@triparc/xray-mcp"],
"env": {
"XRAY_CLIENT_ID": "your-client-id",
"XRAY_CLIENT_SECRET": "your-client-secret"
},
"autoApprove": ["xray_get_*", "xray_list_*"]
}
}
}
```
> **提示:** `autoApprove` 跳过每工具确认对话框仅用于只读工具。如果您更喜欢每次调用手动批准,请删除它。
**HTTP(连接到正在运行的服务器)**
```json
{
"mcpServers": {
"xray": {
"transport": "http",
"url": "http://your-server:3000/mcp",
"headers": {
"X-Xray-Client-Id": "your-client-id",
"X-Xray-Client-Secret": "your-client-secret"
}
}
}
}
```
### Cursor
配置文件:`./cursor/mcp.json` 或 `~/.cursor/mcp.json`
**stdio**
```json
{
"mcpServers": {
"xray": {
"command": "npx",
"args": ["-y", "@triparc/xray-mcp"],
"env": {
"XRAY_CLIENT_ID": "your-client-id",
"XRAY_CLIENT_SECRET": "your-client-secret"
}
}
}
}
```
**HTTP**
```json
{
"mcpServers": {
"xray": {
"transport": "http",
"url": "http://your-server:3000/mcp",
"headers": {
"X-Xray-Client-Id": "your-client-id",
"X-Xray-Client-Secret": "your-client-secret"
}
}
}
}
```
### VS Code
配置文件:`.vscode/mcp.json`
**stdio**
```json
{
"servers": {
"xray": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@triparc/xray-mcp"],
"env": {
"XRAY_CLIENT_ID": "your-client-id",
"XRAY_CLIENT_SECRET": "your-client-secret"
}
}
}
}
```
**HTTP**
```json
{
"servers": {
"xray": {
"type": "http",
"url": "http://your-server:3000/mcp",
"headers": {
"X-Xray-Client-Id": "your-client-id",
"X-Xray-Client-Secret": "your-client-secret"
}
}
}
}
```
> **注意配置键差异:** Claude Desktop 和 Cursor 使用 `"mcpServers"` 和 `"transport": "http"`。VS Code 使用 `"servers"` 和 `"type": "http"`。这些差异由每个 IDE 的 MCP 客户端实现强制执行。
## Docker 部署
Docker 镜像仅在 HTTP 模式下运行(`TRANSPORT=http` 在镜像中设置)。通过环境变量传递凭证:
```bash
docker run -d \
-e XRAY_CLIENT_ID=your-client-id \
-e XRAY_CLIENT_SECRET=your-client-secret \
-e XRAY_CREDENTIAL_MODE=fully-shared \
-p 3000:3000 \
ghcr.io/traveledge/xray-mcp:latest
```
健康检查和就绪端点:
| 端点 | 目的 |
|----------|---------|
| `GET /healthz` | 存活 — 始终返回 `{ "status": "ok" }` |
| `GET /readyz` | 就绪 — 尝试 Xray 令牌交换以验证连接性 |
### Docker Compose
```yaml
services:
xray-mcp:
image: ghcr.io/traveledge/xray-mcp:latest
ports:
- "3000:3000"
environment:
XRAY_CLIENT_ID: your-client-id
XRAY_CLIENT_SECRET: your-client-secret
XRAY_CREDENTIAL_MODE: fully-shared
restart: unless-stopped
```
### 从源代码构建
```bash
docker build -t xray-mcp:local .
# 运行本地构建
docker run -d \
-e XRAY_CLIENT_ID=your-client-id \
-e XRAY_CLIENT_SECRET=your-client-secret \
-e XRAY_CREDENTIAL_MODE=fully-shared \
-p 3000:3000 \
xray-mcp:local
```
Dockerfile 使用多阶段构建:`node:24-alpine` 构建阶段编译 TypeScript;运行时阶段仅复制 `dist/` 和生产 `node_modules` 以获得最小镜像(~50MB)。以非 root `node` 用户和 `tini` 作为 PID 1 运行,以实现正确的信号处理。
## Kubernetes / Helm 部署
```bash
helm install xray-mcp ./helm \
--set credentials.clientId=your-client-id \
--set credentials.clientSecret=your-client-secret \
--set xray.credentialMode=shared-reads
```
### 关键 Helm 值
| 值 | 默认值 | 描述 |
|-------|---------|-------------|
| `replicaCount` | `1` | Pod 副本数量 |
| `image.repository` | `ghcr.io/traveledge/xray-mcp` | 容器镜像 |
| `image.tag` | `""`(使用图表 `appVersion`) | 镜像标签 |
| `xray.region` | `global` | Xray API 区域:`global`,`us`,`eu`,`au` |
| `xray.credentialMode` | `strict` | 凭证模式(见下文) |
| `credentials.clientId` | `""` | Xray 客户端 ID(图表创建 Secret) |
| `credentials.clientSecret` | `""` | Xray 客户端密钥(图表创建 Secret) |
| `existingSecret` | `""` | 现有 Secret 的名称(绕过图表 Secret 创建) |
| `ingress.enabled` | `false` | 启用 Kubernetes Ingress |
| `ingress.hosts` | `xray-mcp.example.com` | Ingress 主机名 |
| `autoscaling.enabled` | `false` | 启用 HPA |
| `autoscaling.maxReplicas` | `5` | HPA 最大副本 |
| `resources.limits.cpu` | `500m` | CPU 限制 |
| `resources.limits.memory` | `512Mi` | 内存限制 |
| `pdb.enabled` | `true` | 启用 PodDisruptionBudget |
### 使用外部 Secret(CSI Secret Store / External Secrets Operator)
设置 `existingSecret` 为预先存在的 Secret 的名称。图表将安装它而不是创建自己的:
```bash
helm install xray-mcp ./helm \
--set existingSecret=my-xray-credentials \
--set xray.credentialMode=shared-reads
```
Secret 必须包含键 `XRAY_CLIENT_ID` 和 `XRAY_CLIENT_SECRET`。
### 使用 Ingress 和 TLS 的生产部署
```bash
helm install xray-mcp ./helm \
--set existingSecret=my-xray-credentials \
--set xray.credentialMode=shared-reads \
--set xray.region=us \
--set ingress.enabled=true \
--set ingress.className=nginx \
--set ingress.hosts[0].host=xray-mcp.yourcompany.com \
--set ingress.hosts[0].paths[0].path=/ \
--set ingress.hosts[0].paths[0].pathType=Prefix \
--set ingress.tls[0].secretName=xray-mcp-tls \
--set ingress.tls[0].hosts[0]=xray-mcp.yourcompany.com \
--set autoscaling.enabled=true \
--set autoscaling.maxReplicas=3
```
### 将 MCP 客户端连接到 Helm 部署
部署后,配置您的 MCP 客户端使用指向 Ingress URL 的 HTTP 传输:
```json
{
"mcpServers": {
"xray": {
"transport": "http",
"url": "https://xray-mcp.yourcompany.com/mcp",
"headers": {
"X-Xray-Client-Id": "your-client-id",
"X-Xray-Client-Secret": "your-client-secret"
},
"autoApprove": ["xray_get_*", "xray_list_*"]
}
}
}
```
在 `fully-shared` 模式下,标头是可选的 — 服务器为所有操作使用自己的凭证。
## 环境变量
### 服务器配置
| 变量 | 必需 | 默认值 | 描述 |
|----------|----------|---------|-------------|
| `XRAY_CLIENT_ID` | 是(stdio) | — | Xray Cloud API 客户端 ID |
| `XRAY_CLIENT_SECRET` | 是(stdio) | — | Xray Cloud API 客户端密钥 |
| `XRAY_REGION` | 否 | `global` | API 区域:`global`,`us`,`eu`,`au` |
| `XRAY_CREDENTIAL_MODE` | 否 | `strict` | 凭证模式:`strict`,`shared-reads`,`fully-shared` |
| `TRANSPORT` | 否 | `stdio` | 传输:`stdio` 或 `http` |
| `PORT` | 否 | `3000` | HTTP 监听端口(仅 HTTP 模式) |
| `ALLOWED_HOSTS` | 否 | — | 用于 DNS 绑定保护的逗号分隔允许主机(仅 HTTP 模式) |
### HTTP 请求头(仅 HTTP 模式)
在 `strict` 和 `shared-reads` 模式下,HTTP 调用者提供每个请求的 Xray 凭证:
| 头部 | 必需 | 描述 |
|--------|----------|-------------|
| `X-Xray-Client-Id` | 是 | 请求 Xray 客户端 ID |
| `X-Xray-Client-Secret` | 是 | 请求 Xray 客户端密钥 |
在 `fully-shared` 模式下,服务器为所有请求使用其自己的 `XRAY_CLIENT_ID` / `XRAY_CLIENT_SECRET`,标头不是必需的。
## 凭证模式
| 模式 | 行为 | 用例 |
|------|----------|----------|
| `strict`(默认) | 每个调用者通过环境变量(stdio)或头部(HTTP)提供自己的凭证 | 个人 stdio 使用;多租户 HTTP,每个用户都有自己的 Xray 密钥 |
| `shared-reads` | 服务器凭证用于读取操作;调用者凭证用于写入 | 团队服务器,允许所有人读取测试数据,但仅限授权用户修改 |
| `fully-shared` | 为所有操作设置单个服务器凭证 | 内部团队服务器,所有团队成员共享一个 Xray 账户 |
**stdio 模式:** 凭证来自 `XRAY_CLIENT_ID` / `XRAY_CLIENT_SECRET` 环境变量。
**HTTP 模式:** 凭证来自 `X-Xray-Client-Id` / `X-Xray-Client-Secret` 请求头(除 `fully-shared` 外,服务器环境变量使用)。
## 工具
90 种工具,涵盖 10 个领域。所有工具都接受可选的 `format` 参数:
- `format: "toon"`(默认)— 令牌优化对象表示法,最小令牌使用量
- `format: "json"` — 来自 Xray API 的原始 JSON 响应
- `format: "summary"` — 单行人类可读摘要
| 领域 | 工具 | 访问权限 |
|--------|-------|--------|
| 测试 | 13 | 读取 / 写入 |
| 测试运行 | 14 | 读取 / 写入 |
| 测试执行 | 8 | 读取 / 写入 |
| 测试计划 | 8 | 读取 / 写入 |
| 测试集 | 6 | 读取 / 写入 |
| 前置条件 | 7 | 读取 / 写入 |
| 文件夹 | 9 | 读取 / 写入 |
| 证据 | 8 | 读取 / 写入 |
| 导入 | 8 | 写入 |
| 管理 | 9 | 读取 / 写入 |
| **总数** | **90** | |
参见 [TOOLS.md](TOOLS.md) 完整的工具参考,包括参数、示例和响应格式。
## TOON 格式
**令牌优化对象表示法(TOON)** 是默认响应格式。它会剥离冗长的 JSON 键,压缩嵌套结构,并使用简洁的状态图标 — 与原始 Xray API 响应相比,可减少 40-70% 的令牌消耗。
示例:具有 50 次运行的测试执行返回 ~800 个令牌的 TOON,而 ~3,500 个令牌的原始 JSON。
**按调用切换格式:**
```
使用 listTestRuns 工具,format: "json" 获取完整的 JSON 输出
```
```
使用 getTestDetails 工具,format: "summary" 获取一行摘要
```
TOON 适用于 LLM 消费。如果您需要将 Xray 响应传递给其他系统,请使用 `format: "json"` 进行规范合规输出。
## 开发
### 本地设置
```bash
# 需要 Node.js >= 22 和 pnpm
npm install -g pnpm
pnpm install
pnpm build
pnpm test
```
### 在 stdio 模式下运行
```bash
XRAY_CLIENT_ID=your-id XRAY_CLIENT_SECRET=your-secret node dist/index.js
```
### 在 HTTP 模式下运行
```bash
TRANSPORT=http XRAY_CLIENT_ID=your-id XRAY_CLIENT_SECRET=your-secret node dist/index.js
```
### 可用脚本
| 脚本 | 描述 |
|--------|-------------|
| `pnpm build` | 编译 TypeScript 到 `dist/` |
| `pnpm dev` | 监视模式 — 更改时重新编译 |
| `pnpm test` | 运行 Vitest 测试套件 |
| `pnpm test:coverage` | 运行测试并生成 V8 覆盖率报告 |
| `pnpm lint` | 运行 Biome 校验和格式化检查 |
| `pnpm lint:fix` | 自动修复校验和格式化问题 |
| `pnpm introspect` | 内省实时 Xray Cloud GraphQL 模式(需要凭证) |
| `pnpm introspect:audit` | 审计所有 90 个工具对抗实时模式 — 报告不匹配 |
## 模式验证
该项目包括一个内省脚本,验证所有 GraphQL 查询对抗实时 Xray Cloud API 模式。这可以捕获字段名称更改、参数删除和类型不匹配等问题,然后再投入生产。
```bash
# 需要 XRAY_CLIENT_ID 和 XRAY_CLIENT_SECRET
export XRAY_CLIENT_ID=your-id
export XRAY_CLIENT_SECRET=your-secret
# 内省模式并保存到 schema/ 目录
pnpm introspect
# 审计所有工具对抗实时模式
pnpm introspect:audit
```
审计检查每个查询和变异:
- 根字段存在(例如,`getTest` 存在于 Query 类型)
- 参数名称和类型与模式匹配
- 已弃用字段
结果写入 `schema/audit-report.md`。`schema/` 目录被 gitignore — 每个开发人员都运行自己的 Xray 实例。
## 贡献
欢迎贡献。请阅读 [CONTRIBUTING.md](CONTRIBUTING.md) 以获取开发工作流、提交约定和拉取请求指南,然后再开启问题或 PR。
## 许可证
[Apache License 2.0](LICENSE)
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器