Skip to main content
Glama
README.md
# AUL Uploader — MCP Server

`server_name`: **`aul_uploader`**

基于 Model Context Protocol 的 MCP 服务器,用于向 AUL 远程游戏库上传游戏、管理配置与封面。双仓库同步:GitHub 为主,GitCode 为镜像。

| library   | 仓库                                                                     | 分支     | 资源扩展名  |
| --------- | ---------------------------------------------------------------------- | ------ | ------ |
| `desktop` | GitHub `znm2500/AU-Launcher-Repo` / GitCode `znm1145/AU-Launcher-Repo` | `data` | `.7z`  |
| `mobile`  | GitHub `znm2500/AUL-Mobile-Repo` / GitCode `znm1145/AUL-Mobile-Repo`   | `data` | `.apk` |

封面命名:`{game_id}.webp`
安装包命名:`{game_id}.{ext}`(ext 由 library 决定)
配置文件:`config.json`(data 分支根目录)

***

## 1. 环境与安装

```bash
npm install
```

- Node.js >= 18

- 无 build 步骤,`node index.js` 直接启动

依赖:

| 包                           | 用途                                  |
| --------------------------- | ----------------------------------- |
| `@modelcontextprotocol/sdk` | MCP stdio / SSE 服务端 SDK             |
| `apk-info-parser`           | 本地解析 APK 清单(包名 / 版本)                |
| `axios`                     | HTTP 请求 GitHub / GitCode / jsDelivr |
| `sharp`                     | 封面缩放并转 WebP                         |

***

## 2. 接入方式

### 2.1 本地(Stdio)

```json
{
  "mcpServers": {
    "aul_uploader": {
      "command": "node",
      "args": ["C:\\absolute\\path\\to\\index.js"]
    }
  }
}
```

`args[0]` 建议写绝对路径,避免工作目录不一致导致找不到文件。

### 2.2 远程(HTTP / SSE)

```bash
# 监听所有网卡
node index.js --serve 3001

# 绑定指定 IP
node index.js --serve 3001 --host 192.168.1.20
```

启动后输出:

```
=== AUL Uploader MCP Server (SSE / HTTP) running ===
  Health check : http://0.0.0.0:3001/health
  SSE endpoint : http://0.0.0.0:3001/sse
  Message POST : http://0.0.0.0:3001/message
```

| 路径         | 方法   | 作用               |
| ---------- | ---- | ---------------- |
| `/health`  | GET  | 健康检查,返回工具数与活跃会话数 |
| `/sse`     | GET  | SSE 下行通道         |
| `/message` | POST | 客户端上行 JSON-RPC   |

客户端配置:

```json
{
  "mcpServers": {
    "aul_uploader_remote": {
      "transport": "sse",
      "url": "http://<host>:3001/sse"
    }
  }
}
```

> 安全提醒:SSE 本身无鉴权,跨公网部署时请在前面套 HTTPS 反代并加鉴权(Basic Auth / Bearer Token / IP 白名单三选一)。

### 2.3 启动方式总览

```bash
# 默认:Stdio 子进程
node index.js

# HTTP/SSE 服务端
node index.js --serve 3001 [--host <ip>]

# 单次 CLI 调试
node index.js --cli <tool> '<json_args>'
node index.js --cli <tool> @args.json
```

优先级:`--cli` > `--serve` > 默认 Stdio。

***

## 3. 工具总览

|  # | 工具                     | 说明                                     | 需要 Token              |
| -: | ---------------------- | -------------------------------------- | --------------------- |
|  1 | `check_tokens`         | 验证 GitHub / GitCode Token 是否有效         | token\_gh + token\_gt |
|  2 | `get_config`           | 读取远程 config.json,返回 games 列表与双仓库 sha   | token\_gh + token\_gt |
|  3 | `upload_cover_image`   | 上传/更新封面(自动缩放转 WebP,双仓库同步)              | token\_gh + token\_gt |
|  4 | `release_game_asset`   | 发布安装包到 Release(v{version} 需预先存在)       | token\_gh + token\_gt |
|  5 | `add_game_entry`       | 向 config.json 添加游戏条目并推送双仓库             | token\_gh + token\_gt |
|  6 | `full_upload_game`     | 一键完整上传:验证 -> 配置 -> 条目 -> 封面 -> Release | token\_gh + token\_gt |
|  7 | `get_apk_id`           | 解析 APK 包名生成 game\_id                   | 否(纯本地)                |
|  8 | `get_cover_image`      | 下载远程封面(CDN 优先,失败回退 GitHub API)         | 否(通常)                 |
|  9 | `delete_repo_file`     | 删除 data 分支中的文件(双仓库同步)                  | token\_gh + token\_gt |
| 10 | `delete_release_asset` | 删除 Release 中的资源文件                      | token\_gh + token\_gt |

***

## 4. 工具详解

### 4.1 `check_tokens`

验证两个平台的 Token 对仓库的访问权限。

**参数**

| 字段         | 类型     | 必填 |
| ---------- | ------ | -- |
| `token_gh` | string | 是  |
| `token_gt` | string | 是  |

**返回**

```json
{ "ok": true, "message": "Token 验证通过" }
```

***

### 4.2 `get_config`

读取远程 `config.json`,返回 games 列表摘要以及双仓库的 blob sha(供 `add_game_entry` 使用)。

**参数**

| 字段         | 类型                       | 必填 | 默认          |
| ---------- | ------------------------ | -- | ----------- |
| `token_gh` | string                   | 是  | —           |
| `token_gt` | string                   | 是  | —           |
| `library`  | `"desktop"` / `"mobile"` | 是  | `"desktop"` |

**返回**

```json
{
  "sha_gh": "abc123...",
  "sha_gt": "def456...",
  "game_count": 42,
  "games": [
    {
      "id": "game_id",
      "name_zh": "游戏名",
      "name_en": "Game Name",
      "engine": "Unity",
      "version": "0.0.1",
      "hot_score": 100
    }
  ],
  "raw_config": { "...": "完整的 config 对象" }
}
```

> `raw_config` 就是完整的 config 对象,`add_game_entry` 需要把它原样传回去。

***

### 4.3 `upload_cover_image`

上传或更新封面图片到 data 分支。自动缩放(最大 640x480,保持比例,不放大)并转为 WebP(质量 80)。双仓库同步,完成后清除 jsDelivr 缓存。

**参数**

| 字段           | 类型     | 必填 | 说明                       |
| ------------ | ------ | -- | ------------------------ |
| `token_gh`   | string | 是  | GitHub Token             |
| `token_gt`   | string | 是  | GitCode Token            |
| `library`    | enum   | 是  | `desktop` / `mobile`     |
| `image_path` | string | 是  | 本地图片绝对路径(webp/png/jpg 等) |
| `game_id`    | string | 是  | 游戏 ID,只允许字母数字下划线         |

**返回**

```json
{
  "ok": true,
  "file": "game_id.webp",
  "library": "desktop"
}
```

***

### 4.4 `release_game_asset`

发布安装包到 GitHub / GitCode Release。对应 tag `v{version}` 必须预先存在。上传前会删除同名旧资产。

**参数**

| 字段              | 类型     | 必填 | 默认          | 说明                                  |
| --------------- | ------ | -- | ----------- | ----------------------------------- |
| `token_gh`      | string | 是  | —           | GitHub Token                        |
| `token_gt`      | string | 是  | —           | GitCode Token                       |
| `library`       | enum   | 是  | `"desktop"` | 决定扩展名 desktop=.7z, mobile=.apk      |
| `version`       | enum   | 是  | —           | `"0.0.1"` / `"0.0.2"`               |
| `game_id`       | string | 是  | —           | 文件命名为 `{game_id}.{ext}`             |
| `file_path`     | string | 是  | —           | 本地安装包绝对路径                           |
| `upload_target` | enum   | 否  | `"both"`    | `"github"` / `"gitcode"` / `"both"` |

