diff --git a/docs/gen-ai/modelcontextprotocol.md b/docs/gen-ai/modelcontextprotocol.md new file mode 100644 index 0000000000..f7a2cc4b7f --- /dev/null +++ b/docs/gen-ai/modelcontextprotocol.md @@ -0,0 +1,111 @@ +# Semantic Conventions for Model Context Protocol (MCP) + +## Background + +The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is an open protocol for interactions between applications and AI models, supporting structured input and output formats. As MCP adoption grows, there's a need to establish semantic conventions for telemetry to ensure consistent observability across implementations. + +## Proposal + +This issue proposes semantic conventions for [Model Context Protocol operations](https://github.com/modelcontextprotocol/specification) to standardize how traces, metrics, and logs are reported across MCP client and server implementations. + +The conventions are based on the [`2025-3-26`](https://github.com/modelcontextprotocol/specification/tree/main/docs/specification/2025-03-26) version of the MCP specification. + +While MCP is intended as primarily for extending gen_ai LLM tool calling, its not strictly tied to being used in gen_ai scenarios. For that reason, the MCP attributes being proposed user their own independent namespace. +MCP uses JSON-RPC for it's calling implementation. The MCP attributes cover the higher-level MCP semantics irrespective of the transport and RPC details. It is recommended that implementations use separate spans for JSON-RPC and MCP, but they can be overlaid if necessary as the attributes have been designed not to conflict. + +These conventions do not document how the trace context needs to be propagated from the client to the server. Changes to the MCP protocol will be needed to enable that proagation. Proposals are being made to the MCP specification. + +## Spans + +### MCP Session + +An MCP session represents the lifecycle of a connection between a client and server. + +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `mcp.session.id` | string | Identifier for the MCP session | `c52f5ef3-c7a1-4f7a-a2e3-e38a7a4966d2` | Yes | +| `mcp.transport` | string | Transport mechanism used | `streamable-http`, `stdio` | No | + +#### Span creation + +- Create a span when an MCP session is established and end it when the session is terminated +- Span name: `mcp.session` + +### MCP Operation + +An MCP operation represents a complete client-server interaction for methods such as tool calls, prompt retrieval, and other protocol-defined operations. + +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `mcp.session.id` | string | Identifier for the MCP session | `c52f5ef3-c7a1-4f7a-a2e3-e38a7a4966d2` | No | +| `mcp.request.type` | string | The MCP operation being performed | `tools.call`, `prompts.get` | Yes | +| `mcp.request.name` | string | Name of the tool or prompt, or URI template for resource | `GetFileInfo`, `file://path/to/file` | No | +| `mcp.request.parameter.` | string | parameter values for tool calls, prompts or substitutions in URI templates | `New York` | No | +| `mcp.request.id` | string | Identifier for the message | `msg_01234567` | No | +| `mcp.client.name` | string | Name of the MCP client | `mcp-js-client` | No | +| `mcp.client.version` | string | Version of the MCP client | `1.0.0` | No | +| `mcp.server.name` | string | Name of the MCP server | `mcp-cs-server` | No | +| `mcp.server.version` | string | Version of the MCP server | `1.0.0` | No | +| `mcp.notification.method` | string | Method for resource change notifications | `notifications/resources/list_changed` | No | + +The schema for MCP attributes does not change according to the type of MCP call that is being made. The attribute pair of `mcp.request.type` and `mcp.request.name` will provide the type and target of the mcp call. +For resource calls, the name should be the URI template for the request, without any value substitutions. + +`mcp.request.parameter.` can be used to log parameters for MCP tool calls and prompts, and for URI template substitutions for resources. As the parameter values are the most likely to contain sensitive or PII information, emitting these values should be guarded behind a flag or other implementation specific control mechanism to only emit the data when safe to do so, for example when running under a debugger. + +#### Span creation + +For clients: +- Create a span when an MCP request is initiated and end it when the response is received +- Span name: `mcp./`, e.g., `mcp.tools.call/GetFileInfo` + +For servers: +- Create a span when an MCP request is received and end it when the response is sent +- Span name: `mcp./`, e.g., `mcp.tools.call/GetFileInfo` + +## Metrics + +### MCP Session Duration + +| Name | Instrument | Unit | Description | +|---|---|---|---| +| `mcp.session.duration` | Histogram | s | Measures the duration of an MCP session in seconds | + +this metric SHOULD be specified with +[`ExplicitBucketBoundaries`](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.43.0/specification/metrics/api.md#instrument-advisory-parameters) +of `[0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 30, 60, 120, 300]`. + +#### MCP Operation Duration + +| Name | Instrument | Unit | Description | +|---|---|---|---| +| `mcp.request.duration` | Histogram | s | Measures the duration of an MCP operation in seconds | + +this metric SHOULD be specified with +[`ExplicitBucketBoundaries`](https://github.com/open-telemetry/opentelemetry-specification/tree/v1.43.0/specification/metrics/api.md#instrument-advisory-parameters) +of `[ 0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10 ]`. + +> Note: These durations are different from those for http, as the http semantic conventions changed their units to seconds, but have not updated the histogram buckets to match. + +Attributes: +| Attribute | Type | Description | Examples | Required | +|---|---|---|---|---| +| `mcp.request.type` | string | The MCP operation being performed | `tools.call`, `prompts.get` | Yes | +| `mcp.request.name` | string | Name of the tool or prompt, or URI template for resource | `GetFileInfo`, `file://path/to/file` | No | + +## Rationale + +These conventions align with existing patterns in the OpenTelemetry ecosystem, particularly following similar patterns to HTTP semantic conventions and those for JSON-RPC. They provide consistent naming and structure across implementations while capturing the unique aspects of the Model Context Protocol. + +## Implementation Status + +Initial support for OpenTelemetry has been implemented in the [C# SDK for MCP](https://github.com/modelcontextprotocol/csharp-sdk/pull/183), which includes: +- Activity tracking for message handling +- Metrics for operation duration +- Appropriate naming conventions and attributes + +## References + +- [Model Context Protocol Specification](https://github.com/modelcontextprotocol/specification) +- [HTTP Semantic Conventions](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/http/http-spans.md) +- [C# SDK OpenTelemetry Implementation](https://github.com/modelcontextprotocol/csharp-sdk/pull/183) diff --git a/model/gen-ai/mcp/metrics.yaml b/model/gen-ai/mcp/metrics.yaml new file mode 100644 index 0000000000..b263a5cedd --- /dev/null +++ b/model/gen-ai/mcp/metrics.yaml @@ -0,0 +1,36 @@ +groups: + - id: metric_attributes.mcp + type: attribute_group + brief: 'MCP attributes' + attributes: + - ref: mcp.request.method + requirement_level: required + - ref: mcp.request.name + requirement_level: optional + + - id: metric.mcp.session.duration + type: metric + metric_name: mcp.session.duration + brief: "Duration of MCP sessions." + instrument: histogram + unit: "s" + stability: development + extends: metric_attributes.mcp + note: > + This metric SHOULD be specified with explicit bucket boundaries of: + `[0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 30, 60, 120, 300]`. + + - id: metric.mcp.request.duration + type: metric + metric_name: mcp.request.duration + brief: "Duration of MCP requests." + instrument: histogram + unit: "s" + stability: development + extends: metric_attributes.mcp + attributes: + - ref: mcp.response.is_error + requirement_level: optional + note: > + This metric SHOULD be specified with explicit bucket boundaries of: + `[0.005, 0.01, 0.025, 0.05, 0.075, 0.1, 0.25, 0.5, 0.75, 1, 2.5, 5, 7.5, 10]`. \ No newline at end of file diff --git a/model/gen-ai/mcp/registry.yaml b/model/gen-ai/mcp/registry.yaml new file mode 100644 index 0000000000..f89789d102 --- /dev/null +++ b/model/gen-ai/mcp/registry.yaml @@ -0,0 +1,96 @@ +groups: + - id: registry.mcp + type: attribute_group + display_name: MCP Attributes + brief: 'This document defines semantic convention attributes in the MCP namespace.' + attributes: + - id: mcp.session.id + type: string + brief: Identifier for the MCP session. + examples: ['c52f5ef3-c7a1-4f7a-a2e3-e38a7a4966d2'] + stability: development + + - id: mcp.transport + type: string + brief: Transport mechanism used. + examples: ['streamable-http', 'stdio'] + stability: development + + - id: mcp.request.method + type: string + brief: The MCP operation being performed, referred to as the method in the MCP specification. + examples: ['tools/call', 'prompts/get'] + stability: development + + - id: mcp.request.name + type: string + brief: Name of the tool or prompt, or URI template for resource. + note: > + For Tools and Prompts, this maps to the `params/name` field in the MCP specification. + + For URI templates, this maps to the `params/uri` field in the MCP specification. + + For Resources with a URI template, the URI template should be reported using this field, without the value substitutions. + Optionally the template values can be reported with the `mcp.request.arguments.` fields. + examples: ['GetFileInfo', 'file://{path_to_file}', 'https://api.example.com/resource/{resource_id}'] + stability: development + + - id: mcp.request.arguments. + type: string + brief: Argument values for tool calls, prompts, or substitutions in URI templates. + note: > + `mcp.request.parameter.` should be used to enumerate the arguments and values for requests: + - Prompts: `mcp.request.arguments.` should be used for arguments pased when calling the prompt. + - Tools: `mcp.request.arguments.` should be used for arguments passed when calling the tool. + can be used to log parameters for MCP tool calls and prompts, and for URI template substitutions for resources. + As the parameter values are the most likely to contain sensitive or PII information, emitting these values should be guarded behind a flag or other implementation specific control mechanism to only emit the data when safe to do so, for example when running in a debug environment. + examples: ['New York'] + stability: development + + - id: mcp.request.id + type: string + brief: Identifier for the message. + examples: ['msg_01234567'] + stability: development + + - id: mcp.response.error + type: string + brief: If the response was an error, the error message should be returned using this field. This can be used to log both protocol errors and application errors. + examples: ['Unknown tool: invalid_tool_name', 'Failed to fetch weather data: API rate limit exceeded'] + stability: development + + - id: mcp.client.name + type: string + brief: Name of the MCP client. + examples: ['mcp-js-client'] + stability: development + + - id: mcp.client.version + type: string + brief: Version of the MCP client. + examples: ['1.0.0'] + stability: development + + - id: mcp.server.name + type: string + brief: Name of the MCP server. + examples: ['mcp-cs-server'] + stability: development + + - id: mcp.server.version + type: string + brief: Version of the MCP server. + examples: ['1.0.0'] + stability: development + + - id: mcp.notification.method + type: string + brief: Method for change notifications, including the lists of prompts, tools and resources or change notifications for resources subscription requests + examples: ['notifications/resources/list_changed'] + stability: development + + - id: mcp.response.is_error + type: bool + brief: Used for metrics to indicate if the request was an error or not. + examples: ['notifications/resources/list_changed'] + stability: development \ No newline at end of file diff --git a/model/gen-ai/mcp/spans.yaml b/model/gen-ai/mcp/spans.yaml new file mode 100644 index 0000000000..8ab198c66f --- /dev/null +++ b/model/gen-ai/mcp/spans.yaml @@ -0,0 +1,60 @@ +groups: + - id: span.mcp.session + type: span + span_kind: [server] + stability: stable + brief: > + This span represents the lifecycle of an MCP session. + note: | + Create a span when an MCP session is established and end it when the session is terminated. + + **Span name:** `mcp.session` + + **Span kind** MUST be `SERVER`. + + attributes: + - ref: mcp.session.id + requirement_level: required + sampling_relevant: true + - ref: mcp.transport + requirement_level: optional + + - id: span.mcp.operation + type: span + span_kind: client + stability: stable + brief: > + This span represents a complete client-server interaction for MCP operations. + note: | + For: + - Requests - Create a span when an MCP request is initiated and end it when the response is received. + - Notifications - Create a span when an MCP notification is sent as there is no active response. + + **Span name:** `mcp./` (e.g., `mcp.tools.call/GetFileInfo`) + + **Span kind** MAY be `CLIENT` or `SERVER`. + + attributes: + - ref: mcp.session.id + requirement_level: optional + - ref: mcp.request.method + requirement_level: required + sampling_relevant: true + - ref: mcp.request.name + requirement_level: optional + - ref: mcp.request.arguments. + requirement_level: optional + - ref: mcp.request.id + requirement_level: optional + - ref: mcp.response.error + requirement_level: optional + - ref: mcp.client.name + requirement_level: optional + - ref: mcp.client.version + requirement_level: optional + - ref: mcp.server.name + requirement_level: optional + - ref: mcp.server.version + requirement_level: optional + - ref: mcp.notification.method + requirement_level: optional \ No newline at end of file