# MCP 使用文档

## 定位

`jimu-platform` 的 MCP 服务是 MJYBrowser 实例编排入口。它可以生成完整 `chrome.exe` 启动参数，也可以在部署节点具备可执行路径时直接启动浏览器；浏览器启动后，如果 CDP 41729 或 Control API 41730 可达，MCP 继续负责标签、环境、截图和验收控制。

```text
MCP Client / AI Agent
  -> POST /api/v1/mcp
  -> Bearer mcp_token
  -> tools/list 或 tools/call
  -> browser.launch_args / browser.launch
  -> chrome.exe --launch-token --mjy-mode --fp-config --proxy-server --user-data-dir
  -> 可选继续接管 CDP 41729 / Control API 41730
```

## 鉴权

请求必须携带 MCP token：

```http
Authorization: Bearer <MCP明文令牌>
Content-Type: application/json
```

平台只保存 token 的 SHA-256 哈希。token 缺失、过期、停用或 scope 不足都会拒绝。

## Scopes

```text
browser:read        browser.list_tabs / control.status
browser:control     browser.launch_token / browser.launch_args / browser.launch / browser.open_tab
                    browser.navigate / browser.close_tab / browser.wait_for_load / control.http_request
                    env.create / env.update / env.delete / managed_tab.open / managed_tab.create
                    acceptance.browserscan / acceptance.gongjux
browser:evaluate    browser.evaluate
browser:screenshot  browser.screenshot
*                   全部工具
```

## 开发工具配置

### 先区分两个 token

```text
launch token
  用途：启动 MJYBrowser。
  填写位置：chrome.exe --launch-token=<一次性加密启动 token>
  作用阶段：浏览器进程启动前后的授权校验。
  约束：不得直接传浏览器授权码；授权码只用于生成短期一次性 token。

MCP token
  用途：让 Cursor、AI Agent 或开发工具生成启动参数、直接启动浏览器、控制已启动浏览器。
  填写位置：HTTP Header: Authorization: Bearer <MCP明文令牌>
  作用阶段：浏览器启动编排 + 启动后的自动化控制。
```

`Authorization: Bearer <MCP明文令牌>` 里的 `<MCP明文令牌>` 要替换成平台签发给你的 **MCP 明文令牌**，
通常以 `mcp_` 开头，例如：

```text
Authorization: Bearer mcp_这里是平台生成并只展示一次的明文控制令牌
```

注意：MCP token 不是会员中心里的浏览器授权码，也不是 `--launch-token`。
平台数据库只保存 MCP token 的 SHA-256 哈希，不保存明文；明文丢失后应停用旧 token 并重新生成。
可在会员中心 → MCP 接入自助生成或停用 MCP token。

### 一次性加密启动 token 怎么生成

`launch token` 必须由授权码临时生成，不能直接使用浏览器授权码。加密 token 的作用是避免授权码明文暴露在命令行、日志或自动化配置里，并通过 `jti` 保证单次使用。

生成链路：

```text
授权码 auth_code
  -> JSON 载荷 {"code":"<授权码>","ts":<unix秒>,"jti":"<32 hex>","purpose":"chrome-launch"}
  -> AES-256-GCM 加密
  -> 拼接 nonce || ciphertext || tag
  -> base64 编码
  -> chrome.exe --launch-token=<base64加密token>
```

格式以当前平台实现为准：

```text
base64( nonce(12B) || ciphertext || tag(16B) )
```

加密参数：

```text
算法      AES-256-GCM
密钥      32 字节 AES key，base64 写入服务端 config.yaml 的 license.token_encryption_key
nonce     12 字节随机数，每次生成 token 都重新随机
明文      {"code":"<授权码>","ts":<unix秒>,"jti":"<32 hex>","purpose":"chrome-launch"}
时效      服务端按 token_timestamp_window 校验时间新鲜度，默认 30 秒
一次性    服务端消费 jti，重复 jti 直接拒绝
兼容      不兼容明文授权码；解密失败直接拒绝
```

生成 token 加密密钥：

```bash
cd /mnt/disk2/chromium/jimu-platform
go run ./cmd/keygen --token-key
```

使用授权码生成一次性加密启动 token：

```bash
go run ./cmd/tokengen \
  --key "<license.token_encryption_key 的 base64 值>" \
  --auth-code "<浏览器授权码>"
```

直接打印 Windows 启动命令：

```bash
go run ./cmd/tokengen \
  --key "<license.token_encryption_key 的 base64 值>" \
  --auth-code "<浏览器授权码>" \
  --print-cmd
```

浏览器侧不会解密这个 token。Chrome 启动后只会把 `--launch-token` 原样随随机 nonce、pid、device 一起 POST 到授权服务；授权服务解密出授权码，完成订阅/授权码校验后，再返回 Ed25519 签名结果给 Chrome 验签。

### Cursor 通过 MCP 代生成 launch token