**返回**

```json
{
  "ok": true,
  "version": "0.0.1",
  "target": "both",
  "file": "game_id.7z"
}
```

***

### 4.5 `add_game_entry`

向 config.json 的 games 数组中追加一个条目并推送回双仓库。自动写入 `publish_time`(如未提供)。

**参数**

| 字段         | 类型     | 必填 | 说明                                           |
| ---------- | ------ | -- | -------------------------------------------- |
| `token_gh` | string | 是  | GitHub Token                                 |
| `token_gt` | string | 是  | GitCode Token                                |
| `library`  | enum   | 是  | `desktop` / `mobile`                         |
| `sha_gh`   | string | 是  | config 在 GitHub 的 sha(来自 `get_config`)       |
| `sha_gt`   | string | 是  | config 在 GitCode 的 sha(来自 `get_config`)      |
| `config`   | object | 是  | 完整 config 对象(来自 `get_config` 的 `raw_config`) |
| `game`     | object | 是  | 游戏数据,结构见下                                    |

`game` 对象:

| 字段             | 类型      | 必填 | 说明                    |
| -------------- | ------- | -- | --------------------- |
| `id`           | string  | 是  | 唯一 ID,只允许字母数字下划线      |
| `name`         | object  | 是  | `{ zh, en }`          |
| `author`       | object  | 是  | `{ zh, en }`          |
| `engine`       | string  | 是  | 引擎名,如 Unity / GMS2    |
| `version`      | enum    | 是  | `"0.0.1"` / `"0.0.2"` |
| `hot_score`    | integer | 否  | >=0,默认 0              |
| `publish_time` | string  | 否  | ISO 时间,默认当前时间         |

**返回**

```json
{
  "ok": true,
  "added_entry": {
    "id": "game_id",
    "name": { "zh": "...", "en": "..." },
    "author": { "zh": "...", "en": "..." },
    "engine": "Unity",
    "version": "0.0.1",
    "hot_score": 0,
    "publish_time": "2026-09-04T00:00:00.000Z"
  }
}
```

**校验规则**:

- `id` 只能包含字母、数字、下划线

- `name.zh` 和 `name.en` 必填

- `author.zh` 和 `author.en` 必填

- `version` 只能是 `0.0.1` 或 `0.0.2`

- `hot_score` 必须是 >=0 的整数

- `id` 不能与已有条目重复

***

### 4.6 `full_upload_game`

一键完整上传,按顺序执行:验证 Token -> 获取配置 -> 添加游戏条目 -> 上传封面 -> 发布 Release。

**参数**

| 字段              | 类型     | 必填 | 默认          | 说明                           |
| --------------- | ------ | -- | ----------- | ---------------------------- |
| `token_gh`      | string | 是  | —           | GitHub Token                 |
| `token_gt`      | string | 是  | —           | GitCode Token                |
| `library`       | enum   | 是  | `"desktop"` | `desktop` / `mobile`         |
| `image_path`    | string | 是  | —           | 本地封面图片绝对路径                   |
| `file_path`     | string | 是  | —           | 本地安装包绝对路径                    |
| `game`          | object | 是  | —           | 同 `add_game_entry` 的 game 结构 |
| `upload_target` | enum   | 否  | `"both"`    | Release 上传目标                 |

**返回**

```json
{
  "ok": true,
  "steps": [
    "1. Token 验证通过",
    "2. 获取配置成功 (当前游戏 N 个)",
    "3. 添加游戏条目成功: game_id",
    "4. 封面上传成功: game_id.webp",
    "5. Release 发布成功: game_id.7z @ v0.0.1"
  ],
  "game_id": "game_id"
}
```

***

### 4.7 `get_apk_id`

纯本地解析 APK,提取包名并将 `.` 替换为 `_`,生成符合 AUL 规则的 game\_id。

**参数**

| 字段         | 类型     | 必填 | 说明          |
| ---------- | ------ | -- | ----------- |
| `apk_path` | string | 是  | 本地 APK 绝对路径 |

**返回**

```json
{
  "ok": true,
  "package_name": "com.example.mygame",
  "game_id": "com_example_mygame",
  "version_name": "1.0.0",
  "version_code": 100
}
```

***

### 4.8 `get_cover_image`

从远程下载封面 `{game_id}.webp`。优先走 jsDelivr CDN(无需 Token,速度快),失败时回退到 GitHub Contents API。

**参数**

| 字段            | 类型      | 必填 | 默认          | 说明                        |
| ------------- | ------- | -- | ----------- | ------------------------- |
| `library`     | enum    | 是  | `"desktop"` | `desktop` / `mobile`      |
| `game_id`     | string  | 是  | —           | 游戏 ID                     |
| `output_path` | string  | 否  | 系统临时目录      | 保存到本地的绝对路径                |
| `use_cdn`     | boolean | 否  | `true`      | 是否优先走 CDN                 |
| `token_gh`    | string  | 否  | —           | 仅 CDN 失败回退 GitHub API 时需要 |

**返回**

```json
{
  "ok": true,
  "game_id": "game_id",
  "library": "desktop",
  "source": "jsdelivr",
  "source_url": "https://cdn.jsdelivr.net/gh/znm2500/AU-Launcher-Repo@data/game_id.webp",
  "saved_path": "D:\\covers\\game_id.webp",
  "size_bytes": 87342
}
```

***

### 4.9 `delete_repo_file`

从 data 分支删除指定文件,双仓库同步。

**参数**

| 字段          | 类型     | 必填 | 说明                       |
| ----------- | ------ | -- | ------------------------ |
| `token_gh`  | string | 是  | GitHub Token             |
| `token_gt`  | string | 是  | GitCode Token            |
| `library`   | enum   | 是  | `desktop` / `mobile`     |
| `file_name` | string | 是  | 要删除的文件名,如 `game_id.webp` |

**返回**

```json
{
  "ok": true,
  "deleted_file": "game_id.webp",
  "library": "desktop"
}
```

***

### 4.10 `delete_release_asset`

从指定 Release(tag 为 `v{version}`)中删除资源文件。

**参数**

| 字段              | 类型     | 必填 | 默认          | 说明                                  |
| --------------- | ------ | -- | ----------- | ----------------------------------- |
| `token_gh`      | string | 是  | —           | GitHub Token                        |
| `token_gt`      | string | 是  | —           | GitCode Token                       |
| `library`       | enum   | 是  | `"desktop"` | `desktop` / `mobile`                |
| `version`       | enum   | 是  | —           | `"0.0.1"` / `"0.0.2"`               |
| `file_name`     | string | 是  | —           | 资源文件名,如 `game_id.7z`                |
| `upload_target` | enum   | 否  | `"both"`    | `"github"` / `"gitcode"` / `"both"` |

**返回**

```json
{
  "ok": true,
  "version": "0.0.1",
  "file": "game_id.7z",
  "target": "both"
}
```

***

## 5. 常见工作流

### 5.1 桌面端上传新游戏

```
full_upload_game(
  library = "desktop",
  game = { id, name:{zh,en}, author:{zh,en}, engine, version },
  image_path = "D:/pics/cover.png",
  file_path = "D:/games/game.7z",
  token_gh = ...,
  token_gt = ...
)
```

### 5.2 移动端上传新 APK

```
1. get_apk_id(apk_path = "D:/apk/app.apk")
   -> 拿到 { game_id, version_name }

2. full_upload_game(
     library = "mobile",
     game = { id: game_id, name:{...}, author:{...}, engine, version },
     file_path = apk_path,
     image_path = ...
   )
```

### 5.3 复用远程已有封面

```
1. get_cover_image(library, game_id, output_path = "D:/temp/cover.webp")
   -> { saved_path }

2. full_upload_game(image_path = saved_path, ...)
```

