# ALCOMD3 MCP 说明

本文档说明 ALCOMD3 的 MCP 接入方式、可用工具、生命周期行为和排障方法。

ALCOMD3 当前实现遵循 MCP `2025-06-18` 规范的 stdio transport。MCP 客户端启动
`alcomd3-mcp` 作为子进程，通过 stdin/stdout 交换 JSON-RPC 消息。`alcomd3-mcp`
再通过 ALCOMD3 GUI 暴露的本机 IPC endpoint 请求应用数据。

## 当前边界

- MCP 功能默认停用，需要在 GUI 中手动启用后才会返回 ALCOMD3 数据。
- GUI 正常运行时会启动本机 IPC endpoint；启用/停用 MCP 只控制 tool call 是否返回数据。
- 当前只提供只读工具，不提供仓库添加、包安装、项目创建、备份或恢复等写操作。
- `initialize` 和 `tools/list` 不会启动 GUI。
- 实际 tool call 需要 GUI 时，如果 endpoint 缺失或不可连接，bridge 会尝试启动 GUI、
  等待 endpoint 出现并重试一次。
- GUI 启动失败或 endpoint 仍不可用时，tool call 返回结构化 `alcomd3_unavailable` 错误。
- MCP 停用时，tool call 返回结构化 `mcp_disabled` 错误，不关闭 endpoint、不 panic。
- GUI MCP 页面会在已知只读 tool call 执行时高亮对应工具，并在完成或失败后短暂保留高亮，
  便于观察很快完成的调用。
- GUI MCP 页面显示的是最近活动过的客户端，不是实时连接列表；超过一段时间没有活动的记录
  会自动隐藏。
- stdio stdout 只输出 MCP JSON-RPC 消息；日志只能写 stderr。
- GUI 内部 IPC 只监听 `127.0.0.1`，不监听公网地址。

## 架构

```text
MCP Host / Client
        |
        | stdio JSON-RPC
        v
alcomd3-mcp
        |
        | reads endpoint metadata
        v
ALCOMD3 data dir / mcp / endpoint.json
        |
        | localhost TCP, newline-delimited JSON
        v
ALCOMD3 GUI IPC server
```

对外 MCP transport 是 stdio。GUI 内部 TCP IPC 是 bridge 与桌面应用之间的私有通道，
不是对 MCP client 直接暴露的 HTTP 或 MCP transport。

## 启用和客户端配置

1. 启动 ALCOMD3。
2. 打开侧边栏中的 MCP 页面。
3. 点击启用，允许 MCP 工具读取 ALCOMD3 数据。
4. 复制页面中的 Bridge Command。
5. 在支持 stdio MCP server 的客户端中添加一个 MCP server，命令使用复制到的
   `alcomd3-mcp` 路径。

通用配置形态如下，具体字段名以 MCP 客户端为准：

```json
{
    "mcpServers": {
        "alcomd3": {
            "command": "C:\\Path\\To\\ALCOMD3\\alcomd3-mcp.exe"
        }
    }
}
```

macOS 和 Linux 使用无 `.exe` 后缀的 `alcomd3-mcp`。以 GUI MCP 页面显示的命令为准。

配置完成后，MCP 客户端可以在 ALCOMD3 未运行时保留 `alcomd3-mcp` stdio 连接。第一次
实际调用工具时，bridge 会尝试启动 ALCOMD3 GUI。GUI 启动后会暴露 endpoint；如果 GUI
中 MCP 已启用，后续调用会返回数据；如果 MCP 已停用，则返回 `mcp_disabled`，用户可在
GUI 中启用 MCP 后重试工具调用。

## 打包位置

- Windows：`alcomd3-mcp.exe` 与主 GUI 可执行文件位于同一安装目录。
- macOS：`alcomd3-mcp` 位于 `.app/Contents/MacOS/`。
- Linux：`alcomd3-mcp` 安装到 `/usr/bin/alcomd3-mcp`。
- AppImage：`alcomd3-mcp` 位于 AppDir 的 `usr/bin/` 内。

`cargo xtask build-alcom` 会同时构建 GUI 主程序和 `alcomd3-mcp`。

## Endpoint metadata

GUI 正常运行时会写入 endpoint metadata。默认路径位于 ALCOMD3 本地数据目录：

```text
VRChatCreatorCompanion/mcp/endpoint.json
```

测试和开发可通过环境变量覆盖路径：

```text
ALCOMD3_MCP_ENDPOINT_FILE
```

测试和开发也可覆盖 bridge 用来启动 GUI 的可执行文件路径：

```text
ALCOMD3_GUI_EXECUTABLE
```

metadata 格式：

```json
{
    "protocolVersion": 1,
    "transport": "tcp",
    "host": "127.0.0.1",
    "port": 49152,
    "token": "opaque-random-token",
    "pid": 12345
}
```

`token` 只用于 bridge 与 GUI 的本机 IPC 鉴权。不要把 endpoint 文件暴露给远程系统。

## 内部 IPC

内部 IPC 使用换行分隔 JSON。请求和响应结构如下：

```text
IpcRequest {
    protocolVersion,
    token,
    requestId,
    client,
    method,
    params
}

IpcResponse {
    requestId,
    ok,
    result?,
    error?
}
```

GUI 会校验 `protocolVersion` 和 `token`。校验失败会返回业务错误，不会执行工具逻辑。
校验通过后，如果 GUI 中 MCP 处于停用状态，GUI 会返回 `mcp_disabled`，不会读取或返回
项目、仓库、包等数据。

## 可用工具

所有工具都返回 JSON。成功时包含 `ok: true`；业务失败时包含
`ok: false` 和 `error: { code, message, data? }`。

