[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-85833":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":17,"stars7d":18,"stars30d":18,"stars90d":16,"forks30d":16,"starsTrendScore":19,"compositeScore":20,"rankGlobal":10,"rankLanguage":10,"license":21,"archived":22,"fork":22,"defaultBranch":23,"hasWiki":24,"hasPages":22,"topics":25,"createdAt":10,"pushedAt":43,"updatedAt":44,"readmeContent":45,"aiSummary":46,"trendingCount":16,"starSnapshotCount":16,"syncStatus":14,"lastSyncTime":47,"discoverSource":48},85833,"codex-control-plane-mcp","aresyn\u002Fcodex-control-plane-mcp","aresyn","Durable MCP control plane for long-running Codex Desktop tasks","https:\u002F\u002Fpypi.org\u002Fproject\u002Fcodex-control-plane-mcp\u002F",null,"Python",219,4,2,7,0,9,13,31,67.9,"Apache License 2.0",false,"main",true,[26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],"agent-tools","agentic-workflows","ai-agents","automation","codex","codex-desktop","developer-tools","hermes","hermes-agent","long-running-tasks","mcp","mcp-server","model-context-protocol","openai-codex","openclaw","orchestration","python","2026-06-20 13:25:40","2026-06-20 18:55:09","[![MseeP.ai Security Assessment Badge](https:\u002F\u002Fmseep.net\u002Fpr\u002Faresyn-codex-control-plane-mcp-badge.png)](https:\u002F\u002Fmseep.ai\u002Fapp\u002Faresyn-codex-control-plane-mcp)\n\n# Codex Control Plane MCP\n\nEnglish | [Русский](README.ru.md)\n\n\u003C!-- mcp-name: io.github.aresyn\u002Fcodex-control-plane-mcp -->\n\n[![CI](https:\u002F\u002Fgithub.com\u002Faresyn\u002Fcodex-control-plane-mcp\u002Factions\u002Fworkflows\u002Fci.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Faresyn\u002Fcodex-control-plane-mcp\u002Factions\u002Fworkflows\u002Fci.yml)\n[![PyPI](https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fv\u002Fcodex-control-plane-mcp.svg)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fcodex-control-plane-mcp\u002F)\n[![Python](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fpython-3.11%2B-blue.svg)](https:\u002F\u002Fwww.python.org\u002F)\n[![License](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Flicense-Apache--2.0-blue.svg)](LICENSE)\n[![MCP](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FMCP-stdio-green.svg)](docs\u002FAPI_CONTRACT.md)\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fraw.githubusercontent.com\u002Faresyn\u002Fcodex-control-plane-mcp\u002Fmain\u002Fassets\u002Frepo_image.png\" alt=\"Codex Control Plane MCP\" width=\"100%\">\n\u003C\u002Fp>\n\nReliable Codex Desktop automation for long tasks.\n\n`codex-control-plane-mcp` turns Codex Desktop and `codex-app-server` into a\ndurable worker that an MCP client can drive safely. Send a task, get an\n`operationId` or `workflowId` right away, poll until the work finishes, approve\nPlan Mode when needed, then read the final report.\n\nThe server handles the awkward parts that thin wrappers usually leave to the\ncaller: app-server startup, thread and turn creation, retry safety, duplicate\nprompt protection, Plan Mode, approvals, local history, diagnostics, and repair.\n\nOpenClaw and Hermes are first-class clients, but the server is useful for any\nlocal orchestrator that needs Codex Desktop to do long-running work without\nholding one MCP call open for hours.\n\n## The short version\n\n```text\nMCP client \u002F orchestrator\n  -> submit a task or start a Plan Mode workflow\n  \u003C- receive operationId or workflowId immediately\n  -> poll status\n  -> answer approvals or approve the plan\n  \u003C- read final report, diagnostics, threadId, and turnId\n```\n\nThat gives you a simple contract:\n\n- no multi-hour MCP calls;\n- no duplicate Codex turns after a client retry;\n- no blind fire-and-forget task submission;\n- a local SQLite record of operations, workflows, turns, hooks, and diagnostics.\n\n## Why not just call Codex directly?\n\n| Capability | Thin Codex wrapper | Codex Control Plane MCP |\n|---|---:|---:|\n| Multi-hour tasks | blocking \u002F fragile | durable async operation |\n| Client timeout recovery | manual | retry-safe `client_request_id` |\n| Duplicate turn protection | no | active prompt detection |\n| Plan Mode workflow | human \u002F manual | pollable workflow state |\n| Approvals and questions | blocking \u002F opaque | pending interactions API |\n| Restart recovery | ad hoc | persisted operation state |\n| Diagnostics | logs only | health, diagnostics, repair tools |\n\nFor a more detailed decision guide, see\n[docs\u002FTHIN_WRAPPERS.md](docs\u002FTHIN_WRAPPERS.md).\n\n## Current support\n\n- Full live target: Windows with Codex Desktop and `codex-app-server`.\n- Linux and macOS: protocol-only checks for now.\n- Local-first: not intended to be exposed as a public network service.\n\n## Security model\n\nThis is a local-first control plane for trusted Codex Desktop environments.\n\nDo not expose it as a network service without authentication.\n\nRecommended first-run posture:\n\n- use `read-only` for untrusted repositories;\n- use `on-request` approval when testing new workflows;\n- Plan Mode never runs with a `read-only` sandbox. If a caller requests\n  `read-only`, MCP raises that turn to `workspace-write` and reports the\n  adjustment in status output;\n- keep `state\u002F`, `logs\u002F`, `.env`, and `.codex\u002F` private.\n\n## What it does\n\n- Durable async queue for Codex write operations.\n- Retry-safe `client_request_id` handling.\n- Active duplicate prompt detection.\n- SQLite leases and heartbeats for competing MCP processes.\n- Recovery after MCP restart during `thread\u002Fstart` or `turn\u002Fstart`.\n- Durable `turn\u002Fsteer` for adding context to an active turn without creating a second turn.\n- Durable `thread\u002Ffork` for branching an existing thread, with or without an initial message.\n- Plan Mode workflows: start plan, poll, approve, execute, read final report.\n- Plan Mode runtime floor: `workspace-write`, with `runtimePolicyAdjusted` in\n  status when MCP raises a `read-only` request.\n- Code review workflows through app-server `review\u002Fstart`, with polling and final report capture.\n- Structured final reports with `output_schema`.\n- Thread lifecycle tools for archive, unarchive, and pollable compaction.\n- Workflow goal sync with Codex Desktop thread goals.\n- Image and local image inputs for turns that start through `turn\u002Fstart`.\n- Pending approvals and questions exposed as pollable MCP state.\n- Turn interrupts by `threadId`\u002F`turnId`, `operationId`, or `workflowId`.\n- Runtime inventory for models, permission profiles, sandbox readiness, hooks, skills, provider features, account status, usage bands, rate-limit state, and supported app-server methods.\n- Health checks, diagnostics, issue analysis, and dry-run repairs.\n- MCP-owned hook history in SQLite for search, summaries, and fallback reads.\n- Redacted app-server progress journal for deltas, warnings, model reroutes, and token usage.\n- Structured MCP errors that automation code can branch on.\n\nWrite and control actions go through `codex-app-server`. The server does not\nmutate Codex internal SQLite databases or transcript files.\n\n## Install\n\nRecommended:\n\n```powershell\npipx install codex-control-plane-mcp\n```\n\nOr run directly:\n\n```powershell\nuvx codex-control-plane-mcp\n```\n\nFrom GitHub:\n\n```powershell\npython -m pip install \"codex-control-plane-mcp @ git+https:\u002F\u002Fgithub.com\u002Faresyn\u002Fcodex-control-plane-mcp.git\"\n```\n\nFor local development:\n\n```powershell\ngit clone https:\u002F\u002Fgithub.com\u002Faresyn\u002Fcodex-control-plane-mcp.git\ncd codex-control-plane-mcp\npy -m venv .venv\n.\\.venv\\Scripts\\Activate.ps1\npython -m pip install -e \".[dev]\"\npython -m pytest -q\n```\n\n## MCP client config\n\nAfter installation, generate a config:\n\n```powershell\ncodex-control-plane-mcp-admin init --state-db .\\state\\codex-mcp-state.sqlite3 --projects-root C:\\Users\\you\\Projects\n```\n\nMinimal stdio entry:\n\n```json\n{\n  \"mcpServers\": {\n    \"codex-control-plane\": {\n      \"command\": \"codex-control-plane-mcp\",\n      \"args\": []\n    }\n  }\n}\n```\n\nRun the MCP stdio server:\n\n```powershell\ncodex-control-plane-mcp\n```\n\nOr run it as a module:\n\n```powershell\npy -m codex_control_plane_mcp.server\n```\n\nThe old `openclaw-codex-mcp` and `openclaw-codex-mcp-hooks` commands remain as\ncompatibility aliases for one release line.\n\n## First setup\n\nThe admin helper can generate a fuller client config, install hooks, and run a\nprotocol smoke:\n\n```powershell\ncodex-control-plane-mcp-admin init --state-db .\\state\\codex-mcp-state.sqlite3 --projects-root C:\\Users\\you\\Projects\n```\n\nThe command prints a JSON block you can copy into an MCP client config. It does\nnot print secrets or private prompts.\n\nYou can also install only the Codex hooks:\n\n```powershell\ncodex-control-plane-mcp-hooks install --state-db .\\state\\codex-mcp-state.sqlite3\ncodex-control-plane-mcp-hooks status\ncodex-control-plane-mcp-hooks doctor\n```\n\nThe installer backs up `~\u002F.codex\u002Fhooks.json`, merges its handlers with your\nexisting hooks, stores `stateDb` as an absolute path, and writes prompts, visible\nagent progress text, final answers, and turn status into the MCP state DB. Tool\ncalls and command outputs are not recorded by default. Restart Codex after\ninstalling or changing hooks.\n\nFor turns launched through `codex-app-server`, the server mirrors the accepted\nprompt, visible assistant messages, and turn status into the same SQLite\nhistory. That keeps search and status reads useful even when app-server does not\nexecute user hooks itself.\n\n## Main workflows\n\nSubmit a durable task:\n\n```text\ncodex_submit_task\n  -> operationId\ncodex_get_operation_status(operationId)\n  -> queued \u002F running \u002F waiting_for_approval \u002F completed \u002F failed\n```\n\nUse the same `client_request_id` when a caller retries after a transport timeout.\nThe retry returns the existing operation instead of creating another turn.\n\nAttach screenshots or other image evidence:\n\n```text\ncodex_submit_task(\n  operation_type=\"start_chat\",\n  message=\"Analyze this screen.\",\n  input_items=[\n    {\"type\": \"localImage\", \"path\": \".\\\\screens\\\\error.png\", \"detail\": \"low\"},\n    {\"type\": \"image\", \"url\": \"https:\u002F\u002Fexample.com\u002Fscreenshot.png\", \"detail\": \"high\"}\n  ]\n)\n```\n\nImage inputs are accepted only for operation types that start a new turn:\n`start_chat`, `send_message`, `execute_plan`, and `fork_thread` with an initial\nmessage. MCP sends the path or URL to `codex-app-server`, but operation status\nand diagnostics return only safe metadata such as type, detail, size, extension,\nand hashes. Binary image content, raw URLs, and full local image paths are not\nstored in public status payloads.\n\nSteer an active turn:\n\n```text\ncodex_submit_task(operation_type=\"steer_turn\", thread_id=..., expected_turn_id=..., message=...)\n  -> operationId\ncodex_get_operation_status(operationId)\n  -> follows the target turn until completed \u002F failed \u002F interrupted\n```\n\nUse `steer_turn` only while the target turn is active. For a completed thread,\nuse `send_message` instead.\n\nFork a thread:\n\n```text\ncodex_submit_task(operation_type=\"fork_thread\", source_thread_id=...)\n  -> operationId\ncodex_get_operation_status(operationId)\n  -> completed, threadId=\u003CforkedThreadId>\n```\n\nStart work in the fork right away:\n\n```text\ncodex_submit_task(operation_type=\"fork_thread\", source_thread_id=..., message=...)\n  -> operationId\ncodex_get_operation_status(operationId)\n  -> follows the first turn in the forked thread\n```\n\nUse `client_request_id` for retry-safe fork requests. Without it, each call is\ntreated as a new fork request. `threadId` in operation status is the forked\nthread; the source thread is reported in `forkState.sourceThreadId`.\n\nManage thread lifecycle:\n\n```text\ncodex_archive_thread(thread_id)\n  -> completed\ncodex_unarchive_thread(thread_id)\n  -> completed\ncodex_start_thread_compaction(thread_id)\n  -> actionId\ncodex_get_thread_compaction_status(actionId)\n  -> running \u002F completed \u002F unknown_after_app_server_exit\n```\n\nArchive and unarchive are audit actions around app-server `thread\u002Farchive` and\n`thread\u002Funarchive`. They refuse to run while the thread has an active turn or a\npending interaction. Compaction uses its own lightweight `actionId` because\n`thread\u002Fcompact\u002Fstart` is asynchronous. Public `thread\u002Fdelete` is intentionally\nnot exposed.\n\nAsk for a structured final report:\n\n```text\ncodex_submit_task(operation_type=\"start_chat\", message=..., output_schema={...})\ncodex_approve_plan(workflowId, output_schema={...})\n  -> operationId \u002F executionOperationId\ncodex_get_operation_status(operationId)\ncodex_get_workflow_status(workflowId)\n  -> finalReport.text + finalReport.structured\n```\n\n`output_schema` is passed to app-server `turn\u002Fstart` and is tracked by a schema\nhash in status output. Object schemas must use the strict form required by Codex:\nset `additionalProperties` to `false`. MCP stores the final assistant message\nas readable text, then parses JSON object output into `finalReport.structured`\nwhen Codex returns valid JSON. Plain text still works and stays available in\n`finalReport.text`.\n\nMCP does not extract hidden chain-of-thought and does not store raw tool\npayloads or command output in final reports.\n\nDrive Plan Mode:\n\n```text\ncodex_start_plan_workflow\n  -> workflowId\ncodex_get_workflow_status(workflowId)\n  -> wait_plan \u002F review_plan \u002F execute_plan\ncodex_approve_plan(workflowId)\n  -> executionOperationId\ncodex_get_workflow_status(workflowId)\n  -> finalReport\n```\n\nPlan Mode has a runtime floor. The public default write policy is still\n`read-only` and `on-request`, but Plan Mode needs a writable workspace on\nWindows. If the caller or server default resolves to `read-only`, MCP sends\n`workspace-write` to `codex-app-server` and returns `requestedSandbox`,\n`effectiveSandbox`, and `runtimePolicyAdjusted` in workflow and operation\nstatus.\n\nMirror a workflow goal into Codex Desktop when the client has one:\n\n```text\ncodex_start_plan_workflow(goal=\"Review the migration plan\", goal_completion_action=\"clear\")\ncodex_get_workflow_status(workflowId)\n  -> threadGoal.syncState + threadGoal.currentGoal\n```\n\nMCP writes a thread goal only when the client passes `goal`. Managed goals use\n`clear` after completion by default. Use `set_complete` or `leave` when the goal\nshould remain visible after the workflow ends.\n\nRun a Codex code review:\n\n```text\ncodex_start_review_workflow(thread_id=..., target_type=\"base_branch\", base_branch=\"main\")\n  -> workflowId\ncodex_get_workflow_status(workflowId)\n  -> wait_review \u002F read_review_report\n```\n\nOr let MCP create a service thread for a local checkout:\n\n```text\ncodex_start_review_workflow(cwd=..., target_type=\"uncommitted_changes\")\n  -> workflowId\ncodex_get_workflow_status(workflowId)\n  -> reviewThreadId + reviewTurnId + finalReport\n```\n\nReview workflows do not write files by themselves. They run inside the selected\nCodex sandbox and approval policy. Use `client_request_id` when a caller may\nretry the start request after a transport timeout.\n\nHandle approvals and questions:\n\n```text\ncodex_list_pending_interactions\ncodex_answer_pending_interaction\n```\n\nStart diagnostics with:\n\n```text\ncodex_get_runtime_capabilities\ncodex_health_summary\ncodex_collect_diagnostics\ncodex_analyze_issue\ncodex_repair_issue\n```\n\nRepair actions default to `dry_run=true`.\n\nStatus and diagnostic tools also return `agentGuidance` and\n`agentGuidanceText` when MCP sees a blocker, failed state, stale run, pending\ninteraction, duplicate prompt, auth problem, rate limit, or unsafe recovery\nloop. Agents should follow `agentGuidance.instructions` before deciding to\nretry or stop. If `agentGuidance.loopGuard.allowed=false`, stop automatic\nrecovery, collect diagnostics, and ask a human. Do not create a new\n`client_request_id` after a timeout unless the guidance explicitly says to start\na replacement workflow.\n\nFor a broken Plan Mode workflow, use\n`retry_workflow_with_runtime_policy`. It creates a new workflow with the selected\nsandbox and approval policy, links it to the old workflow through\n`workflowRetryState`, and does not revive the old terminal turn.\n\n## Runtime capabilities\n\nUse `codex_get_runtime_capabilities` before orchestration or after reconnect. It\nstarts the MCP-owned app-server if needed, calls short best-effort inventory\nmethods, and returns a cached snapshot for five minutes.\n\nThe response includes:\n\n- model count, default model, hidden flags, input modalities, reasoning efforts, and service tier count;\n- permission profiles by `id` and `description`;\n- Windows sandbox readiness;\n- provider capabilities for web search, image generation, and namespace tools;\n- hook and skill counts without raw hook commands or absolute skill paths;\n- redacted account status, coarse usage bands, and operational rate-limit state;\n- supported app-server schema methods with a compact source, version, and hash.\n\nAccount inventory is safe to show to an orchestrator. It reports whether Codex\nis authenticated, the account and plan type, whether an email exists, whether\nusage data is available, and whether a rate limit or credits issue is visible.\nIt does not return raw email, account identifiers, credit balances, spend\nlimits, exact spend used, daily usage buckets, or exact token counts.\n\nIf one inventory method times out or fails, the tool still returns `ok=true`\nwith `runtimeCapabilities.status=\"partial\"` and a machine-readable warning in\n`methodResults`. Set `refresh=true` to bypass the cache. `codex_health_summary`\nshows a small `runtimeCapabilities` subset from the last collected snapshot and\ndoes not start app-server on its own. Pass `include_account=false` when a client\ndoes not need account, usage, or rate-limit status.\n\n## Progress journal\n\n`codex_get_turn_status` and `codex_get_operation_status` include a compact\n`progressEvents` block by default. It captures app-server-visible progress such\nas assistant text deltas, plan deltas, reasoning summary text, token usage,\nmodel reroutes, and warnings.\n\nThe journal helps with orchestration and troubleshooting. It does not extract\nhidden chain-of-thought. It also does not store raw tool payloads, command\noutput, or full unified diffs by default. Diff events are reduced to safe\ncounts, such as changed line count and diff size.\n\nUse `progress_events=0` when a client wants the older, message-only status\nshape. Use `progress_max_chars` to cap returned progress text.\n\n## Tool surface\n\nStable orchestration tools:\n\n- `codex_submit_task`\n- `codex_get_operation_status`\n- `codex_start_plan_workflow`\n- `codex_start_review_workflow`\n- `codex_get_workflow_status`\n- `codex_approve_plan`\n- `codex_list_pending_interactions`\n- `codex_answer_pending_interaction`\n- `codex_interrupt_turn`\n- `codex_archive_thread`\n- `codex_unarchive_thread`\n- `codex_start_thread_compaction`\n- `codex_get_thread_compaction_status`\n- `codex_get_runtime_capabilities`\n- `codex_health_summary`\n- `codex_collect_diagnostics`\n- `codex_repair_issue`\n\nCompatibility and read tools:\n\n- `codex_start_chat`\n- `codex_send_message`\n- `codex_execute_plan`\n- `codex_list_projects`\n- `codex_list_project_chats`\n- `codex_list_active_chats`\n- `codex_search_chats`\n- `codex_get_chat_status`\n- `codex_get_chat`\n- `codex_get_turn_status`\n- `codex_restart_app_server`\n- `codex_get_app_server_status`\n- `codex_get_diagnostic_logs`\n- `codex_analyze_issue`\n\nNew clients should use durable operations and workflows. Low-level write tools\nstay available for compatibility.\n\nSee [docs\u002FAPI_CONTRACT.md](docs\u002FAPI_CONTRACT.md) for schemas, error shape,\nstable tool groups, and versioning rules.\n\n## Result contract\n\nEvery tool declares an `outputSchema` and returns MCP `structuredContent`.\n\nSuccess:\n\n```json\n{\"ok\": true}\n```\n\nDomain or tool error:\n\n```json\n{\n  \"ok\": false,\n  \"error\": {\n    \"code\": \"CODEX_ERROR_CODE\",\n    \"message\": \"Human readable message\",\n    \"details\": {},\n    \"retryable\": false\n  }\n}\n```\n\nCall `codex_health_summary` on startup and reconnect. The `version` block\ncontains `serverName`, `serverVersion`, `contractVersion`, `toolSurfaceHash`,\nand stable\u002Fcompatibility tool lists.\n\n## Configuration\n\nConfiguration can come from environment variables or from a JSON file referenced\nby `CODEX_CONTROL_PLANE_MCP_CONFIG`. The old `OPENCLAW_CODEX_MCP_CONFIG` name is\nstill accepted as a fallback.\n\nCommon variables:\n\n- `CODEX_HOME`: Codex home directory. Defaults to `%USERPROFILE%\\.codex`.\n- `CODEX_PROJECTS_ROOT`: project root scanned by catalog and read tools.\n- `CODEX_ALLOWED_ROOTS`: semicolon-separated path allowlist.\n- `CODEX_PROJECTS_REGISTRY`: optional JSON project registry.\n- `CODEX_MCP_STATE_DB`: local MCP state DB.\n- `CODEX_CONTROL_PLANE_MCP_LOG`: log file path.\n- `CODEX_MCP_HOOK_HISTORY_ENABLED`: enables SQLite hook history. Defaults to `true`.\n- `CODEX_MCP_HOOK_HISTORY_MAX_TEXT_CHARS`: per-message hook capture limit.\n- `CODEX_KB_HISTORY_PROJECTS_ROOT`: optional legacy normalized KB history root.\n- `CODEX_BINARY_PATH`: optional explicit Codex binary path.\n- `CODEX_MCP_DEFAULT_SANDBOX`: default write sandbox. Defaults to `read-only`.\n- `CODEX_MCP_DEFAULT_APPROVAL_POLICY`: default write approval policy. Defaults to `on-request`.\n- `CODEX_MCP_DEFAULT_MODEL`: default Codex model passed to app-server.\n- `CODEX_MCP_DEFAULT_EFFORT`: default effort level.\n- `CODEX_MCP_MAX_IMAGE_INPUT_ITEMS`: max image attachments per `codex_submit_task`. Defaults to `10`.\n- `CODEX_MCP_MAX_IMAGE_INPUT_BYTES`: max bytes for one local image input. Defaults to `20000000`.\n- `CODEX_MCP_APPROVAL_RESPONSE_TIMEOUT_SECONDS`: pending interaction timeout.\n- `DEEPSEEK_ENV_PATH`: optional `.env` file for DeepSeek summary settings.\n- `DEEPSEEK_SUMMARY_ENABLED`: enables or disables remote summary calls.\n\nThe write policy values are defaults, not hard limits. A client call can pass\n`sandbox` or `approval_policy` explicitly when a trusted workflow needs a\ndifferent posture.\n\nPlan Mode is the exception to pure pass-through behavior: `read-only` is treated\nas too restrictive for Plan Mode on Windows and is raised to `workspace-write`.\nMore permissive per-call values, such as `workspace-write`, are passed through.\n\nExample:\n\n```powershell\n$env:CODEX_CONTROL_PLANE_MCP_CONFIG = Join-Path (Get-Location) \"examples\\codex-control-plane-mcp.config.json\"\n$env:CODEX_MCP_DEFAULT_SANDBOX = \"read-only\"\n$env:CODEX_MCP_DEFAULT_APPROVAL_POLICY = \"on-request\"\npy -m codex_control_plane_mcp.server\n```\n\nSee [examples\u002Fcodex-control-plane-mcp.config.json](examples\u002Fcodex-control-plane-mcp.config.json).\n\n## Reliability model\n\nThe server is built for common local orchestration failures:\n\n- MCP client timeout after task submission.\n- Repeated submit with the same `client_request_id`.\n- Repeated submit without an idempotency key but with the same active prompt.\n- MCP process restart between app-server `thread\u002Fstart` and `turn\u002Fstart`.\n- Two MCP processes sharing one SQLite state DB.\n- App-server exit while a turn is active.\n- Pending approval tied to an old app-server generation.\n- App-server or transcript gaps where hook history still captured the prompt,\n  visible agent text, final answer, and completion status.\n\nThese cases are stored in durable operation, workflow, turn, hook, and pending\ninteraction state. Terminal statuses are explicit.\n`unknown_after_app_server_exit` is not treated as success.\n\n## Safety\n\n- Live smoke prompts must include `MCP LIVE TEST \u002F DO NOT MODIFY FILES`.\n- Repairs default to `dry_run=true`.\n- Forced app-server restart can mark active turns as unknown or orphaned. Prefer\n  `restart_app_server_idle`.\n\n## Checks\n\nFast local checks:\n\n```powershell\npython -m pytest -q\npython -m compileall -q openclaw_codex_mcp codex_control_plane_mcp tests scripts\ngit diff --check\n```\n\nProtocol-only MCP smoke:\n\n```powershell\npython .\\scripts\\mcp_live_smoke.py --scenario protocol\n```\n\nSafe live smoke with real Codex Desktop\u002Fapp-server:\n\n```powershell\npython .\\scripts\\mcp_live_smoke.py --scenario safe-operation --cwd \u003CPROJECT_ROOT>\n```\n\nFull live regression:\n\n```powershell\npython .\\scripts\\mcp_live_smoke.py --scenario full --safe-restart --cwd \u003CPROJECT_ROOT>\n```\n\nSee [docs\u002FRELEASE_CHECKLIST.md](docs\u002FRELEASE_CHECKLIST.md). For public launch\npositioning, see [docs\u002FPUBLICATION_GUIDE.md](docs\u002FPUBLICATION_GUIDE.md).\n\n## Packaging\n\nBuild locally:\n\n```powershell\npython -m pip install build\npython -m build\n```\n\nThe wheel includes the MCP server, the hook installer, the admin helper, and the\nbundled Codex hook module.\n\nThe normal install path is:\n\n```powershell\npipx install codex-control-plane-mcp\n```\n\nor:\n\n```powershell\nuvx codex-control-plane-mcp\n```\n\n## Contributing\n\nRead [CONTRIBUTING.md](CONTRIBUTING.md) and [SECURITY.md](SECURITY.md) before\nopening issues that include diagnostics.\n\nGood GitHub topics for this repo:\n\n`python`, `mcp`, `mcp-server`, `model-context-protocol`, `openai-codex`,\n`codex`, `codex-desktop`, `agent-tools`, `ai-agents`, `developer-tools`,\n`automation`, `orchestration`, `agentic-workflows`, `long-running-tasks`,\n`openclaw`, `hermes`, `hermes-agent`.\n","`codex-control-plane-mcp` 项目为长时间运行的 Codex Desktop 任务提供了一个持久可靠的控制平面。其核心功能包括任务提交、状态轮询、计划模式审批及最终报告读取，通过将复杂的管理逻辑如应用服务器启动、线程创建、重试安全和本地历史记录等封装起来，简化了客户端操作。该工具特别适用于需要自动化执行长时间任务而无需保持单个 MCP 调用持续数小时的应用场景，例如使用 OpenClaw 或 Hermes 作为客户端的本地编排器。采用 Python 编写，并遵循 Apache License 2.0 开源协议。","2026-06-21 04:01:47","CREATED_QUERY"]