Skip to main content
Glama

CCM — Codex-Compatible MCP

CCM is a Codex-inspired execution harness for MCP clients. It focuses on a small, stable coding/execution surface, persistent process sessions, Remote Workers, native sandboxing, bounded tool output, patching, and image reads.

CCM does not attempt to reproduce Codex's model loop or own the host application's conversation history. The MCP client remains the orchestrator; CCM owns the execution world.

Status

CCM is currently targeting v0.1 as its first public release.

  • Milestone 1 — Execution Core: implemented and regression-tested.

  • Milestone 2 — Environment + Remote Worker: implemented and regression-tested.

  • Milestone 3 — Editing (apply_patch, view_image): implemented and regression-tested.

  • Milestone 4 — Tool Architecture / Code Mode: implemented and regression-tested.

The v0.1 release gate is defined in PROJECT.md. v0.1 is intended to be directly publishable rather than a private prototype.

Related MCP server: cmd-exec-mcp

Architecture

MCP client
   |
   v
CCM Controller
   |- MCP HTTP server
   |- ToolRegistry
   |- Environment Registry
   |- Workspace Context Manager
   |- RemoteProcessManager / RemoteFileService
   '- WorkerHub
          |
          v
      Remote Worker
         |- native shell / filesystem semantics
         |- Worker-local Workspace Registry
         |- ProcessManager
         |- PTY
         |- native sandbox
         |- apply_patch
         '- view_image

Every execution environment uses the same Remote Worker protocol. The machine hosting the Controller is not a special execution backend: by default, npm start launches a normal Remote Worker locally and connects it through loopback.

Registered workspaces are owned by each Worker, not by the Controller. Entering or hot-registering a real project requires one-shot user approval and returns an opaque workspace_context. ccm.register_workspace already combines registration and entry; with create_if_missing=true, the same one-shot approval may also create the exact missing project directory before registration, so a new project does not need a separate shell mkdir approval followed by workspace approval. Normal development tools carry only the resulting context. Workspace contexts are persisted by the Controller and remain valid across Controller or Worker restarts. Worker-local projectless mappings are persisted as well, so a surviving projectless directory can be resumed after a Worker restart.

An environment does not expose a default workspace or default working directory to the MCP client. Worker bootstrap cwd is an internal/legacy runtime seed only; it is not a project-location hint, a default project, or the parent directory for newly created projects. CCM deliberately has no "Projects Root" policy: project placement comes from the user or the upper-layer orchestrator.

When no real project is selected, create an explicit projectless context with the deferred ccm.create_projectless_context capability through tool_search + exec. Pass environment_id to create it on a specific Worker, or omit environment_id to use the primary environment. Projectless workspaces are created under CCM_PROJECTLESS_ROOT (default: the user's Documents\\CCM directory) and do not require workspace approval. Do not register temporary directories, Documents, drive roots, or other arbitrary paths merely to obtain an execution context.

Identity and lifecycle terminology

CCM deliberately keeps transport identity, execution identity, process identity, and higher-level task state separate. Do not use the word "session" interchangeably for these concepts.

  • Host conversation / ChatGPT conversation: conversation state owned by the MCP client. CCM does not own it and must not assume a one-to-one mapping between a host conversation and an MCP session.

  • MCP session: the current CCM HTTP implementation's stateful Streamable HTTP protocol/transport session. It is created during MCP initialization, identified by the Mcp-Session-Id header, and used by the Controller to find the corresponding transport and protocol server. It may span multiple user turns, and a single host conversation may create more than one MCP session because of reconnects, fresh initialization, Controller restart, or other client lifecycle events. An MCP session is not a durable task, plan, workspace, or conversation identifier.

  • Process session (session_id): a live command/process continuation handle returned by exec_command and consumed by write_stdin. It identifies one running process session and is unrelated to Mcp-Session-Id.

  • Workspace context (workspace_context): an opaque logical execution-context identifier that binds a Worker and workspace/projectless root. Workspace contexts are persisted independently of MCP transport sessions and may remain valid across Controller or Worker restarts.

  • Approval (approval_id): a one-shot authorization record for one exact escalated operation or workspace entry attempt. It is neither an MCP session nor a workspace context.

  • Plan: a logical planning cycle, if/when Plan Mode is used. One MCP session may contain zero, one, or multiple plans. A persisted plan may outlive the MCP session that created it. A session-scoped "active plan" pointer is only a convenience for multi-turn continuity and must never redefine the MCP session itself as the plan identity.

Useful cardinality rules:

host conversation  -> 0..N MCP sessions
MCP session        -> 0..N process sessions
MCP session        -> 0..N logical plans
workspace_context  -> independent of MCP session lifetime
persisted plan     -> may outlive MCP session lifetime

When adding stateful features, choose an identity according to the feature's real lifecycle. Do not key durable intent solely by Mcp-Session-Id merely because it is convenient at the transport layer.

Direct MCP tools

Tool

Purpose

list_environments

Show connected execution environments, capabilities, and coarse effective filesystem read/write scope.

exec_command

Run a native shell command inside an existing workspace_context.

respond_to_escalation

Record an explicit user decision for a pending one-shot CCM approval.

write_stdin

Write to or poll a live process session returned by exec_command.

apply_patch

Apply a Codex-style patch inside an existing workspace_context.

view_image

Read and validate a bounded image inside an existing workspace_context.

send_file

Transfer a file from the Worker selected by workspace_context to the client.

tool_search

Discover deferred ToolRegistry capabilities without expanding the top-level MCP schema.

exec

Dispatch one or more nested registered capabilities, sequentially or safely in parallel.

wait

Resume a nested exec cell that yielded before completion.

Normal repository inspection, search, Git, builds, tests, and diagnostics should usually go through exec_command.

Core deferred capabilities

These are core CCM operations but intentionally stay off the top-level MCP schema. Discover them with tool_search and invoke them through exec.

Capability

Purpose

ccm.create_projectless_context

Create a temporary projectless context on a chosen Worker, or on the primary Worker when no environment is specified.

ccm.list_workspaces

Discover registered projects on one Worker without entering them.

ccm.select_workspace

Enter an explicitly selected registered project after user approval.

ccm.register_workspace

Register and enter an explicitly selected project directory after user approval; optionally create that exact missing directory with create_if_missing=true under the same approval.

ccm.plan_patch

Create or update one durable Plan using Codex-style patch syntax and an explicit opaque plan_id.

ccm.plan_read

Read, range-read, or search only the Plan identified by plan_id; reading does not change planning/implementation workflow.

Durable Plans

CCM provides durable Plan storage without implementing a Controller-side "Plan Mode" state machine. When a user explicitly asks to plan/discuss before implementation and persistence is useful, discover ccm.plan_patch / ccm.plan_read through tool_search and invoke them through exec.

ccm.plan_patch omits plan_id only for the first write. That call creates a Plan and returns an opaque UUID; later reads/patches carry that id explicitly, so Plan identity is independent of MCP transport sessions. Managed Plans are stored centrally under ignored Controller state at .state/plans/<plan_id>.md; no public list/delete/search-other-Plans capability is exposed and v0.1 does not automatically expire or garbage-collect Plan files.

Plan patches reuse the normal Codex-style patch grammar but target one virtual file only: creation uses *** Add File: plan.md, and updates use *** Update File: plan.md. The real .state path is never accepted as a tool argument. Keep the logical Plan current rather than append-only: rewrite or remove completed, invalidated, obsolete, or superseded items while preserving active constraints and unresolved decisions. Unless the user explicitly instructs execution/implementation, Plan work remains planning; imperative wording, completed inspection, workspace approval, registration approval, or sandbox escalation approval does not itself authorize implementation. ccm.plan_read is intentionally lifecycle-neutral so implementation can consult a Plan repeatedly without re-entering planning behavior.

ToolRegistry and Code Mode

CCM stores capability exposure as three independent surfaces:

  • Direct — included in MCP tools/list.

  • Deferred — omitted from the initial schema and discoverable through tool_search.

  • Code Mode — callable as a nested capability through exec.

Convenience states such as Direct, Deferred, CodeModeOnly, DirectModelOnly, DeferredModelOnly, and Hidden are derived from those surfaces rather than stored as one rigid enum.

The direct MCP surface is intentionally kept small and stable. New ordinary capabilities should default to the Deferred + Code Mode surfaces and be invoked through tool_search + exec. Add a new top-level Direct tool only when the capability is a common operational primitive or is fundamental to environment discovery, explicit approval, process continuation, or nested-tool discovery/dispatch. Workspace/context lifecycle tools intentionally remain Deferred.

Keeping ordinary additions off the Direct surface prevents routine feature work from changing the client's top-level MCP schema. In particular, adding a deferred capability should not require deleting and recreating the CCM integration in ChatGPT or another MCP client. Updating CCM server code may still require restarting the Controller and/or Worker processes so the new implementation is loaded; that is separate from recreating the client integration.

Do not promote a capability to Direct merely for convenience. Keep workspace/context lifecycle operations deferred, and prefer deferred ccm-extra.* or other namespaced capabilities for specialized workflows. The common operational file tools apply_patch, view_image, and send_file are intentionally Direct.

CCM deliberately does not embed a second JavaScript interpreter for Code Mode. The host application remains responsible for loops, branching, and data processing. CCM's exec/wait pair is a bounded structured dispatcher over ToolRegistry capabilities. state=completed is terminal. If nested dispatch has finished but an exec_command leaves a live process session, CCM returns state=awaiting_io with next_operation=write_stdin until those process sessions are continued separately.

ChatGPT Share conversation export

ccm-extra.chatgpt_share_export exports public ChatGPT Share conversations without BMG or browser automation.

Supported features:

  • mode=text: readable user/assistant conversation export.

  • mode=full: preserves all message records exposed by the Share payload, including system/tool records and message metadata.

  • ranch=active: follows the current Share branch when available.

  • ranch=all: exports all mapping nodes for debugging or archival.

  • Markdown and JSON output formats.

  • output_path is optional. Omitted or relative paths are written under the Git-ignored .cache/chatgpt-share-export/ directory; absolute paths are honored directly.

  • Non-text messages such as image-only messages are retained rather than silently dropped.

The exporter only recovers information present in the public Share payload. Information removed upstream by ChatGPT is not recoverable.

Bundled specialized capabilities

CCM ships optional Windows workflows ported from WCM. Specialized workflows remain deferred; ccm-extra.send_file is the direct file-transfer exception:

  • ccm-extra.send_file transfers an exact file from a selected CCM environment to the GPT client only when a user-facing handoff is actually needed (preview/download/upload to another tool). It returns an MCP resource_link; resources/read serves the exact file bytes from a bounded Controller-side bridge cache that is persisted under ignored .state/file-transfers and survives Controller restarts. By default the bridge has no time-based expiry and is bounded by CCM_FILE_TRANSFER_CACHE_BYTES; an optional positive CCM_FILE_TRANSFER_TTL_MS can impose a TTL. In ChatGPT, the associated MCP App materializes that resource once into a conversation-scoped ChatGPT file with library:false, persists its stable fileId in widget state, and requests a fresh temporary download URL on each click. This keeps the attachment usable after the tool turn finishes without saving it to the ChatGPT Library. Do not use send_file merely for model-side inspection when the file can be read or viewed locally in CCM; prefer local reading, view_image, command-line inspection, or temporary local previews to avoid unnecessary materialization/approval prompts. The transfer does not use BMG.

  • ccm-extra.quark_upload submits one or more files through that local Quark desktop session and can wait for verified completion.

  • ccm-extra.bilibili_download_dash downloads signed DASH video/audio URLs obtained from an authenticated browser session and remuxes them with ffmpeg -c copy.

Discover deferred specialized workflows with tool_search (for example, quark upload or bilibili) and invoke them through exec. send_file is available directly and is also callable through exec. Long uploads/downloads may return a live process session; continue that session with the top-level write_stdin tool.

The Quark helper reuses only the login state of the local Quark desktop client and does not export account credentials. The Bilibili helper intentionally leaves authenticated playurl discovery to the browser/BMG layer and accepts only the resulting short-lived signed media URLs; it does not export cookies or attempt to bypass account/quality restrictions.

Requirements

CCM requires Node.js 20 or newer and a Rust toolchain with Cargo.

On Windows, building the native execution helpers also requires Visual Studio 2022 Build Tools with the C++ toolchain and the Windows .NET Framework C# compiler. scripts/build-native.mjs locates these automatically when they are installed in standard locations.

Quick start

git clone <your-ccm-repository-url>
cd codex-compatible-mcp
npm ci
npm test
npm start

By default:

MCP endpoint:  http://127.0.0.1:18209/ccm/mcp
Health:        http://127.0.0.1:18209/ccm/health
WorkerHub:     127.0.0.1:18301

npm start builds the native helpers first, starts the Controller, then launches one local Remote Worker unless CCM_SPAWN_LOCAL_WORKER=0.

A standalone Worker can be started with:

npm run worker

The preworker script builds the native helper for the current platform first.

Windows scheduled-task operation

CCM includes public Task Scheduler helpers for both Controller hosts and standalone Remote Workers. They run hidden under the current Windows user, start at logon, use IgnoreNew to avoid duplicate instances, and configure Task Scheduler restart-on-failure behavior. Each supervisor also restarts its own child process if that child exits unexpectedly.

For a Controller machine that should run the Controller, its local Worker, and the OAuth sidecar as one service group:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\install-ccm-autostart.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\ccm-status.ps1

Remove it with:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\uninstall-ccm-autostart.ps1

For a standalone Windows Remote Worker, first create its ignored runtime config:

Copy-Item .\config\worker.env.example .\config\worker.env
notepad .\config\worker.env

Set at least CCM_WORKER_HUB_CONNECT_HOST; normally also give the Worker a stable CCM_ENVIRONMENT_ID. CCM_WORKSPACE is optional legacy/bootstrap configuration and is not a GPT-visible default project. Then install and inspect the Worker task:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\install-ccm-worker-autostart.ps1
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\ccm-worker-status.ps1

Remove it with:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\uninstall-ccm-worker-autostart.ps1

The Remote Worker supervisor reads config/worker.env itself, builds the native helpers on startup, and launches src/worker/agent.mjs. The Worker agent owns connection retry/reconnect behavior, so temporary Controller/network loss does not cause a process restart. config/worker.env, PID files, and supervisor logs are local runtime state and are not committed.

The Worker task installer resolves the current fully qualified Windows identity for both the logon trigger and task principal. This also supports machines whose hostname and local username are identical.

OAuth-protected public endpoint

For ChatGPT/plugin use, expose the OAuth sidecar rather than the raw Controller.

CCM's OAuth gateway follows the same deployment pattern proven in WCM:

  • OAuth 2.0 authorization code flow with PKCE S256

  • dynamic public-client registration

  • Protected Resource Metadata and Authorization Server Metadata

  • bearer access tokens, refresh-token rotation, and revocation

  • a local approval secret required at consent time

  • only the OAuth sidecar is exposed through HTTPS ingress; the Controller and WorkerHub stay private

Prepare a local deployment:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\ccm-enable-oauth.ps1 `
  -PublicBaseUrl https://your-machine.your-tailnet.ts.net
npm run public

The default local ports are:

OAuth sidecar: 127.0.0.1:18208
MCP Controller: 127.0.0.1:18209
WorkerHub:      127.0.0.1:18301

For Tailscale Funnel, apply the path routes after the sidecar is healthy:

powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\scripts\configure-ccm-funnel.ps1 -Apply

The public MCP resource is https://<host>/ccm/mcp. Runtime OAuth configuration is stored in ignored config/ccm.env; OAuth tokens/state and the local approval secret remain under ignored .state/.

Remote Worker example

The WorkerHub has no authentication or transport encryption in v0.1. Keep it on loopback or a trusted/private network.

On the Controller:

$env:CCM_SPAWN_LOCAL_WORKER = "0"
$env:CCM_WORKER_HUB_BIND_HOST = "0.0.0.0"
npm start

On a trusted remote Windows Worker:

$env:CCM_WORKER_HUB_CONNECT_HOST = "<controller-private-ip>"
$env:CCM_WORKER_HUB_PORT = "18301"
$env:CCM_ENVIRONMENT_ID = "build-windows"
$env:CCM_PERMISSION_PROFILE = "workspace-write"
npm run worker

The legacy CCM_WORKER_HUB_HOST variable is accepted as a fallback for both bind and connect configuration, but new deployments should use the explicit bind/connect variables.

Configuration

Variable

Default

Meaning

CCM_HOST

127.0.0.1

MCP HTTP bind host.

CCM_PORT

18209

MCP HTTP port.

CCM_MCP_PATH

/ccm/mcp

MCP endpoint path.

CCM_WORKER_HUB_BIND_HOST

127.0.0.1

Controller-side WorkerHub bind host.

CCM_WORKER_HUB_CONNECT_HOST

127.0.0.1

Worker-side Controller address.

CCM_WORKER_HUB_PORT

18301

WorkerHub TCP port.

CCM_SPAWN_LOCAL_WORKER

enabled

Set to 0 to prevent npm start from spawning a local Worker.

CCM_ENVIRONMENT_ID

OS hostname

Environment id advertised by a Worker.

CCM_WORKER_ID

environment id

Worker connection id.

CCM_WORKSPACE

current directory

Legacy/internal Worker bootstrap seed. It may seed Worker-local registry state for compatibility, but it is not a GPT-visible default workspace/project or a new-project parent.

CCM_PROJECTLESS_ROOT

~/Documents/CCM

Root used for automatically created projectless workspaces.

CCM_WORKSPACE_REGISTRY_FILE

<install>/.state/workspaces.json for the packaged Worker

Worker-local registered and projectless workspace registry.

CCM_WORKSPACE_CONTEXT_FILE

<install>/.state/workspace-contexts.json for the packaged Controller

Persistent Controller workspace-context registry.

CCM_PERMISSION_PROFILE

workspace-write

read-only, workspace-write, or full-access.

CCM_MAX_MCP_TOOL_RESULT_BYTES

2 MiB

Serialized MCP tool-result limit for ordinary results.

CCM_MAX_MCP_FILE_RESULT_BYTES

24 MiB

Serialized MCP result limit when returning an embedded file resource.

CCM_MAX_VIEW_IMAGE_BYTES

1 MiB

Maximum raw image size returned by view_image.

CCM_MAX_SEND_FILE_BYTES

12 MiB

Maximum raw file size returned by ccm-extra.send_file.

CCM_FILE_TRANSFER_TTL_MS

0 (disabled)

Optional positive TTL for persisted send_file bridge resources.

CCM_FILE_TRANSFER_CACHE_BYTES

64 MiB

Maximum total raw bytes retained in the persisted file-transfer bridge cache; oldest entries are evicted first.

CCM_WORKER_RECONNECT_MS

1000 ms

Worker reconnect delay.

Sandbox and platform support

Windows is the current fully supported restricted-execution platform.

read-only and workspace-write command execution use the CCM Windows native sandbox helper. The public environment-discovery surface intentionally does not expose internal bootstrap directories, raw permission profiles, or filesystem permission topology, but list_environments does expose a coarse filesystem_access summary derived from the current effective profile. In the current Windows restricted sandbox, read-only reports host read / no write, workspace-write reports host read / workspace write, and full-access reports host read / host write. Callers should therefore treat workspace boundaries and read boundaries separately: a read outside the selected workspace should be attempted normally when read_scope=host, without requesting escalation merely because the path is outside the workspace. PTY sessions use a Rust ConPTY backend aligned with the useful parts of Codex's current Windows PTY implementation. full-access runs with the Worker's normal host permissions.

Restricted command execution on Linux/macOS is not implemented yet and fails closed rather than silently running unsandboxed. A Linux/macOS Worker therefore currently needs CCM_PERMISSION_PROFILE=full-access for shell execution.

apply_patch enforces its own workspace-write boundary on the Worker, including real-path checks that reject symlink/junction escapes. exec_command can cross the command sandbox only through the one-shot approval flow below.

One-shot sandbox escalation

Restricted Workers support an explicit one-shot escalation flow for exec_command.

When sandbox_permissions=require_escalated is requested on a read-only or workspace-write environment, CCM does not execute the command immediately. It returns an approval_required result containing the selected environment, exact command, execution context, justification, a short-lived approval id, and a SHA-256 hash of the frozen execution intent.

The host should show that request to the user and wait. After the user explicitly approves it, the host calls respond_to_escalation with decision=approve, then retries the exact same exec_command with the returned approval_id. The grant:

  • is valid for five minutes,

  • can be consumed only once,

  • is bound to the environment, command, working directory, shell, and TTY mode,

  • runs that one command with full-access,

  • cannot be reused after execution,

  • does not create a persistent allow rule.

Changing the command or execution context requires a new approval. Denied and expired requests cannot execute.

This approval mechanism controls CCM's sandbox boundary; it does not grant Windows Administrator/UAC privileges. Also, MCP currently provides no cryptographic proof that an approval tool call originated from a human message. CCM enforces the frozen one-shot grant, while the ChatGPT/host interaction layer is responsible for calling respond_to_escalation only after an explicit user decision. A separately authenticated consent UI would be required for CCM itself to independently verify human presence.

Output and transport protection

CCM treats oversized output as a reliability and context-safety problem.

Command capture is bounded, model-facing command output has a token budget, live process reads are incremental, Worker protocol messages have a hard serialized-size ceiling, final MCP tool results have an absolute byte limit, and view_image checks file size before reading/encoding it.

If a hard transport limit would be exceeded, CCM returns or triggers a compact failure instead of attempting to send an oversized response.

MCP result compatibility

CCM returns standard MCP tool results directly. It does not add a custom result envelope such as resultType.

Text tools return normal content: [{ type: "text", ... }] results. view_image returns normal MCP image content and keeps its file metadata in result _meta, so multimodal clients can preserve the image block instead of reducing the result to structured-only output. Other tools may use structuredContent as the standard optional structured companion to content.

view_image is a common Direct operational tool and is also available through Code Mode for nested/batched dispatch. exec passes nested MCP image content through directly while compacting the duplicate structured result, so the model can receive the image without attaching an MCP Apps output template or creating a widget card for every image.

Security notes

Both the MCP HTTP server and WorkerHub bind to loopback by default. v0.1 does not provide authentication or TLS for the WorkerHub. Do not expose it directly to an untrusted network.

The Controller routes execution but does not execute repository commands itself. Shell, PTY, sandbox, patch, and image filesystem operations happen inside the selected Remote Worker.

Generated native binaries, Cargo build output, dependency directories, runtime state, logs, and local environment files are excluded from Git.

Development

npm ci
npm run build:native
npm test

The regression suite covers process exit semantics, PTY interaction, sandbox behavior, long-running sessions, oversized MCP results, multi-Worker routing, disconnect cleanup, patch preflight verification, workspace and symlink/junction boundaries, image validation, and MCP end-to-end calls.

See PROJECT.md for architecture decisions, Codex source-alignment notes, and the performance-first roadmap.

License

Original CCM code is licensed under the MIT License. See LICENSE.

Some native PTY source files are copied or derived from OpenAI Codex (Apache-2.0) and WezTerm (MIT). Their notices and applicable license text are preserved in THIRD_PARTY_NOTICES.md and LICENSES.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables MCP clients to spawn and control Codex CLI and Claude Code sessions on the host machine, with session management and filesystem access.
    4
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables repository-aware lifecycle management and controlled delegation of coding tasks to trusted worker harnesses via MCP, with execution isolation, recovery, and verified handoff.
    10 npm
    8
    Apache 2.0