| Tool | 参数 | 说明 |
| --- | --- | --- |
| `alcomd3_list_projects` | `{}` | 列出 ALCOMD3 已登记项目。 |
| `alcomd3_get_project_details` | `{ "project_path": string }` | 获取已登记项目详情和已安装包摘要。`project_path` 必须匹配 ALCOMD3 已登记项目。 |
| `alcomd3_list_repositories` | `{}` | 列出 ALCOMD3 当前配置的用户仓库和相关显示设置。 |
| `alcomd3_search_packages` | `{ "query"?: string, "limit"?: number }` | 查询当前已加载包数据；不强制刷新仓库。`limit` 默认 30，最大 100。 |

### 路径限制

`alcomd3_get_project_details` 只允许读取 ALCOMD3 数据库中已登记的项目路径。MCP
client 不能通过该工具读取任意本地路径。

### 仓库刷新限制

`alcomd3_search_packages` 使用现有包状态，不调用强制仓库刷新路径。MCP tool call 不会
触发仓库添加、仓库刷新策略重构或包安装。

## 生命周期和多进程行为

`alcomd3-mcp` 通常由 MCP 客户端按 stdio server 方式启动。不同客户端可能为不同会话
启动多个 bridge 进程，这是 MCP 客户端管理方式导致的正常可能性。

ALCOMD3 的生命周期边界：

- GUI 退出时会停止 IPC listener，并删除 endpoint 文件。
- `alcomd3-mcp` 不会因为 GUI 退出而主动退出。它继续保持 MCP stdio 连接，让 Codex
  等 AI 代理不需要重启就能在 GUI 重新启动后恢复调用。
- GUI 只能观察 bridge 发来的内部 IPC 请求，不能可靠判断 MCP client 与 bridge 的 stdio
  会话是否仍然存活。因此 GUI 中的客户端区域按“最近活动”展示，工具高亮才表示当前正在处理的调用。
- GUI 不可用期间，tool call 返回结构化 `alcomd3_unavailable` 错误。
- GUI 可用但 MCP 停用期间，tool call 返回结构化 `mcp_disabled` 错误。
- GUI 重新启动后，新的 endpoint metadata 写入同一路径，后续 tool call 会重新连接到
  GUI；是否返回数据取决于 GUI 中 MCP 是否启用。
- 如果 tool call 发生时 GUI 未运行，bridge 会尝试启动 GUI。为避免 MCP 客户端加载配置
  时弹出 GUI，`initialize` 和 `tools/list` 不触发启动。

如果看到短时间内存在多个 `alcomd3-mcp.exe`：

1. 先确认是否有多个 MCP 客户端或多个客户端会话正在运行。
2. GUI 关闭后 bridge 仍存在并不一定是残留；只要 MCP 客户端还保持 stdio 连接，它就会
   继续运行以便 GUI 重启后恢复。
3. 如果确认 MCP 客户端已经关闭但 bridge 仍存在，通常是旧版本 bridge 或客户端未按
   stdio 生命周期管理导致；关闭对应 MCP 客户端或手动结束旧进程后再使用新版本验证。

## 错误和排障

### `mcp_disabled`

MCP 页面处于停用状态。endpoint 仍可能显示运行中，这是正常状态；启用 MCP 后重新调用
工具即可返回数据。

### `ALCOMD3 is not running or the MCP IPC endpoint is unavailable`

常见原因：

- ALCOMD3 GUI 未运行。
- endpoint 文件不存在、已过期或被删除。
- 客户端启动的是旧路径中的 `alcomd3-mcp`。

处理方式：

1. 启动 ALCOMD3。
2. 在 MCP 页面确认 endpoint running。
3. 重新复制 Bridge Command，更新 MCP 客户端配置。
4. 重启 MCP 客户端。

### `protocol mismatch`

bridge 与 GUI 的内部 IPC 版本不一致。通常说明客户端启动了旧版本 `alcomd3-mcp`。
重新复制 GUI MCP 页面显示的命令，并确认它指向当前安装目录。

### stdout 出现非 JSON 内容

这是错误行为。stdio MCP server 的 stdout 只能写 JSON-RPC。调试输出必须写 stderr。

## 开发 smoke test

在仓库根目录构建 bridge：

```powershell
cargo build -p alcomd3-mcp
```

GUI 未运行时，可以用不存在的 endpoint 验证 bridge 不 panic：

```powershell
$env:ALCOMD3_MCP_ENDPOINT_FILE = Join-Path $env:TEMP "missing-alcomd3-mcp-endpoint.json"
$payload = @'
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"smoke","version":"0.0.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"alcomd3_list_projects","arguments":{}}}
'@
$payload | .\target\debug\alcomd3-mcp.exe
```

预期结果：

- `initialize` 成功。
- `tools/list` 返回四个只读工具。
- `tools/call` 返回 `ok: false` 的可读错误。
- stdout 中没有非 JSON-RPC 日志。

## 相关源码

- Bridge：`alcomd3-mcp/src/main.rs`
- 共享 IPC 协议：`alcomd3-mcp-protocol/src/lib.rs`
- GUI IPC server 和 tool dispatch：`vrc-get-gui/src/mcp.rs`
- GUI Tauri commands：`vrc-get-gui/src/commands/mcp.rs`
- GUI MCP 页面：`vrc-get-gui/app/_main/mcp/index.tsx`
- 打包逻辑：`xtask/src/build_alcom.rs`、`xtask/src/bundle_alcom*`

## 参考

- MCP Specification `2025-06-18`: <https://modelcontextprotocol.io/specification/2025-06-18>
- MCP stdio transport: <https://modelcontextprotocol.io/specification/2025-06-18/basic/transports>
- MCP lifecycle: <https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle>
- MCP tools: <https://modelcontextprotocol.io/specification/2025-06-18/server/tools>
