内容
# 工作空间代理中继MCP
ChatGPT **工作空间代理** 的本地中继 + 仪表盘:代理报告计划、进度、工具调用和结果实时返回到您的机器。

> **为什么:** 工作空间代理触发API是fire-and-forget(`202` 无响应体)。此中继为代理提供MCP回调通道,为您提供实时仪表盘。
## 架构
```
您(浏览器) 您的机器 ChatGPT
┌──────────┐ ┌─────────────────────────┐ ┌─────────────────┐
│ 仪表盘 │◀── │ 工作空间代理中继MCP │ ◀─MCP── │ 工作空间代理 │
│ :8799 │ │ (此仓库) │ └─────────────────┘
└──────────┘ └───────────┬─────────────┘
│ 工具跟踪 POST
▲
┌────────┴────────────┐
│ notion-local-ops-mcp │ 可选:文件 / shell / git
└─────────────────────┘
```
- **此仓库** — 报告MCP(`record_plan`、`record_progress`、`record_result`、…)+ 仪表盘 + SSE。
- **[notion-local-ops-mcp](https://github.com/catoncat/notion-local-ops-mcp)** (可选)— 执行工具;`bind_relay_run` 镜像工具调用至此处。
## 快速开始
```bash
python3.11 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
cp .env.example .env # 至少设置WORKSPACE_AGENT_RELAY_AUTH_TOKEN
workspace-agent-relay-mcp
```
打开 `http://127.0.0.1:8799/`,输入中继 **访问密码**(`WORKSPACE_AGENT_RELAY_AUTH_TOKEN`)。
隧道(可选):`./scripts/dev-tunnel.sh`
## 本地开发(推荐)
日常UI工作,您 **不需要** `pnpm run build`。Python服务器在 `:8799` 提供静态 `frontend/dist` 包 - 该路径类似生产环境,需要每次更改后重新构建。
分别运行后端和Vite开发服务器:
```bash
# 终端 1 — API + MCP + SSE(launchd/dev-tunnel 也可)
.venv/bin/python -m workspace_agent_relay_mcp.server
# 终端 2 — 仪表盘,HMR
./scripts/dev-dashboard.sh
```
打开 **`http://127.0.0.1:5173`** 以访问仪表盘。ChatGPT MCP 保留在 **`http://127.0.0.1:8799/mcp`** (或您的隧道URL)。
`dev-dashboard.sh` 检查中继是否健康,然后启动Vite。它从仓库 `.env` 读取 `WORKSPACE_AGENT_RELAY_AUTH_TOKEN` 并自动为浏览器令牌提供种子 - 无需在 `:5173` 处再次粘贴。
| URL | 用途 |
| --- | --- |
| `http://127.0.0.1:5173` | 前端编辑时仪表盘(HMR) |
| `http://127.0.0.1:8799` | API、MCP、SSE;如果存在 `frontend/dist`,则为静态仪表盘 |
| 隧道 `/mcp` | ChatGPT 工作空间代理连接器 |
仅在CI或需要单端口 `:8799` 仪表盘(无Vite)时运行 `cd frontend && pnpm run build`。
## ChatGPT 工作空间代理设置(必需)
如果没有以下四个步骤,仪表盘将保持为空。
### 1. 在中继仪表盘中注册代理
**设置 → 添加代理** (或使用 `.env` 设置单个默认代理):
| 字段 | 来源 |
| --- | --- |
| 名称 | 您的标签(例如 工作、个人) |
| 触发URL | ChatGPT → 工作空间代理 → `https://api.chatgpt.com/v1/workspace_agents/agtch_…/trigger` |
| 访问令牌 | 同一设置页面(`at-…`)— 存储在中继上,浏览器中不会再次显示 |
对于多个ChatGPT账户,请为每个账户添加一行代理。在侧边栏创建线程时选择代理。
### 2. 连接MCP:中继(必需)
在工作空间代理 → **MCP连接器** 中:
| 字段 | 值 |
| --- | --- |
| URL | `http://127.0.0.1:8799/mcp` (或您的隧道 `/mcp`) |
| 认证 | Bearer = `WORKSPACE_AGENT_RELAY_AUTH_TOKEN` |
确认工具:`record_plan`、`record_progress`、`record_result`、`ask_user`、`get_run_context`、`server_info`。
### 3. 连接MCP:本地操作(推荐)
添加 [notion-local-ops-mcp](https://github.com/catoncat/notion-local-ops-mcp) 作为第二个连接器,以便 **工具调用** 流式传输到仪表盘。有关URL/身份验证,请参阅其README。
### 4. 粘贴代理说明(容易遗漏)
打开 **[`docs/agent-instructions.md`](docs/agent-instructions.md)**:
1. 将占位符 `<YOUR_RELAY_MCP>` 和 `<YOUR_LOCAL_OPS_MCP>` 替换为您的连接器名称(默认值:`workspace-agent-relay-mcp` 和 `notion-local-ops-mcp`)。
2. 复制围栏 **指令正文** 块。
3. ChatGPT → 编辑工作空间代理 → **说明** → 粘贴(追加或替换任何旧的中继部分)。
预期工作流程:
```
record_plan → bind_relay_run → 批量 record_progress → record_result
```
如果没有此粘贴,代理可能仅在ChatGPT内工作,而操作员在中继上看不到任何内容。
### 5. 烟雾测试
从仪表盘发送一个短任务(例如,在 `/tmp` 下创建并读取一个文件)。您应该看到计划 → 工具跟踪(如果连接了本地操作)→ 结果。
## MCP工具(中继)
| 工具 | 用途 |
| --- | --- |
| `record_plan` | 转折开始时的步骤计划(稳定的步骤ID) |
| `record_progress` | 批量步骤更新 + 可选注释 |
| `record_result` | 最终Markdown + 状态(`done` / `failed` / `blocked`) |
| `ask_user` | 暂停人类决策 |
| `get_run_context` | 如果上下文漂移,则恢复运行摘要 |
## 仪表盘
每次运行:您的消息 → 计划检查清单 → 工具跟踪(来自本地操作)→ 进度注释 → `ask_user`(如果有)→ 最终结果。通过SSE更新(无需刷新)。
## 与 notion-local-ops-mcp 配对
1. 代理在 **此中继** 上调用 `record_plan`。
2. 代理使用 `request_id` + `callback_token` 调用 **notion-local-ops-mcp** 上的 `bind_relay_run`(如果本地配置,则无需 `relay_url`)。
3. 跟踪工具将 `/internal/tool-trace` POST到此中继 → 仪表盘。
详情: [notion-local-ops-mcp → 中继桥接(镜像工具调用到仪表盘)](https://github.com/catoncat/notion-local-ops-mcp#relay-bridge-mirror-tool-calls-to-a-dashboard).
## 项目布局
```
src/workspace_agent_relay_mcp/ 服务器、MCP工具、API、SQLite存储、触发客户端
frontend/ React仪表盘
docs/agent-instructions.md 粘贴块到ChatGPT说明
scripts/dev-tunnel.sh cloudflared监管
scripts/dev-dashboard.sh Vite HMR仪表盘(代理/api → 中继)
tests/
```
## 安全
- 永远不要提交 `.env`、隧道或 `*.sqlite*`。
- `WORKSPACE_AGENT_RELAY_AUTH_TOKEN` — 仪表盘 + `/mcp` bearer。
- 工作空间代理访问令牌 — 存储在中继DB或 `.env` 中;如果泄漏,请轮换。
- 每次运行的 `callback_token` 仅存储哈希;API/日志中已编辑。
## 状态
本地优先原型,用于学习工作空间代理回调间隙 — 不是产品。