如果 Cursor 或其它 MCP 客户端只有浏览器授权码，不要让客户端读取或保存 `license.token_encryption_key`。正确链路是让 MCP 服务端使用内存中的配置密钥代生成短期 token：

```text
用户提供浏览器授权码
  -> MCP tools/call browser.launch_token { auth_code }
  -> MCP 返回 launch_token
  -> MCP tools/call browser.launch_args 或 browser.launch { launch_token, mode, ... }
  -> chrome.exe --launch-token=<launch_token>
```

示例：

```json
{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "browser.launch_token",
    "arguments": {
      "auth_code": "<浏览器授权码>"
    }
  }
}
```

返回内容只包含 `launch_token`、时效提示和下一步说明，不回传授权码，也不会暴露 AES key。随后把返回的 `launch_token` 传给 `browser.launch_args` 或 `browser.launch`。

前置条件：服务端 `config.yaml` 必须配置 `license.token_encryption_key`，并且解码后正好是 32 字节。未配置或长度错误时，`browser.launch_token` 会明确返回配置错误。

### 通过 MCP 启动浏览器

`browser.launch_args` 用于预览完整启动命令；`browser.launch` 使用同一参数模型直接启动 `chrome.exe`。服务端可在 `mcp.chrome_path` 配置默认路径，也可以在每次工具调用里传 `chrome_path` 覆盖。

`mode` 有三种：

```text
native
  原生浏览器模式。不加载指纹覆盖，不改变 Chromium 原生指纹；仍可通过 MCP/CDP/Control API 自动化。

global-fp
  全局指纹模式。一个浏览器实例就是一个环境，所有标签共享同一套 fp-config / proxy / storage / cookie / cache。

managed-tabs
  单标签单环境模式。浏览器作为托管容器运行；每个托管标签通过 envId 绑定独立 fp-config / proxy / storage / cookie / cache / viewport / touch。
```

```json
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "browser.launch",
    "arguments": {
      "chrome_path": "D:\\MJYBrowser\\chrome.exe",
      "mode": "global-fp",
      "launch_token": "<平台签发的短期加密启动token>",
      "auth_url": "https://api.jimuie.com/api/v1/license/sign",
      "user_data_dir": "D:\\profiles\\env-a\\profile",
      "cache_dir": "D:\\profiles\\env-a\\cache",
      "fp_config_path": "D:\\profiles\\env-a\\fp-config.json",
      "proxy_server": "socks5://127.0.0.1:1080",
      "control_port": 41730,
      "control_token": "<control_token>",
      "cdp_port": 41729,
      "start_url": "about:blank"
    }
  }
}
```

返回内容包含 `pid`、`argv`、`command`、`warnings`。其中 `proxy_username/proxy_password` 会作为 `proxy_auth` 元数据返回；Chromium 原生启动参数只生成 `--proxy-server`，不会伪造不存在的代理认证开关。

浏览器通过 v2.1 授权或本地 signed lease 后，MCP 才能继续使用 CDP / Control API 工具控制它。

### Cursor

如果你的 Cursor 版本支持 HTTP MCP server，可以在项目或用户级 `mcp.json` 中加入：

```json
{
  "mcpServers": {
    "jimu-browser": {
      "url": "https://api.jimuie.com/api/v1/mcp",
      "headers": {
        "Authorization": "Bearer <MCP明文令牌>"
      }
    }
  }
}
```

本地开发环境可把 `url` 改成：

```json
{
  "mcpServers": {
    "jimu-browser-local": {
      "url": "http://localhost:8080/api/v1/mcp",
      "headers": {
        "Authorization": "Bearer <MCP明文令牌>"
      }
    }
  }
}
```

配置后在 Cursor 的 MCP 工具列表中应能看到：

```text
browser.list_tabs
browser.open_tab
browser.navigate
browser.evaluate
browser.screenshot
browser.close_tab
browser.wait_for_load
browser.mode_status
browser.launch_args
browser.launch
env.list
env.create
env.update
env.delete
managed_tab.open
managed_tab.create
control.status
control.http_request
acceptance.browserscan
acceptance.gongjux
```

其中：

```text
browser.launch*  生成或直接执行 chrome.exe 启动，覆盖授权、模式、指纹、代理、缓存和端口。
browser.*         在 CDP 可达时直接控制已启动浏览器标签页。
env.*             管理 managed-tabs 环境，注入 fp-config / proxy / storage 隔离配置。
managed_tab.*     在指定环境中打开托管标签；managed_tab.create 可一步创建“单标签单环境”。
control.*         在 Control API 可达时代理 MJYBrowser 41730 管理面。
acceptance.*      通过 CDP 新开标签运行 BrowserScan / gongjux 快速验收。
```

### 三模式 / 指纹环境示例

读取当前浏览器模式：

```json
{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "browser.mode_status",
    "arguments": { "control_token": "<control_token>" }
  }
}
```

生成三模式启动参数：

```json
{
  "jsonrpc": "2.0",
  "id": 7,
  "method": "tools/call",
  "params": {
    "name": "browser.launch_args",
    "arguments": {
      "chrome_path": "D:\\MJYBrowser\\chrome.exe",
      "mode": "global-fp",
      "launch_token": "<launch_token>",
      "control_token": "<control_token>",
      "user_data_dir": "D:\\profiles\\env-a\\profile",
      "cache_dir": "D:\\profiles\\env-a\\cache",
      "fp_config_path": "D:\\profiles\\env-a\\fp-config.json",
      "proxy_server": "socks5://127.0.0.1:1080",
      "cdp_port": 41729,
      "start_url": "about:blank"
    }
  }
}
```

创建 managed-tabs 指纹环境：

```json
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "tools/call",
  "params": {
    "name": "env.create",
    "arguments": {
      "env_id": "env-a",
      "control_token": "<control_token>",
      "fp_config_json": { "navigator": { "platform": "Win32" } },
      "proxy_server": "socks5://127.0.0.1:1080"
    }
  }
}
```

在环境中打开托管标签：

```json
{
  "jsonrpc": "2.0",
  "id": 9,
  "method": "tools/call",
  "params": {
    "name": "managed_tab.open",
    "arguments": {
      "env_id": "env-a",
      "control_token": "<control_token>",
      "url": "https://example.com"
    }
  }
}
```

一步创建单标签单环境：

```json
{
  "jsonrpc": "2.0",
  "id": 10,
  "method": "tools/call",
  "params": {
    "name": "managed_tab.create",
    "arguments": {
      "env_id": "env-a",
      "control_token": "<control_token>",
      "fp_config_path": "D:\\profiles\\env-a\\fp-config.json",
      "proxy_server": "socks5://127.0.0.1:1080",
      "url": "https://example.com"
    }
  }
}
```

### Control API / 验收工具示例

读取 Control API 状态：

```json
{
  "jsonrpc": "2.0",
  "id": 6,
  "method": "tools/call",
  "params": {
    "name": "control.status",
    "arguments": { "control_token": "<control_token>" }
  }
}
```

运行 BrowserScan 快速验收：

```json
{
  "jsonrpc": "2.0",
  "id": 8,
  "method": "tools/call",
  "params": {
    "name": "acceptance.browserscan",
    "arguments": { "wait_seconds": 45 }
  }
}
```

### 其它支持 HTTP MCP 的客户端

填入以下三项即可：

```text
Transport / Type: HTTP
Endpoint: https://api.jimuie.com/api/v1/mcp
Header: Authorization: Bearer <MCP明文令牌>
```

### 仅支持 stdio 的客户端

Claude Desktop 等只支持 stdio MCP 的客户端不能直接填写 `/api/v1/mcp` HTTP 地址，
需要一个本地 stdio-to-HTTP bridge。当前仓库还没有内置官方 bridge，生产交付前应补一个
`jimu-mcp-bridge`，由它负责读取本地配置、转发 JSON-RPC 到 `/api/v1/mcp`，并自动附加
`Authorization: Bearer <MCP明文令牌>`。

示意配置如下，需等待 bridge 工具提供后使用：

```json
{
  "mcpServers": {
    "jimu-browser": {
      "command": "jimu-mcp-bridge",
      "args": [
        "--endpoint",
        "https://api.jimuie.com/api/v1/mcp",
        "--token",
        "<MCP明文令牌>"
      ]
    }
  }
}
```

## 初始化

```bash
curl -s http://localhost:8080/api/v1/mcp \
  -H 'Authorization: Bearer <MCP明文令牌>' \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
```

## 工具列表

```bash
curl -s http://localhost:8080/api/v1/mcp \
  -H 'Authorization: Bearer <MCP明文令牌>' \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
```

## 调用示例

打开标签：

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "browser.open_tab",
    "arguments": { "url": "https://example.com" }
  }
}
```

执行 JS：

```json
{
  "jsonrpc": "2.0",
  "id": 4,
  "method": "tools/call",
  "params": {
    "name": "browser.evaluate",
    "arguments": {
      "tab_id": "<tab_id>",
      "js": "document.title"
    }
  }
}
```

截图：

```json
{
  "jsonrpc": "2.0",
  "id": 5,
  "method": "tools/call",
  "params": {
    "name": "browser.screenshot",
    "arguments": {
      "tab_id": "<tab_id>",
      "format": "png"
    }
  }
}
```

## 运行前提

- `config.yaml` 的 `mcp.cdp_endpoint` 默认指向 `http://127.0.0.1:41729`。
- 开发测试浏览器必须带 `--remote-debugging-port=41729 --remote-allow-origins=*`。
- 生产方向优先接 MJYBrowser Control API；当前 CDP 适配是最小可用闭环。

## 审计

每次 `tools/call` 写入 `mcp_call_logs`：token、用户、工具、结果、耗时、来源地址。