feat(codex): add isolated Cortex plugin package - #344
Conversation
cdeust
left a comment
There was a problem hiding this comment.
Reviewed the full diff (9 files, +256/-2) against the host manifests #341 also touched. Scope note: this PR is Codex-only — Gemini was already covered by gemini-extension.json; only its version is re-asserted here.
What holds
The .mcp.json isolation is the right invariant, anchored in a test. plugins/hypermnesia-mcp-codex/.mcp.json never at the repository root, and test_codex_plugin_is_confined_to_a_dedicated_subdirectory asserts not (REPO_ROOT / ".mcp.json").exists(). That is the 2026-06-12 root cause pinned down: a repository-root .mcp.json gets picked up by Claude Code as project-scoped config, where ${CLAUDE_PLUGIN_ROOT} is never substituted, giving -32000 Connection closed on a shadow duplicate. Regression-proofed rather than documented.
The "exact 10-tool lean profile" claim is verifiable, not decorative. LEAN_TOOL_NAMES in mcp_server/tool_profiles.py holds exactly ten names and is_tool_allowed returns tool_name in LEAN_TOOL_NAMES for the lean profile.
CI actually exercises the changed path. The added lines land in the mcp-host-config job ("Validate MCP host configurations"), which passed in 24s on run 30764132033. The job is gated on head.repo.fork == false; this is a same-repository PR, so it really ran. This is the job that exercises the change, not an unrelated fast green.
Claude non-regression is pinned. test_codex_package_does_not_weaken_the_primary_claude_plugin locks hooks, the custom agent, the python3 launcher.py command, and the absence of --profile on the Claude side.
What should be addressed before merge
1. The recommended path is never started
CI runs plugin marketplace add → plugin add → asserts installed and enabled. It performs no MCP handshake against this package. The "six real MCP lifecycle cases" in the PR description come from scripts/verify_mcp_hosts.py, which drives the installed console entry point (hypermnesia-mcp), not the uvx command line this plugin ships.
Net effect: the path the README promotes as recommended carries strictly less execution proof than the path it demotes to fallback. Installation is proven; startup is not.
Suggested fix: extend the job to spawn the plugin's exact command (uvx --from "hypermnesia-mcp[sqlite]" hypermnesia-mcp --profile lean) through one initialize + tools/list round-trip and assert the ten lean tool names — ideally with a cold UV_CACHE_DIR, so the measurement covers the first-run case real users hit.
2. The README contradicts itself on cold start
The fallback paragraph states, verbatim: "install the executable first so the first MCP handshake is not spent downloading the Python environment". The recommended path directly above it ships uvx --from "hypermnesia-mcp[sqlite]" with no pre-installation and no startup timeout.
Mitigating: gemini-extension.json already uses this uvx pattern, so this PR does not introduce it. Still, Codex enforces a startup timeout — the direct-config test on the line above pins startup_timeout_sec=30 precisely because of this — and the plugin .mcp.json format appears to offer no equivalent knob. A cold first launch overrunning the host default is the most likely failure mode of this change, and nothing currently measures it. Either the fallback's warning applies to the recommended path too and should be repeated there, or it is obsolete and should be dropped from both.
3. The documented command is not the tested command
README: codex plugin marketplace add cdeust/Cortex
CI: codex plugin marketplace add "$GITHUB_WORKSPACE"
The GitHub short-form is exercised nowhere. If Codex 0.146 does not resolve owner/repo for marketplace add, the first command in the install guide fails. Worth one explicit check, since it is the entry point of the documented flow.
4. Duplicated version gate (boy-scout)
tests_py/scripts/test_cross_host_manifests.py::test_cross_host_manifest_versions_match_the_release already asserts gemini-extension.json, server.json, manifest.json, and .claude-plugin/plugin.json against package.json. The new test_codex_version_matches_all_release_manifests re-asserts those same four plus the Codex manifest — two lists to keep in sync, one a strict superset of the other. Prefer either adding the Codex manifest to the existing test, or narrowing the new one to the Codex manifest alone.
Related: this brings the manually-bumped identity surfaces to ten. There is no bump script — the invariant is held by tests only — so a redundant list is a real maintenance cost, not a stylistic one.
5. Question on .mcpbignore
The diff adds plugins/hypermnesia-mcp-codex/, but plugins/cortex-deprecated (the v4.15.0 migration shim) is still not listed and therefore ships inside the 562-entry MCPB bundle. Pre-existing, but this PR touches the file — intentional, or an omission worth folding in here?
6. Question without a source
"authentication": "ON_INSTALL" in .agents/plugins/marketplace.json, for a local stdio server that authenticates nothing. Deliberate, or copied from a template? I have not read the OpenAI marketplace schema, so I am not asserting this is wrong — only that the value is unexplained.
None of this challenges the design: the isolation boundary is correct and the Claude contract is protected by test rather than by convention. The gap is execution proof on the promoted path (1–3), not architecture.
cdeust
left a comment
There was a problem hiding this comment.
Re-reviewed at 20a30c30. All six points are addressed, and the blocking one is addressed with execution proof rather than with an assertion about intent.
Blocking point — CI proved plugin INSTALL, never STARTUP
Resolved. The mcp-host-config step now does the three things that were missing:
- After
codex plugin add, it asserts throughcodex mcp list --jsonthat the registered server isuvxwithstartup_timeout_sec == 180.0. This is the part I could not take on faith: it proves Codex actually honours astartup_timeout_seckey declared inside a plugin.mcp.json, rather than silently dropping an unknown field. - It reads both the command and the timeout from the manifest itself (
mapfile+python -coverplugins/hypermnesia-mcp-codex/.mcp.json), so the gate cannot drift away from the shipped artifact the way a transcribed literal would. - It replays
verify_mcp_hosts.pyagainst that command under a freshUV_CACHE_DIR/UV_TOOL_DIRin$RUNNER_TEMP, so the bootstrap is genuinely cold.
Evidence, run 30765134054 / job 91542387856:
PASS codex-cli/lean: initialize + discovery + memory_stats (10 tools, 23.87s)
The recommended path now carries more execution proof than the fallback, which was the asymmetry I objected to. Two design choices worth noting as correct rather than incidental: the CI gate is stricter than the real constraint (the 180 s budget here covers initialize + tools/list + memory_stats, whereas Codex only bounds startup), and --allow-bootstrap-network is scoped to this one cold case, so the SOCKS regression fixture still guards every warm run — the 2026-06-12 -32000 RCA keeps its regression proof.
The other five
- README self-contradiction on cold
uvx. Fixed by hoistinguv tool installahead of both paths and stating the prerequisite once. The framing is accurate and does not overclaim:uv tool installpopulates the shared artifact cache that the plugin'suvx --fromthen reuses; it does not skip environment creation, and the text does not claim it does. marketplace add cdeust/Cortexdocumented but only$GITHUB_WORKSPACEtested. CI now exercises the documented form with--ref "${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}"; the log confirms resolution through the real marketplace path (installedRoot: ~/.codex/.tmp/marketplaces/cortex-codex-plugins). I had a concern about fork PRs, whereGITHUB_HEAD_REFwould name a branch absent fromcdeust/Cortex— it is void: the job already carriesif: ... head.repo.fork == false.- Duplicated version gate. Removed from
test_codex_plugin_contract.pyand folded intotest_cross_host_manifests.py, which is where the other five manifests are already checked. No orphan references to the deleted test remain, and all six manifests agree at4.17.2. plugins/cortex-deprecatedmissing from.mcpbignore. Added and asserted. The directory does exist on this branch, so the omission was real, not theoretical.- Unexplained
authentication: ON_INSTALL. The explanation holds and I verified the source rather than the link's existence: OpenAI's page states "Always includepolicy.installation,policy.authentication, andcategoryon each plugin entry" and shows"authentication": "ON_INSTALL"in its example. It enumerates values forpolicy.installation(AVAILABLE,INSTALLED_BY_DEFAULT,NOT_AVAILABLE) but documents no "no authentication required" value, so "schema-required timing metadata, not an added authentication mechanism" is the correct reading of what is actually published. The non-interactive install in CI is the empirical half of that claim.
Two cosmetic residuals, non-blocking
docs/codex-plugin.mdcites 110.46 s for the clean-cache run and 28.19 s for the warm one, both dated but with no environment stated, while CI measures 23.87 s cold onubuntu-latest. The gap is plausible network variance and neither figure is wrong, but a reader hitting 23.87 s in CI and 110.46 s in the doc has no way to reconcile them. Naming the local environment in one clause would close it. (coding-standards §8:measured on <date> in <environment>.)- The 28.19 s warm figure is local-only; CI exercises the cold path exclusively. That is the right choice — cold is the worst case — so this is a note, not a request.
Neither blocks. CI is green apart from Test (Python 3.12), still running at the time of writing.
Summary
cortex-codex-pluginsrepository marketplacehypermnesia-mcp-codexas an isolated, MCP-only native Codex pluginleanprofileuvxstartup a 180-second manifest ceilingAnthropic compatibility invariant
Claude Code remains Cortex's primary interface. This change does not modify
the Claude marketplace, manifest, hooks, custom agent, launcher, or complete
tool profile.
The Codex
.mcp.jsonis deliberately confined toplugins/hypermnesia-mcp-codex/. A repository-root.mcp.jsonis forbiddenbecause Claude Code would also discover it as project-scoped configuration
when Cortex itself is open, double-registering the server and potentially
shadowing the healthy Claude plugin process.
The new
.agents/marketplace and Codex sub-plugin are excluded from theAnthropic MCPB bundle.
Scope boundary
This PR provides local repository-marketplace installation for Codex and the
ChatGPT desktop Codex runtime. It does not claim ChatGPT web/public-directory
availability. A public plugin would require a separately designed production
HTTPS Streamable HTTP service, authentication, tenant isolation, domain
verification, operations, and privacy/legal review.
References:
Verification
cdeust/CortexGitHub shorthand,discovers, and installs
hypermnesia-mcp-codex@cortex-codex-pluginsuvxcommand completes initialize, tools/list, andmemory_stats with 10 lean tools in 110.46 seconds locally (macOS 26.5.1
arm64, uv 0.8.19) and 23.87 seconds on clean
ubuntu-latestCIlean profiles
pass
deprecated Claude migration shim
The broader local suite reached 7,043 passing tests. Fifty AST tests could not
write macOS's Tree-sitter cache under the sandbox; the two remaining hook
tests fail identically on the untouched checkout because the local specialist
configuration is absent. GitHub CI runs in a clean environment and is the
authoritative full-suite result.
The review follow-up also tightens the repository methodology: measured claims
must now record before/after values, the exact command, code revision,
environment, and experimental conditions.