Skip to content

Render MCP list-tools spans instead of leaving them blank - #329

Open
laminar-coding-agent[bot] wants to merge 2 commits into
mainfrom
fix/openai-agents-mcp-span-io
Open

Render MCP list-tools spans instead of leaving them blank#329
laminar-coding-agent[bot] wants to merge 2 commits into
mainfrom
fix/openai-agents-mcp-span-io

Conversation

@laminar-coding-agent

@laminar-coding-agent laminar-coding-agent Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Problem

_apply_mcp_span_data is the only handler in openai_agents/span_data.py that never calls set_lmnr_span_io. It writes openai.agents.mcp.server and openai.agents.mcp.result and stops there — but those custom attributes are not rendered as span I/O, so an agents.mcp_tools span arrives with lmnr.span.input / lmnr.span.output unset and shows up completely empty in the trace view.

Found while reviewing a chi-bench collection run: 15 agents.mcp_tools spans, every one blank, with all 30 tool names sitting unread in openai.agents.mcp.result.

input len: 0 | output len: 0
openai.agents.mcp.server = chi_bench
openai.agents.mcp.result = ["chart.get_patient_chart_by_patient","chart.list_candidate_orders", ...]

Fix

Set span I/O alongside the attributes — server in, tool list out. Nothing else changes; the existing attributes stay for anyone querying them.

Testing

New tests/test_instrumentations/test_openai_agents/test_mcp_span_data.py (2 tests) covers the populated case and the no-result case. The full tests/test_instrumentations/test_openai_agents/ suite passes (9 passed).

Also exercised end-to-end by a live chi-bench run exporting to production Laminar.

Notes

CLAUDE.md gains an openai_agents section recording the invariant (every _apply_* handler sets span I/O), plus two things that look like bugs and aren't: the first turn's mcp_tools span parenting to the trace root is upstream SDK ordering, and one mcp_tools span per turn is expected even with cache_tools_list=True (the repeats are ~0.3ms cache hits).

🤖 Generated with Claude Code


Note

Low Risk
Small instrumentation change that only adds trace-view I/O attributes for MCP list-tools spans; no auth, export, or runtime behavior changes.

Overview
agents.mcp_tools spans were empty in the trace UI because _apply_mcp_span_data only set openai.agents.mcp.* attributes, which the frontend does not use for I/O.

The handler now also calls set_lmnr_span_io: MCP server name as input ({"server": ...}) and the tool list as output. Existing openai.agents.mcp.server / openai.agents.mcp.result attributes are unchanged for queries.

CLAUDE.md documents the openai_agents invariant (every _apply_*_span_data handler should set span I/O) and notes two upstream SDK behaviors (first-turn MCP span parenting, one MCP span per turn even with cached tool lists).

Tests: test_mcp_span_data.py covers populated and no-result MCP list-tools spans.

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

olzhik11 and others added 2 commits August 25, 2026 12:52
`_apply_mcp_span_data` was the only handler in span_data.py that never
called `set_lmnr_span_io`, so an `agents.mcp_tools` span arrived with
`lmnr.span.input`/`output` unset and showed up empty in the trace view.
The tool list was there all along, just parked in
`openai.agents.mcp.result`, which the UI does not read.

Surfaced on a chi-bench run: 15 `agents.mcp_tools` spans, every one of
them blank, while the attribute held all 30 tool names.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant