HAI-MCP

io.github.smlfg由 GitHub 帳號 smlfg 發布v0.1.0更新於 Oct 24, 2026

Model-agnostic MCP control plane for HAI: bounded missions, owner-gated actions, drift checks.

概覽

AI 產生的概覽

本機 MCP 控制平面,讓助理開啟有界線的任務、申請工作階段租約、依契約檢查活動並記錄證據。

可以做什麼
開啟、重新簽約與關閉帶版本化契約與完成條件的任務,讀取目前契約或狀態,並設定最多兩條活躍工作線。授權與任務、契約版本、角色和條件集綁定的限時工作階段租約。以確定性漂移檢查把規劃或已觀察的活動判定為符合或偏離契約。記錄證明與證據,儲存檢查點並回傳最小的復原下一步。處理收件匣的接收、提煉與暫存項目,並在擁有者確認後把專案識別碼綁定到本機目錄。
適用情境
當你希望代理的工作保持可觀察、有界線且由擁有者把關時使用:任務帶有明確的非目標與完成條件,租約到期失效,行動前做漂移檢查,關閉前記錄證據。適合在多個 LLM 用戶端之間切換、希望治理方式與模型無關的團隊。
執行需求
以本機 Python 套件執行(需 Python 3.12 以上與 uv),預設使用 stdio,設定 HAI_TRANSPORT 後可用 streamable-http。選用設定:HAI_HOME(預設 ~/.hai)、HAI_OWNER_HOME(預設 ~/.hai-owner),以及非回送 HTTP 所需的 HAI_HTTP_HOST、HAI_HTTP_PORT 和 HAI_HTTP_TOKEN。不需帳號或外部服務。
安裝前請注意
它會把任務、租約與證明狀態寫入 HAI_HOME,把擁有者通道寫入 HAI_OWNER_HOME,應讓後者位於 HAI_HOME 之外,以免代理讀到一次性擁有者驗證碼。除非設定了 HAI_HTTP_TOKEN,否則拒絕把 HTTP 綁定到非回送位址,該權杖應視為機密。接受、重新簽約與放棄等擁有者把關操作依賴回傳一次性驗證碼,ack_legacy 模式只是自我宣稱的信用機制。它不執行程式碼、不推送 git、不刪除檔案,且全域同時只允許一個活躍任務。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 HAI-MCP,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

[HAI-MCP banner]

HAI-MCP · Model-agnostic MCP control-plane for the Human Agent Interface (HAI) approach

[License: MIT] [Python ≥ 3.12] [MCP] [Issues]


Why this repo exists

Agents are now driving shells, editors, browsers, and CI. Most of them work without a human in the loop long enough for the human to lose the thread. HAI — the Human Agent Interface — is an opinionated, evidence-based way to keep agentic work observable, bounded, owner-gated, and recoverable so a human can still own the work even when an agent is doing it.

HAI-MCP is the open-source, model-agnostic implementation of that approach. It is one of the pieces of Samuel Fleig's HAI stack — the part that any Model-Context-Protocol-speaking client can talk to, regardless of which LLM sits behind it.

Canonical site: https://www.human-agent-interface.com/ · About Samuel: https://www.human-agent-interface.com/samuel/


What "MCP control-plane" means here

MCP — the Model Context Protocol — is a standard JSON-RPC interface that lets a tool server expose tools, resources, and prompts to an LLM-backed client (Claude Code, Codex, Cursor, Grok, OpenCode, Hermes, …). The client discovers the server's tools and calls them during a conversation; the server stays stateless from the model's point of view.

A control-plane server is one that does not do the work itself — it governs how work is authorised, scoped, recorded, and handed back to the human. Concretely, an MCP control-plane:

ConcernWhat HAI-MCP exposes for it
Mission contracthai_open_mission, hai_get_contract, hai_recontract
Session leasinghai_authorize_session — time-bounded, contract-versioned
Activity classificationhai_check_activity / hai_drift_check — on-contract vs. off-contract
Focus & laneshai_set_focus, hai_status — at most 2 ACTIVE lanes
Owner gateone-time nonces out-of-band (HAI_OWNER_HOME or ntfy), or Touch ID on macOS, for accept / recontract / abandon
Evidence & closurehai_proof, hai_close_mission, hai_stop
Inbox & intakehai_intake, hai_distill, hai_park, hai_park_item
Recoveryhai_checkpoint, hai_recover

HAI-MCP is deliberately not an agent runtime. It never calls an LLM, never runs shell, never pushes to git, and never deletes files. It is the judge — agents call it to ask "may I?" and to record "I did".


Features

  • One state engine, 23 tools — three surfaces (legacy control plane, mission lifecycle, daily-loop wrappers) sharing one hardened core.
  • Strict fail-closed boundary — inputs are typed and rejected, not coerced. A String "2" is refused for an Integer field; the server stays reachable instead of silently mangling types.
  • Versioned mission contracts — every mission has a contract with a monotonic version. Recontracting produces a visible field-level diff and revokes every existing lease.
  • Time-bounded session leases — hai_authorize_session binds a lease to a mission id, a contract version, a duration, a role, a contribution, and a claimed criterion set.
  • Deterministic drift check — hai_check_activity classifies planned or observed activity against the contract without ever calling an LLM.
  • Two-principal owner gate:
    • Default (nonce): the server delivers a one-time code to the owner channel (HAI_OWNER_HOME / file, or ntfy). The client never sees the code. The code is bound to the exact change, single-use, expiring; only the hash is stored in HAI_HOME.
    • touchid (macOS): the server process shows a Touch ID prompt for that exact change. There is no code. The agent's follow-up call applies it; the client cannot approve itself.
    • ack_legacy: the old self-asserted owner_ack flag — an honor system, surfaced as such by hai_health.
  • Mount table — hai_bind_project joins a logical project_id to a device-local directory behind owner_ack + reason.
  • Model-agnostic — same binary, same tools, same contract. Switch LLMs without rewriting governance.
  • Two transports — stdio (default) and streamable-http with optional bearer-token binding (loopback only by default).
  • Checkpoint & recover — hai_checkpoint snapshots context; hai_recover returns the smallest recovery next action.
  • 203 tests green — the engine is covered; the slice remains open for the learning-budget and owner-instrument follow-ups.

Install & run

Requires Python ≥ 3.12 and uv.

bash
git clone https://github.com/smlfg/hai-mcp.gitcd hai-mcpuv sync --all-extrasuv run hai-mcp          # stdio transport, default

Streamable-HTTP transport:

bash
HAI_TRANSPORT=streamable-http \HAI_HTTP_HOST=127.0.0.1 \HAI_HTTP_PORT=8765 \HAI_HTTP_TOKEN="$(openssl rand -hex 32)" \uv run hai-mcp

HTTP binding to non-loopback hosts is refused unless HAI_HTTP_TOKEN is set. See docs/OWNER_GATE.md and the --help output.


Sample usage — wiring the server into a client

The server is transport-agnostic; every MCP client gets the same 23 tools. Drop the snippet into the client's MCP config and restart.

Claude Code / Claude Desktop

json
{  "mcpServers": {    "hai": {      "command": "uv",      "args": [        "run",        "--directory",        "/absolute/path/to/hai-mcp",        "hai-mcp"      ],      "env": {        "HAI_HOME": "/home/you/.hai",        "HAI_OWNER_HOME": "/home/you/.hai-owner"      }    }  }}

Cursor

Cursor plugin: this repo is also a Cursor plugin (.cursor-plugin/plugin.json + mcp.json). It starts the server from PyPI with uvx hai-mcp, state goes to ~/.hai and ~/.hai-owner by default. Requires uv.

Manual config:

json
{  "mcpServers": {    "hai": {      "command": "uv",      "args": [        "run",        "--directory",        "/absolute/path/to/hai-mcp",        "hai-mcp"      ],      "env": {        "HAI_HOME": "/home/you/.hai",        "HAI_OWNER_HOME": "/home/you/.hai-owner"      }    }  }}

Codex / Hermes / any MCP stdio client

Same shape — point at the uv run --directory … hai-mcp command and pass the two env vars. More snippets live in docs/client-snippets/.


Sample usage — driving the protocol

A typical agent loop calls HAI-MCP before it acts and after it acts.

1. Open a bounded mission

text
hai_mission_start(  problem   = "Refactor the evaluator harness to be deterministic.",  artifact  = "Pull request titled 'evaluator: deterministic harness'.",  done_criteria = [    {"id": "C1", "description": "Two A/B cases produce identical verdicts on three reruns."},    {"id": "C2", "description": "Harness runs offline; no live network calls."},  ],  owner             = "samuel",  time_limit_hours  = 6,  non_goals         = ["Do not touch the MCP server.", "Do not change contract shapes."],  constraints       = {"python": ">=3.12", "branch": "slice/eval-determinism"},)

2. Authorise a session lease

text
hai_authorize_session(  mission_id         = "<from open>",  contract_version   = 1,  agent_identity     = "codex-cli",  role               = "implementer",  contribution       = "Deterministic A/B harness",  expected_result    = "Green pytest with frozen inputs.",  duration_minutes   = 90,  criterion_ids      = ["C1", "C2"],  device_id          = "mbp-mirgraatin",  harness_id         = "codex-cli/0.45",)

3. Check an activity before running it

text
hai_check_activity(  session_id     = "<from lease>",  activity_step  = "Replace random.seed with a seeded fixture in tests/test_eval_ab.py",  criterion_id   = "C1",  affected_paths = ["tests/test_eval_ab.py", "tests/fixtures/ab/case1.json"],)# → {"verdict": "on_contract", ...}

4. Close with evidence

text
hai_proof(  mission_id        = "<from open>",  contract_version  = 1,  outcome_summary   = "A/B cases produce identical verdicts on three reruns; harness offline.",  evidence          = {    "C1": {"command": "pytest tests/test_eval_ab.py -q", "exit_code": 0,           "reruns": [0, 0, 0]},    "C2": {"command": "pytest tests/test_eval_ab.py -q --offline", "exit_code": 0},  },)

5. Owner-gated promotion

For hai_accept_next_step, hai_recontract, or abandoning a mission, the first call without owner_code asks the owner out of band.

  • file / ntfy: a one-time code is delivered to HAI_OWNER_HOME or an ntfy topic. Relaying it back as owner_code=<code> completes the action. The client never sees the code; only its hash is stored in HAI_HOME.
  • touchid (macOS): set HAI_OWNER_CHANNEL=touchid on the server. The server shows a Touch ID prompt and returns status: owner_approved. Call the same tool again with the same arguments (no code) to apply that exact change. Optional: HAI_OWNER_TOUCHID_TIMEOUT (default 60), HAI_OWNER_TOUCHID_HELPER (a compiled binary), and HAI_OWNER_TOUCHID_FALLBACK=file only when Touch ID cannot run.

The approval is bound to the exact change and is single-use. On a Mac, uv run python scripts/manual_touchid.py prompt and … gate exercise the real sensor; CI mocks the helper. Detail: docs/OWNER_GATE.md.


State layout

  • Global: $HAI_HOME — default ~/.hai
  • Owner channel: $HAI_OWNER_HOME — default ~/.hai-owner (deliberately outside HAI_HOME so the agent cannot read it)
  • Per-project: <project_path>/Projek-Managment/ (legacy) or device mount + relative prefixes when a project_id is bound
  • Mount table: HAI_HOME/core/projects.json

All writes are resolved and confined to these roots.


Project layout

hai-mcp/├── docs/│   ├── TOOL_CONTRACT.md      # normative tool contract (gates, errors, schemas)│   ├── OWNER_GATE.md         # nonce + ack_legacy owner-gate spec│   ├── BUILD_HANDOFF.md│   ├── client-snippets/      # ready-to-paste mcp.json snippets│   ├── eval/                 # A/B harness contract│   ├── plans/                # dated design slices│   └── visuals/              # mission-lifecycle banner assets├── scripts/                  # stdio smoke + impact-eval runner├── src/hai_mcp/              # the server└── tests/                    # 203 tests

Limitations

HAI-MCP is intentionally narrow. It does not:

  • Call any LLM. The server is dumb on purpose — governance is a separate concern from generation.
  • Execute code, run shells, push git, or delete files. It refuses tools like "commit & push", "run pytest", "rm -rf". Agents are expected to do those things and report back via hai_check_activity / hai_proof.
  • Merge with hai-intake packages. The intake pipeline is a separate stack; coexistence is fine, fusion is not.
  • Provide a UI. There is no dashboard. The control plane speaks MCP and writes JSON; visualisation is the client's job.
  • Multi-mission concurrency. Exactly one active mission globally. Open a new one only after the previous is closed (completed or abandoned).
  • Cross-device writes. Each device sees only its own mounts. The mount table is per-device; the contract is global.
  • Forward compatibility for major MCP bumps. The server pins mcp>=1.9.0,<2; a v2 of MCP will require a separate migration slice.
  • No revocation list / no kill-switch API. Lease invalidation happens via recontract, mission close, or hai_stop; there is no out-of-band "revoke everything right now" tool.
  • No automatic recovery from a corrupted HAI_HOME. If the global state directory is corrupted, the server fails closed — by design, but recovery is manual (see hai_recover).

See docs/TOOL_CONTRACT.md for the full gate matrix and docs/OWNER_GATE.md for the owner-gate contract.


Tests

bash
uv run pytest                       # full suiteuv run python scripts/stdio_smoke.py  # stdio round-trip smoke

The repo carries 203 green tests as of the Touch ID owner-channel slice. CI status lives on the GitHub Actions page of the repository.


Contributing

The control plane is small on purpose — additions go through a contract slice:

  1. Read docs/TOOL_CONTRACT.md.
  2. Open an issue describing the tool / gate / state change.
  3. Land it behind a fail-closed slice with tests + plan in docs/plans/.

Pull requests that change gates, schemas, or the mount table without a matching plan will be asked to follow the same path.


License

MIT — see LICENSE. Copyright © 2026 Samuel Fleig.


Acknowledgements

HAI-MCP is one piece of Samuel Fleig's HAI stack. It stands on:

  • the Model Context Protocol specification,
  • the mcp Python SDK (mcp>=1.9.0,<2),
  • and the legacy ~/.config/hai-agent-mcp Hermes bridge that this server replaces for control-plane work. Coexistence is supported; the bridge is not required.

Canonical HAI site: https://www.human-agent-interface.com/ · About Samuel Fleig: https://www.human-agent-interface.com/samuel/

來源:README.md,提交 30bc0f4

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

1
  1. v0.1.0最新Oct 13, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分