feat(mcp): respect TRACELOOP_TRACE_CONTENT=false in standard MCP instrumentor#4189
feat(mcp): respect TRACELOOP_TRACE_CONTENT=false in standard MCP instrumentor#4189milkisbad wants to merge 6 commits into
Conversation
…rumentor The standard MCP instrumentor was unconditionally recording span input/output attributes, unlike the FastMCP instrumentor which already honored the TRACELOOP_TRACE_CONTENT env var. Guards all content attributes (TRACELOOP_ENTITY_INPUT, TRACELOOP_ENTITY_OUTPUT, MCP_RESPONSE_VALUE) behind the same _should_send_prompts() check, enabling workflows that cannot store prompts/responses to opt out. Closes traceloop#4188.
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughCentralize TRACELOOP_TRACE_CONTENT handling into utils.should_send_prompts() helper and constant SUPPRESSED_ERROR_DESCRIPTION; update FastMCP and MCP instrumentors to conditionally emit prompt/result span attributes (input/output/response value), conditionally record exceptions, and conditionally set detailed error text; add comprehensive tests covering attribute suppression on tool spans and MCP method spans, attribute inclusion when enabled, and error-path redaction to verify sensitive data is not leaked when content tracing is disabled. ChangesTrace content control for MCP instrumentation
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/utils.py (1)
13-14: ⚡ Quick winConsider adding a docstring to document the environment variable behavior.
The function correctly implements the TRACELOOP_TRACE_CONTENT check with a default of "true", but lacks documentation. A docstring would clarify that this controls whether prompt/response content is recorded in spans and that the default is to include content.
📝 Suggested docstring
def should_send_prompts() -> bool: + """Check if prompt/response content should be recorded in spans. + + Returns True unless TRACELOOP_TRACE_CONTENT is explicitly set to 'false' (case-insensitive). + This allows workflows that cannot store sensitive content to opt out. + """ return (os.getenv("TRACELOOP_TRACE_CONTENT") or "true").lower() == "true"🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/utils.py` around lines 13 - 14, Add a concise docstring to the should_send_prompts function that documents the TRACELOOP_TRACE_CONTENT environment variable behavior: explain that the function returns True when TRACELOOP_TRACE_CONTENT is set to "true" (case-insensitive), that the default is "true" when the variable is unset, and that enabling it causes prompt/response content to be recorded in spans; place this docstring directly above the should_send_prompts function definition for visibility.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/utils.py`:
- Around line 13-14: Add a concise docstring to the should_send_prompts function
that documents the TRACELOOP_TRACE_CONTENT environment variable behavior:
explain that the function returns True when TRACELOOP_TRACE_CONTENT is set to
"true" (case-insensitive), that the default is "true" when the variable is
unset, and that enabling it causes prompt/response content to be recorded in
spans; place this docstring directly above the should_send_prompts function
definition for visibility.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 663c86e0-a619-4e47-93aa-3f6db5b03ba7
📒 Files selected for processing (3)
packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/fastmcp_instrumentation.pypackages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/instrumentation.pypackages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/utils.py
|
Thanks for taking this — the gating on One thing that might be in scope given the motivation ("workflows that cannot store prompts/responses"): two error-path
So with Since |
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Changed. It was a bit more complicated than what you wrote. I've identified 2 cases
1 validation error for Model
foo
value is not "bar", got "ber" [type=not_a_bar, **input_value='ber'**, input_type=str]decided to fix both, but it required touching a lot of places. |
|
@YuxiangJiangCT making sure you got the notification |
|
@milkisbad nice, this is more thorough than what I flagged. Both isError branches are behind One asymmetry I noticed: |
@YuxiangJiangCT Hmm could you help me out with this one - not too confident on the stream paths. Any concrete path you have in mind? |
|
Yeah, I can't give you a concrete, probable one, so I'd leave it as is. With content off, both lines in |
|
@YuxiangJiangCT oke how do follow from now on? |
|
Nothing more from me, I'm good with it as-is. The next step is really out of my hands though: it needs a maintainer with write access to approve and kick off CI, and mine doesn't count for that. Tagging one on the PR is probably the fastest nudge. Glad I could help on this one. |
|
This is the right privacy split for MCP instrumentation: always trace metadata, gate content. I would make the metadata/content boundary explicit in docs and tests: method/tool name, server id, duration, status, and error class are always safe; prompt, response value, and serialized payload require TRACELOOP_TRACE_CONTENT=true. Local raw retention can stay a separate opt-in. Generated with ax. |
… also probe non obfuscation of mcp calls metadata
Hi @Necmttn agreed, docs and tests updated. As far as I understand the current logic satisfies the split deifinition. |








The standard MCP instrumentor was unconditionally recording span input/output attributes, unlike the FastMCP instrumentor which already honored the TRACELOOP_TRACE_CONTENT env var. Guards all content attributes (TRACELOOP_ENTITY_INPUT, TRACELOOP_ENTITY_OUTPUT, MCP_RESPONSE_VALUE) behind the same _should_send_prompts() check, enabling workflows that cannot store prompts/responses to opt out. Closes #4188.
feat(instrumentation): ...orfix(instrumentation): ....screens
Details
- disabled confidential information error pass:Summary by CodeRabbit
TRACELOOP_TRACE_CONTENTacross tool spans, MCP method spans, and error paths (ensuring no redacted sentinel text leaks).