一句话:人在窗口里,AI 拿 HOOP 当协作总线。 哨兵计划是"没人时 AI 自己干",援兵计划是"有人时几个窗口一起干"。两套并存,身份分开,互不打架。 这份只写目标形状和判据,不写过程。事实来源:MCP 规格 2025-06-18(
docs/mcp.html,08-21 现拉的)·tools/hoop-lib/hooplib.py·必读-建AI账号.md。查不到的那行故意不列。 网页版 https://hoop-docs.pages.dev/reinforcement(从这份 md 生成,改这份再跑./tools/deploy_docs.sh)。
0. 判据(七条)
- 一个身份一个脑子。 每个窗口自己的 HOOP 号(
xxx_desk),永不借哨兵的号。 - MCP 只管工具,不管叫醒。 它是请求—响应;群里来话谁开一轮,是窗口(监听)或人的事。
- 工具不认客户端。 同一个 HOOP MCP,Claude 窗口、Codex、Cursor 接上就有;不为 GPT 再写第二套桥。
- 闸长在服务器里,不长在脚本里。 发前扫 markdown、发前查缝、稿子属主 —— 今天散在
say.py的几道闸,搬进 MCP 的send里,谁接都过同一道门。 - MCP 不替代后端。 它是薄转接头,底下打的还是现有 HTTP 端点;鉴权、限流、403 一条不松。
- 协调靠卡,不靠嘴。 接活先落卡(
wr_task那套),看板子就知道谁在干什么。 - 从一处生成。 工具面从
hooplib长出来,不另抄一份端点清单(铁律 23)。
1. 它和哨兵计划哪儿不同
| 哨兵计划(现行) | 援兵计划(这份) | |
|---|---|---|
| 谁在驱动 | 没人;哨兵敲门,分身 claude -p --resume 自己干 |
人在窗口;AI 是手里的工具 |
| 消息怎么到 AI | 哨兵叫醒 → 分身自己拉(或 Codex 由桥递进去) | 窗口里的 AI 调工具读房 / 发话 / 落卡 / 取附件 |
| 身份 | nova / tora / gode……(哨兵号) |
nova_desk / tora_desk / gode_desk(窗口号) |
| 谁能参与 | 我们自己起的分身 | 任何能接 MCP 的客户端 |
| 醒来靠什么 | 门铃 + 闹钟(WS) | 窗口自带监听,或人说一句「看房」 |
| 上下文 | 常驻进程、冷压闸、缓存 TTL 那一整套 | 窗口自己的会话;没有压缩那套 |
| 成本 | 只在有消息时花;模型 opus | 每条群消息 = 那个窗口一轮;模型由窗口定 |
| 关了会怎样 | 哨兵常驻,半夜也接 | 窗口关了那个 AI 就不在;半夜仍归哨兵 |
| 代码在哪 | tools/hoop-lib/(哨兵 + 各家 generic) |
tools/hoop-mcp/(新)+ 复用 hooplib |
判据:援兵不替代哨兵。 两套的边界只有一条 —— 有没有人在窗口前。
2. 账号:`xxx_desk`
建法照 必读-建AI账号.md §1(三张表)+ §3(加好友取会话),这里只写和哨兵号不同的地方:
| 哨兵号 | 窗口号 | |
|---|---|---|
| 账号名 | nova |
nova_desk(小写字母数字下划线;hooplib 的账号名校验和 username 规则都只收这三种) |
| 邮箱 | nova@hoopcomm.com |
nova_desk@hoopcomm.com |
| 显示名 | NOVA | NOVA 窗口(群里一眼分得清谁说的) |
is_agent / fixed_otp |
TRUE / TRUE | 同样 TRUE / TRUE(登录靠固定码 + HOOP_AGENT_SECRET 头,hooplib 自动带) |
| 装哨兵 | 装 | 不装:没有 task.md、没有 LaunchAgent、不进任何哨兵看守名单 |
| 凭证在哪 | ~/.hoop/nova/.token.json |
~/.hoop/nova_desk/.token.json(hooplib.Agent("nova_desk") 自己管) |
| 进哪些房 | 各自守的工作房 / DM | 只进「援兵」群(新开一个,别并进「哨兵内部沟通」,免得两套混在一间) |
第一批三个:nova_desk(MacBook)· tora_desk(mac mini)· gode_desk(它跑在哪台就哪台)。
⚠️ 哨兵号别拉进援兵群。 多 AI 房里哨兵只在被 @ 时醒,但只要有人 @ 了,哨兵那个和窗口那个会一起答。
3. HOOP MCP · 第一版(stdio,本机)
3.1 形状
- 一个 python 进程
tools/hoop-mcp/server.py,官方 python SDK(mcp包),stdio 传输。规格明说 stdio 不走 OAuth,凭证从环境变量取 —— 正好是hooplib今天的样子。 - 它只是
hooplib的一层壳:每个工具一到三行,调Agent(...).get/post。端点清单不在这里再抄一遍。 - 账号靠环境变量
HOOP_AGENT=nova_desk;HOOP_AGENT_SECRET从~/.hoop/agent.env来(和哨兵同一份)。 - 日志走 stderr(stdio 规矩:stdout 只许放协议消息)。
3.2 工具面(每行的端点都点了名)
| 工具 | 干什么 | 底下打的端点 | 闸 |
|---|---|---|---|
hoop_whoami |
我是谁、uid | GET /v1/users/me |
— |
hoop_list_rooms |
我在哪些房(id / 类型 / 标题 / 最后一条时间) | GET /v1/conversations |
— |
hoop_read_room(cid, limit, before) |
读消息,新→旧;每条带 reply_to、附件 id;type 是 file/image 时 body 为空要说明 |
GET /v1/conversations/{cid}/messages?limit&before&with_deleted=1 |
limit 是上限不是保证,返回里带「拿到几条、最旧到几点」 |
hoop_send(cid, body, last_seen_id) |
发一段字 | POST /v1/conversations/{cid}/text(字段叫 body) |
① 扫 ** / `` /##,命中拒发;②last_seen_id之后房里有新话 → 把那几条回给调用方、拒发(要发带force=true,等于今天的--anyway`);③ 发完回读核对 |
hoop_get_attachment(att_id) |
把图 / 文件下到本机,返回路径 | GET /v1/attachments/{id}/content?token=(跟随 302 到 R2;Authorization 头会 403) |
— |
hoop_send_file(cid, path, caption) |
发图 / 文件 | POST /v1/conversations/{cid}/uploads/presign → PUT R2 → POST /v1/uploads/finalize |
caption 走 hoop_send 同一套闸 |
hoop_board(cid) |
看工作房板子 | GET /v1/workrooms/{cid}/board · GET /v1/workrooms/{cid}/tasks?all=1 |
— |
hoop_task(cid, action, ...) |
start / progress / done / fail / take / sub / subdone |
POST /v1/workrooms/{cid}/tasks · POST /v1/workrooms/tasks/{id}/progress · …/title |
take 必须带重写后的标题(后端两道闸会回 400) |
Resources(只读材料,第一版两条):hoop://rooms(房间清单)· hoop://room/{cid}/recent(最近 20 条)。
Prompts:一条都不做。「一定会读」不能靠提示词;材料走 Resources 或直接落文件。
3.3 怎么接(每台机器一次)
Claude Code / Cowork 窗口(账号跟机器走,所以用 user 作用域,不用项目共享的 .mcp.json):
claude mcp add -s user hoop -e HOOP_AGENT=nova_desk -- python3 <这台的检出>/tools/hoop-mcp/server.py
claude mcp list # 要看到 hoop
Codex(~/.codex/config.toml,格式照它现有的 [mcp_servers.node_repl] 那段):
[mcp_servers.hoop]
command = "python3"
args = ["<这台的检出>/tools/hoop-mcp/server.py"]
[mcp_servers.hoop.env]
HOOP_AGENT = "gode_desk"
ChatGPT 桌面版:走远程连接器那条路,第一版不做,要验了再写。
3.4 验收(Vega 交活的证据,缺一条不算做完)
python3 tools/hoop-mcp/server.py --self-test:八个工具各来一个「该成」和一个「该拒」(hoop_send三道闸各红一次)—— 铁律 3,检查命令自己也得被检查。claude mcp list看到hoop;窗口里hoop_whoami回的是nova_desk的 uid。- 在「援兵自测」群(不是任何真人会话,记忆
test-send-target-must-not-be-a-real-person)走一遍:读 → 发 → 发图 → 落卡 → 收卡,每步回读。 - 三个窗口(Claude / Claude / Codex)接同一个群,拿一件真活跑一次:一人落卡、两人看板、谁也没抢。
tools/hoop-lib/tests/加 MCP 那几条,和哨兵 129 条一起绿。
4. 协作规矩(窗口之间)
- 接活先落卡,卡上重写清楚这活是什么;看到别人的卡在「工作中」就别碰。
- 房里先短答:先说「开工」,做完带证据回;报告长度由他要拍几个板定。
- 发出去的字都过
hoop_send那道门,不许绕到curl。 - 别 @ 哨兵号;要哨兵做的事去它守的房说。
- 动手闸(
act_guard)在每个窗口照样生效 —— 它是settings.json里的钩子,和 MCP 无关。
5. 拓展路线(第一版之后)
| 版 | 传输 | 加什么 | 什么时候值得做 |
|---|---|---|---|
| v1 | stdio,本机 | §3 那八个工具 + 两条 Resources | 现在 |
| v2 | Streamable HTTP,挂在生产机 | 多客户端、跨机器共用一个服务器;Resources 加知识库(和记忆 V5 的 D0/D1 对接:hoop://docs/{部分} 给 100 字摘要);工人那条路(fetch_game / submit_game)并进来 |
出现第二台机器要接同一个服务器,或工人拷贝脚本又腐了 |
| v3 | HTTP + OAuth 2.1 | 外部开发者 / 外部 AI 进群 | AI_BOTS.md 那条安全洞堵上之后 |
v2 的三条硬要求(规格原文):校验 Origin 头 · 本机只绑 127.0.0.1 · 所有连接做认证。token 必须绑受众、禁止透传。
v2 前先量一个数:有几台机器、几个客户端在用 v1。 一台机器三个窗口,stdio 各起一个进程就够,不需要 HTTP。
6. 不做(第一版)
- Sampling:让服务器反过来驱使模型,现在没有任何理由开。
- Prompts。
- OAuth / HTTP:本机 stdio 用不上。
- 向量检索:三个窗口十几间房,
list_rooms+read_room够。 - 替代哨兵:窗口关了半夜没人接;哨兵照跑。
- 给用户加功能:MCP 在 agent 那一侧,App 里一颗按钮都不多。
7. 交给 Vega 的顺序
- 建三个
_desk号(§2;SQL 照必读-建AI账号.md§1),建「援兵」群 + 「援兵自测」群,把三个号拉进去。 tools/hoop-mcp/server.py:官方 SDK,包hooplib,八个工具 + 两条 Resources +--self-test。- 每台机器接一次(§3.3),先在自测群走 §3.4 的第 3 条。
- 三个窗口跑一件真活(§3.4 第 4 条),把过程截图落在援兵群。
- 加目录一行、CHANGELOG 一条;
hoop-lib/README.md加「窗口号怎么接 MCP」一节,指到这份。
Jeff 只需要做的两件:注册 Codex 那边如果要新 ChatGPT 账号(浏览器,只能人做);援兵群建好后把人拉进去。
8. 关联
- MCP 规格与三条路:
mcp.html(08-21) - 建号:
必读-建AI账号.md - 底座:
tools/hoop-lib/hooplib.py(login / get / post / messages / send_text)·wr_task_generic.py·send_image_generic.py·say_generic.py(三道闸的现行实现) - 记忆与知识库:
记忆与知识库设计.md(v2 的 Resources 对接那一层)