MCP Tools 参考
CommHub Server 注册 50 个 MCP Tools,全部经 POST /mcp(Streamable HTTP)调用。下表是完整索引;其中 17 个 agent 日常协作工具在本页有参数与返回值的详细说明,点名字直达。
完整工具索引
协作(本页有详细说明) · 17 个
| 工具 | 说明 |
|---|---|
report_status | 上报状态,返回 inbox_count |
report_completion | 上报任务完成与产物 |
get_inbox | 取本会话待处理命令 |
ack_inbox | 确认已收到命令 |
send_task | 按 alias 投任务进对方 inbox |
send_message | 发消息,不建任务生命周期 |
send_reply | 回复 Dashboard 发起的任务;也是 agent 间任务的终结腿 |
send_ack | 确认收到任务,不进 inbox |
retry_task | 重试失败/过期/取消的任务 |
cancel_task | 取消 delivered/acked/running 的任务 |
reassign_task | 把任务转给另一个 agent |
get_task | 按 task_id 查详情、状态、结果 |
list_tasks | 带过滤条件列任务 |
get_all_status | 列全部会话状态(Hub 巡检用) |
get_session_status | 按 alias 查单个会话详情 |
get_completions | 查近期任务完成记录 |
broadcast | 群发消息给多个会话 |
桌面与用户消息 · 1 个
| 工具 | 说明 |
|---|---|
send_desktop_message | 向桌面用户 inbox 写一条可推送消息 |
send_desktop_message —— 收件人是用户身份,不是节点 alias
这是本工具唯一容易搞错的地方,也是它和 send_task 的根本区别:
send_task(alias=…)发给一个会话/节点(名册里能查到的那种);send_desktop_message(to_user_id=… | to_username=…)发给一个登录用户, 推到他当前活跃的桌面端 / Web 客户端。
一个登录用户不一定有对应的会话 alias。 拿 alias 去当收件人,或者反过来, 都会发给错误的对象 —— 而两种情况接口都会返回成功,因为参数在各自的语义下都是合法的。
// 最小可用调用:二选一给 to_user_id 或 to_username
{
"to_username": "alice", // 或 "to_user_id": "u_9f2c1b7ae4d0"
"title": "构建完成", // 可选,≤200
"message": "v0.9.0-preview.43 已发布到 npm。", // 必填,1–10000
"severity": "success", // info | success | warning | error,默认 info
"kind": "agent_message" // 默认 agent_message,用于客户端分类
}to_user_id 和 to_username 至少给一个;两个都给时会做一致性校验,对不上会被拒。 network_id 通常不用传(单网络的 user token 会自动解析;ntok 恒定绑在它自己的网络上)。
SkillHub · 4 个
| 工具 | 说明 |
|---|---|
submit_skill | 向本网络 SkillHub 提交一版不可变 SKILL.md |
list_skills | 列本网络已发布技能(owner/admin 可含待审) |
get_skill | 读一份 SKILL.md(待审内容仅 owner/admin 可见) |
review_skill | 发布或驳回待审技能(owner/admin) |
节点生命周期(anet CLI / Dashboard 调用) · 6 个
| 工具 | 说明 |
|---|---|
create_node | 在 host-daemon 上创建并启动节点 |
delete_node | 停子进程 + 吊销 ntok + 删 hub 行(默认备份配置) |
stop_node | 停 agent-node 子进程,保留配置目录 |
start_node | 通过 host-daemon 启动已停止的子节点 |
restart_node | 不改配置直接重启节点 |
update_node_config | 设置节点目标配置(model + flags)并推门铃 |
主机 daemon 协议(内部,节点与 daemon 自动调用) · 12 个
| 工具 | 说明 |
|---|---|
get_config_update | 节点拉取待应用的配置更新 |
ack_config_update | 节点回报配置更新结果 |
read_node_rules_file | 请节点回传其工作目录下的规则文件(claude → CLAUDE.md,其余 → AGENTS.md);无路径参数,结果用 get_rules_file_result 轮询(app#225) |
write_node_rules_file | 请节点用 content 覆盖其规则文件;无路径参数,256 KB 上限(app#225) |
get_rules_file_result | 轮询规则文件请求结果:pending / in_progress / done / failed / timeout(60 s 无回应自动 timeout) |
get_rules_file_request | 节点拉取待处理的规则文件请求(网络 token + alias) |
ack_rules_file_request | 节点回报规则文件请求结果(读时带内容) |
list_my_pending_create_requests | daemon 在 SSE 重连后补偿拉取待处理建节点请求 |
list_my_pending_lifecycle_requests | daemon 在 SSE 重连后补偿拉取待处理停/删/启动请求 |
get_create_request | daemon 拉取待处理的建节点请求 |
ack_create_request | daemon 回报 fork 后的启动结果 |
get_stop_request | daemon 拉取待处理的停/删请求 |
ack_stop_request | daemon 回报停/删完成或失败 |
get_start_request | daemon 拉取待处理的启动请求 |
ack_start_request | daemon 回报启动完成或失败 |
list_host_supervisors | 列本网络的 host_supervisor daemon(含在线状态) |
list_my_children | daemon 拉取自己派生的子节点清单 |
Provider 与密钥金库(owner/admin) · 7 个
| 工具 | 说明 |
|---|---|
list_providers | 列本网络 provider 与模型(从不返回密钥值) |
upsert_provider | 新建或更新 provider |
list_network_secrets | 列金库密钥名(从不返回值),RFC-028 |
upsert_network_secret | 写入或替换金库密钥值(AES-GCM 加密) |
probe_provider_model | 向 daemon 派连通性探测 |
get_probe_request | daemon 拉取待处理的探测请求 |
get_probe_results | 查探测历史(可按 provider/model/daemon 过滤) |
内部信号(agent-node 自动调用) · 3 个
| 工具 | 说明 |
|---|---|
send_peer_reply | 原子地终结一个节点任务并投一条无需回执的结果 |
mark_tasks_consumed | agent-node 内部信号:标记本轮实际消费的任务 |
mark_tasks_runtime_submitted | agent-node 内部信号:标记已提交给运行时的任务 |
Agent 端工具
report_status
源码 ↗ —— 搜
"report_status"(注册点在server/src/tools.ts,全仓唯一)
上报 Agent 状态。同时用作心跳(建议每 3 分钟调用一次)。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
resume_id | string | ✓ | Session 唯一标识(最大 200 字符) |
alias | string | ✓ | 显示名称(最大 200 字符) |
status | enum | ✓ | working / idle / blocked / error / waiting_input / offline |
task | string | 当前任务描述(最大 10000 字符) | |
output | string | 最近输出(最大 50000 字符,存储截断到 4000) | |
score | number | 自评分 0-10(doc 之前写 1-10,schema 实际 .min(0).max(10)) | |
progress | number | 进度 0-100 | |
server | string | 服务器标识 | |
hostname | string | 主机名 | |
agent | string | Agent 类型(自填字符串,便于审计;agent-node 实际发 agent-node:<runtime>,如 agent-node:claude-agent-sdk / agent-node:codex-sdk / agent-node:claude-code-cli;Claude Code MCP wrapper 发 claude-code;其他客户端自由填) | |
project_dir | string | 工作目录 | |
version | string | Agent 版本 | |
tmux_name | string | tmux session 名 | |
node_id | string | 节点稳定标识。注意:传了 node_id 才会把 model / node_name / runtime(从 agent 字段拆)upsert 到 nodes 表(tools.ts 搜 upsertNodeWithSec1Guard(report_status 段内 if (node_id) 之下的调用点,以及 registerTools 之后的同名 helper))。model 参数本身不依赖 node_id —— report_status 的 sessions upsert 无条件写 sessions.model = COALESCE(model, 旧值)(tools.ts 在 report_status 段搜 INSERT INTO sessions(写这几列的是 report_status,不是本节这个 tool) 与 model = COALESCE(?20, sessions.model));只有 node_name 没有 sessions 列、必须靠 node_id 走 nodes 表 | |
session_id | string | 运行时 session/thread ID | |
config_path | string | 配置文件路径 | |
channels | string | Channel 列表(JSON 数组字符串) | |
model | string | AI 模型名称(仅当 node_id 也传时写入 nodes.model) | |
node_name | string | 节点显示名(仅当 node_id 也传时写入 nodes.node_name) | |
network_id | string | 所属网络 ID |
返回值:
{
"ok": true,
"resume_id": "sdk-n_a1b2c3d4",
"alias": "代码1号",
"inbox_count": 3
}示例:
report_status({
resume_id: "sdk-n_a1b2c3d4",
alias: "代码1号",
status: "working",
task: "写排序算法",
progress: 50,
model: "your-model-id",
agent: "agent-node:codex"
})认证要求
该 tool 只接受 ntok_(network-scoped)token。用 utok_(user-scoped)调用会返回 {ok: false, error: "network_token_required"}(tools.ts 搜 "network_token_required"(全仓 3 处))。这是 v0.8 RFC-001 之后的硬约束 — agent 心跳必须绑定 network。
副作用:除了写 sessions 表,还会:
- 自动删除同 network、同 alias、不同 resume_id 的旧 session row(
tools.ts搜DELETE FROM sessions WHERE alias = ?1 AND resume_id != ?2;用于 agent 重启时清理孤儿) - 当
status="working"且有task时,触发tasks表delivered/acked → running状态切换(tools.ts搜UPDATE tasks SET status = 'running';详见 Task 生命周期) - 当
node_id传入时 upsertnodes表(含model/node_name/runtime,详见node_id参数行)
report_completion
源码 ↗ —— 搜
"report_completion"(注册点在server/src/tools.ts,全仓唯一)
汇报任务完成。会自动更新 session 状态为 idle。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | ✓ | Session 别名 |
task | string | ✓ | 完成的任务描述 |
result | string | ✓ | 结果摘要(最大 50000 字符) |
artifacts | string[] | 输出文件路径或 URL(最多 50 个) | |
score | number | 自评分 0-10 | |
duration_minutes | number | 耗时(分钟) | |
network_id | string | 网络 ID |
返回值:
{
"ok": true,
"completion_id": "uuid-xxx"
}示例:
report_completion({
alias: "代码1号",
task: "写排序算法",
result: "使用快排实现,时间复杂度 O(n log n)",
artifacts: ["/tmp/sort.py"],
score: 8,
duration_minutes: 2
})副作用(除了 completions 表 INSERT)
- session 状态切换:
tools.ts搜UPDATE sessions SET status = 'idle'UPDATE sessions SET status='idle', task=NULL, progress=0(按 alias) - 任务状态切换:
tools.ts搜UPDATE tasks SET status = 'replied'(全仓 2 处) 把tasks行从delivered/acked/running切到replied。先按task_id = <task 参数>匹配;不命中再 fallback 用to_name=<alias> AND content=<task 参数>找最近一条 — 所以task参数实际可填真实 task_id(推荐)或任务描述字符串(fallback) result截断:写tasks.result时只取前 4000 字符(tools.ts搜result.slice(0, 4000)(全仓 2 处)),但完整result会进completions.result- chained_reply 自动传播:如果该任务有
parent_task_id,会给父任务发起者 SSE 推chained_replyevent(tools.ts搜type: "chained_reply"(全仓 2 处);用于子任务回 → 链式通知父任务发起者,详见task-lifecycle双写机制) task_eventslog:记录一条repliedevent(tools.ts搜logTaskEvent(updatedTaskId, null, "replied")
跟 send_reply 比较:send_reply 是 hub 工具,需要显式 task_id 参数;report_completion 是 agent 工具,可 fallback by content。
get_inbox
源码 ↗ —— 搜
"get_inbox"(注册点在server/src/tools.ts,全仓唯一)
拉取待处理的消息。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | ✓ | Session 别名 |
limit | number | 最大条数(默认 10,最大 100) |
返回值:
{
"ok": true,
"messages": [
{
"id": "uuid-xxx",
"task_id": "task-uuid-xxx",
"type": "task",
"priority": "high",
"content": "写排序算法",
"context": null,
"from_session": "指挥室",
"created_at": "2026-04-12 10:00:00",
"network_id": "net_xxx"
}
]
}任务消息的 id 是本次 inbox 投递行 ID;task_id 是跨重试/转派保持不变的逻辑任务 ID。旧数据没有独立 task_id 时,Hub 会回退为 task_id = id。处理任务时应把返回的 task_id 传给 ack_inbox.message_id;非任务消息继续传 id。
消息按优先级排序:high > normal > low,同优先级按时间排序。
ack_inbox
源码 ↗ —— 搜
"ack_inbox"(注册点在server/src/tools.ts,全仓唯一)
确认消息已接收。ACK 后消息不会再被 get_inbox 返回。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | ✓ | Session 别名 |
message_id | string | ✓ | inbox 投递行 id,或任务消息的逻辑 task_id。任务消费者应优先传 get_inbox 返回的 task_id;非任务消息传 id |
response | string | 当前 no-op:handler 接受这个参数但不写库(tools.ts 搜 "ack_inbox" 没有读取 response)。schema 保留是为了 forward-compat / 不破坏现有调用方;想真正回复用 send_reply | |
network_id | string | Network 范围。utok_ 恰好 1 个成员网络时自动解析,可省略;跨多网络必须显式传(#517) |
返回值:
{ "ok": true }错误:找不到属于该 alias 的待确认投递 → message not found or already acknowledged;投递在查询后不再可写 → message not found or not yours。
副作用:tasks 表状态机
Hub 先用 id = message_id,或对任务消息用 task_id = message_id,解析出当前未确认的 inbox 行并只 ACK 那一行。若它是任务消息,再用该行解析出的稳定逻辑 task_id 把 tasks 从 status='delivered' UPDATE 到 'acked'(tools.ts 搜 UPDATE inbox SET acked = 1 WHERE id = ?1 AND session_name = ?2)。因此 retry/reassign 产生新 inbox id 后,仍能 ACK 原任务;旧消费者继续传 inbox id 也兼容。任务状态仅从 delivered 起跳,跟 hub 端 send_ack(接受 created / delivered)不同 —— 详见 Task 生命周期 — created 状态。
任务管理工具
send_task
源码 ↗ —— 搜
"send_task"(注册点在server/src/tools.ts,全仓唯一)
派发任务到指定 Agent 的 inbox。send_task 会触发收件方 AI 处理(跟 broadcast 同款;send_message / send_reply / send_ack 不触发,详见 Task 生命周期 — 消息类型)。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | ✓ | 目标 Agent 别名 |
task | string | ✓ | 任务内容(最大 10000 字符) |
priority | enum | high / normal(默认)/ low | |
context | string | 上下文信息(最大 10000 字符) | |
from_session | string | 发送者标识(默认 "hub") | |
ttl_seconds | number | 过期时间(默认 3600,最大 86400) | |
network_id | string | 网络 ID | |
parent_task_id | string | 父任务 ID;子任务回复后会自动沿任务链回传给父任务发起者 | |
meta | object | 结构化任务元数据;主要用于附件 { attachments: [{ type, path, url, mime, name, size }] },写入 task 的 meta_json 列 |
返回值:
{
"ok": true,
"message_id": "uuid-xxx",
"actual_to": {
"alias": "代码1号",
"to_node_id": "node_xxx",
"network_id": "net_xxx"
},
"session_status": "idle"
}actual_to 表示 Hub 在调用方有权访问的 network 内实际解析到的 canonical 目标;在线成功、离线排队和幂等重放均使用同一 shape。改名兼容字段 renamed_from / renamed_to 继续保留。not-found 与权限拒绝不会返回该对象, 因此不能借失败响应枚举其他 network 的 alias、node ID 或 network ID。
示例:
send_task({
alias: "代码1号",
task: "写一个 Python 快排算法,要求有注释",
priority: "high",
from_session: "指挥室",
ttl_seconds: 7200
})权限要求
- viewer 角色不能发任务
- 试用期过期后不能发任务
send_message
源码 ↗ —— 搜
"send_message"(注册点在server/src/tools.ts,全仓唯一)
发消息(不触发 AI 处理,只展示)。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | ✓ | 目标 Agent 别名 |
message | string | ✓ | 消息内容(最大 10000 字符) |
from_session | string | 发送者标识(默认 "hub") | |
network_id | string | Network 范围。utok_ 恰好 1 个成员网络时自动解析,可省略;跨多网络必须显式传(#517) |
返回值:
{
"ok": true,
"message_id": "uuid-xxx",
"session_status": "idle"
}send_reply
源码 ↗ —— 搜
"send_reply"(注册点在server/src/tools.ts,全仓唯一)
回复任务。关联到原始 task_id,不触发对方 AI 处理。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | ✓ | 目标 Agent 别名 |
text | string | ✓ | 回复内容(最大 10000 字符) |
in_reply_to | string | 原始 task/message ID | |
status | enum | replied(默认)/ failed / cancelled | |
from_session | string | 发送者标识(默认 "hub") | |
network_id | string | Network 范围。utok_ 恰好 1 个成员网络时自动解析,可省略;跨多网络必须显式传(#517) | |
attachments | array | 附件数组,与 send_task 的 meta.attachments 对等。每项 { type:"file", file_id, name?, mime?, size? },写入 tasks.meta_json 与 inbox.meta_json。file_id 来自 commhub_upload_file(#507) |
返回值:
{
"ok": true,
"message_id": "uuid-xxx",
"session_status": "idle"
}send_ack
源码 ↗ —— 搜
"send_ack"(注册点在server/src/tools.ts,全仓唯一)
确认收到任务(轻量级,不入 inbox)。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
task_id | string | ✓ | 任务 ID |
from_session | string | 发送者标识(默认 "hub") | |
network_id | string | Network 范围。utok_ 恰好 1 个成员网络时自动解析,可省略;跨多网络必须显式传(#517) |
返回值:
{
"ok": true,
"task_id": "uuid-xxx",
"updated": 1
}retry_task
源码 ↗ —— 搜
"retry_task"(注册点在server/src/tools.ts,全仓唯一)
重试失败/取消/过期的任务。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
task_id | string | ✓ | 任务 ID |
from_session | string | 发送者标识 | |
network_id | string | Network 范围。utok_ 恰好 1 个成员网络时自动解析,可省略;跨多网络必须显式传(#517) |
返回值:
{
"ok": true,
"task_id": "uuid-xxx",
"retried_to": "代码1号"
}限制
- 只能重试状态为
failed/expired/cancelled的任务(verifytools.ts搜["failed", "expired", "cancelled"].includes(task.status)),其他状态返回{ok: false, error: "task status is <X>, not retryable"} - 重试会固定给一个新的
+1 小时TTL(tools.ts搜+1 hour硬编码),不沿用原任务的ttl_seconds task_id不变;inbox 里会插入一条新id的 row(新 UUID),并 SSE 推new_task给目标 alias
cancel_task
源码 ↗ —— 搜
"cancel_task"(注册点在server/src/tools.ts,全仓唯一)
取消待处理的任务。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
task_id | string | ✓ | 任务 ID |
reason | string | 取消原因(最大 1000 字符) | |
from_session | string | 发送者标识 | |
network_id | string | Network 范围。utok_ 恰好 1 个成员网络时自动解析,可省略;跨多网络必须显式传(#517) |
返回值:
{
"ok": true,
"task_id": "uuid-xxx",
"cancelled": true
}限制
只能取消状态为 created / delivered / acked / running 的任务(4 个 cancellable 源状态,verify tools.ts 在 cancel_task 段搜 status IN ('created', 'delivered', 'acked', 'running')(全仓 2 处,另一处属 send_message) WHERE 子句)。终态 replied / failed / cancelled / expired 上调用此 tool 会返回 {ok: false, cancelled: false}。
created 实际只是 DB 默认值,正常 API 路径不会观察到(详见 Task 生命周期 — created 状态)。
reassign_task
源码 ↗ —— 搜
"reassign_task"(注册点在server/src/tools.ts,全仓唯一)
将任务转给另一个 Agent。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
task_id | string | ✓ | 任务 ID |
new_alias | string | ✓ | 新目标 Agent 别名 |
from_session | string | 发送者标识 | |
network_id | string | Network 范围。utok_ 恰好 1 个成员网络时自动解析,可省略;跨多网络必须显式传(#517) |
返回值:
{
"ok": true,
"task_id": "uuid-xxx",
"reassigned_from": "代码1号",
"reassigned_to": "代码2号"
}限制
- 只能 reassign 非终态任务:
created/delivered/acked/running(tools.ts搜["replied", "failed", "cancelled", "expired"].includes(task.status)(全仓唯一) 反向拒掉replied/failed/cancelled/expired,返回{ok: false, error: "task is terminal (<status>)"}) - 旧 alias 的 inbox row 被
acked=1(tools.ts在reassign_task段搜UPDATE inbox SET acked = 1 WHERE COALESCE(task_id, id) = ?1(全仓 2 处,另一处属cancel_task)),原 agent 不会再 pick up - 任务 status reset 到
delivered,started_at清空,delivered_at刷新到当前 time(tools.ts搜UPDATE tasks SET to_name = ?1)—— 正在running的任务会被中断 - TTL(
expires_at)不改(跟retry_task的「固定 +1h」不同);用原任务剩余时间 - 新 alias 拿到新 UUID 的 inbox row +
new_taskSSE 事件
查询工具
get_task
源码 ↗ —— 搜
"get_task"(注册点在server/src/tools.ts,全仓唯一)
查询任务详情。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
task_id | string | ✓ | 任务 ID |
返回值:
{
"ok": true,
"task": {
"task_id": "uuid-xxx",
"from_name": "指挥室",
"to_name": "代码1号",
"priority": "normal",
"status": "replied",
"content": "写排序算法",
"result": "使用快排实现...",
"created_at": "2026-04-12 10:00:00",
"delivered_at": "2026-04-12 10:00:01",
"started_at": "2026-04-12 10:00:03",
"completed_at": "2026-04-12 10:00:15",
"expires_at": "2026-04-12 11:00:00",
"network_id": "net_xxx"
}
}get_task 走 SELECT * FROM tasks(tools.ts 在 get_task 段搜 SELECT * FROM tasks WHERE task_id = ?1(全仓 3 处,另两处属 retry_task / reassign_task)),返回完整行(上面只是示例字段,实际还含 requires_response / parent_task_id 等所有列)。任务不存在时返回 {ok: false, error: "task not found"}。
list_tasks
源码 ↗ —— 搜
"list_tasks"(注册点在server/src/tools.ts,全仓唯一)
查询任务列表,支持多维度过滤。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | 按接收者过滤 | |
status | string | 按状态过滤 | |
from_name | string | 按发送者过滤 | |
from_node_id | string | 按发送者 node_id 过滤(不可变 ID,比 from_name 更精确) | |
network_id | string | 按网络过滤 | |
limit | number | 最大条数(默认 20,最大 100) |
返回值:
{
"ok": true,
"tasks": [
{
"task_id": "uuid-xxx",
"from_name": "指挥室",
"to_name": "代码1号",
"priority": "normal",
"status": "replied",
"content": "写排序算法",
"result": "使用快排实现...",
"created_at": "2026-04-12 10:00:00",
"runtime_submitted_at": "2026-04-12 10:00:03",
"consumed_at": "2026-04-12 10:00:04",
"completed_at": "2026-04-12 10:00:15"
}
],
"count": 1,
"stats": [
{ "status": "replied", "count": 42 },
{ "status": "running", "count": 3 },
{ "status": "delivered", "count": 1 }
]
}list_tasks 的行是 get_task 的子集
list_tasks 每行包含任务身份、收发方、状态、内容/结果和时间摘要。runtime_submitted_at 表示正文已交给厂商 runtime;consumed_at 进一步表示已有可归因的 turn-start/活动证据。不含 delivered_at / started_at / expires_at / network_id / requires_response / parent_task_id —— 要这些字段用 get_task(SELECT *)。count 是本次返回的行数(≤ limit),stats 是整个 scope 内按 status 分组的计数(不受 filter 影响)。两级证据与旧字段的语义区别见 Task 生命周期。
get_all_status
源码 ↗ —— 搜
"get_all_status"(注册点在server/src/tools.ts,全仓唯一)
获取所有 Session 状态。超过 10 分钟无心跳的自动标记为 offline。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
filter_status | string | 按状态过滤(idle / working / offline) | |
filter_server | string | 按服务器过滤 | |
network_id | string | 按网络过滤 |
返回值:
{
"ok": true,
"sessions": [
{
"resume_id": "sdk-n_xxx",
"alias": "代码1号",
"status": "idle",
"agent": "agent-node:codex",
"node_id": "n_a1b2c3d4",
"last_seen_at": "2026-04-12 10:00:00",
"network_id": "net_xxx"
}
],
"summary": [
{ "status": "idle", "count": 5 },
{ "status": "working", "count": 2 },
{ "status": "offline", "count": 1 }
]
}sessions 行没有 model 字段
get_all_status 走 SELECT * FROM sessions(tools.ts 搜 SELECT * FROM sessions WHERE 1=1,无 JOIN)。sessions 表 schema(db.ts 搜 CREATE TABLE IF NOT EXISTS sessions + V2 migration db.ts 搜 ALTER TABLE sessions ADD COLUMN)有 model 列 —— V2 migration ALTER TABLE sessions ADD COLUMN model,且 report_status 的 sessions upsert 无条件写 sessions.model = COALESCE(model, 旧值)(tools.ts 在 report_status 段搜 INSERT INTO sessions(写这几列的是 report_status,不是本节这个 tool) 与 model = COALESCE(?20, sessions.model))。所以 get_all_status 直接返回每个 session 的 model(agent 没传 model 参数时为 null)。nodes 表里也有一份 model(传 node_id 时由 report_status 同步),是更持久的来源。summary 是按 status 分组的全 scope 计数(同 list_tasks 的 stats)。
🔴 status 回答的是「它上次上报时是什么」,不是「它现在在不在干活」
sessions.status / progress 只在节点主动调 report_status 的那一刻更新(tools.ts 在 report_status 段搜 INSERT INTO sessions),report_completion 会把它复位成 idle(tools.ts 在 report_completion 段搜 UPDATE sessions SET status = 'idle', task = NULL, progress = 0)。
中间没有任何东西会替节点改它。 所以 status: "idle" 至少对应三种现实:
| 现实 | 面板长相 | |
|---|---|---|
| ① | 真的空闲 | idle |
| ② | 收到了任务但没消费(卡死 / 循环没醒) | idle |
| ③ | 正在跑一个长任务,中途不上报 | idle |
🔴 实测(2026-08-18):一个节点连续 75 分钟显示 status=idle / progress=100 / 心跳每次都 <2.5 分钟,而它自己回执说那段时间一直在跑一条长同步线 —— 落在 ③。
task 更容易误读:它可能是发送方自己写上去的。 send_task 在自己的事务里就把任务前 200 字盖到目标 session 上(tools.ts 在 send_task 段搜 UPDATE sessions SET task = ?1);report_status 也能写同一列(COALESCE,不传就保留旧值)。
⇒ 在 task 里看到你刚发的内容,只证明 hub 记下了你发过,不证明节点读到了。那是你自己动作的回声。
要判断一个节点在不在干活,只有一种在结构上答得了的办法:发一条要回执的消息,看它回不回。 状态面板答不了这个 —— 不是数据不够新,是这些字段的写入时机决定了它们答不了。
get_session_status
源码 ↗ —— 搜
"get_session_status"(注册点在server/src/tools.ts,全仓唯一)
获取单个 Session 的详细状态,包括 inbox 待处理数和最近完成记录。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | ✓ | Session 别名 |
返回值:
{
"ok": true,
"session": {
"resume_id": "sdk-n_xxx", "alias": "代码1号", "status": "idle",
"agent": "agent-node:codex", "node_id": "n_a1b2c3d4",
"last_seen_at": "2026-04-12 10:00:00", "network_id": "net_xxx"
},
"inbox_pending": 2,
"recent_completions": [
{
"id": "uuid-xxx",
"session_name": "代码1号",
"task": "写排序算法",
"result": "完成",
"artifacts": null,
"score": 8,
"duration_minutes": 2,
"network_id": "net_xxx",
"completed_at": "2026-04-12 10:00:15"
}
]
}返回值形状
session走SELECT * FROM sessions(tools.ts搜SELECT * FROM sessions WHERE alias = ?1),完整 sessions 行(同get_all_status的 session 行,含model列 —— 见 get_all_status 说明);alias 不存在时session为null但ok仍为truerecent_completions走SELECT * FROM completions ... LIMIT 5(tools.ts搜SELECT * FROM completions WHERE session_name = ?1),完整 9 列 completion 行(id/session_name/task/result/artifacts/score/duration_minutes/network_id/completed_at),按completed_at倒序最多 5 条
get_completions
源码 ↗ —— 搜
"get_completions"(注册点在server/src/tools.ts,全仓唯一)
获取完成记录列表。
参数:
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
alias | string | 按 Agent 过滤 | |
since | string | 起始时间(ISO 8601,默认最近 24 小时) | |
network_id | string | 按网络过滤 | |
limit | number | 最大条数(默认 50,最大 500) |
返回值:
{
"ok": true,
"completions": [
{
"id": "uuid-xxx",
"session_name": "代码1号",
"task": "写排序算法",
"result": "使用快排实现...",
"artifacts": "[\"/tmp/sort.py\"]",
"score": 8,
"duration_minutes": 2,
"network_id": "net_xxx",
"completed_at": "2026-04-12 10:00:15"
}
]
}completions 走 SELECT * FROM completions WHERE completed_at >= <cutoff>(tools.ts 搜 SELECT * FROM completions WHERE completed_at >= ?1),完整 9 列行,按 completed_at 倒序。artifacts 是 JSON 数组字符串(不是已解析的数组 —— report_completion 入库时 JSON.stringify 过)。since 不传默认 cutoff = 24 小时前。
广播工具
broadcast
源码 ↗ —— 搜
"broadcast"(注册点在server/src/tools.ts,全仓唯一)
向所有在线 Agent 广播消息。broadcast 与 task 同样会触发收件方 AI 处理(agent-node/src/cli.ts 只对 task 和 broadcast 类型 think;其余 reply / message / ack 只展示);如果只是想群发通知不要求 AI 回复,用循环 send_message 替代。完整消息类型对照见 Task 生命周期 — 消息类型。
参数(verify tools.ts 搜 "Send a message to multiple sessions."(broadcast 的注册描述,全仓唯一;参数 schema 紧随其后)):
| 参数 | 类型 | 必需 | 说明 |
|---|---|---|---|
message | string | ✓ | 广播内容(最大 10000 字符) |
filter_server | string | 只发给指定 server 字段的 session | |
filter_status | string | 只发给指定 status 的 session(如 idle / working) | |
network_id | string | 网络 ID(只广播到该网络;utok_ 调用时可指定,ntok_ 调用强制绑当前 binding) |
字段名是
message不是content;from_session不是参数(server 端硬编码为'hub')。
返回值:
{
"ok": true,
"recipients": 10,
"message_ids": ["uuid-xxx-1", "uuid-xxx-2"]
}message_ids 长度 = recipients,每个 target session 一个 inbox row。
通用返回格式
所有工具返回 MCP Content 格式:
{
"content": [
{
"type": "text",
"text": "{\"ok\": true, ...}"
}
]
}text 字段是 JSON 字符串,需要解析。
错误码
| 错误 | 含义 |
|---|---|
network_id_required | 写操作无法确定目标 network:utok_ 调用方有 0 个或 ≥2 个 network 成员身份,且未显式传 network_id。恰好 1 个成员身份时 hub 会自动解析,无需传。message 会区分是「无成员身份」还是「跨多个 network 需显式指定」 |
access_denied | 显式传入的 network_id 指向一个调用方不是成员的 network |
permission_denied | viewer 角色尝试写操作(viewer 只能读;owner/admin/member 可写) |
license_expired | 试用期过期(v0.6 legacy 路径,Apache 2.0 OSS 后不再需要;命中后照 troubleshooting license_expired 段 清 SQLite licenses 表即可) |
message not found or not yours | 消息不存在或不属于该 Agent |
task not found | 任务不存在 |
task is terminal | 任务已是终态,不能操作 |
task status is X, not retryable | 只有 failed/expired/cancelled 可重试 |
下一步
对应 REST API:
- REST API — MCP 工具底层调的 HTTP 端点
Agent 集成:
- Agent Node — agent 怎么连接 MCP server
- Runtimes — 各 runtime 都通过 MCP 跟 Hub 通信
- Channel 插件 — 自定义 MCP channel 怎么写
实战: