Metadata-Version: 2.5
Name: harflow-mcp
Version: 0.0.5
Summary: Local MCP server that dispatches coding tasks to headless agents (Claude Code, Codex, opencode, vibe, Antigravity)
Author: Nayanda Haberty
License-Expression: Apache-2.0
License-File: LICENSE
Requires-Python: >=3.11
Requires-Dist: mcp<3,>=2.0
Requires-Dist: tomlkit<1,>=0.13
Description-Content-Type: text/markdown

# HarflowMCP

<!-- mcp-name: io.github.Harflow-Dev/harflow-mcp -->

HarflowMCP is a local MCP server that dispatches coding tasks to Claude Code, Codex, opencode, Vibe, Antigravity, and the Cursor Agent CLI. It provides persistent task history, bounded reads, cancellation, continuation, and reusable workflows. On measured Claude Code versions, callers can opt in to approving individual Bash, Read, Write and Edit requests one exact action at a time (see [harness permissions](docs/harness-permissions.md#exact-action-caller-approvals)); on macOS with codex-cli 0.163.0 the same opt-in approves individual Codex commands and, with `caller_write_approvals`, patches through `codex app-server` (see [Codex caller approvals](docs/harness-permissions.md#codex-caller-approvals-codex-app-server)), and can grant a task a bounded list of specific Bash commands with `allowed_commands` instead of `unrestricted` access (see [dispatch-time command grants](docs/harness-permissions.md#dispatch-time-command-grants-allowed_commands)).

Signing into the Cursor editor does not sign in the `agent` CLI. Headless Cursor dispatch needs `agent login` or `CURSOR_API_KEY`. Confirm with `agent status`: it has to report an access token. That check reads the CLI credential store for the current `HOME`, so a shell whose home directory is somewhere else still says it is not logged in after a successful `agent login`. Cursor refuses caller approvals and `allowed_commands`. Its `read_only` launch asks for plan mode; `write_in_repo`, `publish`, and `unrestricted` share one print-mode command until a measured boundary separates them. There is no live follow-up on stdin. The pinned CLI is `2026.10.22-27dcf5f` on macOS arm64. See [harness permissions](docs/harness-permissions.md) and [backend CLI facts](docs/backend-cli-facts.md).

MCP task status and single-task waits default to compact polling while preserving the complete
final summary, approval attention and recovery diagnostics. Use `detail="full"` for execution
metadata; `include_tail=true` explicitly includes the raw tail in either mode. Workflow discovery
returns names, descriptions, revisions and IDs by default; `get_workflow(name)` reads the full
graph. Prefer wait holds of 50 seconds or less on remote MCP connections. See the
[waiting and polling guide](docs/multi-task-waiting.md).

After a dispatch server restart, surviving execution is reported as a quiet observation change;
lost or uncertain owner/capture evidence remains visible. Full diagnostics retain the original
dispatcher identity. See [supervision](docs/supervision.md#dispatch-origin-owner-and-responding-server).
For stable read-only parent-process observation continuity, use `harflow-ctl status TASK_ID --observer-parent --json` (also supported by `status-batch`); see [public contracts](docs/contracts.md#ctl-parent-observation-continuity).

Workflow callers can see every pending child question in status and wait replies and answer them independently by decision ID through the root run. Questions and structured clarification items remain complete, and forwarded answers return a durable child acceptance receipt. Resolved attention reasons disappear when execution resumes; unreadable workflow approval metadata is reported separately from requests needing a decision. See [workflow input and recovery](docs/workflows.md).

Permission features use cached, binary-bound qualification: measured versions seed the cache, and unseen versions run isolated no-paid behavior probes before use. `harflow-ctl qualify <backend>` explicitly reruns the probes; cached discovery reports per-feature results. Add `--qualification-only` to `permission-preview` or `workflow-preview NAME` to discover only the features requested by that launch without provider self-tests; `qualify --feature FEATURE` is repeatable. Ordinary permission previews may qualify requested features. Automatic probes currently require macOS isolation. See [qualification](docs/harness-permissions.md).

Current seed measurements for these two features: `allowed_commands` is qualified on Claude Code 2.1.310 and 2.1.312; caller approvals are qualified on Claude Code 2.1.302 (Bash approvals) and 2.1.310/2.1.312, and on Codex through `codex app-server` for codex-cli 0.163.0 on macOS only (commands, and patches with `caller_write_approvals`); other backends refuse them. Approvals are not available to native workflow children, and a request unanswered after 1800 seconds (or at the node's attempt deadline) is rejected by Harflow, never approved. After a denial there is no approve-later path: recovery is always a new `resume_task` or `continue_task` execution guided by `denial_remedy` (`allowed_commands` covers only Bash `approval_required` and chained-command parts; a denied Read, Write or Edit needs a resumed run so the agent can raise a fresh request; a `deny_rule` cannot be lifted by grants). Workflow permission-grant retry and approval notifications are not available. On compatible engines the Mac Monitor can answer caller-owned requests; authority follows the existing inferred, cooperative same-user model and does not authenticate a human or the app. See [harness permissions](docs/harness-permissions.md#exact-action-caller-approvals).

Vibe 3.0.1 headless dispatch uses its Rust CLI and the `ask` approval profile for `read_only`. This is an approval policy, not a write-tool exclusion: inherited policies or custom profiles can pre-approve writes. The retained `VIBE_CLI=python` selector is ignored by Vibe 3; interactive takeover inherits the user's environment.

Vibe provider HTTP 402 failures retain a safe explanation even without final agent prose. A measured usage-limit response is reported as a usage limit; an unknown payment response stays a provider error and asks you to check billing and usage. Neither automatically retries or switches providers.

`publish` authorizes publication attempts; its enforcement depends on the backend:

| Backend | Publish mechanism |
| --- | --- |
| Claude | Allows `git commit`, `git push`, `gh pr create/edit/view/comment/review/checks/diff/list`, and `gh repo view`, including their `--help` forms. |
| Codex | Enables network in its workspace sandbox; it does not restrict individual GitHub commands. |
| opencode | Uses the same `build` policy as `write_in_repo`; inherited harness settings still decide command approval. |
| Vibe / Antigravity | Uses the same approval bypass as `unrestricted`; individual GitHub operations are not filtered. |
| Cursor | Uses the same print-mode command as `write_in_repo` and `unrestricted`. Plan mode is requested only for `read_only`. Individual GitHub operations are not filtered, and caller approvals and `allowed_commands` are refused. |

Claude's built-in list excludes merge, repository deletion, releases and raw `gh api` calls.
Its prefix matcher cannot safely distinguish read API calls from writes; use `gh pr view --json`
or `gh repo view --json` for supported reads. These are Harflow-supplied command grants,
not an OS Git sandbox; inherited settings and hooks can still allow or deny commands.
Permission previews expose the actual mechanism and caveats. See [publication permissions](docs/contracts.md#publication-permission-policy).

Version 0.0.5 is a pre-release. [Harflow](https://github.com/Harflow-Dev/HarflowMac), the companion macOS application, is maintained separately and prepares its own exact paired engine runtime. Its managed runtime and MCP registrations work independently of the app process; see the [managed runtime guide](https://github.com/Harflow-Dev/HarflowMac/blob/main/docs/managed-runtime.md).

Detached task owners preserve output capture and live input across MCP server restarts.
Tasks can take turns on a named, exclusive resource (a simulator, a device, a database) with `resources`; a waiting task is acknowledged at once and reports `waiting_for_resources` until it spawns. A task can also run in its own linked Git worktree with `worktree`, leaving your checkout untouched. Workflows can declare run and node resource scopes and share one root-run worktree across nodes and linked child runs. See [resources and worktrees](docs/resources-and-worktrees.md). Final review summaries and workflow plans receive task-identifiable files discoverable through task artifacts, including read-only runs. Child workflows receive pinned parent specifications throughout their nodes. Every task also gets scratch folders shared across its resume chain and its group (`HARFLOW_CHAIN_SCRATCH`, `HARFLOW_GROUP_SCRATCH`), so outputs survive between runs; see [shared scratch](docs/shared-scratch.md).

Workflow scheduler recovery is explicit; see [supervision and recovery](docs/supervision.md).
Task status distinguishes the dispatching server, execution owner and responding server.
A normal attachment to a task launched by this server is not recovered; another observer or missing
identity is explained explicitly. Detail reads separately report dispatcher liveness, and routine
status polling provides a successor reference without scanning history. See [supervision and recovery](docs/supervision.md).
Git outcomes retain partial observations with per-probe failure and budget diagnostics. Commit
ranges include imported history and cannot identify task-created commits or authorship; see
[observed task outcomes](docs/task-outcomes.md).
Task observations retry transient metadata replacements up to three reads and retain uncertainty
when metadata cannot be read reliably.
Recovered tasks disclose owner/process uncertainty and capture continuity. Qualified Claude
transcripts can supply bounded display-only recovery activity; see [public contracts](docs/contracts.md#supervision-and-recovery-activity).
Live-input capability does not promise that stdin is still open: status reports `input_channel`
and `input_closed_reason`. Wait for settlement before resuming a task whose input has closed.
MCP task status exposes paged successor links; resumes and continuations retain their source IDs.
Claude read-only plan mode permits built-in plan files; successful observed plan writes appear
as metadata-only task artifacts. Harness session history and logs can also persist outside the
checkout. See [harness permissions](docs/harness-permissions.md).
New launches and resumes require at least 256 MiB free on state, checkout and temporary-storage
filesystems. Confirmed-dead detached executions can resume their recorded conversation; live or
uncertain sessions remain protected. See [supervision and recovery](docs/supervision.md).
Backend discovery reports qualification gates for writable paths, caller approvals and command
grants, with network caveats returned as complete entries. At unrestricted access, validated extra writable paths are disclosed as a no-op.
Waits return for approvals that still need a decision or require reconciliation; a recorded
approval or rejection awaiting delivery does not by itself interrupt the next wait.
Live background wait bounds are persisted and configurable; see [task continuation](docs/task-continuation.md#live-background-wait-bound).

Use `harflow-ctl version-info --json` to inspect runtime identity and compatibility without initializing state. Engine operations require compatible Harflow state, task metadata, saved workflow definitions, workflow run documents and workflow ownership receipts. Known qualified storage lines migrate conservatively before new-line writes. Use `harflow-ctl state-inspect --json` to inspect an incompatible root without changing it, then explicitly confirm its `state-recover` proposal to retain a sibling backup and create fresh state. `HARFLOW_STATE_ROOT` can also select a separate fresh state directory; see [state ownership and recovery](docs/contracts.md#state-ownership-and-recovery) for compatibility requirements.

Root workflow status and waits retain verified nested questions with their full source
paths and usage-limit details, even when another child link is unavailable. Answers
route by the current decision ID; unavailable decisions report specific retry guidance.
Pending workflow questions, recovery and goal revision can pass to a verified human
Monitor responder when the original caller's qualified process is confirmed gone.
Live or unknown callers retain ownership. Caller identity is captured before
launch detaches; unsupported launcher ancestry and older runs without evidence
remain unknown. See [the interaction contract](docs/contracts.md#caller-loss-and-workflow-interaction-handover).

- [Getting started](docs/getting-started.md)
- [Workflows](docs/workflows.md), including acknowledged context sections and bounded instruction inspection
- [Task continuation](docs/task-continuation.md)
- [Resources and worktrees](docs/resources-and-worktrees.md)
- [Shared scratch folders](docs/shared-scratch.md)
- [Task artifacts](docs/task-artifacts.md)
- [Task and workflow notifications](docs/task-notifications.md) (qualified Harflow database required)
- [Public contracts and runtime compatibility](docs/contracts.md)
- [Release validation and publication](docs/releasing.md)
- [Development and technical references](docs/development.md)

History pages expose optional completion and ownership metadata for retained-history
summaries. Workflow completion time records the terminal status transition independently
of settlement; legacy and mixed-writer completion without a matching sequence witness remains unknown. See [compact reads](docs/compact-task-reads.md#retained-history-metadata)
for ownership, pinned workflow identity and completeness requirements.

Finished retained-history statistics are available to verified direct callers through
`harflow-ctl statistics-page --since=<ISO8601> --before=<ISO8601> --json`.
Clients require capability `statistics-page.v1`; older engines remain unsupported. Results
disclose retention, missing accounting and bounded preparation rather than assuming complete
history or zero usage. See [statistics contracts](docs/contracts.md#finished-retained-history-statistics).

For narrowly authorized branch preparation on qualified Claude Code, exact `allowed_commands`
grants for fetch, fast-forward-only pull and non-force branch switching/creation work at
`write_in_repo` as well as `publish`. Initial transitions refuse dirty checkouts without stashing
or resetting; commit/push authority remains separate. See the
[grant grammar and per-run workflow migration](docs/harness-permissions.md#dispatch-time-command-grants-allowed_commands).
Other backends explicitly refuse command-grant requests rather than silently broadening access.

GitHub dependencies using SSH URLs are configured to use HTTPS in headless child processes by
default. Set `HARFLOW_GIT_HTTPS_REWRITE=0` on the server to disable this, or override a task with
`git_https_rewrite` (`harflow-ctl run --no-git-https-rewrite`). Configure private repository credentials
with `gh auth setup-git`; Harflow never reads or stores tokens. See [Git transport](docs/git-transport.md)
for observations and sandbox limitations.

See the [Changelog](CHANGELOG.md) for change history.

Licensed under [Apache-2.0](LICENSE). Git history preserves source authorship; the license notice does not assert ownership of prior contributions.

Read-only reviewers can opt in to a qualified group-scoped report output directory with
`group_report_output: true` and a nonempty `group` (`--group-report-output` in `harflow-ctl`).
The initial supported configuration is headless Codex CLI 0.165.0 on macOS with network disabled
and compatible execution configuration; unsupported combinations fail explicitly. The repository
stays read-only. See [shared scratch and review reports](docs/shared-scratch.md#read-only-review-reports).

Messages to tasks, workflow runs and workflow nodes queue by default, preserving exact text and order.
Use `send_message(..., delivery="now")` or `harflow-ctl send TASK TEXT --delivery now` to request
immediate continuation; unsafe interruption returns a reason and leaves the message queued.
See [queued messaging](docs/contracts.md#queued-task-and-workflow-messaging).
