Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "cortex-codex-plugins",
"interface": {
"displayName": "Cortex for Codex"
},
"plugins": [
{
"name": "hypermnesia-mcp-codex",
"source": {
"source": "local",
"path": "./plugins/hypermnesia-mcp-codex"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Developer Tools"
}
]
}
29 changes: 29 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,11 @@ jobs:
# the repository's existing release-toolchain pin.
node-version: "24"

- name: Install uv (pinned)
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
version: "0.11.3"

# Vendor parsers catch configuration drift that a generic MCP client
# cannot: Claude's custom plugin component path, Gemini's extension
# schema, and Codex's config.toml transport/timeouts. Versions and bytes
Expand All @@ -418,6 +423,30 @@ jobs:
"$cli_bin/codex" mcp list --json \
-c 'mcp_servers={cortex={command="hypermnesia-mcp",startup_timeout_sec=30,tool_timeout_sec=600,env={CORTEX_MEMORY_STORE_BACKEND="sqlite"}}}' \
| python -c 'import json,sys; servers={s["name"]:s for s in json.load(sys.stdin)}; c=servers["cortex"]; assert c["transport"]["type"]=="stdio"; assert c["transport"]["command"]=="hypermnesia-mcp"; assert c["transport"]["env"]["CORTEX_MEMORY_STORE_BACKEND"]=="sqlite"; assert c["startup_timeout_sec"]==30.0; assert c["tool_timeout_sec"]==600.0'
marketplace_ref="${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}"
"$cli_bin/codex" plugin marketplace add cdeust/Cortex \
--ref "$marketplace_ref" --json
"$cli_bin/codex" plugin list --available --json \
| python -c 'import json,sys; d=json.load(sys.stdin); expected=json.load(open("package.json"))["version"]; ps=d.get("available",[])+d.get("installed",[]); p=[x for x in ps if x.get("pluginId")=="hypermnesia-mcp-codex@cortex-codex-plugins"]; assert len(p)==1, p; assert p[0]["version"]==expected'
"$cli_bin/codex" plugin add hypermnesia-mcp-codex@cortex-codex-plugins --json
"$cli_bin/codex" plugin list --json \
| python -c 'import json,sys; d=json.load(sys.stdin); p=[x for x in d.get("installed",[]) if x.get("pluginId")=="hypermnesia-mcp-codex@cortex-codex-plugins"]; assert len(p)==1, p; assert p[0]["installed"] and p[0]["enabled"]'
"$cli_bin/codex" mcp list --json \
| python -c 'import json,sys; ss=[s for s in json.load(sys.stdin) if s.get("name")=="cortex"]; assert len(ss)==1, ss; s=ss[0]; assert s["startup_timeout_sec"]==180.0, s; assert s["transport"]["command"]=="uvx", s'
mapfile -t plugin_command < <(
python -c 'import json; s=json.load(open("plugins/hypermnesia-mcp-codex/.mcp.json"))["mcpServers"]["cortex"]; print(s["command"]); print(*s["args"], sep="\n")'
)
plugin_timeout="$(
python -c 'import json; print(json.load(open("plugins/hypermnesia-mcp-codex/.mcp.json"))["mcpServers"]["cortex"]["startup_timeout_sec"])'
)"
UV_CACHE_DIR="$RUNNER_TEMP/cortex-codex-cold-uv-cache" \
UV_TOOL_DIR="$RUNNER_TEMP/cortex-codex-cold-uv-tools" \
PYTHONPATH="$GITHUB_WORKSPACE" \
python scripts/verify_mcp_hosts.py \
--timeout "$plugin_timeout" --clients codex-cli --profiles lean \
--command-includes-profile \
--allow-bootstrap-network \
-- "${plugin_command[@]}"

test-windows:
name: Test (Windows, SQLite backend)
Expand Down
5 changes: 4 additions & 1 deletion .mcpbignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ deps/
# these files (scripts/, docker/) is already excluded above.
requirements/

