Skip to content

feat(v1): expose MCP tools to Codex - #2140

Merged
hallerite merged 1 commit into
mainfrom
fix/codex-mcp-harness
Jul 27, 2026
Merged

feat(v1): expose MCP tools to Codex#2140
hallerite merged 1 commit into
mainfrom
fix/codex-mcp-harness

Conversation

@hallerite

@hallerite hallerite commented Jul 26, 2026

Copy link
Copy Markdown
Member

Summary

  • advertise MCP support from the Codex harness
  • configure each task MCP HTTP server for both initial and resumed Codex exec segments
  • expose the corresponding MCP namespaces directly to the model
  • preserve Verifiers MCP server names and leave task prompts unchanged

Validation

  • uv run ruff check --fix .
  • uv run pytest tests/ — 909 passed, 63 skipped (credentialed e2e cases require PRIME_API_KEY)
  • uv run pre-commit run --all-files
  • pre-push ty (ci parity)

Note

Medium Risk
Changes how Codex is launched with external MCP dependencies and namespace mapping; misconfiguration could break tool exposure or resume segments, but scope is limited to the Codex harness.

Overview
Codex rollouts can now use task MCP HTTP servers on both initial exec and exec resume --last segments, aligned with other agent harnesses.

CodexHarness sets SUPPORTS_MCP = True and threads mcp_urls into _config_args, which emits a single -c mcp_servers={...} table (so dotted server IDs are not split as TOML paths) with required=true and fixed startup/tool timeouts. When MCP is present, it also sets features.code_mode.direct_only_tool_namespaces using namespaces derived from server names—sanitized mcp__ prefixes, SHA1 suffixes on collisions, and 49-character truncation—to match Codex v0.144.5’s exposed tool namespaces while keeping Verifiers server IDs unchanged in config.

Reviewed by Cursor Bugbot for commit c533f05. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Expose MCP tools to Codex by passing server URLs and namespaces through CodexHarness

  • Sets SUPPORTS_MCP = True on CodexHarness so the harness advertises MCP capability at runtime.
  • Updates launch and resume in harness.py to pass mcp_urls into _config_args.
  • _config_args now builds a TOML mcp_servers config entry (with required=true, 60s startup timeout, 600s tool timeout) and a features.code_mode.direct_only_tool_namespaces list from the provided URLs.
  • Namespace strings are normalized (non-[a-zA-Z0-9_] chars replaced with _, mcp__ prefix enforced), collision-detected with a 12-hex SHA1 suffix, and truncated to 49 chars if needed.

Macroscope summarized c533f05.

@hallerite
hallerite marked this pull request as ready for review July 26, 2026 20:23
Comment thread verifiers/v1/harnesses/codex/harness.py Outdated
@macroscopeapp

macroscopeapp Bot commented Jul 26, 2026

Copy link
Copy Markdown

Approvability

Verdict: Needs human review

Unable to check for correctness in c533f05. This PR enables MCP support in the Codex harness with new namespace normalization and configuration logic. Multiple unresolved review comments question the design approach, and the feature enablement introduces significant new runtime behavior that warrants human review.

You can customize Macroscope's approvability policy. Learn more.

Comment thread verifiers/v1/harnesses/codex/harness.py Outdated
if mcp_urls:
prompt = "\n\n".join(
[
"Task-specific MCP tools are already configured and directly available.",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should not alter the prompt, we don't do this for other harnesses, either

Comment thread verifiers/v1/harnesses/codex/harness.py Outdated
for arg in self._mcp_config_args(index, name, url)
]
direct_mcp_namespaces = [
f"mcp__{self._mcp_server_name(index, name)}"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why change mcp server names here?

Comment thread verifiers/v1/harnesses/codex/harness.py Outdated
]

@staticmethod
def _mcp_server_name(index: int, name: str) -> str:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why change mcp server names here?

Comment thread verifiers/v1/harnesses/codex/harness.py Outdated
return f"vf_{index}_{label}"

@classmethod
def _mcp_config_args(cls, index: int, name: str, url: str) -> list[str]:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fold this into _config_args

Comment thread tests/v1/test_e2e.py Outdated
@pytest.mark.e2e
@pytest.mark.codex
@pytest.mark.docker
async def test_codex_resume_with_tool(run_v1, tmp_path):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i'd drop this test

@hallerite
hallerite force-pushed the fix/codex-mcp-harness branch from 778fdc1 to 39fef46 Compare July 27, 2026 13:08

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 39fef46. Configure here.

Comment thread verifiers/v1/harnesses/codex/harness.py Outdated
@hallerite
hallerite force-pushed the fix/codex-mcp-harness branch from 39fef46 to 9eb12ab Compare July 27, 2026 13:15
@hallerite
hallerite force-pushed the fix/codex-mcp-harness branch from 9eb12ab to c533f05 Compare July 27, 2026 13:45
@hallerite
hallerite merged commit 8233c84 into main Jul 27, 2026
12 checks passed
@hallerite
hallerite deleted the fix/codex-mcp-harness branch July 27, 2026 14:03
eligotts added a commit that referenced this pull request Jul 31, 2026
…fload

Picks up 35 main commits: the v1 structure cleanup (#2146) that retires
StrictBaseModel and renames _NODE_DUMP_EXCLUDE -> EXCLUDE_FIELDS, the
ruff 0.16 / ty tooling bump (#2147, #2148), runtime-on-agent + agent
config stamped on the trace (#2106), Reward score/weight records (#2119),
MCP tools for Codex (#2140), and assorted v1 fixes.

Resolutions:
- trace.py: main's restructure subsumes this branch's block wholesale —
  EXCLUDE_FIELDS already carries multi_modal_data, and TRACE_VERSION=1 is
  main's deliberate reset (this branch never touched it). Took main.
- graph.py: kept the raw-mm sidecar validators and
  previous_multi_modal_data; adopted main's plain BaseModel now that
  StrictBaseModel is gone.
- clients/train.py: kept the is_multimodal import — still used by the
  bridge path that threads previous_multi_modal_data.

Ruff 0.16 flagged two spots this branch added that main's cleanup pass
never saw: a constant getattr in the ingress offload walker, and the
blind except at the prepare_request_body boundary (annotated noqa, per
main's own convention at rollout boundaries).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants