anomalyco / anomalyco/opencode
[FEATURE]: propagate W3C trace context (traceparent/baggage) in MCP tools/call _meta per SEP-414
@nexxeln is already working on this.
Since Sep 2, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- PR merge metrics
- PR metrics pending
Description
Feature hasn't been suggested before.
- I have verified this feature I'm about to request hasn't been suggested before. Related but different: #45997 / #46008 added
_meta.sessionID(thanks, this is great); #28295 asked fortraceparentas an HTTP header on remote MCP transports and was closed for inactivity. This request is aboutparams._metaontools/call, which is the only channel a stdio MCP server has, and follows the now-final MCP spec (SEP-414).
Describe the enhancement you want to request
What: when OpenCode invokes an MCP tool, include the W3C trace context of the active tool-call span in CallToolRequest.params._meta, using the keys the MCP spec reserves for this in SEP-414: traceparent, optionally tracestate, and baggage (unprefixed, by spec exception to the _meta prefix rule). For example:
{
"method": "tools/call",
"params": {
"name": "engram_search",
"arguments": { "...": "..." },
"_meta": {
"sessionID": "ses_…",
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"baggage": "session.id=ses_…,opencode.tool.call_id=call_…"
}
}
}
_meta.sessionID from #46008 can stay as is; baggage just carries the same value under the spec-conventional key so servers built against the OTel GenAI MCP semantic conventions pick it up without OpenCode-specific code.
Why: OpenCode already opens an OpenTelemetry span per tool call (session/tools.ts has session.id and tool.call_id in scope at the call site; with experimental.openTelemetry those spans export). An MCP server that traces its own work today has no way to parent its spans onto that span, so the client-side and server-side halves of one tool call land in the backend as two unrelated traces. With traceparent in _meta the server span becomes a child of OpenCode's, and a trace view shows: model turn → tool call → what the server actually did (retrieval stages, cache hits, lock waits) in one waterfall. The OTel GenAI MCP semantic conventions (Development) say clients SHOULD inject propagators into params._meta and servers SHOULD use it as the parent; the Rust SDK (rmcp ≥ 3.1) already exposes RequestMetaObject::get_traceparent/get_baggage for exactly this.
Where: the same place #46008 adds _meta.sessionID (packages/core/src/mcp/client.ts), reading the current span context from the OTel API (propagation.inject into a carrier and copying the three keys) when tracing is enabled; when it is not, traceparent can simply be omitted.
Workaround today: a plugin's tool.execute.before hook can inject a reserved argument (we use args._otel = { traceparent, baggage }) and the server lifts it into _meta. It works, but it couples the server to an OpenCode-specific argument and leaks into the stored tool input; native _meta propagation makes that unnecessary.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.