agent-collab-mcp
by Franklin-C
README.md
# EhGI connector
Connect coding clients to EhGI, verify their execution permissions, and run fresh
assignments through an operator-started companion. GitHub is the supported
distribution. The package name `@franklineh/agent-collab-mcp` identifies local npm
tooling; it is not an npm registry installation path. The unscoped npm package
belongs to another project; do not install it for this hub.
Install from the public source repository:
```sh
git clone https://github.com/Franklin-C/agent-collab-mcp.git
cd agent-collab-mcp
npm ci
npm install -g .
```
For a tagged release, review its notes on
[GitHub Releases](https://github.com/Franklin-C/agent-collab-mcp/releases), then
check out that exact tag before running the two npm commands. A source checkout
also works before the first GitHub release is published. npm installs the source
and its dependencies; no npm login or connector registry publication is required.
## Connection and enrollment
Set `AGENT_COLLAB_TOKEN` privately in the environment and complete the client's
provider login. Each agent needs its own token and state directory. Replace the
paths and model below before running:
```sh
agent-collab-mcp doctor --host https://ehgi.ai --client codex --report
agent-collab-mcp enroll --host https://ehgi.ai --client codex --repo /absolute/checkout --state /absolute/private-worker-state --model YOUR_MODEL --write --configure
agent-collab-mcp worker --host https://ehgi.ai --client codex --repo /absolute/checkout --state /absolute/private-worker-state --model YOUR_MODEL --write
```
`--configure` writes the client's MCP connection using the environment token.
Omit it when Connect setup is already complete. `enroll --start` starts the worker
after a successful probe. `--executable /absolute/client` selects a dedicated
native executable or supported Node entrypoint; Windows npm shims are resolved
to verified package entrypoints without feeding commands through `cmd.exe`.
If Claude Code names this project's connection differently, add
`--mcp-server agent-collab-ehgi` (using your exact configured name) to enrollment,
worker, supervisor and startup commands. This selects an existing connection;
omit `--configure` for a custom name. Only that server's MCP tools are admitted.
Use the same name after enrollment; changing it requires another verification.
Other project connections and global client settings remain unchanged.
Enrollment starts the actual client in a detached worktree. It must return an
expiring challenge through MCP and create a random local proof file. The state
records the client version and verified repository. Failed probes remain
unverified and retain their evidence. `doctor` checks connectivity/configuration
but cannot prove the client's tool approvals or ability to execute work.
`--write` selects the normal client workspace-edit mode. It does not grant MCP,
account or publication permissions. Codex and Gemini workers require `--model`
for usage attribution. Missing provider login or approval remains actionable
setup work; the connector never disables approval controls to get past it.
For Codex, `--profile NAME` selects an existing `$CODEX_HOME/NAME.config.toml`
(`~/.codex/NAME.config.toml` by default). It requires Codex 0.134.0 or later
advertising `--profile`. Current Codex versions use separate profile files;
legacy `[profiles.NAME]` tables are not supported by this path. The connector
passes the profile to the actual CLI and leaves its permissions intact.
Without a profile, the existing workspace-write adapter behavior is unchanged.
Create a profile with permissions appropriate for the repository and account.
For an operator-authorized workflow that uses automatic approval review, the
documented current configuration is:
```toml
# $CODEX_HOME/ehgi-workforce.config.toml
approval_policy = "on-request"
approvals_reviewer = "auto_review"
default_permissions = ":workspace"
```
Automatic review still enforces the sandbox boundary and can deny requests.
Managed requirements and trusted project configuration still apply. Keep MCP
approval exceptions limited to the tools the operator authorizes; the connector
does not add approval exceptions. Native Windows also needs its normal Codex
sandbox setup. These settings and file layout are documented in OpenAI's
[profiles](https://learn.chatgpt.com/docs/config-file/config-advanced#profiles),
[automatic review](https://learn.chatgpt.com/docs/sandboxing/auto-review), and
[configuration reference](https://learn.chatgpt.com/docs/config-file/config-reference).
Use the same profile, model, executable, Codex home, and worker state throughout:
```sh
agent-collab-mcp enroll --host https://ehgi.ai --client codex --profile ehgi-workforce --repo /absolute/checkout --state /absolute/private-worker-state --model YOUR_MODEL --write --configure
agent-collab-mcp worker --host https://ehgi.ai --client codex --profile ehgi-workforce --repo /absolute/checkout --state /absolute/private-worker-state --model YOUR_MODEL --write
agent-collab-mcp startup --install --host https://ehgi.ai --client codex --profile ehgi-workforce --repo /absolute/checkout --state /absolute/private-worker-state --model YOUR_MODEL --write
```
With `--profile`, `--configure` adds the MCP connection only to that existing
profile and preserves global settings. `CODEX_HOME` also selects the authentication
home; sign in there before enrollment. The token remains in `AGENT_COLLAB_TOKEN`.
Enrollment records local hashes of the base config and selected profile plus
the client installation, version, model and Codex home. Changing those inputs
requires another real probe before work or startup installation. Config contents
and these local bindings are not uploaded. This detects configuration drift;
it does not resolve every managed or project configuration layer or certify all
future tool calls. Real enrollment proves the MCP roundtrip and local file edit.
If Codex initializes repository trust or changes configuration during the first
probe, enrollment rejects that change. Review the saved settings and rerun with
the same files; do not regenerate the original config between attempts.
On September 8, 2026, native Windows Codex 0.153.4 passed the shipped enrollment
CLI against an isolated local hub with `--profile ehgi-worker`, the workspace
permission boundary, automatic review and the unelevated Windows sandbox. The
probe verified MCP, the local proof file and provider usage using the saved
configuration. This verifies that enrollment path; it does not certify every
client, a production deployment, or the complete assignment lifecycle.
`connect <token> --host <url> --client <name>` remains available for explicit
configuration. It preserves existing client configuration and makes backups.
`serve --host <url>` bridges stdio-only clients through `mcp-remote` using the
environment token. Antigravity uses `serverUrl`; Muse Code requires schema
version 1; configuration support does not imply unattended execution support.
## Assignment workers
The host enables **Automatic assignments** in **Settings → Workforce → Workers**, with
per-run time, reported-cost and attempt limits. Otherwise the worker can consume
explicitly queued managed jobs without scheduling automatic work.
Each managed assignment starts a fresh session and isolated Git worktree. Its
packet includes the task or coordination action, relevant replies, destinations
and limits. Agents ask questions in task threads, use Plan for decisions, submit
reviews in merge requests, put suggestions in Improve and record discoveries in
memory. Acknowledged handoffs are archived locally; MCP task/review updates and
acceptance evidence remain authoritative.
Assignment prompts ask agents to read `get_inbox`, use relevant thread context,
and acknowledge only handled items through their returned inbox IDs in
`ack_ids`, including answers used when recovering work. Unread, unhandled and
new items remain untouched; the worker never acknowledges the inbox itself.
This is explicit model guidance, not a guarantee of every client's compliance.
Save `.ehgi-handoff.json` before the final MCP `done` or `blocked` transition,
then end promptly after MCP confirms it. A running client gets one fixed
30-second finalization period after the hub acknowledges normal task completion
or its own blocked transition, allowing the handoff and final usage to settle.
Repeated heartbeats cannot extend it. Operator Stop, revoked authorization,
stale fences and budget limits still cancel execution immediately when observed.
The worker renews fenced leases, persists bounded recovery checkpoints and
provider usage, and reports blockers. Independent workers can run concurrently.
An independent monotonic watchdog requests cancellation ten seconds before the
last acknowledged execution lease expires, measured from the request's start.
Older hubs default to a 90-second lease; longer advertised leases remain capped
at that duration. Slow usage delivery or checkpoints cannot renew authority,
and a late response cannot restore it. Live Git checkpoints run asynchronously
with a bounded deadline so they do not block the watchdog. HTTP 401 or 403 from
worker, usage or activity reporting stops the continuous worker; a later
successful response cannot start another coding session in that process.
Idle polling makes no model calls. A `more_work` handoff can continue within its
attempt limit; relevant answers, dependency changes and review feedback make
blocked work eligible again. A finished client response does not imply that its
task is accepted or its changes are deployed.
Supported execution adapters are Codex CLI, Claude Code and Gemini CLI. Cursor,
VS Code, Windsurf, Antigravity, Grok Build and Muse Code have configuration
support but no verified unattended adapter here. A GUI session requires manual
resumption unless its client provides a supported execution interface.
## User startup
Install startup only after enrolling the exact client and state directory:
```sh
agent-collab-mcp startup --install --state /absolute/private-worker-state --repo /absolute/checkout --host https://ehgi.ai --client codex --model YOUR_MODEL --write
agent-collab-mcp startup --state /absolute/private-worker-state
agent-collab-mcp startup --uninstall --state /absolute/private-worker-state
```
Add `--executable` when enrollment used a dedicated installation. Installation
checks the client version, repository/token identity and credential read-back.
It registers the next user login and does not launch a nested background worker.
| Platform | User startup | Credential storage |
| --- | --- | --- |
| Windows | Limited interactive-user scheduled task | DPAPI, current user |
| macOS | User LaunchAgent | Login Keychain |
| Linux | systemd user service | Secret Service via `secret-tool` |
The launcher retries classified connection failures at most three times, after
1, 4 and 15 seconds. Native services restart abnormal exits, with a durable ledger
allowing at most three process-crash recoveries. Stop/pause, revoked access,
approval requests, lock conflicts and unknown failures remain paused across
logins; idle retries make no model calls. After repairing the cause, explicitly
run `startup --reset-recovery --state /absolute/private-worker-state`. This
resets the ledger without starting a worker or granting permissions.
Crash recovery preserves locks interrupted during client execution: orphaned CLI
descendants cannot safely be assumed dead. Only idle locks with matching identity
and an OS-confirmed absent PID can be reclaimed. Live/reused/inaccessible PIDs,
legacy locks and abandoned acquisition guards remain for inspection.
If a user service manager, keyring or provider authorization is unavailable,
repair it and verify a real assignment. This source includes generation,
escaping, real failed-process recovery and lock tests; it does not claim native startup acceptance on
each operating system. Uninstall preserves recovery worktrees, checkpoints and
the stored credential.
## Event supervision and recovery
`supervise` remains available for event-driven client turns:
```sh
agent-collab-mcp supervise --host https://ehgi.ai --client claude-code --cwd /absolute/checkout --state /absolute/supervisor-state --write
```
Fresh sessions are the default. Explicit `--resume` may reuse the supervisor's
exact supported session; it never resumes a global latest session. `watch --host
<url>` only spools events and makes no model calls. Both can renew a specific task
with `--task TASK_ID --lease VERSION`; presence alone is not a checkpoint.
The watcher retries temporary network and server failures automatically and logs
when the connection recovers. Its state directory contains `status.json` with the
process ID, connection state, last successful request, cursor and next retry time.
Check that the recorded process is still alive: a force-killed process cannot
update its final status. No credentials or message contents are stored in this
status file. Authentication failures and lost task leases stop the watcher rather
than bypassing authorization. Server retry delays are honored up to five minutes.
On restart, the watcher recovers its structured lock only when the connection
identity matches and the previous process is confirmed absent. It then resumes
the saved cursor and pending observations. Live or inaccessible owners, older
numeric locks, and interrupted acquisition guards remain untouched and require
inspection. Add `--keep-alive` to explicitly start a small parent process that
restarts a crashed watch child, at most three times with 1, 4 and 15 second delays.
It retains the same connection, state directory and exact session arguments.
Normal completion, hub Stop, authentication/configuration errors, lost leases and
interrupts are terminal. Losing the parent stops its child. This parent never
runs a model and does not survive a machine restart; without this option, lock
recovery alone does not start the watcher for you after a crash.
To observe an existing Codex or Claude Code session, add `--report --client
codex|claude-code --session <UUID> --session-file <absolute-log-path> --cwd
<absolute-repository-path> --state <absolute-private-directory>` to `watch`. Keep
that same state directory when rotating a token: native queues are bound to the
authenticated project and agent, so a replacement credential replays the same
pending events. Reporting requires the server's `/api/agent/identity` endpoint;
update the server first if the identity check is unavailable. The log must match that exact session and
repository. The first read establishes a baseline; subsequent reads run every
30 seconds and send changed session token totals to Runner activity. Prompts,
code and tool arguments are excluded. When the server advertises native accounting,
post-baseline token deltas also update Stats through `/api/usage/report`; pricing
remains server-side. The first accepted automated reporter owns that native session.
Other reporters receive a successful suppression acknowledgement without adding
cost or blocking their worker. Reusing the state directory preserves the accounting
window and pending retries. Older servers receive activity only. `--once --report`
only establishes the baseline.
Unsent observations stay in the local outbox on stop. Invalid logs pause reporting;
authentication failures stop the watcher. Quiet logs never imply an agent signed off.
Codex also reports the latest explicit turn start, completion or abort after the
baseline read. A turn finishing does not mark the session offline. Claude turn
lifecycle reporting is not yet supported; its token observations remain available.
For either client, add `--session-pid <coding-client-pid>` to observe its actual
process departure. The PID must be alive and the session log must verify at startup.
A confirmed process exit reports Client disconnected and ends the watcher. The
server marks the agent offline only while that runtime still owns its latest
presence and no other runtime reported recently. Newer MCP work, ambiguous process
access and missing lifecycle evidence retain normal presence expiry. PID reuse
can delay departure detection; it never triggers a guessed disconnect.
On supporting servers, native reporting discovers the agent's current active,
owned task without extra flags. This is observational only: it neither claims
work nor renews the discovered lease. With `--task <id> --lease <version>`, new turn activity includes the task only
after a successful watch confirmation. Failed or stale confirmations drop that
context. Session token totals stay unassigned; they span more than one task.
Reporting status includes Claude's explicit branch and successful Edit/Write/MultiEdit
filenames. Codex paginated logs can supply filenames through completed `FileChange`
items; only their explicit absolute change-map paths are read, never diffs, commands
or output. Both clients keep at most 50 repository-relative filenames (4 KiB total).
Failed edits, unknown event formats and paths outside the repository are excluded.
Changes after the baseline are queued for the website's Runner activity panel.
This requires a server version supporting workspace observations; older servers
reject the new event and pause reporting. Codex branch changes and files omitted
from its structured log remain unknown; the watcher never guesses from a shared checkout.
On supporting servers, Codex native subscription-limit events also update the
agent's allowance meter. Claude reports its five-hour and seven-day allowance
through the existing statusline relay when that client supplies `rate_limits`.
Context-window percentages are never treated as subscription allowance. Missing
or unsupported reports remain unknown; positive reports become stale after ten
minutes. A confirmed limit remains until its reported reset, then becomes unknown
until the next provider report. Only provider, window, remaining percentage,
observation time and reset time are stored; no account identifier is required.
An event-only watcher does **not** resume a desktop conversation. A connected
watcher means events are being collected, not that an agent is currently coding.
On supporting servers, `watch` marks its polls as passive: they refresh only the
watcher timestamp, not the agent's session presence or last tool. Recent accepted
native work observations refresh session presence; historical replay and waiting
events do not. Legacy supervisors retain their existing presence behavior. This
distinguishes a surviving watcher from an active session without treating a quiet
log or a finished turn as logout.
For unattended work, the operator must start a supported CLI worker or supervisor.
The supervisor saves pending events before moving its cursor and checks stop,
authentication and the supplied lease before replaying after restart. Failed
packets remain pending. Three ordinary failures pause dispatch; a recognized
approval denial pauses immediately. Repair the cause before `--retry-failed`.
Do not share state, remove active locks or start a supervisor inside a worker.
Verify that a stale lock's recorded process has exited before removing it.
## Reviews and branch cleanup
Projects can use independent-owner review or the host-selected **Personal team**
policy for distinct agents sharing one operator. Self-review and stale-head
approval remain invalid. Author/lead/host merge permission is a separate policy.
The agent merge tool cannot override readiness; only the human host can do that.
EhGI reserves each repository while merging and rechecks the actual base ref,
head, reviews, checks and authority. Automatic branch cleanup honors the project
setting and preserves branches needed by tasks, PRs or active agents. The merge
UI and `merge_merge_request` with `{"pr_number": 123, "action": "cleanup", "dry_run": true}` support preview; set `dry_run` to `false` to apply.
Request, commit and audit history remain available after branch removal.
Workers automatically check local housekeeping at idle and acknowledged-job
boundaries, once per minute in rotating batches of ten. The hub verifies the
exact job/fence and terminal task state before and after fetching the base.
Active leases/workspaces, uncertain receipts, replaced fences and incomplete
acceptance remain ineligible. The existing worker lock stays held throughout
cleanup. Local Git checks still preserve dirty, ignored, untracked and unmerged
work. No extra model calls are made, and remote refs and archived handoffs remain.
At most 100 receipts remain actionable. Replaced executions, absent branches and
overflow are recorded in `housekeeping-retained.jsonl`, with its count and name
saved in worker state. Their worktrees and source remain intact for inspection or
explicit cleanup. Origin checks repeat before fetch, client execution and cleanup;
a repository change pauses the worker instead of trusting another repository's
merge history.
Local managed worktrees can also be cleaned explicitly:
```sh
agent-collab-mcp cleanup --repo /absolute/checkout --state /absolute/private-worker-state --base main
agent-collab-mcp cleanup --repo /absolute/checkout --state /absolute/private-worker-state --base main --verify-github --apply
```
Fetch the base first. The default is a dry run; `--apply` acquires the worker lock
and removes only clean, verified merged `workforce/*` worktrees inside the
selected state directory. Optional `--verify-github` uses existing `gh` login to
prove squash merges. Local ref deletion checks its expected SHA. Unpublished,
dirty, ignored, untracked, outside or active work stays intact regardless of age.
This command leaves remote branches and enrollment evidence unchanged.
## Activity, usage and release verification
Structured activity goes to the hub without additional model calls. The
allowlist includes run/tool states and provider token counts; it excludes
prompts, source, tool arguments/results, paths and credentials. Reports are
batched and retried with stable IDs. Detailed activity stays outside model
context unless an assignment needs it; reading updates still consumes tokens.
Usage comes only from provider-reported counters. Codex samples its exact local
session checkpoint every five seconds while running, with bounded asynchronous
reads and one final sample after exit. One normalizer reconciles these counts
with stdout into cumulative totals for a fresh billing invocation, so the final
report does not charge interim tokens again. A successful fresh run can still
use final stdout when no checkpoint becomes available. Other adapters report
the structured usage their clients emit, often at turn completion.
Worker and supervisor reports also retain `native_session: {client, id}` when
Codex or Claude supplies a native session UUID. This correlation metadata does
not replace the existing billing session or event ID, reset cumulative counters,
or reset cumulative counters. On supporting servers, it identifies the shared
accounting fence across native watchers, workers, supervisors and statusline reports.
Fresh invocations never inherit an earlier session's identity when the current
client has not reported one. Update every collector before using native accounting:
old collectors and manual estimates without native identity cannot be correlated.
Reports without a verified native UUID retain their existing accounting behavior.
Readers check the exact session and workspace, file identity, append-only
content, counter consistency and deadlines. Explicit native resume subtracts a
pre-launch baseline and pauses on ambiguous accounting. The worker interleaves
usage delivery with budget, Stop and lease checks; a growing outbox cannot defer
those checks indefinitely. After the child exits, final delivery has a separate
five-second bound and keeps unacknowledged reports and stable IDs for retry.
Reporting failures never justify repeating completed coding work.
Unrecoverable or ambiguous usage persistently pauses further paid work in the
local `usageAttention` record. Restarting, resetting startup recovery or
re-enrolling does not clear it. An operator must reconcile the retained session
before clearing that record. Provider checkpoint delay, polling and delivery
latency still permit overshoot; this is not a strict spending ceiling. Passive
sampling adds no model calls, but more reports create additional hub requests.
Supervisor `--phase implementation|review|coordination` is optional; use it only
when the phase is known. Worker assignments supply their own phase.
The native trials used two Codex 0.153.4 clients with the scoped permissions above.
The later live-meter correction passed fixture tests and replayed all eleven
retained sessions' counters exactly; actual live disk-flush timing and native
explicit-resume acceptance remain to be tested. At the last provider probe,
Claude Code 2.1.139 was logged out and Gemini CLI 0.58.0 had no configured
authentication method.
Rollout still needs actual enrollment, concurrent tasks, questions, reviews,
merge, recovery and Stop checks across authorized clients.
`update-check` reads the public repository's latest stable GitHub release and
checks its tag and repository URLs. It never installs anything or upgrades an
active worker. No published release returns `unreleased`; a rate limit or failed
request returns `unavailable`, preserving the previous confirmed cache. Missing
releases and rate limits use a short backoff, respecting Retry-After up to one day.
To release, a maintainer first creates and pushes `vVERSION` at the reviewed
standalone main commit whose package.json contains VERSION. Manually dispatch
`connector-release.yml` on that same main commit with VERSION. The workflow checks
the existing tag against the clean checkout, runs tests and syntax checks, packs
the connector, and creates a draft GitHub release with the archive and its SHA-256
file. It downloads the archive again, compares it byte for byte, and rechecks the
tag before publishing. A failed verification leaves a draft. Existing releases
are never overwritten. Configure required reviewers on the `connector-release`
environment before the first dispatch. There is no automatic tag trigger or npm
publishing credential; `private: true` prevents accidental npm publication.
The `.tgz` asset is an installable package (`npm install -g ./downloaded-file.tgz`),
not the full development checkout. Use the matching GitHub tag checkout with
`npm ci` to run tests or develop the connector.
`node scripts/prepare-release.mjs VERSION` verifies source/tag identity without
publishing. Source export and passing local tests are not a published release.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues