chrono-handoff
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@chrono-handoffGive me a 3-second countdown, then cue me to press the RESET button in 6 seconds."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
chrono-handoff
时间锚定的人机动作交接组件 —— 让 AI agent 驱动人类在指定时刻执行物理动作。
概述
LLM agent 无法直接作用于物理世界,而人类操作者的动作延迟不可预测。若采用 事件触发耦合(人完成动作 → 通知 agent → agent 推理 → agent 下发指令), LLM 的单轮推理耗时(5–30 s)将完整地落在关键路径上,无法满足秒级时序窗口。
本组件将耦合方式改为 时间触发:agent 提交一份声明式的动作计划 (时刻,动作)序列,由独立于 agent 会话生命周期的 conductor 进程持有 单调时钟并按绝对时刻执行;倒计时面板作为人类操作者的时间基准,传感器回读 用于闭环确认。
核心约束:conductor 不得阻塞等待 LLM。agent 调用即在毫秒级返回, 计划提交完成后即可结束会话轮次。
Related MCP server: Consensus
Quickstart
要求
Python 3.10+(建议 3.13+:计时抖动更低,见安装说明)
可选:
pywebview(独立原生窗口)、pyserial(串口观测)
安装
git clone https://github.com/wjunhere/chrono-handoff.git
cd chrono-handoff
# 建议 3.13+:实测抖动更低,3.12 会让 selftest 间歇性失败(见 docs/agent-setup.md §一.0)
uv venv .venv --python "$(uv python find 3.13)"
uv pip install --python .venv/Scripts/python.exe -e ".[all]"
.venv/Scripts/chrono selftest # 机制自检,预期 10/10用独立环境,别装进全局解释器:装和跑必须是同一个解释器,否则原生窗口会 降级成浏览器标签页。
chrono doctor的panel window行会核对这点,并在缺失时 直接给出该装的解释器路径。 没装uv就用自己的 conda:conda create -n chrono python=3.13。
安装选项
命令 | 内容 |
| 仅核心(计时引擎 + CLI + 浏览器面板) |
| 加 MCP 接入 |
| 加跨平台采样级音频( |
| 全部(MCP + 音频 + 原生窗口 + 串口) |
启动
chrono doctor # 环境探测:时钟 / 音频 / 控制台 / 串口
chrono daemon --window --background # conductor + 原生提示窗口 + IPC--window 托管常驻置顶窗口;cue 触发时窗口自动前置。
触发一次提示
chrono submit --json '{
"id": "reset-demo",
"instruction": "按一下开发板上的 RESET 键",
"lead_s": 3,
"ioi_ms": 500,
"tail_beats": 6,
"target_in_s": 8,
"duration_s": 25
}'返回 run_id 并立即退出;计划在 conductor 中执行。
chrono status reset-demo # 当前状态
chrono observe reset-demo # 增量读取事件日志
chrono cancel reset-demo # 中止接入 Pi agent
在 ~/.pi/agent/mcp.json 中注册:
{
"mcpServers": {
"chrono-handoff": {
"command": "chrono",
"args": ["mcp"],
"lifecycle": "lazy",
"searchKeywords": {
"*": ["human in the loop", "countdown timer", "operator cue", "timing"],
"chrono_cue": ["ask human physical action", "pop up panel", "press button", "reset device"]
}
}
}
}MCP 服务端为瘦客户端,首次调用时自动拉起 daemon(CHRONO_AUTOSTART=0 可关闭)。
自动拉起时的窗口形式由 CHRONO_MCP_WINDOW 控制:默认 1 显示窗口;
hidden 启动隐藏、cue 触发时再浮出;0 完全不建窗(同时不建控制台,因此放弃键盘输入与提示音,适合无人值守/自动化)。
完整步骤见 docs/agent-setup.md。
用法
MCP 工具
工具 | 用途 |
| 提示人类在指定时刻执行物理动作,立即返回 |
| 提交声明式动作计划(多动作 / 带窗口 / 带闭环) |
| 增量读取运行事件日志 |
| 有界等待,返回状态快照而非阻塞 |
| 单次运行状态或近期运行列表 |
| 中止在途运行 |
| 读取 / 更新人类偏移估计 |
chrono_cue 调用示例:
chrono_cue(
instruction = "按一下开发板上的 RESET 键",
target_in_s = 6, # 6 秒后动作应命中
lead_s = 3, # 倒计时时长
ioi_ms = 500, # 拍间距
tail_beats = 6 # 命中后脉冲延续
)CLI
命令 | 说明 |
| 环境能力探测 |
| 无人工参与的机制自检 |
| 启动 conductor 常驻进程 |
| 原生提示窗口( |
| 提交计划 |
| 运行控制 |
| 标记动作已确认生效 |
| 人类偏移估计 |
| 交互式提示面板 + 一次提示 |
| 面板连接到运行中的 daemon |
| 查看 / 编辑设置 |
| 运行 MCP stdio 服务端 |
| M1 实验:拍点栅格下的人类偏移测量 |
提示通道
通道 | 实现 | 适用 |
听觉 | 非阻塞音频,多种后端(见下) | 默认;不占用视觉通道 |
视觉 | 置顶窗口 / 浏览器面板 / 终端 | 噪音环境、听觉受限 |
触觉 | HTTP 源可对接移动端震动 | 视觉与听觉均不可用时 |
音频后端按精度分级,chrono doctor 会报告实际选中的后端:
后端 | 平台 | 实现 | 精度 |
| 全平台 | 常驻 PortAudio 流,按帧偏移混音 | 采样级( |
| Windows |
| 设备级( |
| 全平台 | 外部播放器进程( | 近似(进程启动 10–250 ms 抖动) |
| 全平台 | ASCII BEL,由终端发声 | 未知 |
| 全平台 | 静音 | —— |
--audio 可强制指定后端;指定本平台不提供的后端会报错而非静默替换——
静默降级到 cmd 会让一次测量运行带上错误的精度等级。
部署拓扑
拓扑 | 命令 | 特性 |
分离(推荐) |
| 窗口仅作显示器,关闭不影响计划执行 |
一体化 |
| 单进程,适用于演示 |
浏览器面板 |
| 支持局域网内移动端访问 |
目录结构
src/chrono_handoff/
├── clock.py 单调时钟、亚毫秒落点、无漂移拍点网格
├── model.py CuePlan / SignalSpec / WindowSpec / Event
├── audio.py 跨平台非阻塞音频(后端分级 + 采样级混音)
├── cue.py 提示通道(音频转出 + 终端倒计时)
├── inputs.py 观测源:控制台 / stdin / HTTP / 串口 / 合成
├── effectors.py 执行器抽象:人类 / 串口 / HTTP / 日志
├── calibrate.py 人类偏移估计(median + MAD + 截断)
├── conductor.py 快控制器:拍点网格、动作窗口、闭环、事件日志
├── daemon.py 常驻进程与单实例守卫
├── mcp_server.py MCP 表面 + IPC 客户端
├── remote.py 跨进程 conductor 代理
├── webui.py 提示面板服务端
├── window.py 原生置顶窗口(WebView2)
├── winshell.py Windows 11 原生外观(圆角 / 亚克力 / 主题描边)
├── settings.py 设置持久化
├── statics/ 单文件前端 + 本地字体
├── probe.py M1 实验协议
├── analyze.py 离线日志分析
└── cli.py 命令行入口验证
chrono selftest # 核心机制,10 项
basedpyright src scripts desktop/sidecar # 静态检查,要求 0 error(standard 模式)
python scripts/e2e_audio.py # 音频后端:混音/选择/非阻塞不变量
python scripts/e2e_panel.py # 面板 HTTP 全链路
python scripts/e2e_panel_attach.py # 面板附加到 daemon(chrono panel)
python scripts/e2e_window.py # 原生窗口
python scripts/e2e_ui_layout.py # 布局几何
python scripts/e2e_resize.py # 窗口缩放
python scripts/e2e_theme_drag.py # 主题对比度与拖拽隔离
python scripts/e2e_daemon_window.py # 一体化模式
python scripts/e2e_split_mode.py # 分离模式
python scripts/e2e_state_paths.py # 用户状态落点(与 cwd 无关)
python scripts/e2e_update_window.py # cue 安全窗口:不安全时 409 拒,安全时 daemon 自退
python scripts/e2e_desktop_shell.py # Tauri 桌面外壳(需先 cargo build)
cd desktop/src-tauri && cargo test # 外壳几何算式(边方向/夹紧/累计位移/窗口位置与恢复)
python desktop/sidecar/build.py # 冻结侧车并自检(--no-build 只自检,--stale-check 只比指纹)这些在 CI 里自动跑(.github/workflows/ci.yml):
job | 平台 | 跑什么 |
| Ubuntu / Windows / macOS |
|
| Windows |
|
| Ubuntu / Windows / macOS | 打包冻结侧车并跑它的会失败的自检:能力对等、PE subsystem、冻结内 |
| Ubuntu / macOS | 外壳能不能在 Windows 之外编译并通过几何算式测试 |
没覆盖的,写着以免误读:
外壳没有在 macOS/Linux 上“跑起来”过。 最后一个 job 只证明能编译;真跑还需要各平台自己的侧车和真实桌面会话。
侧车自检只在 Windows 上验过。 Linux/macOS 那两个 job 的第一次运行就是它的第一次运行(PyInstaller 不能交叉编译,这恰好是它存在的理由)。
自检里的
selftest是测时序的,机器忙时会偶发失败(本机见过一次9/10,重跑三次都10/10)。失败会打出是哪一项[FAIL]。窗口套件的合成输入在某些机器上会掉事件,套件会把那类断言报成
SKIP并汇总,不会报成通过——所以看到绿色也请看一眼有没有 SKIP。
性能
Windows 11 / CPython 3.13,详见 docs/implementation-notes.md。
指标 | 实测 |
拍点落点偏差(中位 / p99) | 0.02 ms / 2.3 ms |
40 拍 @50 ms 累计漂移 | +0.01 ms(绝对格点,不累积) |
单拍音频调用开销 |
|
跨平台后端节拍落点 | 中位 0.016 ms,与 Windows 原生后端等价 |
音频流欠载 | 0(60 s 连续运行) |
按压时刻记录精度 | 0.5 ms |
停滞网格行为 | 丢拍不爆发,不追帧 |
约束:GIL 是精度上限,CPU 密集任务须置于独立进程;音频设备输出延迟 (约 10–50 ms)尚未测量,该分量被吸收进校准偏移。
平台支持
计时核心为纯标准库实现,可移植。人类提示通道为 Windows 优先:
组件 | Windows | Linux / macOS |
计时核心、MCP、IPC | 完全支持 | 完全支持 |
浏览器面板 | 完全支持 | 完全支持 |
串口 / HTTP 观测 | 完全支持 | 完全支持 |
原生窗口外观 | 圆角 / 亚克力 / 主题描边 | 降级为系统默认外观 |
音频提示 |
|
|
控制台按键观测 | 支持 | 降级为 stdin 行输入 |
文档
文档 | 内容 |
接入 agent 的完整步骤 | |
提示组件使用与集成 | |
协议与接口设计 | |
实现细节与实测数据 | |
面板 ↔ 窗口宿主契约(换壳时唯一要改的地方) | |
Tauri 2 桌面外壳:现状、阻塞点与两条出路 | |
自动更新:分工、cue 安全窗口、签名与发版 | |
M1 测量实验方法 | |
理论依据(时间触发 / 人机节拍同步) | |
问题定义与量化 | |
相关项目调研 | |
实例:龙芯 2K1000LA PMON 引导窗口捕获 |
设计要点
计划事前提交:倒计时开始前,
(时刻, 动作)序列已注册在 conductor 中; 倒计时归零不触发 agent 推理。窗口而非单点:计划可指定动作时窗并在窗内重复下发,由机器侧的重复 尝试吸收人类抖动。
闭环确认:
verify字段指定回读模式,确认动作实际生效。人类执行器不可重放:
HumanEffector.caps().repeatable = False; 缺失新计划时进入安全保持,而非重放上一次人类动作。
许可
代码 MIT(见 LICENSE)。src/chrono_handoff/statics/fonts/ 下的字体文件
(Inter、JetBrains Mono)遵循 SIL Open Font License 1.1,
允许再分发与捆绑 —— 它们的声明放在 THIRD-PARTY.md,不插进 MIT 正文
(插进去会让 GitHub 认不出许可,而认不出的许可法律上读作“保留所有权利”)。
This server cannot be deployed
Maintenance
Related MCP Connectors
Durable, user-controlled goals and governed plans for AI agents.
Agent-native spaced-recall system of record. Deterministic dueAt via remote MCP for Muse/any agent.
Concierge MCP for agentic workflows: verified time + drift, uuid, diff, calc, attest, verify.
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
Related MCP Servers
- AlicenseBqualityBmaintenanceEnables external agents to delegate real-world actions to Hermes Agent via MCP tools such as hermes_run and hermes_plan.1237 npm7MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI coding agents on a team to coordinate by declaring plans, checking them against other in-flight plans and shared memory, receiving proceed/wait verdicts, and recording handoffs and rulings.MIT
- AlicenseAqualityCmaintenanceLets AI agents drive a live, persistent Isaac Sim session: load any articulated robot from a USD plus JSON config, set normalized joint targets and named poses, tune gains and couplings live, run joint range tests, and capture screenshots. It also launches and monitors detached Isaac Lab training runs, with Kit kept up between calls so each experiment costs a frame instead of a full relaunch.26MIT
- AlicenseNot gradedqualityAmaintenanceEnables MCP agents to run, continue, observe, check status of, and abort bounded GUI automation tasks through a shared local runtime with visual detection and deterministic input.Apache 2.0