feat(contrib/mark3labs/mcp-go): skip telemetry injection for UI-only tools#4942
feat(contrib/mark3labs/mcp-go): skip telemetry injection for UI-only tools#4942jboolean wants to merge 1 commit into
Conversation
🎉 All green!🧪 All tests passed 🎯 Code Coverage (details) 🔗 Commit SHA: 2ff4a7b | Docs | Datadog PR Page | Give us feedback! |
BenchmarksBenchmark execution time: 2026-07-01 16:38:29 Comparing candidate commit 2ff4a7b in PR branch Found 0 performance improvements and 0 performance regressions! Performance is the same for 321 metrics, 2 unstable metrics, 1 flaky benchmarks without significant changes.
|
0f308e2 to
301b597
Compare
d0e5464 to
0d1c005
Compare
0d1c005 to
a8261f9
Compare
301b597 to
ce524bf
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a8261f9663
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if meta == nil { | ||
| return true | ||
| } | ||
| uiMap, ok := meta.AdditionalFields["ui"].(map[string]any) |
There was a problem hiding this comment.
Handle typed UI metadata before defaulting callable
When a server constructs the same valid _meta.ui.visibility wire format with a typed Go value, such as a struct or map[string][]string, this assertion falls through and treats the tool as model-callable. mcp.Meta.AdditionalFields accepts arbitrary values and will marshal those typed values correctly, so app-only tools declared that way still get required telemetry injected in tools/list, leaving the UI calls rejected for the scenario this change is meant to fix.
Useful? React with 👍 / 👎.
ce524bf to
ec14544
Compare
a850ceb to
cb69328
Compare
ec14544 to
0c444d5
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files🚀 New features to boost your workflow:
|
cb69328 to
5f2c10d
Compare
Config Audit |
2ff4a7b to
33051de
Compare
08d7e54 to
13679e8
Compare
33051de to
0c444d5
Compare
5f2c10d to
2ff4a7b
Compare
13679e8 to
2de53a9
Compare

This PR stack ports functionality added in the clone of this contrib in dd-source back to dd-trace-go.
Summary
The intent-capture
ListToolshook unconditionally addstelemetryas a required field to every tool's input schema. That breaks tools annotated as UI-only (_meta.ui.visibilityexcluding"model"): they are invoked by the app UI, not by the model, so the UI caller has nointentto supply. OpenAI's MCP client strictly validates tool arguments against the advertised schema and rejects every UI-driven call as a result.This change adds an
isModelCallablehelper that inspects*mcp.Meta.AdditionalFields["ui"]["visibility"](handling both[]stringand[]anyshapes from JSON round-trips) and short-circuits the injection when the model is not in the visibility list. Tools with no_meta.ui.visibilitycontinue to default to model-callable per the MCP Apps spec.Ported from internal dd-source PR #420911.
Test plan
TestIntentCaptureSkipsUIOnlyTools— three tools (model-only, UI-only[app], dual[app, model]); assertstelemetryis injected for model and dual but not for UI-only.Stacked on #4941.
MCP standard reference
The
_meta.ui.visibilityfield is part of the official MCP Apps extension. Values:["model", "app"](default),["model"], or["app"]— they control which actor may invoke the tool. UI-only tools (["app"]) are invoked by the host shell, never by the model. This PR's skip logic respects that standard.Parallel port in the modelcontextprotocol/go-sdk contrib: #4949