Documentation
¶
Overview ¶
Package mcp provides OpenTelemetry instrumentation helpers that follow the OTel GenAI semantic conventions for the Model Context Protocol (https://opentelemetry.io/docs/specs/semconv/gen-ai/mcp/).
MCP attributes use the `mcp.*` namespace (separate from `gen_ai.*`). Trace context propagates through the MCP `params._meta` field so that requests crossing client/server boundaries chain into a single trace.
The package is structured so that callers describe what they are doing in MCP terms (method name, tool name, session id) and the helpers produce the spec-conformant spans, metrics, and propagation. All helpers are no-op-safe when telemetry is disabled.
Index ¶
- Constants
- func ClassifyError(err error) string
- func ConversationIDFromBaggage(ctx context.Context) string
- func EnsureMeta(m map[string]any) map[string]any
- func ExtractMeta(ctx context.Context, meta map[string]any) context.Context
- func InjectMeta(ctx context.Context, meta map[string]any)
- type CallOptions
- type Span
Constants ¶
const ( AttrMethodName = "mcp.method.name" AttrProtocolVersion = "mcp.protocol.version" AttrResourceURI = "mcp.resource.uri" AttrSessionID = "mcp.session.id" )
MCP attribute keys defined by the OTel semantic conventions (https://opentelemetry.io/docs/specs/semconv/registry/attributes/mcp/). All are Development stability.
const ( AttrJSONRPCRequestID = "jsonrpc.request.id" AttrJSONRPCProtocolVersion = "jsonrpc.protocol.version" AttrRPCResponseStatusCode = "rpc.response.status_code" )
JSON-RPC attribute keys used alongside MCP spans for request id and response status when applicable.
const ( AttrGenAIOperationName = "gen_ai.operation.name" AttrGenAIToolName = "gen_ai.tool.name" AttrGenAIPromptName = "gen_ai.prompt.name" )
gen_ai.* attribute keys that the MCP semconv overlays on MCP spans when applicable. These are duplicated here as constants so the MCP package doesn't depend on the genai package — keeping the two telemetry helpers compositional.
const ( MethodInitialize = "initialize" MethodPing = "ping" MethodCompletionComplete = "completion/complete" MethodPromptsList = "prompts/list" MethodPromptsGet = "prompts/get" MethodResourcesList = "resources/list" MethodResourcesRead = "resources/read" MethodResourcesSubscribe = "resources/subscribe" MethodResourcesUnsub = "resources/unsubscribe" MethodResourcesTemplates = "resources/templates/list" MethodRootsList = "roots/list" MethodSamplingCreate = "sampling/createMessage" MethodToolsList = "tools/list" MethodToolsCall = "tools/call" MethodLoggingSetLevel = "logging/setLevel" MethodElicitationCreate = "elicitation/create" )
Well-known MCP method names (https://modelcontextprotocol.io/specification). These match the values listed in the OTel semconv registry.
const OperationExecuteTool = "execute_tool"
OperationExecuteTool is the gen_ai.operation.name value used on MCP tools/call spans per the spec.
Variables ¶
This section is empty.
Functions ¶
func ClassifyError ¶
ClassifyError maps an MCP error to a low-cardinality error.type value. MCP errors are often plain RPC errors; this helper picks reasonable labels for cancellation and falls back to the type name otherwise.
func ConversationIDFromBaggage ¶
ConversationIDFromBaggage reads `gen_ai.conversation.id` from the context's W3C baggage. The MCP package mirrors the genai package's convention so MCP spans automatically carry the session id when the runtime has seeded it; the value also propagates across MCP server boundaries via the standard `baggage` header alongside `traceparent`.
Exported so adjacent code (e.g. the MCP OAuth transport) can attach the same attribute to spans it creates directly via `otel.Tracer`.
func EnsureMeta ¶
EnsureMeta returns a metadata map suitable for InjectMeta to write trace context into. When m is non-nil it is shallow-copied so an upstream caller that reuses the same request struct (e.g. on retry) does not see stale `traceparent` keys from a previous span injected into the map they own. When m is nil a fresh map is allocated.
func ExtractMeta ¶
ExtractMeta reads trace context from the given MCP `_meta` map and returns a context with the parent span attached. Use on the server side to chain incoming spans onto the client's caller.
func InjectMeta ¶
InjectMeta writes the active trace context into the given MCP `_meta` map so the receiving server can extract it and parent its SERVER span onto our CLIENT span. Per the MCP semconv, the keys written are `traceparent`, `tracestate`, and `baggage` (W3C TraceContext + Baggage).
If meta is nil, InjectMeta is a no-op — callers should ensure the map is non-nil before calling so the keys actually persist on the request.
Types ¶
type CallOptions ¶
type CallOptions struct {
// Method is the MCP method name (e.g. "tools/call"). Required.
Method string
// Target is the low-cardinality target of the operation: tool name
// for tools/call, prompt name for prompts/get, etc. When set the
// span name becomes "{method} {target}"; otherwise just "{method}".
Target string
// ToolName, when set, is recorded as gen_ai.tool.name and used as
// the default Target for tools/call.
ToolName string
// PromptName, when set, is recorded as gen_ai.prompt.name and used
// as the default Target for prompts/get.
PromptName string
// ResourceURI, when set, is recorded as mcp.resource.uri and used
// as the default Target for resources/* methods.
ResourceURI string
// SessionID identifies the MCP session and is recorded as
// mcp.session.id when set.
SessionID string
// ProtocolVersion is recorded as mcp.protocol.version when set.
ProtocolVersion string
// JSONRPCRequestID is recorded as jsonrpc.request.id when set
// (client-side requests; ignored for notifications).
JSONRPCRequestID string
// ServerAddress / ServerPort identify the MCP endpoint when known.
ServerAddress string
ServerPort int
}
CallOptions describes an MCP request being made or handled. Used by both client- and server-side helpers so call sites depend on a single vocabulary.
type Span ¶
type Span struct {
// contains filtered or unexported fields
}
Span is the handle returned by StartClient / StartServer. It carries enough state to record `mcp.{client,server}.operation.duration` and to flush span attributes as the operation proceeds.
func StartClient ¶
StartClient begins a CLIENT-kind MCP span and returns a context carrying it. Callers MUST call Span.End to flush the span and metrics.
func StartServer ¶
StartServer begins a SERVER-kind MCP span. Use after extracting trace context from the incoming `params._meta` so the span chains onto the caller. Callers MUST call Span.End.
func (*Span) End ¶
func (s *Span) End()
End closes the span and records the operation duration metric. Safe to call multiple times; subsequent calls are no-ops.
func (*Span) RecordError ¶
RecordError marks the span as failed and stores error.type for the duration metric. errType should be a short, low-cardinality string; when empty, ClassifyError(err) supplies a value (one of "context_canceled", "deadline_exceeded", "rpc_error").
func (*Span) SetAttributes ¶
SetAttributes adds extra attributes to the span. Use for MCP extensions or for response-side attributes the caller learns later (e.g. rpc.response.status_code).