# Claude Code plugin assets (not used by the MCPB / uv server runtime)
# Host plugin assets (not used by the MCPB / uv server runtime)
.claude-plugin/
.agents/
agents/
commands/
skills/
plugins/hypermnesia-mcp-codex/
plugins/cortex-deprecated/
scripts/
docker/
Dockerfile
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ adheres to [Semantic Versioning](https://semver.org/).

### Added

- **Native Codex local plugin packaging.** A dedicated
`cortex-codex-plugins` repository marketplace now exposes an isolated,
MCP-only Codex package backed by the published PyPI stdio server on the
exact 10-tool `lean` profile. Its 180-second startup ceiling is backed by a
clean-cache `uvx` lifecycle measured at 110.46 seconds locally (macOS 26.5.1
arm64, uv 0.8.19) and 23.87 seconds on `ubuntu-latest` CI. This is additive:
Claude Code remains the primary integration and keeps its complete profile,
lifecycle hooks, custom agent, marketplace, and installation path unchanged.
- **Hook-free MCP protocol and host-configuration gates.** CI now starts the
installed production stdio entry point under representative Claude, Gemini,
and Codex client identities, completes the MCP lifecycle for both the full
Expand All @@ -19,6 +27,8 @@ adheres to [Semantic Versioning](https://semver.org/).

### Changed

- Benchmark provenance now requires the date, environment, exact command, code
revision, and experimental conditions alongside before/after measurements.
- Claude's wiki-groomer agent now lives in a Claude-specific manifest path,
preventing Gemini CLI from auto-loading Claude-only agent frontmatter while
preserving the Claude plugin behavior and tool list.
Expand Down
15 changes: 9 additions & 6 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ separate **cortex-viz** MCP (reads this same store read-only).
are tracked as a follow-up (found 2026-07-14 during #114), not a
standard to add to.
- No invented constants: every hardcoded number carries a `# source:`
comment (paper, committed benchmark, or dated measurement). A number
without one blocks the diff in review.
comment (paper, committed benchmark, or dated measurement naming the
environment and conditions). A number without one blocks the diff in review.

## What NOT to do

Expand All @@ -103,13 +103,16 @@ separate **cortex-viz** MCP (reads this same store read-only).
Every change to the retrieval or memory system:

1. **No source, no implementation.** Every algorithm/constant/threshold
traces to a published paper, a committed benchmark, or a dated
measurement. No source → say "I don't know" and stop.
traces to a published paper, a committed benchmark, or a dated measurement
that names the environment and experimental conditions. No source → say
"I don't know" and stop.
2. **Verify sources, don't guess.** Read the actual paper; confirm its
experimental conditions match ours (small corpus, conversational
content, 384-dim embeddings) before reusing an equation or constant.
3. **Benchmark before commit.** Re-run the affected benchmarks; no
regression accepted. Results must be reproducible on a clean DB.
3. **Benchmark before commit.** Re-run the affected benchmarks; no regression
accepted. Record the before/after values, exact command, code revision,
environment, and experimental conditions. Results must be reproducible on
a clean DB.
4. **Audit trail.** Every module docstring cites its paper and equations;
`docs/provenance/paper-implementation-audit.md` stays current.

Expand Down
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,29 @@ Or add it to `~/.gemini/settings.json` directly:
}
```

**OpenAI Codex CLI** — install the executable first so the first MCP handshake is not spent downloading the Python environment, then register it:
**OpenAI Codex and ChatGPT desktop — native local plugin (recommended).** The
repository now carries an isolated Codex marketplace and an exact 10-tool
lean MCP surface. Claude Code remains the primary integration and retains its
automatic hooks, custom agent, full tool profile, and unchanged marketplace.
Pre-install the same published package once so the plugin's first `uvx`
handshake can reuse the local uv cache instead of spending its startup budget
downloading the Python environment. The bundled server also declares a
180-second startup ceiling, backed by a 110.46-second clean-cache launch
measured on 2026-08-02 on local macOS 26.5.1 arm64 with uv 0.8.19 (the clean
`ubuntu-latest` CI run completed in 23.87 seconds):

```bash
uv tool install "hypermnesia-mcp[sqlite]"
codex plugin marketplace add cdeust/Cortex
codex plugin add hypermnesia-mcp-codex@cortex-codex-plugins
```

Restart the ChatGPT desktop app and start a new task after installation. See
[the Codex plugin guide](docs/codex-plugin.md) for the host boundary and the
public-directory requirements Cortex deliberately does not claim.

**Direct Codex MCP configuration (fallback).** After the same pre-installation,
register the executable directly:

```bash
uv tool install "hypermnesia-mcp[sqlite]"
Expand Down
69 changes: 69 additions & 0 deletions docs/codex-plugin.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Cortex plugin for Codex

Cortex ships a native Codex package in an isolated repository subdirectory.
It points at the same Cortex product as the existing Claude Code plugin, but
the two packages deliberately offer different host integrations:

- **Claude Code is primary.** Its marketplace package keeps automatic hooks,
custom agents, the complete MCP tool profile, and the existing installation
flow.
- **Codex is additive.** Its MCP-only package starts the published PyPI server
over local stdio with the exact 10-tool `lean` profile. It installs no
lifecycle hooks, skills, apps, or agents and does not alter the Claude
package.

The Codex `.mcp.json` lives under `plugins/hypermnesia-mcp-codex/`, never at
the repository root. This preserves Cortex's Claude contract: Claude Code
must not discover a second project-scoped MCP server when this repository is
the active working directory.

## Install from the repository marketplace

Add the Cortex repository marketplace and install the plugin:

```bash
uv tool install "hypermnesia-mcp[sqlite]"
codex plugin marketplace add cdeust/Cortex
codex plugin add hypermnesia-mcp-codex@cortex-codex-plugins
```

Restart the ChatGPT desktop app and start a new task so Codex loads the new
plugin components. The plugin uses `uvx`, so `uv` must be available on `PATH`.
The preliminary `uv tool install` is deliberate: it downloads the published
package before Codex's startup window, allowing the first plugin handshake to
reuse uv's local artifact cache.

The bundled server declares `startup_timeout_sec: 180`. This is a bounded
startup ceiling, not a delay. On 2026-08-02, a local macOS 26.5.1 arm64 run
with uv 0.8.19 and clean `UV_CACHE_DIR` and `UV_TOOL_DIR` completed
`initialize`, `tools/list`, and `memory_stats` in 110.46 seconds with exactly
ten lean tools. A follow-up on the same machine after the tool installation
completed the same contract in 28.19 seconds. The clean `ubuntu-latest` CI
runner completed it in 23.87 seconds; CI reads the command and timeout from the
manifest itself.

The bundled MCP command is equivalent to:

```bash
uvx --from "hypermnesia-mcp[sqlite]" \
hypermnesia-mcp --profile lean
```

This is a local plugin. It does not make Cortex available to ChatGPT web and
does not expose the local memory database over the internet.

The repository-marketplace schema requires both `policy.installation` and
`policy.authentication`. Cortex uses the documented `ON_INSTALL` value. This
is marketplace timing metadata, not an added authentication mechanism: the
local stdio server declares no credentials or remote endpoint, and the
non-interactive install is exercised in CI. See OpenAI's
[marketplace metadata contract](https://developers.openai.com/plugins/build/plugins#marketplace-metadata).

## Public directory boundary

A future hosted Cortex integration is a separate security and product scope.
Public submission requires a stable HTTPS MCP Streamable HTTP endpoint,
authentication and per-user or per-organization isolation, reviewable tool
metadata, domain verification, operational monitoring, and the applicable
privacy and legal material. None of those remote-deployment claims are made by
this local package.
40 changes: 40 additions & 0 deletions plugins/hypermnesia-mcp-codex/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "hypermnesia-mcp-codex",
"version": "4.17.2",
"description": "Cortex persistent local-first memory for Codex, with Claude Code remaining the primary automatic integration.",
"author": {
"name": "Clement Deust",
"email": "admin@ai-architect.tools",
"url": "https://github.com/cdeust"
},
"homepage": "https://github.com/cdeust/Cortex/blob/main/docs/codex-plugin.md",
"repository": "https://github.com/cdeust/Cortex",
"license": "MIT",
"keywords": [
"memory",
"mcp",
"codex",
"claude-code",
"local-first"
],
"mcpServers": "./.mcp.json",
"interface": {
"displayName": "Cortex Memory",
"shortDescription": "Persistent local memory for Codex",
"longDescription": "Use Cortex's focused local-memory tools from Codex. Claude Code remains the primary integration, with automatic lifecycle hooks, custom agents, and the complete tool profile.",
"developerName": "Clement Deust",
"category": "Developer Tools",
"capabilities": [
"Persistent project memory",
"Decision and correction recall",
"Local-first storage",
"Memory inspection"
],
"websiteURL": "https://github.com/cdeust/Cortex",
"defaultPrompt": [
"Recall the decisions relevant to this repository.",
"Show what Cortex remembers about this project.",
"Store the durable lesson from this task."
]
}
}
15 changes: 15 additions & 0 deletions plugins/hypermnesia-mcp-codex/.mcp.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"mcpServers": {
"cortex": {
"command": "uvx",
"args": [
"--from",
"hypermnesia-mcp[sqlite]",
"hypermnesia-mcp",
"--profile",
"lean"
],
"startup_timeout_sec": 180
}
}
}
Loading