agent-bridge-mcp
README.md
# Agent Bridge MCP
`agent-bridge-mcp` is a local Model Context Protocol (MCP) server that gives an MCP host one controlled way to delegate tasks among local coding-agent CLIs and the Manus API. It is intentionally not an agent orchestrator with ambient filesystem access: normal installs require configuration, project roots are allowlisted, the default execution mode is read-only, and caller-selected authority cannot exceed the configured ceiling.
## What is implemented in v0.3.0-rc.9
| Backend | Transport | Native resume | Filesystem control | RC9 release-evidence status | Authentication used by bridge |
| --- | --- | ---: | --- | --- | --- |
| Codex | local `codex` CLI; hosted model provider | Yes | `read-only`, `workspace-write`, or `full-access` | Required by both RC9 profiles | Codex CLI login |
| Claude | local `claude` (Claude Code) CLI; hosted model provider | Yes | Claude permission mode derived from the selected sandbox | Required by both RC9 profiles | **Claude CLI** login/OAuth or keychain; Claude Desktop/Cowork login is not used |
| Manus | Manus API v2 over HTTPS | Yes, by Manus task id | None. Manus is remote and cannot inspect or edit local files. | Disabled and not live-certified by the core profile; RC9 recognizes a Manus-required profile but refuses accepted export until its live artifacts are profile-input-bound | Credential file or `MANUS_API_KEY` |
| Gemini | local `gemini` CLI; hosted model provider | No | Cannot enforce read-only; it rejects that mode | No RC9 acceptance profile; enabled Gemini fails accepted export | Gemini CLI's own authentication |
Gemini and Manus are disabled by default. Manus must be deliberately enabled after its credential and account-capability acknowledgement have been configured. Remote prompt transmission is separately disabled by default and requires an agent/root/data-class allowlist, `allow_remote_egress=true`, a `data_classification`, and a consumed exact-scope `remote_egress` approval on every call. Every direct remote call also requires a distinct `paid_or_unknown_cost` approval because a caller-supplied zero cannot prove provider cost is zero. Both categories are always fresh, one-time records; reusable records are rejected before any provider launch. An optional `policy.cumulativeRemoteCost` breaker atomically reserves the **approved maximum** in whole USD cents before launch across every session. Unknown, zero, fractional-cent, over-cap, corrupt/missing-ledger, and concurrent-oversubscription cases fail before the provider call. Persisted reservations never replenish after success, error, timeout, cancellation, or process crash because the bridge cannot prove that an accepted request was not billed. Reservation intentionally precedes approval consumption, so a later local failure can conservatively burn budget without calling the provider. This is approved-cost accounting, not provider invoice reconciliation; abrupt OS/power-loss durability still depends on the host filesystem. `list_agents` reports reachability/authentication/capabilities and cooperative readiness; it is a health probe, not proof that a paid task can complete or that a remote agent can access the requested workspace.
### Capability-scoped release evidence
Schema-v2 release evidence validates the shared config against an RC9 release schema mirrored from the runtime config contract, then derives its profile from those exact bytes after verifying `configSha256`; the descriptor supplies only an `expectedProfile` guard and cannot select or waive the derived gates. `windows-local-core` requires Codex and Claude enabled, Gemini and Manus disabled, direct remote egress disabled, and an empty remote-agent allowlist. `windows-local-manus` recognizes the state where Manus and remote egress are enabled, only Manus is in the remote allowlist, and the account-default capability acknowledgement/profile is configured. RC9 deliberately refuses `--require-accepted` for that Manus profile until its live-canary artifacts are bound to the shared-config profile input; this prevents a disposable harness config from being presented as proof about the installed shared config. Ambiguous configurations fail closed. The report exports a sanitized capability projection—booleans plus the remote-allowlist count—and a digest bound to release ID, runtime SHA-256, and config SHA-256; it never exports raw config, credentials, roots, agent IDs from the allowlist, or the account-profile label. Any config-byte change invalidates the packet. A core-profile acceptance is not an offline claim—Codex and Claude CLIs still use hosted providers—and it must be described as **“Manus disabled; not live-certified.”** Legacy schema-v1 packets retain their original unconditional Manus gate and historical marker semantics and are never reinterpreted under schema v2.
Manus task references are accepted only when they match the provider's 22-character alphanumeric task-ID contract. After `task.create`, RC6 allows a bounded 15-second visibility grace: a `task.listMessages` 404 is checked against `task.detail` before it is classified. A detail-confirmed task whose messages remain unavailable is reported as `unknown` and resumable; only a task absent from both surfaces through the grace becomes `not_found` and non-resumable. Public provider-identifier metadata exposes only SHA-256 request correlations, never raw provider request IDs or native task IDs. Returned agent output can still contain user or project content and is not automatically safe to publish.
Before previewing approvals or consuming authority, the bridge performs a local-only Manus preflight: a non-empty configured credential must exist, account-default capabilities must be acknowledged, the model must be one of the supported Manus profiles, and the finalized prompt must fit a conservative 4,500 UTF-8 byte ceiling. This preflight makes no provider request. Ordinary continuation sends a new message only to a provider task whose persisted state is `stopped`. A `waiting` task must use the specialized waiting-action path. For a persisted `timed_out`, `aborted`, `error`, or `unknown` result, `reconcile_manus_task` requires remote-egress consent, data classification, and the current session revision, then performs GET-only provider polling without sending a user message. A local reconciliation timeout records the task as still unresolved and never sends a provider stop request; once reconciliation reaches `stopped`, ordinary continuation is available again.
Those durable per-call egress/cost approvals protect bridge-managed direct remote APIs such as Manus. Codex, Claude, and Gemini are local CLI processes but can send prompts and workspace-derived content to their hosted providers; their account, provider, and CLI policies are an outer trust boundary. `list_agents` reports `directRemoteApi` and `offMachineEgress` separately so a local executable is never mistaken for local-only processing.
On Windows, direct executables are spawned without a shell. Canonical static npm-generated `.cmd` shims are recognized only when they name one contained `node_modules` entry point; that entry is launched with the bridge's own Node executable, so prompts, models, roots, and extension arguments never pass through `cmd.exe`. Dynamic/custom `.cmd` files and all `.bat` launchers fail closed with `UNSAFE_WINDOWS_BATCH_SHIM`. Configure their underlying `.exe` or use a canonical static npm `.cmd` shim. This prevents batch metacharacters from escaping bridge root, sandbox, and approval boundaries.
## Install and configure
Requires Node.js 20+ and the CLIs you enable on `PATH`.
Choose the path that matches the job:
- **Develop or verify from source:** use the commands below and the source-development config.
- **Operate an installed release:** start with [Build, test, and package](#build-test-and-package), including its immutable Windows install/canary sequence, then follow [Creator Operations](docs/CREATOR_OPERATIONS.md). Do not point a client at source `dist` or directly at a versioned release directory.
```powershell
npm ci
npm run verify
New-Item -ItemType Directory -Force "$env:USERPROFILE\.agent-bridge" | Out-Null
Copy-Item config.example.json "$env:USERPROFILE\.agent-bridge\config.json"
```
The commands above create a **source-development** config at `%USERPROFILE%\.agent-bridge\config.json`. The template intentionally has an empty `allowedRoots` array and will not start until you replace it with one or more existing absolute project directories. An immutable installed release instead uses the shared config at `%USERPROFILE%\.codex\agent-bridge\config.json`, and every Codex/Claude registration must set `AGENT_BRIDGE_CONFIG` to that shared file while launching the stable shim. A config can otherwise be selected with `--config <path>` or `AGENT_BRIDGE_CONFIG`; an adjacent `config.json` next to the server is used only when present. Missing, malformed, or rootless configuration is rejected rather than falling back to an unrestricted directory. Do not let the source-development fallback and installed shared config silently diverge.
The runtime defaults are a 600-second timeout and `read-only` sandbox. `config.example.json` deliberately uses a 900-second sample timeout; it is not the runtime default. Sandbox precedence is: the per-turn request when supplied, otherwise `defaults.sandbox`; that requested/default authority is then constrained by both `agents.<id>.sandboxCeiling` and `policy.sandboxCeiling`, and the most restrictive result wins. A `workspace-write` ceiling permits a separately requested write turn but does not itself make writes the default. `policy.sandboxCeiling` defaults to `workspace-write` for compatibility, so legacy configs can still request writes but can no longer request `full-access`. Full access requires the config to say `"sandboxCeiling": "full-access"` explicitly. `agents.<id>.sandboxCeiling` can lower the limit for one backend. The sample `cumulativeRemoteCost.maxReservedCents` is a state-wide lifetime reservation ceiling for the current ledger; increasing it is an explicit operator action and there is intentionally no reset MCP tool. After the first reservation, an initialization marker makes deletion of only the ledger fail closed. A local OS user who can delete both the ledger and marker can reset this accounting boundary, so keep `stateDir` outside shared/workspace storage and protect its ACL. Omit the policy to disable that breaker. The bridge canonicalizes allowed roots and the working directory, then canonicalizes again immediately before launch, so a junction/symlink escape is rejected.
An MCPB package can opt into the same validator without installing a fake adjacent config by setting `AGENT_BRIDGE_BUNDLE_MODE=1` and providing `AGENT_BRIDGE_ALLOWED_ROOT`. Bundle mode defaults to read-only authority, Codex and Claude enabled, and Gemini, Manus, and remote egress disabled. The MCPB manifest may also provide `AGENT_BRIDGE_STATE_DIR`, backend `AGENT_BRIDGE_ENABLE_*` toggles, `AGENT_BRIDGE_DEFAULT_SANDBOX`, and `AGENT_BRIDGE_SANDBOX_CEILING`. Enabling remote egress additionally requires Manus plus `AGENT_BRIDGE_REMOTE_EGRESS=true` and one `AGENT_BRIDGE_REMOTE_DATA_CLASS`. Explicit `--config` or `AGENT_BRIDGE_CONFIG` selection always wins over bundle mode.
### Manus credential
Run the supplied setup script from PowerShell:
```powershell
.\scripts\setup-manus.ps1
```
It writes the key to `%USERPROFILE%\.agent-bridge\secrets\manus-api-key` with a user-only ACL. Enable `agents.manus`, set `credentialFile` to that path, and set `acknowledgeAccountDefaultCapabilities=true` plus a stable non-secret `accountCapabilityProfile` label only after reviewing the Manus account's enabled default skills. Agent Bridge sends empty per-message `connectors`, `force_skills`, and task references on creation and clears connectors on continuation, but Manus API v2 does not provide a bridge-enforceable switch that proves account-default skills are disabled. The acknowledgement records acceptance of that provider-side capability boundary; it does not grant local filesystem access or authorize a connector action. The provider endpoint, request-capability policy version, and account-profile label are bound into every remote approval envelope so a changed account/capability review requires new approvals. Do not put the key in source control or an MCP manifest. The Manus endpoint is restricted to HTTPS `api.manus.ai` (or its subdomains); the development override accepts loopback HTTP(S) only. Manus receives task text over its API and has **no local filesystem access**; provide relevant file contents or a remote-accessible artifact instead.
A key pasted into chat is exposed. Rotation is the recommended remediation. If the operator explicitly declines rotation, record that decision as an accepted residual risk, retain the key only in the ACL-protected credential file, and leave credential hygiene itself failed or acknowledged rather than calling it a pass.
## MCP operations
`get_creator_status` is the local-only creator overview. It aggregates runtime/config state, configured capabilities, approved-cost reservations, and a mutation-free bounded sample of session, approval, and workboard state without launching a CLI or contacting a provider. Its `scanned`, `truncated`, and `unreadable` fields are sampling evidence rather than unbounded totals; incomplete state forces attention. Backend health is intentionally separate through `list_agents`.
The server exposes sequential bridge operations (`list_agents`, `delegate_task`, `continue_session`, `handoff`, `list_sessions`, `get_session`, and pageable `get_turn_output`), passive `diagnose_install`, read-only `get_budget_status`, durable approval operations (`request_approval`, `decide_approval`, `list_approvals`), exact remote planning through `preview_turn_approval` and `preview_recommendation_approval`, GET-only `reconcile_manus_task`, narrow Manus waiting-action operations (`get_manus_waiting_action`, `preview_manus_confirmation`, `confirm_manus_action`), independent `collect_recommendations`, and cooperative workboard creation, execution, review, inspection, lifecycle, cancellation, retry, and item-approval operations. Sessions retain backend-native IDs internally for compatible resumes. When a different agent takes over, or a native resume is unavailable/incompatible, the bridge prepends a bounded, escaped transcript explicitly marked as untrusted context. A remote preview returns two different hashes: `prompt_sha256` identifies the finalized outbound prompt for comparison, while `payload_sha256` identifies the complete approval envelope, including model, sandbox, timeout, continuity/resume state, session revision, extension policy, provider endpoint, request-capability policy version, and non-secret account-capability profile. Approval records must use the envelope hash. Pass the preview's `session_revision` back on continuation or handoff so concurrent transcript changes require a new preview. Inline agent output is clipped; use the returned `output_ref` or `get_turn_output` to retrieve the complete persisted output in bounded pages.
### Manus waiting actions
Manus tasks can pause in a `waiting` state. Agent Bridge persists only the native task ID, event ID, and a known event type; provider descriptions and dynamic schemas are deliberately discarded because they can contain secrets, personal data, or new authority. The public tools never return the native task ID. Although Manus documents many confirmation types and may add more, this release allows only four fixed decisions:
| Manus event | Allowed bridge decision | Additional approval |
|---|---|---|
| `needConnectMyBrowser` | `browser_skip` | `browser_or_connectors` |
| `gmailSendAction`, `outlookSendMailsAction` | `email_save_draft` | `browser_or_connectors` |
| `videoGenerate` | `video_standard` | `paid_or_unknown_cost` with a positive bounded cost |
| `apiHighCreditNotice` | `high_credit_reject` | `paid_or_unknown_cost` fixed at zero USD |
Every decision also requires a fresh one-time `remote_egress` approval, an allowed data class/root, the exact preview digest, and the unchanged session revision. The confirmation preview exposes an execution envelope that binds the provider endpoint, connector/default-skill capability-policy version, and non-secret account profile. The adapter re-reads the newest live provider action before consuming either approval or reserving budget. Only after that revalidation succeeds does it commit authority, persist the attempted-confirmation record immediately before the non-idempotent `task.confirmAction` POST, and then require the response to say `ok=true`, `confirmed=true`, and return the same task ID. Accepted confirmation is persisted before the bridge resumes polling. Unknown actions, user questions, browser selection, actual email sending, premium video, credit acceptance, secrets, deploys, terminal commands, calendar/marketing actions, connector authorization, and persistent `global_allow`/`always_allow` grants fail closed. This intentionally narrower contract sits on top of the [Manus task lifecycle](https://open.manus.ai/docs/v2/task-lifecycle) and [`task.confirmAction`](https://open.manus.ai/docs/v2/task.confirmAction) APIs.
Start with [docs/CREATOR_OPERATIONS.md](docs/CREATOR_OPERATIONS.md). Its companion [threat matrix](docs/THREAT_MATRIX.md), [live acceptance checklist](docs/LIVE_ACCEPTANCE.md), [evidence conventions](docs/EVIDENCE_CONVENTIONS.md), [privacy boundary](PRIVACY.md), and [examples](examples/) define the supported creator workflow and the evidence required before promotion.
### Cooperative workboards
A workboard has explicit `active`, `paused`, `completed`, `canceled`, and `archived` lifecycle states. Items can declare kind, acceptance criteria, data/filesystem/network/capability requirements, inert typed artifact/evidence references, and a workflow approval gate. Lifecycle changes refuse live leases; retries clear outcomes without replenishing attempts or usage.
A workboard holds dependency-aware work items under `stateDir/workboards`. Persisted boards use an explicit schema version and are recursively validated on load/save. The original unversioned v0.3-dev shape migrates in memory when read and is persisted by the next locked save, avoiding an unlocked migration race. Unknown future schemas, corrupt records, and inconsistent status/submission/review combinations fail closed. Each item has an attempt/time budget, an ownership lease, an isolated bridge session, a submission, and an independent review. Execution and review wall-time/turn usage are accounted separately. The review-attempt limit is internally derived from `maxAttempts`; failed reviewer calls consume it, retain the submission for retry, and block the item when exhausted. `token_budget_hint` is advisory because backend token accounting is not comparable or consistently available. Separate ready items can run concurrently up to `maxParallel`, but every workboard execution and review is forced to `read-only` regardless of the bridge default. Strict cooperative turns suppress configured `extraArgs` and `extraEnv`, so those settings cannot override the read-only flags. A reviewer cannot be the agent that submitted the item. Only accepted submissions are included in the bounded integrator briefing.
Current workboards pass a local `cwd` and text, not a remote-accessible, hash-verified artifact bundle. Manus therefore cannot run or independently review a workboard item and is reported as not cooperative-ready for local-code evidence. Use it only through an explicitly approved direct remote delegation until an artifact-preparation workflow is implemented. Recommendation `brief` scope is deliberately isolated to backends that report no local-filesystem capability; Codex and Claude must use `workspace` scope, while Manus may review only the supplied brief. This boundary proves only that the backend cannot inspect the local workspace through Agent Bridge. It does **not** enforce provider-side read-only or no-side-effect behavior; Manus account-default skills remain an acknowledged external capability. The collection records `briefSha256` so the inline artifact can be identified without implying workspace access.
This development release deliberately does not allow cooperative write work. Per-session locks cannot prevent two separate agent sessions from editing the same files, so safe parallel writes require a later workspace-ownership design.
### Passive diagnostics
`diagnose_install` and `--doctor --json` report runtime/config identity, the config-content hash when readable, root-scope warnings, state size/session counts, sanitized backend status, and executable path-drift hints. They intentionally expose selected local paths: the runtime path, state path, configured/resolved executable paths, and roots named by scope warnings. They omit raw config bytes, agent environment values, credential values, raw provider/CLI details, prompts, and transcripts. Do not embed secrets in filesystem paths. A local authentication result of `unknown` is not considered usable. These commands probe enabled backends; use `scripts/inspect-install.ps1` for passive registration/process/ACL evidence without starting or delegating to an agent. Its `fallbackConfig.divergentRegistrationRisk=true` result means a bridge registration can read a different adjacent/state config than the installed shared config and is a cutover blocker. RC6 also recognizes valid single-quoted TOML strings in Codex registration evidence.
### Experimental daemon/proxy runtime
The source includes an experimental local-IPC daemon/proxy runtime built on the bounded framed-RPC codec and protocol/config-bound mutual HMAC handshake. It uses Windows named pipes or Unix domain sockets only—never TCP—and implements explicit lifecycle, exclusive endpoint binding, strict handshake state, request correlation, connection/in-flight limits, handler cancellation on disconnect, and clean shutdown. Importing or constructing it starts nothing; tests use disposable endpoints only. It is not wired into the MCP entrypoint or release package, so direct stdio remains the only supported runtime path.
On Unix, the runtime applies mode `0600` to the socket. Node's `net` API cannot configure or verify a user-only Windows named-pipe ACL or expose peer identity, so Windows security evidence truthfully reports that gap and provides a fail-closed authorization hook. Do not deploy the experimental daemon until a Windows ACL provisioning/verification layer and MCP routing adapter are implemented and reviewed.
Use the process diagnostic before adding it to an MCP host:
```powershell
node .\dist\agent-bridge.mjs --config "$env:USERPROFILE\.agent-bridge\config.json" --doctor
```
`--doctor` exits nonzero if any enabled backend is not usable. It reports configuration source, roots, sandbox, and backend health; it does not run a functional delegated task.
## Data, locks, and limits
Bridge state lives under `stateDir` (default `%USERPROFILE%\.agent-bridge`): plaintext sessions, workboards, approvals, cumulative-budget reservations, and their lock directories. Session and budget writes are atomic replacement writes; budget temp bytes are flushed before rename and the parent directory is synced where the platform permits. A running session holds a lock; another turn waits up to `sessionLockWaitMs`, then fails with `SESSION_BUSY`. The cumulative direct-remote ledger uses a separate token-owned lock so different sessions cannot oversubscribe it. Unlike normal session/workboard locks, the spend lock is never auto-reclaimed: a paused old owner could otherwise overwrite a newer reservation. If its process crashes, direct-remote launches fail closed until every bridge host is stopped and an operator removes only `stateDir\budget-locks\cumulative-remote-cost.lock`.
Session transcripts are plaintext JSON at rest. They can contain prompts, outputs, error tails, paths, and sensitive task context. Protect `stateDir`, do not put secrets in prompts, and treat `get_session` as disclosure of its stored transcript. `get_session` deliberately removes native backend IDs and metadata and limits each returned field, but it is not encryption or redaction. The bridge passes a bounded plaintext context summary between agents; truncation can omit earlier context, so critical decisions should be repeated in the current prompt.
## Build, test, and package
```powershell
npm run verify
node .\scripts\package.mjs
```
`npm run package` builds first; `npm pack` also builds through its `prepack` hook. The release command requires a checked-out Git commit, creates a fresh `.release-staging` directory, emits `agent-bridge-v<package-version>.mcpb`, and verifies that packaged `server/agent-bridge.mjs`, its source map, and the Windows operational scripts byte-for-byte equal the committed candidate inputs. The bundle includes `manifest.json`, the runtime, its source map, `operations/`, and `release-metadata.json`; every runtime and operational payload is SHA-256- and byte-count-pinned in release metadata. The operational set is deliberately narrow: readiness, the one-lock cutover, immutable-release rollback, passive inspection, client registration, and their shared safety modules. It refuses an existing output path and never modifies an installed MCP server. Do not install a development package over active hosts; use a new immutable directory and defer registration changes until running tasks finish.
The MCPB uses manifest schema 0.3 and host-provided `user_config`; it does not embed a mutable placeholder config. The packaging command reports both bundle and runtime SHA-256 values. Validate `manifest.template.json` with the official MCPB CLI before a release. On Windows, install and inspect an artifact without touching the active pointer:
```powershell
.\scripts\install-release.ps1 -BundlePath .\agent-bridge-v0.3.0-rc.9.mcpb -ExpectedBundleSha256 <reported-bundle-sha256>
$candidate = "$env:USERPROFILE\.codex\agent-bridge\releases\<release-id>"
& "$candidate\operations\inspect-install.ps1"
node .\scripts\canary-release.mjs --release-path "$env:USERPROFILE\.codex\agent-bridge\releases\<release-id>" --install-root "$env:USERPROFILE\.codex\agent-bridge" --expected-version 0.3.0-rc.9 --expected-runtime-sha256 <reported-runtime-sha256> --evidence-dir "<durable-private-root>\installed-canary"
node .\scripts\canary-windows-shim.mjs --release-path "$env:USERPROFILE\.codex\agent-bridge\releases\<release-id>" --install-root "$env:USERPROFILE\.codex\agent-bridge" --expected-version 0.3.0-rc.9 --expected-runtime-sha256 <reported-runtime-sha256> --evidence-dir "<durable-private-root>\windows-shim-canary"
```
The provider-disabled installed-release canary launches the absolute immutable runtime with disposable config/state/root, verifies all required MCP tools and diagnostic identity, then attempts fixed inert Manus and Gemini delegations. Both must fail at the disabled adapter registry with zero sessions and zero approvals; a credential, provider, or authentication error is not equivalent. The canary also proves the stable shim, shared config, and promotion marker did not change. The Windows shim canary runs the same installed runtime with a local mock CLI behind a canonical npm `.cmd` in a spaced path; it verifies runtime identity, exact hostile argv preservation, read-only delegation, no shell-injection sentinel, and unchanged stable files without calling a provider. Create new durable private evidence directories **outside** the stable install root. Provider-backed release tests accept an absolute `AGENT_BRIDGE_SERVER_PATH` plus required `AGENT_BRIDGE_INSTALL_ROOT`, `AGENT_BRIDGE_EXPECTED_VERSION`, and `AGENT_BRIDGE_EXPECTED_RUNTIME_SHA256`; they verify the runtime is exactly under that install's `releases\<release-id>\server`. Set `AGENT_BRIDGE_LIVE_REQUIRED=1` so source `dist`, authentication, or quota skips cannot be mistaken for a release pass, and retain each structured result as sanitized JSON.
The Manus harness is a two-stage, durable one-use transaction. Preview it with `node test/live-manus.mjs --evidence-dir <new-absolute-private-directory>`; preview performs only local identity/credential checks, creates a cryptographic nonce and pending ticket, and makes no Manus API or health call. Review the preview, then run the exact nonce-bound command it prints. Execution atomically consumes the ticket before bridge startup, approval elicitation, health probes, or paid work; replay fails. It clears ambient `MANUS_API_KEY` and `MANUS_API_BASE_URL`, requires exact output and stopped status, verifies the budget delta and both consumed approvals, and retains private config/state/work/result evidence instead of deleting it.
Ignored RC5/RC6/RC7/RC8 bundles and their `.release-staging` directories are historical artifacts only. They are not RC9 inputs and must never be promoted as the current candidate.
After promotion and restarted-client acceptance, create a schema-v2 descriptor from [the example](examples/evidence-export-descriptor.example.json) inside an operator-controlled evidence root and run `npm run evidence:release -- --descriptor <absolute-descriptor.json> --output-dir <evidence-root>\<packet-id> --require-accepted`. The output-directory basename must equal the packet ID. The exporter verifies the installed metadata, promotion marker, shared config, bundle contents, candidate hashes, derives the capability profile from the hash-verified config, and rejects an expected-profile mismatch, unsupported capability state, missing selected gate, or config/runtime drift. An accepted export atomically claims the same durable install cutover lock used by switch/cutover operations, then holds it through final marker/shim/runtime/config verification, packet rename, and parent-directory sync; an existing or stale owner fails closed and must not be deleted automatically. The exporter accepts input artifacts only from the canonical evidence root, rejects confidential/restricted data and overwrites, redacts narrative/provider-ID JSON fields even when private state was renamed, and scans JSON keys and values for Manus-native identifiers before emitting synchronized `evidence-report.json`, `evidence-report.md`, and `manifest.json`. Run `npm run evidence:verify -- --packet-dir <absolute-packet-directory>` to detect missing, extra, or changed files and validate the profile digest. The manifest is an integrity cross-check, not a signature against a malicious local editor. Protect the evidence root's Windows ACL separately. Promotion is provisional until the final accepted export succeeds. A blocked pre-promotion packet may be exported without `--require-accepted`; it is evidence, not acceptance.
Preview registration normalization for Codex, Claude Code, and detected Claude Desktop profiles with `<candidate-release>\operations\configure-clients.ps1`. It is dry-run by default, refuses active target processes or ambiguous registrations, and supports an exact-byte restore manifest for changed files. Do not use its standalone `-Apply` mode for a normal release cutover. Run release operations from the candidate's installed immutable directory, not from a mutable source checkout.
Release cutover is a deliberate maintenance-window operation, not an unattended watcher action. Fully quit Codex, Claude Code, Claude Desktop, and other MCP hosts, then run `<candidate-release>\operations\check-cutover-readiness.ps1`. It requires repeated empty samples across Agent Bridge nodes and known Codex/Claude host families and descendants. Use `<candidate-release>\operations\cutover-release.ps1 -ReleaseId <version+sha7>` for the actual one-lock registration-and-release transaction. First audit the state ACL: omitting `-ApplyStateAcl` is correct when it is compliant. If it is noncompliant, provide a new absolute `-StateAclBackupPath` outside both the state and install trees, obtain explicit authorization, then add `-ApplyStateAcl`. Successful ACL hardening is a separately committed, forward-only security improvement: later registration or promotion failure restores registrations/pointers but retains the hash-pinned ACL backup and does not reintroduce the weak ACL. `protect-state.ps1 -RestoreFrom <backup> -ExpectedBackupSha256 <lowercase-sha256>` is the explicit manual recovery path; its own partial mutation failure restores and verifies the pre-image automatically. Any existing fallback config whose canonical path or SHA-256 differs from the installed shared config blocks cutover before ACL mutation. The watcher may report readiness but must never invoke a mutation command.
Immediately after each candidate or rollback switch, before restarting a client, run the pointer-only stable-shim gate with the exact hashes returned by the reviewed switch:
```powershell
node .\scripts\canary-live-pointer.mjs --release-path <absolute-current-release-path> --install-root <absolute-install-root> --expected-version <exact-version> --expected-source-git-sha <reviewed-source-git-sha> --expected-runtime-sha256 <exact-runtime-sha256> --expected-metadata-sha256 <reviewed-metadata-sha256> --expected-manifest-sha256 <reviewed-manifest-sha256> --expected-stable-shim-sha256 <exact-shim-sha256> --expected-shared-config-sha256 <exact-config-sha256> --evidence-dir <new-absolute-private-evidence-directory> --profile strict
```
Use `--profile rollback-minimum` only for the exact historical `0.2.1+4785d63` rollback runtime; strict is limited to `0.3.0-rc.9`. Obtain the source Git, metadata, and manifest hashes from the reviewed installed/package record, not from an unreviewed live path. The gate validates all metadata-pinned immutable payloads, the manifest/runtime identity, exact marker/shim/config binding, and the sanitized `windows-local-core` projection. Through the stable shim it performs only MCP initialization and `tools/list`; it does not call `list_agents`, delegate to a provider, or create a session. It strips ambient Agent Bridge selectors and provider/credential overrides, permits enabled Codex and Claude, and requires Gemini, Manus, direct remote egress, and the direct-remote allowlist to remain disabled or empty. The new evidence directory must be outside the install root and must not already exist. Raw config, credentials, provider details, roots, and session contents are never copied into its evidence.
Before cutover, `scripts\rehearse-rollback.ps1` can install exact-hash candidate and prior bundles into a brand-new external fixture, switch candidate → prior → candidate, exercise the fixture stable shim and provider-disabled MCP canaries, and retain a hashed evidence manifest. It accepts no live install or client-registration path. The trusted switch primitive still requires every MCP host to be closed, and this disposable proof does not replace the post-cutover live rollback drill.
`<trusted-release>\operations\switch-release.ps1` is the lower-level release/rollback primitive. It verifies the target installed runtime, uses a refusing maintenance shim, writes the release marker before enabling the live shim, creates an exact rollback backup, and fails closed on active processes. Use the newest verified operational script bytes even when its `-ReleaseId` target is an older installed runtime. `protect-state.ps1` requires a nonexisting external `-BackupPath` for mutation and captures owner/DACL semantics without SACLs; inspect its target before using `-Force`.
See [HANDOFF.md](HANDOFF.md) for the release and rollback procedure and [SECURITY.md](SECURITY.md) for the security model.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues