traceloop / traceloop/openllmetry

๐Ÿ› Bug Report: MCP `InstrumentedStreamWriter.send()` assumes dict-shaped `request.result` and can fail for object/model results

Open Beginner friendly
#4,038 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
7.4k
Forks
1.1k
Avg merge
8d 14h
Merged PRs (30d)
2

Description

Which component is this bug for?

Traceloop SDK

๐Ÿ“œ Description

In opentelemetry-instrumentation-mcp, InstrumentedStreamWriter.send() assumes request.result is always a dict:

if "isError" in request.result:
    if request.result["isError"] is True:
        span.set_status(
            Status(
                StatusCode.ERROR,
                f"{request.result['content'][0]['text']}",
            )
        )

Impact

  • Response-stream error handling can fail at runtime
  • Error spans may not be set correctly
  • Behavior is inconsistent across MCP instrumentation paths

Possible errors

  • TypeError: argument of type 'X' is not iterable
  • TypeError: 'X' object is not subscriptable
  • KeyError: 'content'
  • IndexError: list index out of range

File

  • packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/instrumentation.py

Method

  • InstrumentedStreamWriter.send()

Proposed fix
Normalize request.result access before reading fields:

  • use .get(...) for dicts
  • use getattr(...) for objects
๐Ÿ‘Ÿ Reproduction steps
  1. Use MCP instrumentation with a response/result object that exposes fields via attributes rather than dict keys.
  2. Trigger a response where the MCP result represents an error.
  3. Exercise the InstrumentedStreamWriter.send() path.
  4. Observe failure or missing error handling around:
request.result["content"][0]["text"]
๐Ÿ‘ Expected behavior

The stream writer should support both of these shapes:

dict-style

request.result["isError"]
request.result["content"][0]["text"]

object-style

request.result.isError
request.result.content[0].text

without crashing, and should always set the span status correctly for MCP error responses.

๐Ÿ‘Ž Actual Behavior with Screenshots

The code currently assumes only dict-style access in InstrumentedStreamWriter.send().

This causes inconsistent handling and can break when request.result is not a dict.

๐Ÿค– Python Version

No response

๐Ÿ“ƒ Provide any additional context for the Bug.

No response

๐Ÿ‘€ Have you spent some time to check if this bug has been raised before?
  • I checked and didn't find similar issue
Are you willing to submit PR?

None

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up โ€” it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/instrumentation.py, focusing on InstrumentedStreamWriter.send(). Reproduce the error-handling path with both dict-style and object-style request.result values, then verify that the stream writer does not crash and sets the span status correctly for MCP error responses.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
observability
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.