anomalyco / anomalyco/opencode

[FEATURE]: propagate W3C trace context (traceparent/baggage) in MCP tools/call _meta per SEP-414

Open
#46,856 0 comments 0 reactions 1 assignee View on GitHub

@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 for traceparent as an HTTP header on remote MCP transports and was closed for inactivity. This request is about params._meta on tools/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

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.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.