Company OS MCP Server
Dedicated stdio MCP server for the Company OS HTTP API.
One-command companion connection
After the package is published, connect the current project to a model-free Company OS companion stack with one command:
npx --yes @hsm/company-os-mcp-server connect codex
# or
npx --yes @hsm/company-os-mcp-server connect claudecompanyos connect runs the installer and Compose definition embedded in that exact npm release, pulls the matching versioned Company OS image, starts Postgres and hsm_console in companion mode, verifies ledger health, and generates the project-scoped host configuration from companyos.integration.json. It does not fetch mutable files from the source repository. Use --no-start when the stack already exists and only host configuration should be regenerated. The harness-first command stays in the terminal by default; pass --open to open the optional Console. COMPANY_OS_IMAGE remains an explicit operator override for prerelease or private-registry testing.
No provider key or model setting is requested. The host supplies its own model. On first use, the MCP tools conduct the durable Passport flow:
company_passport_startcompany_passport_answercompany_passport_preparefor human reviewcompany_passport_answerto record the explicit authority/change-set confirmationcompany_passport_commission
Commissioning creates a distinct claude-code or codex company agent, grants eight bounded 30-day scopes, and writes owner/host credentials to private 0600 binding files under HSMII_HOME (default ~/.hsm-ii). Credentials are never written to .mcp.json, .codex/config.toml, command arguments, or MCP results.
It exposes Company OS tasks, memory, tool catalog workflows, run events, tenant-scoped trace queries, approval/HITL endpoints, and the Gestion Velora customer-intake/email handoff as MCP tools. Mutating or approval-sensitive tools require confirm=true by default.
company_os_trace_query is the read-only fleet-debugging seam. Ask for bounded rows from otel-v1-apm-span-*, then pass a returned run id to company_os_why or company_os_timeline for the authoritative ledger explanation. The MCP server calls the Company OS API rather than OpenSearch, so company scoping stays server-owned.
The MCP initialization response also publishes the mandatory operator contract: identify → understand → govern → simulate → authorize → execute → verify → record. Read-only work stops after grounded understanding; mutations must close the complete loop and leave independently verified task-trail evidence.
Console-session CLI login
companyos login
companyos status
companyos logoutcompanyos login opens Company OS Console with an OAuth-style Authorization Code + PKCE request. The existing HttpOnly operator and company-principal sessions stay in the browser. After the operator chooses a company and approves the requested scopes, Company OS creates a separate scoped CLI worker and returns a one-hour access credential plus a rotating refresh credential. Only the refresh envelope is persisted. On macOS it is stored in a mode-0600 file under ~/Library/Application Support/Company OS/ so CLI use does not trigger Keychain approval dialogs; Linux and Windows use their operating-system credential stores. No user access key is written to ~/.hsm-ii or a project file. Each authenticated CLI invocation rotates the refresh credential. companyos logout revokes every credential for that isolated CLI worker before deleting its locally stored refresh envelope. This CLI session flow does not create ~/.hsm-ii; the Passport/MCP host commissioning flow described above is a separate installation path.
Terminal chat
Use the Company OS AgentChat harness directly from a terminal, including a Tern shell tab:
company-os chatThis is a terminal client for the authenticated Company OS host. On the same machine as Zeron, it reads the active company identity and transport credential from the private local auth home, confirms the selected company with the host, then sends each turn directly to the host API on port 3847. A valid company principal or scoped CLI session is required; an old tenant binding can expire. The terminal prints the confirmed company before accepting a turn. Company OS owns the chat thread, selects the adopted model, runs its agent harness, and records the run and receipts in the company ledger. The terminal can close without discarding the host thread; the printed thread ID can be resumed later:
company-os chat --thread-id <thread-uuid>If the selected local company's principal expired, a signed-in owner or admin on an approved device can authorize a fresh local CLI session with company-os login --company <company-id>. Chat uses that session directly through the local host after authorization.
On another machine, the CLI uses a scoped remote login. That login requires company_os:tools and a non-loopback HTTPS Company OS endpoint:
./company-os login --console-url https://<company-os-host> --device
./company-os chatCompany OS performs model selection and provider execution on the host; no provider key is needed in the terminal process.
For a headless terminal, use companyos login --device, open the displayed Console URL on a signed-in device, and enter the one-time code.
Run
cd services/company-os-mcp-server
npm install
npm run build
HSM_COMPANY_API_BASE=http://127.0.0.1:3847 HSM_COMPANY_ID=<company-uuid> npm run mcpThe same transport and handler contract is available as a thin operator CLI. It prints canonical API JSON without building a second run-story projection:
npm run build
HSM_COMPANY_API_BASE=http://127.0.0.1:3847 HSM_COMPANY_ID=<company-uuid> \
npx company-os what <run-uuid>MCP operator commands
companyos mcp checks the selected CLI company's host, connector projection, and read-only stdio MCP handshake. companyos mcp --help lists the command tree; each command has its own --help without contacting the host.
companyos mcp status
companyos mcp doctor --client omp
companyos mcp tools --search task
companyos mcp connect omp
companyos mcp connectors list
companyos mcp connectors show github
companyos mcp connectors resources github
companyos mcp connectors prompts githubConnector reads use the host's company-scoped MCP connector routes. The list prints connector keys, provider, status, and redacted OAuth state; --json returns the canonical response. --quiet on the list prints connector keys. Resource and prompt responses identify live transport when one is attached; stored projections are shown otherwise.
An authorized operator can request companyos mcp connectors enable ID --confirm or disable ID --confirm. The host rechecks company authority and returns a governance receipt. --idempotency-key KEY makes retries explicit. A CLI confirmation never grants authority. OAuth and reconnect are omitted from this CLI until their live provider transport paths are proved end to end.
companyos mcp serve --stdio exposes the current CLI session's read-only tools to an MCP client. Its standard output carries MCP protocol data only. The generated OMP profile invokes this public command, so it does not depend on a package-internal JavaScript path. Rerun companyos mcp connect omp to refresh an older profile. companyos mcp doctor --client omp checks the local OMP version, plugin health, and profile even if the Company OS host is unavailable; its host and live MCP checks still require a valid CLI session.
For an OMP upgrade, run the offline compatibility smoke with the installed binary before trying a live Company OS session:
npm --prefix services/company-os-mcp-server run build
node services/company-os-mcp-server/scripts/omp-compatibility-smoke.mjs
COMPANY_OS_OMP_BIN=/path/to/omp2 node services/company-os-mcp-server/scripts/omp-compatibility-smoke.mjsThe smoke uses a temporary profile and dummy model credential. It checks OMP RPC startup, pinned adapter loading, and stdio MCP initialize/tools/list without a model prompt or company credentials. It does not verify the live host or governed broker. After login and host startup, companyos mcp doctor --client omp checks the real read-only handshake. Governed OMP runs retain their separate host-issued broker grant and receipt path.
The CLI exposes vocabulary, task lifecycle commands, paginated task/run events, ps, inspect, what, why, timeline, diff, preview, prepare-fork, and select-winner. The first daily-operator slice is:
company-os task list --state open
company-os task create --title "Investigate deployment" --confirm
company-os task run <task-id> --prompt "Collect evidence" --idempotency-key "task:<task-id>:run:1" --confirm
company-os events <run-id> --follow
company-os task cancel <task-id> --reason "Superseded" --confirmCompany branding and invoice rules are also available through the CLI. Every named company resolves to the Gestion Velora document baseline adapted to its identity; an operator can later store an approved, versioned profile override:
company-os company profile show
company-os company profile set --file PROFILE.json --dry-run
company-os company invoice-format show
company-os company invoice-format set --file INVOICE_FORMAT.json --confirmThe active profile is injected into task llm-context and is available to MCP clients through company_os_get_document_profile. See docs/company-os/document-branding-and-invoicing.md for the schema and override rules.
events --follow emits canonical execution-event objects as JSONL, advances with the server's last_seq, and drains once more after the canonical run story reports a terminal state. Task creation, execution, cancellation, fork preparation, and Gate selection require --confirm; API authentication, principal scoping, idempotency, spend, settlement, and receipts remain server-owned.
The approval inbox and receipt evidence commands are server-backed:
company-os approvals --status pending
company-os approval decide <approval-id> --decision approved --confirm
company-os receipt list
company-os receipt show terminal:<receipt-uuid>
company-os receipt verify terminal:<receipt-uuid>
company-os verify task <task-id>
company-os verify run <run-id>approvals returns the authenticated company's canonical approval rows and explicitly classifies pre-envelope rows as legacy_unverifiable. The decision command requires confirmation, refreshes that authoritative inbox, and binds the submitted choice to the server-stored presentation, subject, and request digests. It never accepts a caller-invented approval projection.
Receipt IDs are family-qualified (terminal:, run_event:, governance:, or spend:), so show can resolve the exact tenant-scoped source row. Terminal receipts are verified by recomputing the database-owned canonical hash and checking both chain linkage and the stored company head. Timeline families without a digest contract return verification_supported=false and never claim to be verified.
verify task and verify run use the same authenticated company principal to replay immutable lifecycle histories and compare them with their live projections. The responses include verified, has_drift, drift_kind, aggregate versions, and redacted evidence for each checked projection; missing history or a replay failure is never reported as verified.
Grok Remote MCP bridge
The package also includes a stateful Streamable HTTP MCP server for an xAI/Grok Remote MCP connector. It reuses the same Company OS handlers and operator contract as stdio; it is not a second agent runtime or policy engine.
Start it after the Company OS API is available:
cd services/company-os-mcp-server
npm run build
HSM_COMPANY_API_BASE=https://company-os.internal \
HSM_COMPANY_ID=<company-uuid> \
HSM_COMPANY_PRINCIPAL_TOKEN=<server-held-principal-token> \
HSM_COMPANY_PRINCIPAL_COMPANY_ID=<company-uuid> \
HSM_COMPANY_OS_REMOTE_MCP_TOKEN=<strong-random-grok-token> \
npm run start:httpThe endpoint is http://127.0.0.1:3850/mcp by default and exposes an unauthenticated GET /healthz. Put it behind an HTTPS reverse proxy before giving the URL to Grok. The inbound Grok token is accepted only as a bearer header and is never forwarded to Company OS; the server adds only its own API and company principal credentials. Every session is bound to the configured company, and a request containing another company_id is refused.
The default remote allowlist is read-only:
company_os_health, company_os_list_companies, company_os_get_company,
company_os_get_document_profile, company_os_dashboard, company_os_list_tasks,
company_os_get_task, company_os_list_agent_runs, company_os_run_story,
company_os_list_run_surfaces, company_os_trace_query, company_os_search_memory,
company_os_list_approvals,
company_os_show_approval, company_os_verify_task, company_os_verify_runOverride it explicitly with HSM_COMPANY_OS_REMOTE_MCP_TOOLS. Any tool outside the read-only admission set additionally requires HSM_COMPANY_OS_REMOTE_MCP_ALLOW_MUTATIONS=1; the existing Company OS confirmation, governance, approval, execution, verification, and receipt checks still apply. The remote boundary always runs in bound approval mode, whatever the local stdio setting is: a mutating call must cite a workflow approval that a different principal already approved (not expired and not yet used), and the remote session cannot decide approvals itself. A model-supplied confirm=true is not human approval.
Conceptual xAI Remote MCP configuration:
{
"type": "mcp",
"server_url": "https://company-os.example.com/mcp",
"server_label": "company_os",
"server_description": "Governed Company OS tasks, memory, runs, and verification",
"allowed_tools": [
"company_os_dashboard",
"company_os_list_tasks",
"company_os_get_task",
"company_os_list_agent_runs",
"company_os_run_story",
"company_os_search_memory",
"company_os_verify_task"
],
"authorization": "<same-grok-token-as-HSM_COMPANY_OS_REMOTE_MCP_TOKEN>"
}Use HSM_COMPANY_OS_REMOTE_MCP_HOST, ..._PORT, and ..._PATH to change the listener. Non-loopback binds must also set HSM_COMPANY_OS_REMOTE_MCP_ALLOWED_HOSTS; comma-separated origin allowlisting is available through HSM_COMPANY_OS_REMOTE_MCP_ALLOWED_ORIGINS. The bridge also enforces bounded JSON bodies and a per-source fixed-window request limit.
Result presentation contract
Every MCP tool call returns both forms of the same disposable projection:
structuredContentuses the checked-inhsm.company_os.result.v1envelope (schemas/company_os_result.v1.json). Itsdatafield contains the redacted canonical Company OS payload;outcome,governance,authority,bounds, andlinksmake state and next action explicit for an agent or rich client.contentis a Markdown fallback designed for chat hosts that ignore structured results. It leads with status, summary, verification, explicit evidence references, next action, and a Console link whenHSM_COMPANY_OS_CONSOLE_ORIGINis configured.
The envelope is not a second ledger or a second run story. A successful tool call is never treated as verification: the result says not_available unless the canonical payload explicitly reports verification. Waiting, approval required, governed refusal, infrastructure failure, and oversized payloads are distinct states. Oversized structured payloads become an explicit partial result with bounds.truncated=true; JSON is never cut mid-object. Console links are navigation only and grant no authority.
Environment
HSM_COMPANY_API_BASEorHSM_COMPANY_API_URL: Company OS API base. Defaults tohttp://127.0.0.1:3847.HSM_COMPANY_API_BEARERorHSM_COMPANY_API_TOKEN: optional bearer token.HSM_COMPANY_ID: default company UUID for tools that acceptcompany_id.HSM_COMPANY_PRINCIPAL_TOKEN(orHSM_PRINCIPAL_TOKEN): optional verified principal credential.HSM_COMPANY_PRINCIPAL_COMPANY_ID: optional explicit company binding for the principal credential; defaults toHSM_COMPANY_ID.OUROBOROS_ACTOR_IDorHSM_COMPANY_TASK_ACTOR: actor recorded for approval and HITL calls.HSM_COMPANY_MCP_APPROVAL_MODE:strictby default. Setpermissiveonly for trusted local automation.boundrequires every mutating call to cite a workflow approval already approved by a different principal, and refuses to decide approvals from the MCP session; the remote bridge always uses it.HSM_AI_CORPUS_INDEX: optional owner-only private Codex/Claude corpus index with local conversation vectors (mode 0600 preferred; 0400/0500/0700 are accepted when a mounted volume forces owner bits). Group/other access is always rejected. When absent,company_os_private_corpus_searchreportsavailable=false; private recall defaults to semantic-only retrieval and fails rather than silently claiming a lexical fallback is semantic.HSM_AI_CORPUS_SHA256: mandatory exact SHA-256 when an index is configured. Search fails closed if the current index digest differs.HSM_AI_CORPUS_BINDING_FILE: optional absolute path to a mode-0600 binding file containing onlyHSM_AI_CORPUS_INDEX=<absolute path>andHSM_AI_CORPUS_SHA256=<64 hex characters>. The repository launcher reads$HSM_COMPANY_OS_AUTH_HOME/private-corpus/active.envby default when neither corpus variable is already set; it parses only those two named values and never sources the file.HSM_AI_CORPUS_SEARCH_SCRIPT: optional absolute path to the fixed local search adapter for packaged layouts.HSM_AI_CORPUS_PYTHON: optional Python executable used with the fixed argument-only search adapter; defaults topython3.
Remote Grok MCP bridge settings:
HSM_COMPANY_OS_REMOTE_MCP_TOKEN: required inbound bearer token issued to the Grok connector.HSM_COMPANY_OS_REMOTE_MCP_TOOLS: optional comma-separated remote allowlist; absent means the read-only default above.HSM_COMPANY_OS_REMOTE_MCP_ALLOW_MUTATIONS: set to1only when intentionally adding non-read-only tools.HSM_COMPANY_OS_REMOTE_MCP_HOST: listener host; defaults to127.0.0.1.HSM_COMPANY_OS_REMOTE_MCP_PORT: listener port; defaults to3850.HSM_COMPANY_OS_REMOTE_MCP_PATH: MCP path; defaults to/mcp.HSM_COMPANY_OS_REMOTE_MCP_MAX_BODY_BYTES: maximum JSON request body; defaults to1048576.HSM_COMPANY_OS_REMOTE_MCP_MAX_REQUESTS_PER_MINUTE: fixed-window request limit per source; defaults to120.HSM_COMPANY_OS_REMOTE_MCP_ALLOWED_HOSTS: optional exact Host header allowlist for DNS-rebinding protection.HSM_COMPANY_OS_REMOTE_MCP_ALLOWED_ORIGINS: optional exact Origin header allowlist.HSM_COMPANY_OS_CONSOLE_ORIGIN: optional absolute HTTPS Console origin used for result deep links; links are omitted when unset.
The HTTP bridge requires HSM_COMPANY_ID, HSM_COMPANY_PRINCIPAL_TOKEN, and the matching principal company binding even for its read-only default. It can load those server-held credentials from the normal private Company OS binding files described above.
Lifecycle convergence proof
The lifecycle tools expose company-scoped task events, agent-run lease and recovery fields, approved recovery executions, Beads outbox settlement, durable projection health, and a snapshot-bound projection-proof scan. Follow each projection proof next_cursor unchanged until complete=true; every page is bound to the first page's snapshot_as_of, and zero_drift=true requires complete current evidence with matching source revisions and counts.
npm run proof:five-loop is a destructive local acceptance harness: it creates uniquely labelled governed proof Beads, kills both the verified hsm_console process and its verified Beads outbox sidecar once, and waits for supervised PID/instance rotation, automatic completion, recovery execution, projection convergence, and an unattended supervision soak. Run it only against a loopback, shell-supervised runtime backed by an isolated proof database/company, and set all three explicit gates:
HSM_FIVE_LOOP_ISOLATED_RUNTIME=1 \
HSM_FIVE_LOOP_ALLOW_MUTATION=1 \
HSM_FIVE_LOOP_ALLOW_PROCESS_KILL=1 \
HSM_FIVE_LOOP_SCOPE_LABEL=mcp-five-loop-proof-scope-<unique> \
HSM_HARNESS_CHECKPOINT_DIR=/private/tmp/<unique>/checkpoints \
HSM_HARNESS_TOOL_CHECKPOINT_DIR=/private/tmp/<unique>/tool-checkpoints \
HSM_COMPANY_OS_AUTH_HOME=/private/tmp/<unique>/auth \
HSM_BR_BV_BINDING_FILE=/private/tmp/<unique>/binding.env \
npm run proof:five-loopHSM_HARNESS_TOOL_CHECKPOINT_DIR is a different directory from HSM_HARNESS_CHECKPOINT_DIR, and both must exist. Without the tool one, every mutating worker tool — bash, company_tool_call, company_create_task — is refused with required mutation evidence store HSM_HARNESS_TOOL_CHECKPOINT_DIR is unset or blank, while read-only tools keep succeeding. The worker then looks alive (heartbeats, tool cycles, finalize_response) while accomplishing nothing, and the proof fails as an unexplained timed out waiting for automatic task completion. Preflight checks both.
Isolation requires overriding all five HSM_COMPANY_OS_*DATABASE_URL variables, not just HSM_COMPANY_OS_DATABASE_URL. The repo .env defines every lane against the shared database, so overriding one leaves the migration lane pointed at production — which is how an unpublished migration reached a shared database on 2026-08-30. The lane principals must also be the NOINHERITcompany_*_login roles: startup refuses a superuser LOGIN.
The launcher writes hsm-console.pid, beads-projection-sync.pid, and beads-outbox-worker.pid beneath the private auth home (or to their explicit HSM_*_PID_FILE overrides). The proof refuses to kill a PID unless its live command matches the expected owned process. Use an empty, unique company tenant; the harness refuses a tenant that already contains tasks, correlations, or runs.
The harness writes its durable readback artifact under artifacts/company-os-five-loop/; it never treats process logs as acceptance evidence. Each artifact also carries an independent acceptance envelope. It reports ok=true only when every durable phase is present, crash recovery rotated the lease generation while preserving run/session identity, the supervision soak stayed healthy, and the complete projection scan proved snapshot-bound zero drift. Partial-run failure metadata is sanitized before it is persisted.
The principal header is stripped from caller-provided headers and added back only for the exact HSM_COMPANY_API_BASE origin when the request company scope matches the configured principal company. Unscoped health/company-list calls, cross-company calls, and redirects never receive the principal token.
The MCP façade includes the short run-story/frame aliases ps, inspect, what, why, timeline, diff, preview, rewind, and replay. The steer alias is the governed live-run control: it requires strict confirmation and a principal token, and a refused delivery is never reported as successful. pause, signal, and attach remain explicit unsupported vocabulary entries.
Beads projection proof scan
Use company_os_list_beads_projection_proofs to independently verify the Company OS projection of the Beads ledger. Each row identifies one immutable Bead-to-task link and its latest evidence at the scan boundary, including the exact canonical_status, evidence digest, source revision, canonical snapshot and epoch digests, and whether the evidence was current, expired, or missing at snapshot_as_of. Every page repeats snapshot-wide integrity counters for missing/expired evidence, unknown status, malformed or mismatched digests/revisions, mixed source epochs, and expected-vs-observed link totals. zero_drift=true is computed by Company OS only when all of those checks pass.
The endpoint uses opaque keyset cursors rather than offsets. Start without a cursor, retain snapshot_as_of and total_links as scan evidence, then pass each next_cursor unchanged until complete=true. Every continuation remains bound to the first page's timestamp, so links or evidence appended during the scan cannot shift or duplicate pages.
Company OS terminal intent flows back to Beads through the supervised scripts/company-os-beads-outbox-worker.mjs sidecar. It requires the server-only executor bearer plus an active principal token bound to the same configured company, executes only scripts/br-governed.mjs, and settles only after two matching canonical Beads readbacks. A recovered executing attempt is read back and moved to reconciliation; it is never blindly re-executed.
Approval Model
The server does not invent a new approval ledger. It wraps existing Company OS endpoints:
company_os_operator_vocabulary is the read-only Phase 7 discovery call. It returns the server-authored hsm.company_os.operator_vocabulary.v1 contract, including whether each verb is read-only, governed, preview-only, or currently unsupported. MCP does not reinterpret those dispositions or turn an unsupported verb into a provider-specific command.
company_os_record_task_decisioncompany_os_dispatch_command(typed registry operations through the host command plane; keyed operations needidempotency_key, approval-gated ones needapproval_id)company_os_set_task_requires_humancompany_os_resume_tool_executioncompany_os_hitl_should_pausecompany_os_hitl_record_overridecompany_os_hitl_preferences
In strict mode, mutating tools return an approval_required error unless the caller passes confirm=true after explicit operator approval.
Voice Commander / Gestion Velora handoff
The phone-call bridge uses the existing Company OS customer and task ledger:
company_os_upsert_customercreates or updates a customer/prospect by a stableexternal_ref.company_os_create_customer_requestforcessource=phoneand usessource_refto make retries idempotent.company_os_promote_customer_request_to_taskpromotes that request into the canonical Company OS task and flat Bead routing contract.company_os_ingest_email_operator_itemplaces an approved call summary in the email queue aspending_draft.company_os_propose_email_replyadds a suggested reply; Company OS leaves itpending_approvalfor a separate human verifier and does not send it.
All five tools require confirmation in strict mode. Their schemas accept approved summaries, structured metadata, and evidence references. They do not accept raw transcript or recording parameters, and nested transcript, audio, credential, and secret fields are rejected before an HTTP request is made.
Tool Catalog Flow
Company OS enforces discover -> describe -> call for catalog tools:
company_os_discover_toolscompany_os_describe_toolcompany_os_call_tool
company_os_call_tool defaults to dry_run=true; non-dry-run calls require confirm=true in strict mode.
Remote HTTP MCP bounds and refusal receipts
Remote sessions are bounded by HSM_COMPANY_OS_REMOTE_MCP_MAX_SESSIONS and closed after HSM_COMPANY_OS_REMOTE_MCP_SESSION_IDLE_TTL_MS; request-rate windows are evicted after one minute and capped by HSM_COMPANY_OS_REMOTE_MCP_MAX_RATE_LIMIT_KEYS.
Refusal responses are authoritative and remain fail-open when the asynchronous governance receipt sink is unavailable. The server increments its refusal- receipt failure counter, invokes the failure observer when configured, and emits a structured error rather than silently discarding the failure.