Skip to content

CodeGraph MCP tools are not exposed because OMO wrapper does not bridge framed stdio or project cwd #71

Description

@ipad4

Summary

CodeGraph is registered and indexed successfully under LazyCodex/OMO 4.13.0, but Codex sessions still do not expose any mcp__codegraph__* tools. The OMO CodeGraph wrapper currently forwards stdio directly to codegraph serve --mcp, but Codex sends MCP Content-Length framed messages while CodeGraph 1.0.1 accepts newline-delimited JSON on this path.

There is also a second visible surface: when the same wrapper is driven with newline JSON from the registered plugin cwd, CodeGraph reports the plugin directory as an unindexed workspace and returns an empty tool list. Driving the same wrapper from the actual project root returns the expected CodeGraph tools.

Environment

  • LazyCodex package: lazycodex-ai@4.13.0
  • Installed OMO plugin: omo@sisyphuslabs@4.13.0
  • Codex CLI: codex-cli 0.141.0
  • CodeGraph: 1.0.1
  • Node: v22.22.1
  • OS: macOS 15.7.3, arm64
  • Workspace: /Users/admin/Desktop/lazycodex
  • Relevant MCP config from codex mcp get codegraph:
codegraph
  enabled: true
  transport: stdio
  command: node
  args: /Users/admin/.codex/plugins/cache/sisyphuslabs/omo/4.13.0/components/codegraph/dist/serve.js
  cwd: /Users/admin/.codex/plugins/cache/sisyphuslabs/omo/4.13.0/.
  env: -

Repository Decision

  • Target repository: code-yeongyu/lazycodex
  • Why this belongs there: LazyCodex/OMO owns the bundled CodeGraph MCP registration and wrapper launched by Codex. Upstream Codex correctly registers the server and sends standard MCP stdio frames; the failure is in the LazyCodex wrapper/upstream CodeGraph integration path.
  • LazyCodex evidence: latest /tmp/lazycodex-source was synced to main@4a15494c5bff. The current CodeGraph wrapper source at plugins/omo/components/codegraph/src/serve.ts still launches codegraph serve --mcp with inherited stdio on the available path.
  • Upstream Codex evidence: latest /tmp/openai-codex-source was synced to main@b17f30eb2a67. codex mcp get codegraph shows Codex loads the OMO server as enabled; the user-visible failure is that no CodeGraph tools are discoverable after startup.

Reproduction

  1. Use LazyCodex/OMO 4.13.0 with CodeGraph enabled:
[plugins."omo@sisyphuslabs".mcp_servers.codegraph]
enabled = true
  1. Confirm the server is registered:
codex mcp get codegraph
  1. Confirm CodeGraph itself is initialized in the target workspace:
/Users/admin/.omo/codegraph/bin/codegraph status --json

Observed status includes:

{"initialized":true,"version":"1.0.1","fileCount":556,"nodeCount":10556,"edgeCount":28539,"pendingChanges":{"added":0,"modified":0,"removed":0}}
  1. Start a fresh Codex ephemeral session and search for CodeGraph tools:
codex exec --ephemeral -C /Users/admin/Desktop/lazycodex --sandbox read-only '只做诊断,不要修改文件。调用工具发现搜索 codegraph 和 mcp__codegraph。最后只用中文回答一行:是否看到 CodeGraph MCP 工具,以及工具发现返回的数量。'

Observed final line:

没有看到 CodeGraph MCP 工具;工具发现返回数量:codegraph 0 个,mcp__codegraph 0 个。

Expected Behavior

A new Codex session should expose CodeGraph MCP tools such as mcp__codegraph__codegraph_search, mcp__codegraph__codegraph_node, mcp__codegraph__codegraph_explore, and mcp__codegraph__codegraph_callers when CodeGraph is enabled and the workspace has a valid .codegraph index.

Actual Behavior

No CodeGraph MCP tools are exposed to Codex tool discovery, even though:

  • the MCP server is enabled in Codex config,
  • the OMO CodeGraph wrapper path exists,
  • CodeGraph is installed and initialized,
  • direct newline JSON interaction from the project root can list tools.