### 5.4 分步上传(需要中间结果时)

```
1. check_tokens
2. get_config -> 拿到 { sha_gh, sha_gt, raw_config }
3. add_game_entry(config = raw_config, sha_gh, sha_gt, game = ...)
4. upload_cover_image(image_path, game_id)
5. release_game_asset(version, game_id, file_path)
```

### 5.5 只读操作(免 Token)

| 操作          | 工具                           |
| ----------- | ---------------------------- |
| 查游戏列表       | `get_config`(需 token)        |
| 下载封面        | `get_cover_image`(通常免 token) |
| 生成 game\_id | `get_apk_id`(纯本地)            |

***

## 6. 同步工具描述到 TRAE

`tools/*.json` 与 `SERVER_METADATA.json` 需拷贝到 TRAE solo agent lite 目录,TRAE 才能在 UI 侧展示工具:

```
源:
  SERVER_METADATA.json
  tools/*.json

目标:
  %USERPROFILE%\.trae-cn\mcps\s_AUL-Repo-Manager-<hash>\solo_agent_lite\aul_uploader\
    ├─ SERVER_METADATA.json
    └─ tools\*.json
```

PowerShell 一键同步:

```powershell
$src = "c:\Users\Weaver\Documents\GitHub\aul-uploader-mcp"
$dst = "$env:USERPROFILE\.trae-cn\mcps\s_AUL-Repo-Manager-<hash>\solo_agent_lite\aul_uploader"
New-Item -ItemType Directory -Force -Path (Join-Path $dst "tools") | Out-Null
Copy-Item -Force (Join-Path $src "SERVER_METADATA.json") $dst
Get-ChildItem (Join-Path $src "tools") -Filter *.json | ForEach-Object {
  Copy-Item -Force $_.FullName (Join-Path $dst "tools")
}
```

***

## 7. 错误排查

| 症状                   | 常见原因                       | 解决                               |
| -------------------- | -------------------------- | -------------------------------- |
| `node.exe not found` | 配置里写死了错误的 node 路径          | 改成 `"command": "node"` 让 PATH 解析 |
| Token 验证失败           | Token 过期或无仓库权限             | 重新生成 Token,确保有 repo 读写权限         |
| config 更新 409        | sha 过期,仓库有新提交              | 重新调用 `get_config` 获取最新 sha       |
| 封面上传后 CDN 不刷新        | jsDelivr 有缓存               | 等待,代码已自动调用 purge 接口              |
| Release 上传失败         | tag `v{version}` 不存在       | 先在仓库创建对应 Release                 |
| GitCode 上传失败         | GitCode API 限流或 token 权限不足 | 检查 token 权限,稍后重试                 |

TDQS

A3.8/5.0

Scored across 8 tools

Disambiguation4/5

Each tool covers a distinct resource or action: token validation, config fetching, cover upload/download, release asset publishing, entry addition, APK ID generation, and the composite full upload flow. The only mild ambiguity is that full_upload_game overlaps with the individual upload steps, but its description clearly positions it as the complete one-click alternative.

Naming Consistency4/5

Most tools follow a clear verb_noun pattern like check_tokens, get_config, add_game_entry, upload_cover_image, and get_apk_id. The main deviation is full_upload_game, which does not start with the verb, but the overall naming is still predictable and readable.

Tool Count5/5

With 8 tools, the set is well scoped for an upload pipeline: it covers authentication, config retrieval, APK parsing, cover image handling, asset release, entry creation, and a composite workflow. Each tool earns its place without the set feeling bloated or too sparse.

Completeness4/5

The core upload lifecycle is fully supported: token validation, config fetching, adding entries, uploading covers, publishing release assets, and the full end-to-end flow. Minor gaps exist, such as the lack of update/delete operations for game entries and no release tag creation, but these are mostly outside the primary uploader scope and can be worked around.

Maintenance

ActivityMaintained
ResponsivenessNo issues