MCP tool execution events and metadata not exposed to LLM (breaks multi-turn conversations with Codex and other stateful tools)

Resolved 💬 6 comments Opened Oct 17, 2025 by hughescr Closed Jan 13, 2026

Bug Description:

Claude Code's MCP client implementation filters out intermediate events and metadata emitted during tool execution, preventing the LLM from accessing critical information needed for multi-turn interactions with MCP tools like Codex.

Environment:

  • Claude Code version: 2.0.1
  • Codex MCP server version: 0.47.0
  • Platform: macOS (Darwin 25.0.0)

Concrete Example: Codex MCP Server

When calling mcp__Codex__codex, the server emits a codex/event notification:

{
  "jsonrpc": "2.0",
  "method": "codex/event",
  "params": {
    "_meta": {"requestId": 2},
    "id": "",
    "msg": {
      "type": "session_configured",
      "session_id": "0199f3a1-15e4-77d3-93ef-f954c7978c66",
      "model": "gpt-5-codex",
      "reasoning_effort": "high",
      "rollout_path": "~/.codex/sessions/2025/10/17/rollout-2025-10-17T12-24-04-0199f3a1-15e4-77d3-93ef-f954c7978c66.jsonl"
    }
  }
}

What Happens:

  1. ✅ Codex MCP server correctly emits the event via JSON-RPC
  2. ✅ Event is sent over stdio (verified in MCP Inspector)
  3. ✅ Claude Code's MCP client receives the event
  4. Event is filtered out - LLM never sees it
  5. ❌ LLM only receives final text response
  6. mcp__Codex__codex-reply requires conversationId (the session_id from the event)
  7. Multi-turn conversations are impossible

The Architectural Gap:

Codex MCP Server
    ↓ emits codex/event with session_id
    ↓ (stdio JSON-RPC channel)
Claude Code MCP Client
    ↓ receives events ✓
    ↓ filters/processes
    ✗ drops events before LLM
    ↓ only passes final text
LLM (Claude)
    ↓ cannot see session_id
    ↓ cannot use codex-reply

Verification:

  • MCP Inspector shows all events including session_id
  • Claude LLM only sees final text response ✗

The Tension:

While it's understandable that:

  1. Flooding the LLM's context with every event would be problematic
  2. Special-casing every MCP tool (like extracting Codex's session_id) doesn't scale

Claude Code should not drop ALL intermediate events either.

Proposed Solutions:

Option A - Surface all events in tool results (simple):

{
  "events": [
    {"type": "session_configured", "session_id": "0199f3a1-..."}
  ],
  "content": "Consider layering a small abstraction..."
}

Option B - Per-tool configurable event metadata (recommended):

Allow MCP server configurations to specify which events to capture and which fields to extract. Example config:

{
  "mcpServers": {
    "Codex": {
      "command": "codex",
      "args": ["mcp-server"],
      "accumulate_event_metadata": [
        {
          "event_filter": "params?.msg?.type==\"session_configured\"",
          "fields": ["params.msg.session_id"]
        }
      ]
    }
  }
}

This would:

  1. Monitor all intermediate events emitted during tool execution
  2. Apply the event_filter expression to each event
  3. For matching events, extract only the specified fields (like lodash pick)
  4. Preserve the original event structure shape with pruned fields
  5. Return the pruned metadata alongside the final tool result

Result exposed to LLM:

{
  "metadata": [
    {
      "params": {
        "msg": {
          "session_id": "0199f3a1-15e4-77d3-93ef-f954c7978c66"
        }
      }
    }
  ],
  "content": "Consider layering a small abstraction..."
}

This approach:

  • ✅ Avoids context window bloat (only specified fields extracted)
  • ✅ Preserves original event structure for easy access
  • ✅ Scales to any MCP tool without hardcoding
  • ✅ User-configurable per MCP server
  • ✅ Backwards compatible (omit config = no metadata accumulation)

Option C - Debug mode (fallback):

Expose all MCP communication when in a debug/verbose mode for development and troubleshooting.

Impact:

This affects any MCP tool that:

  • Requires stateful multi-turn interactions
  • Emits session/conversation identifiers in events
  • Uses intermediate metadata for coordination
  • Relies on the LLM having access to full MCP protocol communication

Related Issues:

  • #3174 (notifications/message not displayed)
  • #4157 (progress notifications)
  • #5960 (streaming responses)

But this issue is specifically about tool execution events and metadata being hidden from the LLM.

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