hwcontract
An MCP server that judges hardware behavior against timing or serial contracts, returning pass/marginal/fail verdicts for coding agents to iterate on real signal measurements.
README
<!-- mcp-name: io.github.MohibShaikh/hwcontract -->
hwcontract
A zero-dependency MCP server that judges hardware against a contract. Coding agents (Claude Code, Codex, opencode) write firmware that's correct on paper but wrong on the wire — a WS2812 pulse 180ns short, an ESC bit out of spec, a boot log that silently panics. This closes the loop: it captures what the hardware actually did and returns pass / marginal / fail the agent can iterate on.
marginal is the valuable verdict — in-spec but low-headroom, the bug that works on
your bench and fails on a cold board in the field.
Demo — a real capture, no hardware needed
python3 demo/ws2812b_neopixel.py downloads a real 24-LED NeoPixel capture
(recorded off hardware by the sigrok project, 24 MHz), extracts the data line, and
judges it against two contracts:
measured on the real WS2812B signal (300000 samples @24MHz):
T0H 333 ns T1H 833 ns T1L 417 ns T0L 917 ns RESET 992250 ns
=== generic WS2812 contract -> FAIL ===
T1L 600 417 FAIL 183ns short (typ 600) # real WS2812B low times are shorter
T0L 800 917 marginal
T1H 700 833 marginal
=== matching WS2812B contract -> PASS ===
(all pass)
Same real signal: it fails the generic WS2812 contract (correctly — a WS2812B isn't a WS2812) and passes the matching WS2812B one. That's the tool doing its job: measure the real signal, hold it to a spec, and make contracts chip-specific.
How it fits together
observers (capture) judge (this repo)
───────────────────── ─────────────────
logic analyzer ─ pulse widths ─┐
serial port ─ log text ─────┼─► contract × observation ─► pass/marginal/fail
┘ (judge.py)
judge.py— the pure judge (timing + serial). No hardware, no framework, cached.sigrok_adapter.py— logic-analyzer capture → pulse-width observations (WS2812/DShot).serial_adapter.py— serial log capture (or replay a saved log).server.py— the MCP server (stdio JSON-RPC, stdlib only).*.contract.yaml— what "correct" looks like. Human-editable. Also serve as regression tests.
Install
pip install hwcontract # judge + logic-analyzer adapter
pip install "hwcontract[serial]" # + live serial capture (pyserial)
pip install "hwcontract[untrusted]" # + google-re2 (ReDoS-immune, for untrusted contracts)
pip install "hwcontract[all]" # everything
Also needs sigrok-cli on PATH for live logic-analyzer capture (check_ws2812 /
check_dshot). Judge-only tools (judge_contract, judge_serial) need nothing extra.
Wire it into an agent
One stanza per client (not auto-discovered — add it once). After pip install, the
hwcontract command is on your PATH.
Claude Code
claude mcp add hwcontract -- hwcontract
Codex CLI — ~/.codex/config.toml
[mcp_servers.hwcontract]
command = "hwcontract"
opencode / Cursor / Gemini / any stdio MCP client
{ "mcpServers": { "hwcontract": { "command": "hwcontract" } } }
Transport is stdio by default (local, no auth surface). For remote-only clients (e.g. ChatGPT connectors), run
hwcontract --http 8791and expose it via a tunnel withHWCONTRACT_TOKENset for bearer auth.
If the client can't find hwcontract (PATH issues)
GUI apps and some agents don't inherit your shell PATH, so a bare hwcontract
can fail with "command not found". Two robust fixes:
- Use the absolute path:
which hwcontract→ put that full path incommand. - Or invoke via Python (no PATH lookup for the script):
command: "python3",args: ["-m", "hwcontract.server"]— works from any directory once installed.
Contract paths: pass an absolute contract_path, or set HWCONTRACT_ROOT
to your contracts folder — relative paths resolve against it (default: the process's
working directory, which the client controls and may not be your project). Paths
outside the root are rejected. Bundled examples install with the package under
hwcontract/examples/.
Tools
| Tool | Hardware? | What it does |
|---|---|---|
judge_contract |
no | Judge given observations against a timing contract. Replay / testing. |
judge_serial |
no | Judge a given log string against a serial contract's expect/forbid. |
check_ws2812 |
yes | Capture a live WS2812 line and judge it, one call. |
check_dshot |
yes | Same, for a DShot600 ESC signal. |
capture_ws2812 |
yes | Just capture → observations (no judging). |
check_serial |
yes | Read a serial port for N seconds and judge the log. |
Contracts
Timing (ws2812.contract.yaml, dshot.contract.yaml) — pulse widths in ns:
contract: ws2812
headroom_pct: 20 # in-spec but within 20% of a rail => "marginal"
edges:
- {name: T0H, min: 200, typ: 350, max: 500} # '0' bit high time
Serial (boot.contract.yaml) — Python regex:
contract: boot
kind: serial
expect: ["IMU init OK", "boot v\\d+"]
forbid: ["panic", "Guru Meditation", "\\bnan\\b"]
Add a protocol = drop a new YAML. No code change for another timing signal.
Kill switch
Instantly disable every hardware-touching tool (captures) while leaving the pure judge tools working:
export HWCONTRACT_SAFE=1 # env, or:
touch /home/tsd/projects/hardware/KILLSWITCH # file next to server.py
Security
Every tool argument is treated as hostile (the caller is an LLM that can be prompt-
injected): contract paths are confined to the server dir (override HWCONTRACT_ROOT),
driver/channel/port are charset-validated, samples/seconds/samplerate are
clamped, sigrok-cli runs with a timeout, YAML is safe_load. Do not expose this
server over the network without adding authentication.
Self-tests (no hardware, run from anywhere)
hwcontract --selftest # full MCP round-trip
python3 -m hwcontract.judge --demo
python3 -m hwcontract.sigrok_adapter --demo
python3 -m hwcontract.serial_adapter --demo
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。