Skip to content

Measure MCP catalog costs in Codex ​

Use actual harness usage to evaluate catalog changes. A tools/list JSON byte count measures transport size. It does not establish how many tokens a client submits to a model, whether it defers schemas, or the total cost of an analysis. The pinned Codex observations include actual loading controls, an unavailable-host negative control and a completed real-package pilot.

Run a controlled loading comparison ​

Build the selected source checkout with the pinned Node and npm versions first:

sh
npm ci
npm run build:cached
npm run eval:mcp-catalog -- --model gpt-6.1-sol \
  --output "$HOME/.cache/rea-catalog-run" --repetitions 3 --plan

Remove --plan to execute the matrix. This makes real model requests using the local Codex authentication. The output directory must not already exist. No account configuration is changed. The runner copies only authentication into an external disposable profile and removes that profile after each trial. Execution stays outside both source checkouts even when results are saved inside one, so ancestor repository instructions and skills do not pollute the trial. The npm entrypoint holds the driver's artifact lock throughout the matrix. A selected external checkout has its own lock, so the matrix also pins one runtime fingerprint and binds its catalog receipt to that manifest. Freshness checks stop further model calls if the runtime changes between trials. Each trial's before/after fingerprints must match the matrix pin; different builds never form a valid pair. Matrix admission/freshness audits sit outside individual guarded trial resource measurements. Do not rebuild the selected runtime concurrently.

This lane requires Linux, Python 3, a working user systemd manager with cgroup v2, and an installed Codex CLI supporting the recorded flags. It reuses the existing resource observer: one CPU, 4 GiB hard memory limit, 3 GiB early stop, no swap, and a 192-task ceiling. Runs are sequential. Unsupported clients, resource stops, failed startup, missing usage, and unverified cleanup remain failed measurements. They do not become zero-cost successes.

Trials disable account apps and plugins explicitly. A fresh CODEX_HOME alone does not prevent account-connected tools from appearing in the client executor catalog. For a deliberate mixed-catalog investigation, run agent-trial.py with --include-account-tools; keep those results separate from REA-only trials. The settings receipt records the same feature policy written to Codex config.

Each repetition compares no server, all REA tools, and a client-selected subset (binary_session by default), in the supported client-code host mode. Alternate repetitions reverse ordering. All variants receive the same developer instructions and exact-response prompt. A valid loading trial completes one turn, returns CATALOG_OK, and performs no tool calls. REA is marked required in every server-enabled configuration. The runner explicitly disables/enables the stable code_mode_host feature for direct/client-code modes. The old code_mode and code_mode_only switches do not override Codex 0.165's enabled host default. The requested flags and CLI version are retained; verify the actual call shape in completed-task traces too. --modes direct client-code adds a diagnostic host-disabled control. This installed Codex reports that disabling the host makes tool dispatch unavailable; it does not provide a qualified eager/direct comparison. An empty response alone cannot qualify tool availability. Errors invalidate that profile even when the model still emits the expected marker.

Useful controls:

sh
# Compare full input guidance with the default compact input presentation.
npm run eval:mcp-catalog -- --model gpt-6.1-sol \
  --output "$HOME/.cache/rea-catalog-full" --input-profile full --repetitions 3

# Choose exact tool names in the working host mode.
npm run eval:mcp-catalog -- --model gpt-6.1-sol \
  --output "$HOME/.cache/rea-catalog-selected" --modes client-code \
  --selected-tools analyze_javascript_application inspect_analysis_view

enabled_tools filters the catalog after client discovery. It does not reduce the server's original tools/list transport. Server tool-family scope is a separate existing control; do not attribute client filtering results to it. The output-schema profile remains REA's default in these experiments.

Read the evidence ​

report.json retains every attempted trial and compares each enabled-server trial with its same-mode, same-repetition no-server control. It reports valid pair counts and the median/range of observed input-token differences. Failed pairs are explicit and excluded from the median. A small or negative delta can reflect client framing, randomized workspace paths, and measurement variation; it does not establish a negative schema cost.

Usage, cleanup and resource receipts are collected independently of the verdict. A failed host, malformed event or wrong marker can retain observed usage and resource costs. Stage-specific issues explain invalidity; missing observations remain unknown. A changed matrix records its unattempted cells explicitly.

Each trial retains its exact prompt, runtime file digests, requested model alias, Codex version, settings/source hashes, JSONL events, actual usage, answer, cleanup receipt, and process-family resource receipt. The selected rollout capture keeps per-response usage and tool exchanges; authentication, ambient environment, account metadata, and encrypted reasoning are excluded. Tool output and local paths remain evidence and should be reviewed before sharing the raw files.

The metrics have distinct meanings:

MetricMeaning and limit
Catalog bytes and SHA-256Built server advertisement, including output schemas; not model input.
turn.completed.usage.input_tokensObserved whole-turn usage reported by Codex; includes cached input.
Cached/uncached inputReport both. Cache hits do not remove tokens from the context.
Per-response usageRetained usage records help locate discovery and continuation costs. Do not add cumulative thread counts again.
Paired input deltaIncremental loading observation including instructions/client framing; not an exact schema-only token count.
Elapsed and family CPUWhole guarded trial, including local setup and client/network waits; remote inference CPU is unmeasured.
Family peak memoryKernel cgroup peak at payload exit, including observer and file cache; not final whole-scope counters.

These are fresh client/server sessions. OS caches and API prefix caches can already be warm. No cold-cache claim follows from a new session. The requested model alias is recorded; a resolved server-side model version is not inferred. The harness usage is not an independent billing reconciliation. The usage event shape follows the documented Codex non-interactive JSON output.

Evaluate completed investigations too ​

A no-tool response can avoid deferred discovery entirely. Before changing the catalog based on this lane, compare completed tasks through the real harness. Use npm run verify:agent and its known-answer rubric, or run a selected real artifact through tests/support/analysis-efficiency/agent-trial.py under resource-run.py --observe-payload-exit. Use the same task, artifact digest, model/reasoning, authority, result coverage, and correctness oracle in every arm. The existing runner accepts exact --enabled-tools and defaults to client-code host mode. Its direct option is a host-disabled diagnostic, not a claim of working native dispatch in the installed client. Use --capture-tool-context to locate per-response costs. Its task summary explicitly leaves factual correctness unassessed until an independent oracle or transcript review establishes the requested facts.

Count discovery, arguments, replies, retries, and continuations. Check the requested facts against source bytes or another independent oracle, real produced Evidence IDs and source links, partial/unknown coverage, and cleanup. Preserve failed attempts. A successful small-package task is a pilot, not proof of broad application performance or provider compatibility.

Released under the MIT License.