Evidence

Framed MCP requests sent to the installed OMO wrapper fail with JSON parse errors:

{
  "mode": "content-length",
  "stdout": "{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32700,\"message\":\"Parse error: invalid JSON\"}}\n{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32700,\"message\":\"Parse error: invalid JSON\"}}\n{\"jsonrpc\":\"2.0\",\"id\":null,\"error\":{\"code\":-32700,\"message\":\"Parse error: invalid JSON\"}}\n",
  "stderr": ""
}

The same installed wrapper accepts newline-delimited JSON, but when launched from the registered plugin cwd it treats the plugin cache as the workspace and returns no tools:

{
  "mode": "newline-json",
  "cwd": "/Users/admin/.codex/plugins/cache/sisyphuslabs/omo/4.13.0",
  "stdout": "... Codegraph — inactive (workspace not indexed) ...",
  "tools": []
}

When the same wrapper is launched from the actual project root and driven with newline JSON, it returns tools:

{
  "mode": "newline-json",
  "cwd": "project-root",
  "tools": [
    "codegraph_search",
    "codegraph_callers",
    "codegraph_node",
    "codegraph_explore"
  ]
}

The latest LazyCodex source still shows the available path using inherited stdio:

/tmp/lazycodex-source/plugins/omo/components/codegraph/src/serve.ts:129: return runProcess(resolution.command, [...resolution.argsPrefix, "serve", "--mcp"], {
/tmp/lazycodex-source/plugins/omo/components/codegraph/src/serve.ts:131:   stdio: "inherit",

Related upstream context: colbymchenry/codegraph#172 reported the same protocol mismatch class for CodeGraph MCP: Content-Length framed MCP clients versus newline-delimited JSON transport.

Root Cause

The failure appears to have two coupled causes in the LazyCodex/OMO CodeGraph integration:

  1. The OMO wrapper's available path directly inherits stdio into codegraph serve --mcp. Codex speaks standard MCP stdio framing (Content-Length: ...\r\n\r\n<body>), while CodeGraph 1.0.1 on this path parses newline-delimited JSON. The header bytes are treated as JSON and produce Parse error: invalid JSON.
  2. The registered MCP cwd is the plugin cache root, not the user's project root. Once framing is bridged, the wrapper also needs to ensure CodeGraph serves the target workspace or still exposes tools with projectPath support; otherwise tools/list can remain empty because the plugin cache has no .codegraph index.

Proposed Fix

Update the OMO CodeGraph wrapper to own the MCP boundary instead of blindly inheriting stdio:

  • Accept standard MCP Content-Length frames from Codex.
  • Translate framed JSON-RPC bodies to the newline-delimited JSON that the current CodeGraph server expects, or upgrade/require a CodeGraph version that natively supports framed MCP stdio.
  • Translate CodeGraph newline JSON responses back to framed MCP responses for Codex.
  • Preserve existing newline JSON smoke/manual behavior if possible.
  • Ensure the child CodeGraph process uses the active workspace root, or that the wrapper exposes tools even when launched from the plugin cwd and relies on projectPath arguments for workspace selection.
  • Add a regression smoke test that drives the built installed wrapper with real Content-Length framed initialize + tools/list, not only newline JSON.

Verification Plan

  • Run a direct framed MCP smoke against components/codegraph/dist/serve.js and assert initialize succeeds without Parse error: invalid JSON.
  • Assert tools/list returns codegraph_search, codegraph_node, codegraph_explore, and codegraph_callers for an indexed workspace.
  • Run codex exec --ephemeral -C <indexed-workspace> --sandbox read-only ... and confirm tool discovery finds CodeGraph tools.
  • Regression check: verify the unavailable/fallback MCP server path still responds with a framed initialize response and an empty tool list when CodeGraph is intentionally unavailable.

This issue or PR was generated by LazyCodex.
Tag: lazycodex-generated

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions