modelcontextprotocol / modelcontextprotocol/kotlin-sdk

[Proposal] SEP-414: OpenTelemetry Trace Context Propagation design (#800)

Open
#1,000 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
1.5k
Forks
248
Avg merge
1d 20h
Merged PRs (30d)
23

Description

Proposal: SEP-414 OpenTelemetry Trace Context Propagation Design (#800)
Motivation & Context

Tracking implementation of SEP-414 in kotlin-sdk for the 2026-07-28 MCP spec milestone (aligned with umbrella issue #842).

SEP-414 establishes standards-track conventions for OpenTelemetry (OTel) trace context propagation across Model Context Protocol implementations:

  1. When OTel trace context is propagated via _meta, the keys traceparent, tracestate, and baggage follow W3C Trace Context and W3C Baggage formats.
  2. It documents an explicit exception to the DNS prefixing rule for keys in _meta (traceparent, tracestate, and baggage are top-level un-namespaced keys in _meta).
  3. Cross-SDK implementations are already in place in C# SDK (Diagnostics.cs), Python SDK (#1693), and TypeScript SDK.

This proposal outlines the idiomatic Kotlin Multiplatform (KMP) architecture for implementing SEP-414 in kotlin-sdk.


Proposed Architecture & Component Design
1. Protocol Constants and Type-Safe Metadata Access (kotlin-sdk-core)

In kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/common.kt:

  • Add standardized W3C Trace Context key constants:
    public object TraceContextKeys {
        public const val TRACEPARENT: String = "traceparent"
        public const val TRACESTATE: String = "tracestate"
        public const val BAGGAGE: String = "baggage"
    }
    
  • Add extension accessors on WithMeta:
    public val WithMeta.traceParent: String?
        get() = meta?.get(TraceContextKeys.TRACEPARENT)?.jsonPrimitive?.contentOrNull
    
    public val WithMeta.traceState: String?
        get() = meta?.get(TraceContextKeys.TRACESTATE)?.jsonPrimitive?.contentOrNull
    
    public val WithMeta.baggage: String?
        get() = meta?.get(TraceContextKeys.BAGGAGE)?.jsonPrimitive?.contentOrNull
    
  • Provide non-destructive metadata augmentation helper withTraceContext(...) on request/notification builders that preserves existing custom _meta entries while injecting trace headers.
2. Multiplatform Propagation Carrier Interface

To keep kotlin-sdk-core lightweight and platform-agnostic while enabling OpenTelemetry integration:

  • Define a minimal carrier abstraction in kotlin-sdk-core:
    public interface McpTraceCarrier {
        public fun get(key: String): String?
        public fun set(key: String, value: String)
        public fun keys(): Set<String>
    }
    
  • Implement McpTraceCarrier for JsonObject and MutableMap<String, JsonElement>.
  • On JVM platforms (jvmMain), provide direct adaptors for OpenTelemetry's TextMapGetter<WithMeta> and TextMapSetter<MutableMap<String, JsonElement>> so developers using io.opentelemetry:opentelemetry-context can inject/extract contexts in one line:
    OpenTelemetry.getPropagators().getTextMapPropagator().inject(context, metaMap, McpMetaTextMapSetter)
    
3. Client & Server Interceptor Integration
  • Client (kotlin-sdk-client):
    • Add optional traceContextProvider: (() -> Map<String, String>)? to client options or a request pipeline interceptor.
    • Automatically populate _meta.traceparent on outgoing tools/call, resources/read, and prompts/get requests when an active trace is present in the coroutine context.
  • Server (kotlin-sdk-server):
    • Extract incoming traceparent / tracestate from request.params._meta before dispatching to handlers.
    • Expose the extracted trace context in RequestContext so tool/resource handlers can attach child spans or link spans.
4. Documentation & Verification
  • Document the conventions in docs/ with non-normative JSON examples matching SEP-414.
  • Add unit tests in kotlin-sdk-core verifying:
    • Extraction of valid W3C traceparent strings.
    • Non-destructive injection into existing _meta objects.
    • Preservation of un-namespaced keys as specified by SEP-414.

Next Steps

If this design matches the maintainers' vision for #800 / #842, we are ready to submit a focused PR implementing the kotlin-sdk-core constants, extension helpers, and unit tests.

AI assistance disclosure: AI was used to discover this opportunity and draft the change or text. The submission was checked against the prepared artifact and recorded verification evidence.

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 by reading kotlin-sdk-core/src/commonMain/kotlin/io/modelcontextprotocol/kotlin/sdk/types/common.kt and the SEP-414 conventions. Then compare the proposed core carrier, client/server integration, documentation, and unit-test work with the existing SDK structure and maintainer direction for #800/#842. Done means an agreed focused implementation scope with verification for extraction, non-destructive injection, and preserved metadata keys.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
api, backend-api-design, documentation, observability, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.