diff --git a/.chloggen/2083.yaml b/.chloggen/2083.yaml
new file mode 100644
index 0000000000..e23949a527
--- /dev/null
+++ b/.chloggen/2083.yaml
@@ -0,0 +1,4 @@
+change_type: enhancement
+component: mcp
+note: Add MCP semantic conventions
+issues: [2043, 2083]
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 70c40c5469..70a9d2e5dd 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -105,6 +105,7 @@
/docs/gen-ai/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-genai-approvers
/model/gen-ai/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-genai-approvers
/model/openai/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-genai-approvers
+/model/mcp/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-genai-approvers
# Security semantic conventions
/docs/dns/ @open-telemetry/specs-semconv-approvers @open-telemetry/semconv-security-approvers
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index 72dd7fbd48..760104a9c6 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -68,6 +68,7 @@ body:
- area:k8s
- area:log
- area:mainframe
+ - area:mcp
- area:messaging
- area:network
- area:nfs
diff --git a/.github/ISSUE_TEMPLATE/change_proposal.yaml b/.github/ISSUE_TEMPLATE/change_proposal.yaml
index 9920af2bc9..713fa0d4e2 100644
--- a/.github/ISSUE_TEMPLATE/change_proposal.yaml
+++ b/.github/ISSUE_TEMPLATE/change_proposal.yaml
@@ -60,6 +60,7 @@ body:
- area:k8s
- area:log
- area:mainframe
+ - area:mcp
- area:messaging
- area:network
- area:nfs
diff --git a/.github/ISSUE_TEMPLATE/new-conventions.yaml b/.github/ISSUE_TEMPLATE/new-conventions.yaml
index 007cbe2ddd..e75cc16afb 100644
--- a/.github/ISSUE_TEMPLATE/new-conventions.yaml
+++ b/.github/ISSUE_TEMPLATE/new-conventions.yaml
@@ -71,6 +71,7 @@ body:
- area:k8s
- area:log
- area:mainframe
+ - area:mcp
- area:messaging
- area:network
- area:nfs
diff --git a/AREAS.md b/AREAS.md
index 0b78b5f191..b23d7433b1 100644
--- a/AREAS.md
+++ b/AREAS.md
@@ -28,7 +28,7 @@ their owners, related project (and project board) as well as its current status.
|------|--------|---------|-------|-------|--------|-------|
| Semantic Conventions: System | [semconv-system-approvers](https://github.com/orgs/open-telemetry/teams/semconv-system-approvers) | https://github.com/open-telemetry/community/blob/main/projects/system-semconv.md | https://github.com/orgs/open-telemetry/projects/55 | `area:system`, `area:host`, `area:process`, `area:nfs`, `area:os`, `area:cpu`, `area:disk`, `area:network`, `area:linux` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
| Semantic Conventions: K8s | [semconv-k8s-approvers](https://github.com/orgs/open-telemetry/teams/semconv-k8s-approvers) | https://github.com/open-telemetry/community/blob/main/projects/k8s-semconv.md | https://github.com/orgs/open-telemetry/projects/114 | `area:k8s`, `area:container`, `area:oci` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
-| Semantic Conventions: GenAI | [semconv-genai-approvers](https://github.com/orgs/open-telemetry/teams/semconv-genai-approvers) | https://github.com/open-telemetry/community/blob/main/projects/gen-ai.md | https://github.com/orgs/open-telemetry/projects/82 | `area:gen-ai`, `area:openai` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
+| Semantic Conventions: GenAI | [semconv-genai-approvers](https://github.com/orgs/open-telemetry/teams/semconv-genai-approvers) | https://github.com/open-telemetry/community/blob/main/projects/gen-ai.md | https://github.com/orgs/open-telemetry/projects/82 | `area:gen-ai`, `area:openai`, `area:mcp` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
| Semantic Conventions: CI/CD | [semconv-cicd-approvers](https://github.com/orgs/open-telemetry/teams/semconv-cicd-approvers) | https://github.com/open-telemetry/community/blob/main/projects/ci-cd-phase-2.md | https://github.com/orgs/open-telemetry/projects/79 | `area:cicd`, `area:artifact`, `area:deployment`, `area:test`, `area:vcs` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
| Semantic Conventions: Security | [semconv-security-approvers](https://github.com/orgs/open-telemetry/teams/semconv-security-approvers) | https://github.com/open-telemetry/community/blob/main/projects/security-semconv.md | https://github.com/orgs/open-telemetry/projects/104 | `area:security`, `area:log`, `area:user`, `area:dns`, `area:file`, `area:tls`, `area:network`, `area:process` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
| Semantic Conventions: Browser Instrumentation | [semconv-browser-approvers](https://github.com/orgs/open-telemetry/teams/semconv-browser-approvers) | https://github.com/open-telemetry/community/blob/main/projects/browser-phase-1.md | https://github.com/orgs/open-telemetry/projects/146 | `area:browser` | `accepting_contributions`, `active` | The SIG is looking for contributions! |
diff --git a/areas.yaml b/areas.yaml
index de54794d0c..ffb47d536d 100644
--- a/areas.yaml
+++ b/areas.yaml
@@ -42,6 +42,7 @@ areas:
labels:
- area:gen-ai
- area:openai
+ - area:mcp
status:
- accepting_contributions
- active
diff --git a/docs/gen-ai/README.md b/docs/gen-ai/README.md
index 9d927cfc94..19921b967e 100644
--- a/docs/gen-ai/README.md
+++ b/docs/gen-ai/README.md
@@ -40,4 +40,8 @@ Technology specific semantic conventions are defined for the following GenAI sys
* [OpenAI](./openai.md): Semantic Conventions for OpenAI.
* [AWS Bedrock](./aws-bedrock.md): Semantic Conventions for AWS Bedrock.
+See also:
+
+* [Model Context Protocol](./mcp.md): Semantic Conventions for [MCP](https://modelcontextprotocol.io)
+
[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status
diff --git a/docs/gen-ai/gen-ai-spans.md b/docs/gen-ai/gen-ai-spans.md
index c4e10aaa7f..96ffadc8f6 100644
--- a/docs/gen-ai/gen-ai-spans.md
+++ b/docs/gen-ai/gen-ai-spans.md
@@ -364,10 +364,15 @@ Describes tool execution span.
**Span name** SHOULD be `execute_tool {gen_ai.tool.name}`.
-GenAI instrumentations that are able to instrument tool execution call SHOULD do so.
-However, it's common for tools to be executed by the application code. It's recommended
-for the application developers to follow this semantic convention for tools invoked
-by the application code.
+GenAI instrumentations that can instrument tool execution calls SHOULD do so,
+unless another instrumentation can reliably cover all supported tool types.
+MCP tool executions may also be traced by the
+[corresponding MCP instrumentation](/docs/gen-ai/mcp.md#client).
+
+Tools are often executed directly by application code. Application developers
+are encouraged to follow this semantic convention for tools invoked by their
+own code and to manually instrument any tool calls that automatic
+instrumentations do not cover.
**Span kind** SHOULD be `INTERNAL`.
diff --git a/docs/gen-ai/mcp.md b/docs/gen-ai/mcp.md
new file mode 100644
index 0000000000..0ff7b1342b
--- /dev/null
+++ b/docs/gen-ai/mcp.md
@@ -0,0 +1,1119 @@
+
+
+# Semantic conventions for Model Context Protocol (MCP)
+
+**Status**: [Development][DocumentStatus]
+
+
+
+- [Spans](#spans)
+ - [Context propagation](#context-propagation)
+ - [Client](#client)
+ - [Server](#server)
+- [Metrics](#metrics)
+ - [Metric: `mcp.client.operation.duration`](#metric-mcpclientoperationduration)
+ - [Metric: `mcp.server.operation.duration`](#metric-mcpserveroperationduration)
+ - [Metric: `mcp.client.session.duration`](#metric-mcpclientsessionduration)
+ - [Metric: `mcp.server.session.duration`](#metric-mcpserversessionduration)
+- [Recording MCP transport](#recording-mcp-transport)
+- [Examples](#examples)
+ - [Stdio transport](#stdio-transport)
+ - [Initialize](#initialize)
+ - [Tool call](#tool-call)
+ - [Streamable HTTP](#streamable-http)
+ - [Initialize](#initialize-1)
+ - [Tool call](#tool-call-1)
+
+
+
+[Model Context Protocol](https://github.com/modelcontextprotocol/modelcontextprotocol) (MCP) is based on JSON RPC.
+
+When instrumenting MCP calls, it's RECOMMENDED to follow MCP conventions instead of [RPC semantic conventions](/docs/rpc/README.md)
+since MCP spans and metrics provide domain-specific context and record details
+that are not covered by the RPC conventions such as message exchanges within streaming calls.
+
+HTTP conventions (when HTTP is used as transport) do not adequately cover MCP requests
+and notifications either, given that multiple MCP requests could be sent over a single
+HTTP request in the corresponding request and response streams.
+
+## Spans
+
+### Context propagation
+
+Model Context Protocol works on top of JSON-RPC and does not define a standard
+Trace Context propagation mechanism. MCP is transport independent and works across different transports. The specification expects clients to implement at least stdio or Streamable HTTP.
+
+HTTP trace context propagation only covers the HTTP request, but not the individual
+messages client and server exchange within the request/response streams.
+
+Instrumentations SHOULD propagate trace context inside MCP request [`params._meta`](https://modelcontextprotocol.io/specification/2025-11-25/basic#_meta)
+property bag.
+
+> [!NOTE]
+> The propagation format defined here is likely to change. Please check out
+> context propagation discussions in MCP repository:
+> [modelcontextprotocol#246](https://github.com/modelcontextprotocol/modelcontextprotocol/issues/246)
+> and
+> [modelcontextprotocol#414](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/414).
+>
+> If the MCP or JSON-RPC specifications provide official guidance, instrumentations
+> SHOULD prioritize that over the recommendation provided in this section.
+
+For example, when using [W3C Trace Context](https://www.w3.org/TR/trace-context/) propagation,
+inject `traceparent` and `tracestate` to the MCP message `params._meta` when creating request
+or notification and extract them on the receiver side to use as the remote parent.
+
+Here's an example of tool call request with injected trace context.
+
+```json
+{
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "get-weather",
+ "_meta": {
+ "traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
+ "tracestate": "rojo=00f067aa0ba902b7,congo=t61rcWkgMzE"
+ }
+ },
+ "id": 1,
+}
+```
+
+Or, if user application uses [W3C Baggage](https://www.w3.org/TR/baggage/) in addition
+to the Trace-Context, `baggage` should be propagated in the same `params._meta`
+property bag similarly to the following example:
+
+```json
+{
+ "jsonrpc": "2.0",
+ "method": "tools/call",
+ "params": {
+ "name": "get-weather",
+ "_meta": {
+ "traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
+ "baggage": "userId=alice,serverNode=DF%2028,isProduction=false"
+ }
+ },
+ "id": 1,
+}
+```
+
+MCP server instrumentation SHOULD, by default, use context extracted from MCP
+`params._meta` as a parent for MCP server span and SHOULD link current ambient
+context, if it's present.
+
+> [!NOTE]
+> MCP and underlying transport (such as HTTP) contexts are independent. One MCP
+> request can be served by multiple HTTP requests (for example, because of retries)
+> and one streamable HTTP request can serve more than one MCP request/notification.
+> The MCP client span becomes a parent of the MCP server span regardless of transport used;
+> span links allow recording the transport context (if present).
+
+### Client
+
+
+
+
+
+
+**Status:** 
+
+This span describes the MCP call from the client side.
+
+It's reported by the MCP client when it initiates the request
+or notification or by the MCP server when server initiates the operation.
+It covers the time to receive the response or ack from the peer.
+
+**Span name** SHOULD follow the format `{mcp.method.name} {target}`
+where target SHOULD match `{gen_ai.tool.name}` or `{gen_ai.prompt.name}` when
+applicable.
+If there is no low-cardinality `target` available, the Span name SHOULD be `{mcp.method.name}`.
+
+Instrumentation MAY allow users to opt into including `{mcp.resource.uri}`
+as `target` in the span name when it is available but SHOULD NOT include it by default
+to avoid high cardinality span names.
+
+**Span status** SHOULD be set to `ERROR` when `error.type` attribute is present.
+The status description SHOULD match the `JSONRPCError.message` if the message is available.
+
+Refer to the [Recording Errors](/docs/general/recording-errors.md) document
+for more details.
+
+MCP tool call execution spans are compatible with GenAI [execute_tool spans](/docs/gen-ai/gen-ai-spans.md#execute-tool-span).
+
+If the MCP instrumentation can reliably detect that outer GenAI instrumentation
+is already tracing the tool execution, it SHOULD NOT create a separate span.
+Instead, it SHOULD add MCP-specific attributes to the existing tool execution span.
+
+Instrumentations that support this behavior MAY provide a configuration
+option to enable it.
+
+**Span kind** SHOULD be `CLIENT`.
+
+**Attributes:**
+
+| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values |
+| --- | --- | --- | --- | --- | --- |
+| [`mcp.method.name`](/docs/registry/attributes/mcp.md) |  | `Required` | string | The name of the request or notification method. | `notifications/cancelled`; `initialize`; `notifications/initialized` |
+| [`error.type`](/docs/registry/attributes/error.md) |  | `Conditionally Required` If and only if the operation fails. | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` |
+| [`gen_ai.prompt.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific prompt. | string | The name of the prompt or prompt template provided in the request or response. | `analyze-code` |
+| [`gen_ai.tool.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific tool. | string | Name of the tool utilized by the agent. | `Flights` |
+| [`jsonrpc.request.id`](/docs/registry/attributes/jsonrpc.md) |  | `Conditionally Required` When the client executes a request. | string | A string representation of the `id` property of the request and its corresponding response. [2] | `10`; `request-7` |
+| [`mcp.resource.uri`](/docs/registry/attributes/mcp.md) |  | `Conditionally Required` [3] | string | The value of the resource uri. [4] | `postgres://database/customers/schema`; `file:///home/user/documents/report.pdf` |
+| [`rpc.response.status_code`](/docs/registry/attributes/rpc.md) |  | `Conditionally Required` If response contains an error code. | string | The error code from the JSON-RPC response. [5] | `OK`; `DEADLINE_EXCEEDED`; `-32602` |
+| [`gen_ai.operation.name`](/docs/registry/attributes/gen-ai.md) |  | `Recommended` [6] | string | The name of the GenAI operation being performed. [7] | `execute_tool` |
+| [`jsonrpc.protocol.version`](/docs/registry/attributes/jsonrpc.md) |  | `Recommended` when it's not `2.0`. | string | Protocol version, as specified in the `jsonrpc` property of the request and its corresponding response. | `2.0`; `1.0` |
+| [`mcp.protocol.version`](/docs/registry/attributes/mcp.md) |  | `Recommended` | string | The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used. | `2025-06-18` |
+| [`mcp.session.id`](/docs/registry/attributes/mcp.md) |  | `Recommended` [8] | string | Identifies [MCP session](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#session-management). | `191c4850af6c49e08843a3f6c80e5046` |
+| [`network.protocol.name`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | [OSI application layer](https://wikipedia.org/wiki/Application_layer) or non-OSI equivalent. [9] | `http`; `websocket` |
+| [`network.protocol.version`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | The actual version of the protocol used for network communication. | `1.1`; `2` |
+| [`network.transport`](/docs/registry/attributes/network.md) |  | `Recommended` | string | The transport protocol used for the MCP session. [10] | `tcp`; `quic`; `pipe` |
+| [`server.address`](/docs/registry/attributes/server.md) |  | `Recommended` If applicable | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [11] | `example.com`; `10.1.2.80`; `/tmp/my.sock` |
+| [`server.port`](/docs/registry/attributes/server.md) |  | `Recommended` When `server.address` is set | int | Server port number. [12] | `80`; `8080`; `443` |
+| [`gen_ai.tool.call.arguments`](/docs/registry/attributes/gen-ai.md) |  | `Opt-In` | any | Parameters passed to the tool call. [13] | {
"location": "San Francisco?",
"date": "2025-10-01"
} |
+| [`gen_ai.tool.call.result`](/docs/registry/attributes/gen-ai.md) |  | `Opt-In` | any | The result returned by the tool call (if any and if execution was successful). [14] | {
"temperature_range": {
"high": 75,
"low": 60
},
"conditions": "sunny"
} |
+
+**[1] `error.type`:** This attribute SHOULD be set to the string representation of the JSON-RPC
+error code, if one is returned.
+
+When JSON-RPC call is successful, but an error is returned within the
+result payload, this attribute SHOULD be set to the low-cardinality
+string representation of the error. When
+[CallToolResult](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/9c8a44e47e16b789a1f9d47c89ea23ed13a37cf9/schema/2025-06-18/schema.ts#L715)
+is returned with `isError` set to `true`, this attribute SHOULD be set to
+`tool_error`.
+
+**[2] `jsonrpc.request.id`:** Under the [JSON-RPC specification](https://www.jsonrpc.org/specification), the `id` property may be a string, number, null, or omitted entirely. When omitted, the request is treated as a notification. Using `null` is not equivalent to omitting the `id`, but it is discouraged.
+Instrumentations SHOULD NOT capture this attribute when the `id` is `null` or omitted.
+
+**[3] `mcp.resource.uri`:** When the client executes a request type that includes a resource URI parameter.
+
+**[4] `mcp.resource.uri`:** This is a URI of the resource provided in the following requests or notifications: `resources/read`, `resources/subscribe`, `resources/unsubscribe`, or `notifications/resources/updated`.
+
+**[5] `rpc.response.status_code`:** Usually it represents an error code, but may also represent partial success, warning, or differentiate between various types of successful outcomes.
+Semantic conventions for individual RPC frameworks SHOULD document what `rpc.response.status_code` means in the context of that system and which values are considered to represent errors.
+
+**[6] `gen_ai.operation.name`:** SHOULD be set to `execute_tool` when the operation describes a tool call and SHOULD NOT be set otherwise.
+
+**[7] `gen_ai.operation.name`:** Populating this attribute for tool calling along with `mcp.method.name` allows consumers to treat MCP tool calls spans similarly with other tool call types.
+
+**[8] `mcp.session.id`:** When the MCP request or notification is part of a session.
+
+**[9] `network.protocol.name`:** The value SHOULD be normalized to lowercase.
+
+**[10] `network.transport`:** This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+is HTTP.
+It SHOULD be set to `pipe` if the transport is stdio.
+
+**[11] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.
+
+**[12] `server.port`:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.
+
+**[13] `gen_ai.tool.call.arguments`:**
+
+> [!WARNING]
+> This attribute may contain sensitive information.
+
+It's expected to be an object - in case a serialized string is available
+to the instrumentation, the instrumentation SHOULD do the best effort to
+deserialize it to an object. When recorded on spans, it MAY be recorded as a JSON string if structured format is not supported and SHOULD be recorded in structured form otherwise.
+
+**[14] `gen_ai.tool.call.result`:**
+
+> [!WARNING]
+> This attribute may contain sensitive information.
+
+It's expected to be an object - in case a serialized string is available
+to the instrumentation, the instrumentation SHOULD do the best effort to
+deserialize it to an object. When recorded on spans, it MAY be recorded as a JSON string if structured format is not supported and SHOULD be recorded in structured form otherwise.
+
+---
+
+`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. |  |
+
+---
+
+`gen_ai.operation.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `chat` | Chat completion operation such as [OpenAI Chat API](https://platform.openai.com/docs/api-reference/chat) |  |
+| `create_agent` | Create GenAI agent |  |
+| `embeddings` | Embeddings operation such as [OpenAI Create embeddings API](https://platform.openai.com/docs/api-reference/embeddings/create) |  |
+| `execute_tool` | Execute a tool |  |
+| `generate_content` | Multimodal content generation operation such as [Gemini Generate Content](https://ai.google.dev/api/generate-content) |  |
+| `invoke_agent` | Invoke GenAI agent |  |
+| `text_completion` | Text completions operation such as [OpenAI Completions API (Legacy)](https://platform.openai.com/docs/api-reference/completions) |  |
+
+---
+
+`mcp.method.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `completion/complete` | Request to complete a prompt. |  |
+| `elicitation/create` | Request from the server to elicit additional information from the user via the client |  |
+| `initialize` | Request to initialize the MCP client. |  |
+| `logging/setLevel` | Request to set the logging level. |  |
+| `notifications/cancelled` | Notification cancelling a previously-issued request. |  |
+| `notifications/initialized` | Notification indicating that the MCP client has been initialized. |  |
+| `notifications/message` | Notification indicating that a message has been received. |  |
+| `notifications/progress` | Notification indicating the progress for a long-running operation. |  |
+| `notifications/prompts/list_changed` | Notification indicating that the list of prompts has changed. |  |
+| `notifications/resources/list_changed` | Notification indicating that the list of resources has changed. |  |
+| `notifications/resources/updated` | Notification indicating that a resource has been updated. |  |
+| `notifications/roots/list_changed` | Notification indicating that the list of roots has changed. |  |
+| `notifications/tools/list_changed` | Notification indicating that the list of tools has changed. |  |
+| `ping` | Request to check that the other party is still alive. |  |
+| `prompts/get` | Request to get a prompt. |  |
+| `prompts/list` | Request to list prompts available on server. |  |
+| `resources/list` | Request to list resources available on server. |  |
+| `resources/read` | Request to read a resource. |  |
+| `resources/subscribe` | Request to subscribe to a resource. |  |
+| `resources/templates/list` | Request to list resource templates available on server. |  |
+| `resources/unsubscribe` | Request to unsubscribe from resource updates. |  |
+| `roots/list` | Request to list roots available on server. |  |
+| `sampling/createMessage` | Request to create a sampling message. |  |
+| `tools/call` | Request to call a tool. |  |
+| `tools/list` | Request to list tools available on server. |  |
+
+---
+
+`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `pipe` | Named or anonymous pipe. |  |
+| `quic` | QUIC |  |
+| `tcp` | TCP |  |
+| `udp` | UDP |  |
+| `unix` | Unix domain socket |  |
+
+
+
+
+
+### Server
+
+
+
+
+
+
+**Status:** 
+
+This span describes the processing of the MCP request or notification initiated by the peer.
+
+It's reported by the MCP server when client initiates the request
+(or notification) or by the MCP client when server initiates the operation.
+
+**Span name** SHOULD follow the format `{mcp.method.name} {target}`
+where target SHOULD match `{gen_ai.tool.name}` or `{gen_ai.prompt.name}` when
+applicable.
+If there is no low-cardinality `target` available, the Span name SHOULD be `{mcp.method.name}`.
+
+Instrumentation MAY allow users to opt into including `{mcp.resource.uri}`
+as `target` in the span name when it is available but SHOULD NOT include it by default
+to avoid high cardinality span names.
+
+**Span status** SHOULD be set to `ERROR` when `error.type` attribute is present.
+The status description SHOULD match the `JSONRPCError.message` if the message is available.
+
+Refer to the [Recording Errors](/docs/general/recording-errors.md) document
+for more details.
+
+**Span kind** SHOULD be `SERVER`.
+
+**Attributes:**
+
+| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values |
+| --- | --- | --- | --- | --- | --- |
+| [`mcp.method.name`](/docs/registry/attributes/mcp.md) |  | `Required` | string | The name of the request or notification method. | `notifications/cancelled`; `initialize`; `notifications/initialized` |
+| [`error.type`](/docs/registry/attributes/error.md) |  | `Conditionally Required` If and only if the operation fails. | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` |
+| [`gen_ai.prompt.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific prompt. | string | The name of the prompt or prompt template provided in the request or response. | `analyze-code` |
+| [`gen_ai.tool.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific tool. | string | Name of the tool utilized by the agent. | `Flights` |
+| [`jsonrpc.request.id`](/docs/registry/attributes/jsonrpc.md) |  | `Conditionally Required` When the client executes a request. | string | A string representation of the `id` property of the request and its corresponding response. [2] | `10`; `request-7` |
+| [`mcp.resource.uri`](/docs/registry/attributes/mcp.md) |  | `Conditionally Required` [3] | string | The value of the resource uri. [4] | `postgres://database/customers/schema`; `file:///home/user/documents/report.pdf` |
+| [`rpc.response.status_code`](/docs/registry/attributes/rpc.md) |  | `Conditionally Required` If response contains an error code. | string | The error code from the JSON-RPC response. [5] | `OK`; `DEADLINE_EXCEEDED`; `-32602` |
+| [`client.address`](/docs/registry/attributes/client.md) |  | `Recommended` If applicable | string | Client address - domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [6] | `client.example.com`; `10.1.2.80`; `/tmp/my.sock` |
+| [`client.port`](/docs/registry/attributes/client.md) |  | `Recommended` When `client.address` is set | int | Client port number. [7] | `65123` |
+| [`gen_ai.operation.name`](/docs/registry/attributes/gen-ai.md) |  | `Recommended` [8] | string | The name of the GenAI operation being performed. [9] | `execute_tool` |
+| [`jsonrpc.protocol.version`](/docs/registry/attributes/jsonrpc.md) |  | `Recommended` when it's not `2.0`. | string | Protocol version, as specified in the `jsonrpc` property of the request and its corresponding response. | `2.0`; `1.0` |
+| [`mcp.protocol.version`](/docs/registry/attributes/mcp.md) |  | `Recommended` | string | The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used. | `2025-06-18` |
+| [`mcp.session.id`](/docs/registry/attributes/mcp.md) |  | `Recommended` [10] | string | Identifies [MCP session](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#session-management). | `191c4850af6c49e08843a3f6c80e5046` |
+| [`network.protocol.name`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | [OSI application layer](https://wikipedia.org/wiki/Application_layer) or non-OSI equivalent. [11] | `http`; `websocket` |
+| [`network.protocol.version`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | The actual version of the protocol used for network communication. | `1.1`; `2` |
+| [`network.transport`](/docs/registry/attributes/network.md) |  | `Recommended` | string | The transport protocol used for the MCP session. [12] | `tcp`; `quic`; `pipe` |
+
+**[1] `error.type`:** This attribute SHOULD be set to the string representation of the JSON-RPC
+error code, if one is returned.
+
+When JSON-RPC call is successful, but an error is returned within the
+result payload, this attribute SHOULD be set to the low-cardinality
+string representation of the error. When
+[CallToolResult](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/9c8a44e47e16b789a1f9d47c89ea23ed13a37cf9/schema/2025-06-18/schema.ts#L715)
+is returned with `isError` set to `true`, this attribute SHOULD be set to
+`tool_error`.
+
+**[2] `jsonrpc.request.id`:** Under the [JSON-RPC specification](https://www.jsonrpc.org/specification), the `id` property may be a string, number, null, or omitted entirely. When omitted, the request is treated as a notification. Using `null` is not equivalent to omitting the `id`, but it is discouraged.
+Instrumentations SHOULD NOT capture this attribute when the `id` is `null` or omitted.
+
+**[3] `mcp.resource.uri`:** When the client executes a request type that includes a resource URI parameter.
+
+**[4] `mcp.resource.uri`:** This is a URI of the resource provided in the following requests or notifications: `resources/read`, `resources/subscribe`, `resources/unsubscribe`, or `notifications/resources/updated`.
+
+**[5] `rpc.response.status_code`:** Usually it represents an error code, but may also represent partial success, warning, or differentiate between various types of successful outcomes.
+Semantic conventions for individual RPC frameworks SHOULD document what `rpc.response.status_code` means in the context of that system and which values are considered to represent errors.
+
+**[6] `client.address`:** When observed from the server side, and when communicating through an intermediary, `client.address` SHOULD represent the client address behind any intermediaries, for example proxies, if it's available.
+
+**[7] `client.port`:** When observed from the server side, and when communicating through an intermediary, `client.port` SHOULD represent the client port behind any intermediaries, for example proxies, if it's available.
+
+**[8] `gen_ai.operation.name`:** SHOULD be set to `execute_tool` when the operation describes a tool call and SHOULD NOT be set otherwise.
+
+**[9] `gen_ai.operation.name`:** Populating this attribute for tool calling along with `mcp.method.name` allows consumers to treat MCP tool calls spans similarly with other tool call types.
+
+**[10] `mcp.session.id`:** When the MCP request or notification is part of a session.
+
+**[11] `network.protocol.name`:** The value SHOULD be normalized to lowercase.
+
+**[12] `network.transport`:** This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+is HTTP.
+It SHOULD be set to `pipe` if the transport is stdio.
+
+---
+
+`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. |  |
+
+---
+
+`gen_ai.operation.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `chat` | Chat completion operation such as [OpenAI Chat API](https://platform.openai.com/docs/api-reference/chat) |  |
+| `create_agent` | Create GenAI agent |  |
+| `embeddings` | Embeddings operation such as [OpenAI Create embeddings API](https://platform.openai.com/docs/api-reference/embeddings/create) |  |
+| `execute_tool` | Execute a tool |  |
+| `generate_content` | Multimodal content generation operation such as [Gemini Generate Content](https://ai.google.dev/api/generate-content) |  |
+| `invoke_agent` | Invoke GenAI agent |  |
+| `text_completion` | Text completions operation such as [OpenAI Completions API (Legacy)](https://platform.openai.com/docs/api-reference/completions) |  |
+
+---
+
+`mcp.method.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `completion/complete` | Request to complete a prompt. |  |
+| `elicitation/create` | Request from the server to elicit additional information from the user via the client |  |
+| `initialize` | Request to initialize the MCP client. |  |
+| `logging/setLevel` | Request to set the logging level. |  |
+| `notifications/cancelled` | Notification cancelling a previously-issued request. |  |
+| `notifications/initialized` | Notification indicating that the MCP client has been initialized. |  |
+| `notifications/message` | Notification indicating that a message has been received. |  |
+| `notifications/progress` | Notification indicating the progress for a long-running operation. |  |
+| `notifications/prompts/list_changed` | Notification indicating that the list of prompts has changed. |  |
+| `notifications/resources/list_changed` | Notification indicating that the list of resources has changed. |  |
+| `notifications/resources/updated` | Notification indicating that a resource has been updated. |  |
+| `notifications/roots/list_changed` | Notification indicating that the list of roots has changed. |  |
+| `notifications/tools/list_changed` | Notification indicating that the list of tools has changed. |  |
+| `ping` | Request to check that the other party is still alive. |  |
+| `prompts/get` | Request to get a prompt. |  |
+| `prompts/list` | Request to list prompts available on server. |  |
+| `resources/list` | Request to list resources available on server. |  |
+| `resources/read` | Request to read a resource. |  |
+| `resources/subscribe` | Request to subscribe to a resource. |  |
+| `resources/templates/list` | Request to list resource templates available on server. |  |
+| `resources/unsubscribe` | Request to unsubscribe from resource updates. |  |
+| `roots/list` | Request to list roots available on server. |  |
+| `sampling/createMessage` | Request to create a sampling message. |  |
+| `tools/call` | Request to call a tool. |  |
+| `tools/list` | Request to list tools available on server. |  |
+
+---
+
+`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `pipe` | Named or anonymous pipe. |  |
+| `quic` | QUIC |  |
+| `tcp` | TCP |  |
+| `udp` | UDP |  |
+| `unix` | Unix domain socket |  |
+
+
+
+
+
+## Metrics
+
+### Metric: `mcp.client.operation.duration`
+
+This metric is [recommended][MetricRecommended].
+
+This metric SHOULD be specified with
+[`ExplicitBucketBoundaries`](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.50.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 ]`.
+
+
+
+
+
+
+| Name | Instrument Type | Unit (UCUM) | Description | Stability | Entity Associations |
+| -------- | --------------- | ----------- | -------------- | --------- | ------ |
+| `mcp.client.operation.duration` | Histogram | `s` | The duration of the MCP request or notification as observed on the sender from the time it was sent until the response or ack is received. |  | |
+
+**Attributes:**
+
+| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values |
+| --- | --- | --- | --- | --- | --- |
+| [`mcp.method.name`](/docs/registry/attributes/mcp.md) |  | `Required` | string | The name of the request or notification method. | `notifications/cancelled`; `initialize`; `notifications/initialized` |
+| [`error.type`](/docs/registry/attributes/error.md) |  | `Conditionally Required` If and only if the operation fails. | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` |
+| [`gen_ai.prompt.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific prompt. | string | The name of the prompt or prompt template provided in the request or response. | `analyze-code` |
+| [`gen_ai.tool.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific tool. | string | Name of the tool utilized by the agent. | `Flights` |
+| [`rpc.response.status_code`](/docs/registry/attributes/rpc.md) |  | `Conditionally Required` If response contains an error code. | string | The error code from the JSON-RPC response. [2] | `OK`; `DEADLINE_EXCEEDED`; `-32602` |
+| [`gen_ai.operation.name`](/docs/registry/attributes/gen-ai.md) |  | `Recommended` [3] | string | The name of the GenAI operation being performed. [4] | `execute_tool` |
+| [`jsonrpc.protocol.version`](/docs/registry/attributes/jsonrpc.md) |  | `Recommended` when it's not `2.0`. | string | Protocol version, as specified in the `jsonrpc` property of the request and its corresponding response. | `2.0`; `1.0` |
+| [`mcp.protocol.version`](/docs/registry/attributes/mcp.md) |  | `Recommended` | string | The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used. | `2025-06-18` |
+| [`network.protocol.name`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | [OSI application layer](https://wikipedia.org/wiki/Application_layer) or non-OSI equivalent. [5] | `http`; `websocket` |
+| [`network.protocol.version`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | The actual version of the protocol used for network communication. | `1.1`; `2` |
+| [`network.transport`](/docs/registry/attributes/network.md) |  | `Recommended` | string | The transport protocol used for the MCP session. [6] | `tcp`; `quic`; `pipe` |
+| [`server.address`](/docs/registry/attributes/server.md) |  | `Recommended` If applicable | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [7] | `example.com`; `10.1.2.80`; `/tmp/my.sock` |
+| [`server.port`](/docs/registry/attributes/server.md) |  | `Recommended` When `server.address` is set | int | Server port number. [8] | `80`; `8080`; `443` |
+| [`mcp.resource.uri`](/docs/registry/attributes/mcp.md) |  | `Opt-In` | string | The value of the resource uri. [9] | `postgres://database/customers/schema`; `file:///home/user/documents/report.pdf` |
+
+**[1] `error.type`:** This attribute SHOULD be set to the string representation of the JSON-RPC
+error code, if one is returned.
+
+When JSON-RPC call is successful, but an error is returned within the
+result payload, this attribute SHOULD be set to the low-cardinality
+string representation of the error. When
+[CallToolResult](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/9c8a44e47e16b789a1f9d47c89ea23ed13a37cf9/schema/2025-06-18/schema.ts#L715)
+is returned with `isError` set to `true`, this attribute SHOULD be set to
+`tool_error`.
+
+**[2] `rpc.response.status_code`:** Usually it represents an error code, but may also represent partial success, warning, or differentiate between various types of successful outcomes.
+Semantic conventions for individual RPC frameworks SHOULD document what `rpc.response.status_code` means in the context of that system and which values are considered to represent errors.
+
+**[3] `gen_ai.operation.name`:** SHOULD be set to `execute_tool` when the operation describes a tool call and SHOULD NOT be set otherwise.
+
+**[4] `gen_ai.operation.name`:** Populating this attribute for tool calling along with `mcp.method.name` allows consumers to treat MCP tool calls spans similarly with other tool call types.
+
+**[5] `network.protocol.name`:** The value SHOULD be normalized to lowercase.
+
+**[6] `network.transport`:** This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+is HTTP.
+It SHOULD be set to `pipe` if the transport is stdio.
+
+**[7] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.
+
+**[8] `server.port`:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.
+
+**[9] `mcp.resource.uri`:** This is a URI of the resource provided in the following requests or notifications: `resources/read`, `resources/subscribe`, `resources/unsubscribe`, or `notifications/resources/updated`.
+
+---
+
+`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. |  |
+
+---
+
+`gen_ai.operation.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `chat` | Chat completion operation such as [OpenAI Chat API](https://platform.openai.com/docs/api-reference/chat) |  |
+| `create_agent` | Create GenAI agent |  |
+| `embeddings` | Embeddings operation such as [OpenAI Create embeddings API](https://platform.openai.com/docs/api-reference/embeddings/create) |  |
+| `execute_tool` | Execute a tool |  |
+| `generate_content` | Multimodal content generation operation such as [Gemini Generate Content](https://ai.google.dev/api/generate-content) |  |
+| `invoke_agent` | Invoke GenAI agent |  |
+| `text_completion` | Text completions operation such as [OpenAI Completions API (Legacy)](https://platform.openai.com/docs/api-reference/completions) |  |
+
+---
+
+`mcp.method.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `completion/complete` | Request to complete a prompt. |  |
+| `elicitation/create` | Request from the server to elicit additional information from the user via the client |  |
+| `initialize` | Request to initialize the MCP client. |  |
+| `logging/setLevel` | Request to set the logging level. |  |
+| `notifications/cancelled` | Notification cancelling a previously-issued request. |  |
+| `notifications/initialized` | Notification indicating that the MCP client has been initialized. |  |
+| `notifications/message` | Notification indicating that a message has been received. |  |
+| `notifications/progress` | Notification indicating the progress for a long-running operation. |  |
+| `notifications/prompts/list_changed` | Notification indicating that the list of prompts has changed. |  |
+| `notifications/resources/list_changed` | Notification indicating that the list of resources has changed. |  |
+| `notifications/resources/updated` | Notification indicating that a resource has been updated. |  |
+| `notifications/roots/list_changed` | Notification indicating that the list of roots has changed. |  |
+| `notifications/tools/list_changed` | Notification indicating that the list of tools has changed. |  |
+| `ping` | Request to check that the other party is still alive. |  |
+| `prompts/get` | Request to get a prompt. |  |
+| `prompts/list` | Request to list prompts available on server. |  |
+| `resources/list` | Request to list resources available on server. |  |
+| `resources/read` | Request to read a resource. |  |
+| `resources/subscribe` | Request to subscribe to a resource. |  |
+| `resources/templates/list` | Request to list resource templates available on server. |  |
+| `resources/unsubscribe` | Request to unsubscribe from resource updates. |  |
+| `roots/list` | Request to list roots available on server. |  |
+| `sampling/createMessage` | Request to create a sampling message. |  |
+| `tools/call` | Request to call a tool. |  |
+| `tools/list` | Request to list tools available on server. |  |
+
+---
+
+`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `pipe` | Named or anonymous pipe. |  |
+| `quic` | QUIC |  |
+| `tcp` | TCP |  |
+| `udp` | UDP |  |
+| `unix` | Unix domain socket |  |
+
+
+
+
+
+### Metric: `mcp.server.operation.duration`
+
+This metric is [recommended][MetricRecommended].
+
+This metric SHOULD be specified with
+[`ExplicitBucketBoundaries`](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.50.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 ]`.
+
+
+
+
+
+
+| Name | Instrument Type | Unit (UCUM) | Description | Stability | Entity Associations |
+| -------- | --------------- | ----------- | -------------- | --------- | ------ |
+| `mcp.server.operation.duration` | Histogram | `s` | MCP request or notification duration as observed on the receiver from the time it was received until the result or ack is sent. |  | |
+
+**Attributes:**
+
+| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values |
+| --- | --- | --- | --- | --- | --- |
+| [`mcp.method.name`](/docs/registry/attributes/mcp.md) |  | `Required` | string | The name of the request or notification method. | `notifications/cancelled`; `initialize`; `notifications/initialized` |
+| [`error.type`](/docs/registry/attributes/error.md) |  | `Conditionally Required` If and only if the operation fails. | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` |
+| [`gen_ai.prompt.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific prompt. | string | The name of the prompt or prompt template provided in the request or response. | `analyze-code` |
+| [`gen_ai.tool.name`](/docs/registry/attributes/gen-ai.md) |  | `Conditionally Required` When operation is related to a specific tool. | string | Name of the tool utilized by the agent. | `Flights` |
+| [`rpc.response.status_code`](/docs/registry/attributes/rpc.md) |  | `Conditionally Required` If response contains an error code. | string | The error code from the JSON-RPC response. [2] | `OK`; `DEADLINE_EXCEEDED`; `-32602` |
+| [`gen_ai.operation.name`](/docs/registry/attributes/gen-ai.md) |  | `Recommended` [3] | string | The name of the GenAI operation being performed. [4] | `execute_tool` |
+| [`jsonrpc.protocol.version`](/docs/registry/attributes/jsonrpc.md) |  | `Recommended` when it's not `2.0`. | string | Protocol version, as specified in the `jsonrpc` property of the request and its corresponding response. | `2.0`; `1.0` |
+| [`mcp.protocol.version`](/docs/registry/attributes/mcp.md) |  | `Recommended` | string | The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used. | `2025-06-18` |
+| [`network.protocol.name`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | [OSI application layer](https://wikipedia.org/wiki/Application_layer) or non-OSI equivalent. [5] | `http`; `websocket` |
+| [`network.protocol.version`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | The actual version of the protocol used for network communication. | `1.1`; `2` |
+| [`network.transport`](/docs/registry/attributes/network.md) |  | `Recommended` | string | The transport protocol used for the MCP session. [6] | `tcp`; `quic`; `pipe` |
+| [`mcp.resource.uri`](/docs/registry/attributes/mcp.md) |  | `Opt-In` | string | The value of the resource uri. [7] | `postgres://database/customers/schema`; `file:///home/user/documents/report.pdf` |
+
+**[1] `error.type`:** This attribute SHOULD be set to the string representation of the JSON-RPC
+error code, if one is returned.
+
+When JSON-RPC call is successful, but an error is returned within the
+result payload, this attribute SHOULD be set to the low-cardinality
+string representation of the error. When
+[CallToolResult](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/9c8a44e47e16b789a1f9d47c89ea23ed13a37cf9/schema/2025-06-18/schema.ts#L715)
+is returned with `isError` set to `true`, this attribute SHOULD be set to
+`tool_error`.
+
+**[2] `rpc.response.status_code`:** Usually it represents an error code, but may also represent partial success, warning, or differentiate between various types of successful outcomes.
+Semantic conventions for individual RPC frameworks SHOULD document what `rpc.response.status_code` means in the context of that system and which values are considered to represent errors.
+
+**[3] `gen_ai.operation.name`:** SHOULD be set to `execute_tool` when the operation describes a tool call and SHOULD NOT be set otherwise.
+
+**[4] `gen_ai.operation.name`:** Populating this attribute for tool calling along with `mcp.method.name` allows consumers to treat MCP tool calls spans similarly with other tool call types.
+
+**[5] `network.protocol.name`:** The value SHOULD be normalized to lowercase.
+
+**[6] `network.transport`:** This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+is HTTP.
+It SHOULD be set to `pipe` if the transport is stdio.
+
+**[7] `mcp.resource.uri`:** This is a URI of the resource provided in the following requests or notifications: `resources/read`, `resources/subscribe`, `resources/unsubscribe`, or `notifications/resources/updated`.
+
+---
+
+`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. |  |
+
+---
+
+`gen_ai.operation.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `chat` | Chat completion operation such as [OpenAI Chat API](https://platform.openai.com/docs/api-reference/chat) |  |
+| `create_agent` | Create GenAI agent |  |
+| `embeddings` | Embeddings operation such as [OpenAI Create embeddings API](https://platform.openai.com/docs/api-reference/embeddings/create) |  |
+| `execute_tool` | Execute a tool |  |
+| `generate_content` | Multimodal content generation operation such as [Gemini Generate Content](https://ai.google.dev/api/generate-content) |  |
+| `invoke_agent` | Invoke GenAI agent |  |
+| `text_completion` | Text completions operation such as [OpenAI Completions API (Legacy)](https://platform.openai.com/docs/api-reference/completions) |  |
+
+---
+
+`mcp.method.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `completion/complete` | Request to complete a prompt. |  |
+| `elicitation/create` | Request from the server to elicit additional information from the user via the client |  |
+| `initialize` | Request to initialize the MCP client. |  |
+| `logging/setLevel` | Request to set the logging level. |  |
+| `notifications/cancelled` | Notification cancelling a previously-issued request. |  |
+| `notifications/initialized` | Notification indicating that the MCP client has been initialized. |  |
+| `notifications/message` | Notification indicating that a message has been received. |  |
+| `notifications/progress` | Notification indicating the progress for a long-running operation. |  |
+| `notifications/prompts/list_changed` | Notification indicating that the list of prompts has changed. |  |
+| `notifications/resources/list_changed` | Notification indicating that the list of resources has changed. |  |
+| `notifications/resources/updated` | Notification indicating that a resource has been updated. |  |
+| `notifications/roots/list_changed` | Notification indicating that the list of roots has changed. |  |
+| `notifications/tools/list_changed` | Notification indicating that the list of tools has changed. |  |
+| `ping` | Request to check that the other party is still alive. |  |
+| `prompts/get` | Request to get a prompt. |  |
+| `prompts/list` | Request to list prompts available on server. |  |
+| `resources/list` | Request to list resources available on server. |  |
+| `resources/read` | Request to read a resource. |  |
+| `resources/subscribe` | Request to subscribe to a resource. |  |
+| `resources/templates/list` | Request to list resource templates available on server. |  |
+| `resources/unsubscribe` | Request to unsubscribe from resource updates. |  |
+| `roots/list` | Request to list roots available on server. |  |
+| `sampling/createMessage` | Request to create a sampling message. |  |
+| `tools/call` | Request to call a tool. |  |
+| `tools/list` | Request to list tools available on server. |  |
+
+---
+
+`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `pipe` | Named or anonymous pipe. |  |
+| `quic` | QUIC |  |
+| `tcp` | TCP |  |
+| `udp` | UDP |  |
+| `unix` | Unix domain socket |  |
+
+
+
+
+
+### Metric: `mcp.client.session.duration`
+
+This metric is [recommended][MetricRecommended].
+
+This metric SHOULD be specified with
+[`ExplicitBucketBoundaries`](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.50.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 ]`.
+
+
+
+
+
+
+| Name | Instrument Type | Unit (UCUM) | Description | Stability | Entity Associations |
+| -------- | --------------- | ----------- | -------------- | --------- | ------ |
+| `mcp.client.session.duration` | Histogram | `s` | The duration of the MCP session as observed on the MCP client. |  | |
+
+**Attributes:**
+
+| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values |
+| --- | --- | --- | --- | --- | --- |
+| [`error.type`](/docs/registry/attributes/error.md) |  | `Conditionally Required` If and only if session ends with an error. | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` |
+| [`jsonrpc.protocol.version`](/docs/registry/attributes/jsonrpc.md) |  | `Recommended` when it's not `2.0`. | string | Protocol version, as specified in the `jsonrpc` property of the request and its corresponding response. | `2.0`; `1.0` |
+| [`mcp.protocol.version`](/docs/registry/attributes/mcp.md) |  | `Recommended` | string | The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used. | `2025-06-18` |
+| [`network.protocol.name`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | [OSI application layer](https://wikipedia.org/wiki/Application_layer) or non-OSI equivalent. [2] | `http`; `websocket` |
+| [`network.protocol.version`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | The actual version of the protocol used for network communication. | `1.1`; `2` |
+| [`network.transport`](/docs/registry/attributes/network.md) |  | `Recommended` | string | The transport protocol used for the MCP session. [3] | `tcp`; `quic`; `pipe` |
+| [`server.address`](/docs/registry/attributes/server.md) |  | `Recommended` If applicable | string | Server domain name if available without reverse DNS lookup; otherwise, IP address or Unix domain socket name. [4] | `example.com`; `10.1.2.80`; `/tmp/my.sock` |
+| [`server.port`](/docs/registry/attributes/server.md) |  | `Recommended` When `server.address` is set | int | Server port number. [5] | `80`; `8080`; `443` |
+
+**[1] `error.type`:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality.
+
+When `error.type` is set to a type (e.g., an exception type), its
+canonical class name identifying the type within the artifact SHOULD be used.
+
+Instrumentations SHOULD document the list of errors they report.
+
+The cardinality of `error.type` within one instrumentation library SHOULD be low.
+Telemetry consumers that aggregate data from multiple instrumentation libraries and applications
+should be prepared for `error.type` to have high cardinality at query time when no
+additional filters are applied.
+
+If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`.
+
+If a specific domain defines its own set of error identifiers (such as HTTP or RPC status codes),
+it's RECOMMENDED to:
+
+- Use a domain-specific attribute
+- Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not.
+
+**[2] `network.protocol.name`:** The value SHOULD be normalized to lowercase.
+
+**[3] `network.transport`:** This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+is HTTP. It SHOULD be set to `pipe` if the transport is stdio.
+
+**[4] `server.address`:** When observed from the client side, and when communicating through an intermediary, `server.address` SHOULD represent the server address behind any intermediaries, for example proxies, if it's available.
+
+**[5] `server.port`:** When observed from the client side, and when communicating through an intermediary, `server.port` SHOULD represent the server port behind any intermediaries, for example proxies, if it's available.
+
+---
+
+`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. |  |
+
+---
+
+`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `pipe` | Named or anonymous pipe. |  |
+| `quic` | QUIC |  |
+| `tcp` | TCP |  |
+| `udp` | UDP |  |
+| `unix` | Unix domain socket |  |
+
+
+
+
+
+### Metric: `mcp.server.session.duration`
+
+This metric is [recommended][MetricRecommended].
+
+This metric SHOULD be specified with
+[`ExplicitBucketBoundaries`](https://github.com/open-telemetry/opentelemetry-specification/blob/v1.50.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 ]`.
+
+
+
+
+
+
+| Name | Instrument Type | Unit (UCUM) | Description | Stability | Entity Associations |
+| -------- | --------------- | ----------- | -------------- | --------- | ------ |
+| `mcp.server.session.duration` | Histogram | `s` | The duration of the MCP session as observed on the MCP server. |  | |
+
+**Attributes:**
+
+| Key | Stability | [Requirement Level](https://opentelemetry.io/docs/specs/semconv/general/attribute-requirement-level/) | Value Type | Description | Example Values |
+| --- | --- | --- | --- | --- | --- |
+| [`error.type`](/docs/registry/attributes/error.md) |  | `Conditionally Required` If and only if session ends with an error. | string | Describes a class of error the operation ended with. [1] | `timeout`; `java.net.UnknownHostException`; `server_certificate_invalid`; `500` |
+| [`jsonrpc.protocol.version`](/docs/registry/attributes/jsonrpc.md) |  | `Recommended` when it's not `2.0`. | string | Protocol version, as specified in the `jsonrpc` property of the request and its corresponding response. | `2.0`; `1.0` |
+| [`mcp.protocol.version`](/docs/registry/attributes/mcp.md) |  | `Recommended` | string | The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used. | `2025-06-18` |
+| [`network.protocol.name`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | [OSI application layer](https://wikipedia.org/wiki/Application_layer) or non-OSI equivalent. [2] | `http`; `websocket` |
+| [`network.protocol.version`](/docs/registry/attributes/network.md) |  | `Recommended` When applicable. | string | The actual version of the protocol used for network communication. | `1.1`; `2` |
+| [`network.transport`](/docs/registry/attributes/network.md) |  | `Recommended` | string | The transport protocol used for the MCP session. [3] | `tcp`; `quic`; `pipe` |
+
+**[1] `error.type`:** The `error.type` SHOULD be predictable, and SHOULD have low cardinality.
+
+When `error.type` is set to a type (e.g., an exception type), its
+canonical class name identifying the type within the artifact SHOULD be used.
+
+Instrumentations SHOULD document the list of errors they report.
+
+The cardinality of `error.type` within one instrumentation library SHOULD be low.
+Telemetry consumers that aggregate data from multiple instrumentation libraries and applications
+should be prepared for `error.type` to have high cardinality at query time when no
+additional filters are applied.
+
+If the operation has completed successfully, instrumentations SHOULD NOT set `error.type`.
+
+If a specific domain defines its own set of error identifiers (such as HTTP or RPC status codes),
+it's RECOMMENDED to:
+
+- Use a domain-specific attribute
+- Set `error.type` to capture all errors, regardless of whether they are defined within the domain-specific set or not.
+
+**[2] `network.protocol.name`:** The value SHOULD be normalized to lowercase.
+
+**[3] `network.transport`:** This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+is HTTP. It SHOULD be set to `pipe` if the transport is stdio.
+
+---
+
+`error.type` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `_OTHER` | A fallback error value to be used when the instrumentation doesn't define a custom value. |  |
+
+---
+
+`network.transport` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `pipe` | Named or anonymous pipe. |  |
+| `quic` | QUIC |  |
+| `tcp` | TCP |  |
+| `udp` | UDP |  |
+| `unix` | Unix domain socket |  |
+
+
+
+
+
+[DocumentStatus]: https://opentelemetry.io/docs/specs/otel/document-status
+[MetricRecommended]: /docs/general/metric-requirement-level.md#recommended
+
+## Recording MCP transport
+
+The following table shows how to capture MCP transport and can be used be telemetry
+consumers to deduce transport type.
+
+| MCP transport | `network.transport` attribute | `network.protocol.*` attributes | `mcp.protocol.version` attribute | Comments |
+| :----------------- | :------------------------------------- | :-------------------------------------------------------------------------- | :------------------------------- | :--------------------------------------------------------------- |
+| stdio | `pipe` | | any | |
+| Streamable HTTP | `tcp` (or `quic`) | `network.protocol.name = http`
`network.protocol.version = 2` | `2025-06-18` or newer | `mcp.protocol.version` distinguishes streamable HTTP from SSE |
+| HTTP with SSE | `tcp` (or `quic`) | `network.protocol.name = http`
`network.protocol.version = 1.1` (or 2) | `2024-11-05` or older | `mcp.protocol.version` distinguishes streamable HTTP from SSE |
+| Custom: websockets | `tcp` (or another applicable protocol) | `network.protocol.name = websocket` | any | |
+| Custom: gRPC | `tcp` (or another applicable protocol) | `network.protocol.name = http`
`network.protocol.version = 2` | any | See [gRPC conventions](/docs/rpc/grpc.md) for additional details |
+
+Note: Applications may enable instrumentation for the underlying application protocol
+like HTTP (when applicable) alongside MCP instrumentation to capture additional
+transport-level details, such as transport-specific error codes.
+
+## Examples
+
+In these examples, we assume that GenAI framework is configured to use MCP tools,
+and that tool calls are handled manually, so that GenAI framework does not
+instrument corresponding tool calls.
+
+### Stdio transport
+
+#### Initialize
+
+```
+initialize (CLIENT, trace=t1, span=s1) # MCP client
+|
+-- initialize - (SERVER, trace=t1, span=s2, parent=s1) # MCP server
+```
+
+MCP client span (`s1`):
+
+| Property | Value |
+| :------------------------------- | :----------------------------------- |
+| Span name | `"initialize"` |
+| Span kind | `CLIENT` |
+| Span status | `UNSET` |
+| Attribute `jsonrpc.request.id` | `"1"` |
+| Attribute `mcp.method.name` | `"initialize"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.transport` | `"pipe"` |
+
+MCP server span (`s2`):
+
+| Property | Value |
+| :------------------------------- | :----------------------------------- |
+| Span name | `"initialize"` |
+| Span kind | `SERVER` |
+| Span parent | `s1` (MCP client span) |
+| Span status | `UNSET` |
+| Attribute `jsonrpc.request.id` | `"1"` |
+| Attribute `mcp.method.name` | `"initialize"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.transport` | `"pipe"` |
+
+#### Tool call
+
+```
+invoke_agent weather-forecast-agent (INTERNAL, trace=t1, span=s1) # GenAI agent
+ |
+ -- chat {model} - (CLIENT, trace=t1, span=s2, parent=s1) # GenAI model client
+ |
+ -- tools/call get-weather - (CLIENT, trace=t1, span=s3, parent=s1) # MCP client
+ | |
+ | --- tools/call get-weather (SERVER, trace=t1, span=s4, parent=s3) # MCP server
+ |
+ -- chat {model} - (CLIENT, trace=t1, span=s5, parent=s1) # GenAI model client
+```
+
+MCP client span (`s3`):
+
+| Property | Value |
+| :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Span name | `"tools/call get-weather"` |
+| Span kind | `CLIENT` |
+| Span status | `UNSET` |
+| Attribute `gen_ai.operation.name` | `"execute_tool"` |
+| Attribute `gen_ai.tool.call.arguments` | (if enabled)
{
"location": "San Francisco?",
"date": "2025-10-01"
} |
+| Attribute `gen_ai.tool.call.result` | (if enabled)
{
"temperature_range": {
"high": 75,
"low": 60
}
} |
+| Attribute `gen_ai.tool.name` | `"get-weather"` |
+| Attribute `jsonrpc.request.id` | `"3"` |
+| Attribute `mcp.method.name` | `"tools/call"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.transport` | `"pipe"` |
+
+MCP server span (`s4`):
+
+| Property | Value |
+| :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Span name | `"tools/call get-weather"` |
+| Span kind | `SERVER` |
+| Span parent | `s3` (MCP client span) |
+| Span status | `UNSET` |
+| Attribute `gen_ai.operation.name` | `"execute_tool"` |
+| Attribute `gen_ai.tool.call.arguments` | (if enabled)
{
"location": "San Francisco?",
"date": "2025-10-01"
} |
+| Attribute `gen_ai.tool.call.result` | (if enabled)
{
"temperature_range": {
"high": 75,
"low": 60
}
} |
+| Attribute `gen_ai.tool.name` | `"get-weather"` |
+| Attribute `jsonrpc.request.id` | `"3"` |
+| Attribute `mcp.method.name` | `"tools/call"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.transport` | `"pipe"` |
+
+### Streamable HTTP
+
+In the HTTP examples, we assume that HTTP instrumentation is enabled on both client
+and server side along with the MCP instrumentation.
+
+#### Initialize
+
+```
+initialize (CLIENT, trace=t1, span=s1) # MCP client
+ |
+ -- POST - (CLIENT, trace=t1, span=s2, parent=s1) # HTTP client
+ | |
+ | --- POST - (SERVER, trace=t1, span=s3, parent=s2) # HTTP server
+ |
+ -- initialize - (SERVER, trace=t1, span=s4, parent=s1) # MCP server
+ |
+ -- HTTP - (CLIENT, trace=t1, span=s5, parent=s1) # HTTP client - notifications channel
+```
+
+Here, in addition to MCP client and server spans, we see HTTP client (`s3`)
+and server (`s4`) spans. MCP server span remains a child of the MCP client span
+(`s1`) and has a link to HTTP server span (`s3`) that was current when MCP server
+span started.
+
+MCP client span (`s1`):
+
+| Property | Value |
+| :----------------------------------- | :----------------------------------- |
+| Span name | `"initialize"` |
+| Span kind | `CLIENT` |
+| Span status | `UNSET` |
+| Attribute `jsonrpc.request.id` | `"1"` |
+| Attribute `mcp.method.name` | `"initialize"` |
+| Attribute `mcp.request.id` | `"1"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.protocol.name ` | `"http"` |
+| Attribute `network.protocol.version` |`"2"` |
+| Attribute `network.transport` | `"tcp"` |
+
+MCP server span (`s4`):
+
+| Property | Value |
+| :----------------------------------- | :----------------------------------- |
+| Span name | `"initialize"` |
+| Span kind | `SERVER` |
+| Span parent | `s1` (MCP client span) |
+| Span links | [`s3`] (HTTP server span) |
+| Span status | `UNSET` |
+| Attribute `jsonrpc.request.id` | `"1"` |
+| Attribute `mcp.method.name` | `"initialize"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.protocol.name ` | `"http"` |
+| Attribute `network.protocol.version` | `"2"` |
+| Attribute `network.transport` | `"tcp"` |
+
+#### Tool call
+
+```
+invoke_agent weather-forecast-agent (INTERNAL, trace=t1, span=s1) # GenAI agent
+ |
+ -- chat {model} - (CLIENT, trace=t1, span=s2, parent=s1) # GenAI model
+ | |
+ | --- POST (CLIENT, trace=t1, span=s3, parent=s2) # HTTP client
+ |
+ -- tools/call get-weather - (CLIENT, trace=t1, span=s4, parent=s1) # MCP client
+ | |
+ | --- POST - (CLIENT, trace=t1, span=s5, parent=s4) # HTTP client
+ | | |
+ | | ---- POST - (SERVER, trace=t1, span=s6, parent=s5) # HTTP server
+ | |
+ | --- tools/call get-weather (SERVER, trace=t1, span=s7, parent=s4) # MCP server
+ |
+ -- chat {model} - (CLIENT, trace=t1, span=s8, parent=s1) # GenAI model
+ | |
+ | --- POST (CLIENT, trace=t1, span=s9, parent=s8) # HTTP server
+```
+
+Similarly to HTTP `initialize` example, MCP server (`s7`) span becomes a child of
+MCP client span (`s4`).
+
+MCP client span (`s4`):
+
+| Property | Value |
+| :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Span name | `"tools/call get-weather"` |
+| Span kind | `CLIENT` |
+| Span status | `UNSET` |
+| Attribute `gen_ai.operation.name` | `"execute_tool"` |
+| Attribute `gen_ai.tool.call.arguments` | (if enabled)
{
"location": "San Francisco?",
"date": "2025-10-01"
} |
+| Attribute `gen_ai.tool.call.result` | (if enabled)
{
"temperature_range": {
"high": 75,
"low": 60
}
} |
+| Attribute `gen_ai.tool.name` | `"get-weather"` |
+| Attribute `jsonrpc.request.id` | `"3"` |
+| Attribute `mcp.method.name` | `"tools/call"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.protocol.name ` | `"http"` |
+| Attribute `network.protocol.version` | `"2"` |
+| Attribute `network.transport` | `"tcp"` |
+
+MCP server span (`s7`):
+
+| Property | Value |
+| :------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| Span name | `"tools/call get-weather"` |
+| Span kind | `SERVER` |
+| Span parent | `s4` (MCP client span) |
+| Span links | [`s6`] (HTTP server span) |
+| Span status | `UNSET` |
+| Attribute `gen_ai.operation.name` | `"execute_tool"` |
+| Attribute `gen_ai.tool.call.arguments` | (if enabled)
{
"location": "San Francisco?",
"date": "2025-10-01"
} |
+| Attribute `gen_ai.tool.call.result` | (if enabled)
{
"temperature_range": {
"high": 75,
"low": 60
}
} |
+| Attribute `gen_ai.tool.name` | `"get-weather"` |
+| Attribute `jsonrpc.request.id` | `"3"` |
+| Attribute `mcp.method.name` | `"tools/call"` |
+| Attribute `mcp.session.id` | `"8267461134f24305af708e66b8eda71a"` |
+| Attribute `mcp.protocol.version` | `"2025-06-18"` |
+| Attribute `network.protocol.name ` | `"http"` |
+| Attribute `network.protocol.version` | `"2"` |
+| Attribute `network.transport` | `"tcp"` |
diff --git a/docs/registry/attributes/README.md b/docs/registry/attributes/README.md
index e08766db04..b3ebffa36e 100644
--- a/docs/registry/attributes/README.md
+++ b/docs/registry/attributes/README.md
@@ -79,6 +79,7 @@ Currently, the following namespaces exist:
- [Linux](linux.md)
- [Log](log.md)
- [Mainframe](mainframe.md)
+- [MCP](mcp.md)
- [Messaging](messaging.md)
- [Network](network.md)
- [NFS](nfs.md)
diff --git a/docs/registry/attributes/gen-ai.md b/docs/registry/attributes/gen-ai.md
index 34a73fa908..bec186d9cc 100644
--- a/docs/registry/attributes/gen-ai.md
+++ b/docs/registry/attributes/gen-ai.md
@@ -29,6 +29,7 @@ This document defines the attributes used to describe telemetry in the context o
| `gen_ai.operation.name` |  | string | The name of the operation being performed. [4] | `chat`; `generate_content`; `text_completion` |
| `gen_ai.output.messages` |  | any | Messages returned by the model where each message represents a specific model response (choice, candidate). [5] | [
{
"role": "assistant",
"parts": [
{
"type": "text",
"content": "The weather in Paris is currently rainy with a temperature of 57°F."
}
],
"finish_reason": "stop"
}
] |
| `gen_ai.output.type` |  | string | Represents the content type requested by the client. [6] | `text`; `json`; `image` |
+| `gen_ai.prompt.name` |  | string | The name of the prompt that uniquely identifies it. | `analyze-code` |
| `gen_ai.provider.name` |  | string | The Generative AI provider as identified by the client or server instrumentation. [7] | `openai`; `gcp.gen_ai`; `gcp.vertex_ai` |
| `gen_ai.request.choice.count` |  | int | The target number of candidate completions to return. | `3` |
| `gen_ai.request.encoding_formats` |  | string[] | The encoding formats requested in an embeddings operation, if specified. [8] | `["base64"]`; `["float", "binary"]` |
diff --git a/docs/registry/attributes/mcp.md b/docs/registry/attributes/mcp.md
new file mode 100644
index 0000000000..5f920d4193
--- /dev/null
+++ b/docs/registry/attributes/mcp.md
@@ -0,0 +1,51 @@
+
+
+
+# MCP
+
+## MCP Attributes
+
+[Model Context Protocol (MCP)](https://modelcontextprotocol.io) attributes
+
+**Attributes:**
+
+| Key | Stability | Value Type | Description | Example Values |
+| --- | --- | --- | --- | --- |
+| `mcp.method.name` |  | string | The name of the request or notification method. | `notifications/cancelled`; `initialize`; `notifications/initialized` |
+| `mcp.protocol.version` |  | string | The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used. | `2025-06-18` |
+| `mcp.resource.uri` |  | string | The value of the resource uri. [1] | `postgres://database/customers/schema`; `file:///home/user/documents/report.pdf` |
+| `mcp.session.id` |  | string | Identifies [MCP session](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#session-management). | `191c4850af6c49e08843a3f6c80e5046` |
+
+**[1] `mcp.resource.uri`:** This is a URI of the resource provided in the following requests or notifications: `resources/read`, `resources/subscribe`, `resources/unsubscribe`, or `notifications/resources/updated`.
+
+---
+
+`mcp.method.name` has the following list of well-known values. If one of them applies, then the respective value MUST be used; otherwise, a custom value MAY be used.
+
+| Value | Description | Stability |
+| --- | --- | --- |
+| `completion/complete` | Request to complete a prompt. |  |
+| `elicitation/create` | Request from the server to elicit additional information from the user via the client |  |
+| `initialize` | Request to initialize the MCP client. |  |
+| `logging/setLevel` | Request to set the logging level. |  |
+| `notifications/cancelled` | Notification cancelling a previously-issued request. |  |
+| `notifications/initialized` | Notification indicating that the MCP client has been initialized. |  |
+| `notifications/message` | Notification indicating that a message has been received. |  |
+| `notifications/progress` | Notification indicating the progress for a long-running operation. |  |
+| `notifications/prompts/list_changed` | Notification indicating that the list of prompts has changed. |  |
+| `notifications/resources/list_changed` | Notification indicating that the list of resources has changed. |  |
+| `notifications/resources/updated` | Notification indicating that a resource has been updated. |  |
+| `notifications/roots/list_changed` | Notification indicating that the list of roots has changed. |  |
+| `notifications/tools/list_changed` | Notification indicating that the list of tools has changed. |  |
+| `ping` | Request to check that the other party is still alive. |  |
+| `prompts/get` | Request to get a prompt. |  |
+| `prompts/list` | Request to list prompts available on server. |  |
+| `resources/list` | Request to list resources available on server. |  |
+| `resources/read` | Request to read a resource. |  |
+| `resources/subscribe` | Request to subscribe to a resource. |  |
+| `resources/templates/list` | Request to list resource templates available on server. |  |
+| `resources/unsubscribe` | Request to unsubscribe from resource updates. |  |
+| `roots/list` | Request to list roots available on server. |  |
+| `sampling/createMessage` | Request to create a sampling message. |  |
+| `tools/call` | Request to call a tool. |  |
+| `tools/list` | Request to list tools available on server. |  |
diff --git a/model/gen-ai/registry.yaml b/model/gen-ai/registry.yaml
index 8b3fa51dd4..5105358897 100644
--- a/model/gen-ai/registry.yaml
+++ b/model/gen-ai/registry.yaml
@@ -591,3 +591,8 @@ groups:
type: string
brief: A free-form explanation for the assigned score provided by the evaluator.
examples: ["The response is factually accurate but lacks sufficient detail to fully address the question."]
+ - id: gen_ai.prompt.name
+ type: string
+ brief: The name of the prompt that uniquely identifies it.
+ stability: development
+ examples: ["analyze-code"]
diff --git a/model/gen-ai/spans.yaml b/model/gen-ai/spans.yaml
index 542de5fdff..9cbf6775af 100644
--- a/model/gen-ai/spans.yaml
+++ b/model/gen-ai/spans.yaml
@@ -307,10 +307,15 @@ groups:
**Span name** SHOULD be `execute_tool {gen_ai.tool.name}`.
- GenAI instrumentations that are able to instrument tool execution call SHOULD do so.
- However, it's common for tools to be executed by the application code. It's recommended
- for the application developers to follow this semantic convention for tools invoked
- by the application code.
+ GenAI instrumentations that can instrument tool execution calls SHOULD do so,
+ unless another instrumentation can reliably cover all supported tool types.
+ MCP tool executions may also be traced by the
+ [corresponding MCP instrumentation](/docs/gen-ai/mcp.md#client).
+
+ Tools are often executed directly by application code. Application developers
+ are encouraged to follow this semantic convention for tools invoked by their
+ own code and to manually instrument any tool calls that automatic
+ instrumentations do not cover.
attributes:
- ref: gen_ai.operation.name
requirement_level: required
diff --git a/model/mcp/common.yaml b/model/mcp/common.yaml
new file mode 100644
index 0000000000..16c307224a
--- /dev/null
+++ b/model/mcp/common.yaml
@@ -0,0 +1,63 @@
+groups:
+ - id: mcp.common.attributes
+ type: attribute_group
+ brief: Common MCP attributes
+ attributes:
+ - ref: gen_ai.tool.name
+ requirement_level:
+ conditionally_required: When operation is related to a specific tool.
+ - ref: gen_ai.operation.name
+ brief: The name of the GenAI operation being performed.
+ examples: ["execute_tool"]
+ requirement_level:
+ recommended: >
+ SHOULD be set to `execute_tool` when the operation describes a tool
+ call and SHOULD NOT be set otherwise.
+ note: >
+ Populating this attribute for tool calling along with `mcp.method.name`
+ allows consumers to treat MCP tool calls spans similarly with other tool
+ call types.
+ - ref: gen_ai.prompt.name
+ brief: The name of the prompt or prompt template provided in the request or response.
+ requirement_level:
+ conditionally_required: When operation is related to a specific prompt.
+ - ref: network.transport
+ brief: The transport protocol used for the MCP session.
+ note: |
+ This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+ is HTTP.
+ It SHOULD be set to `pipe` if the transport is stdio.
+ examples: ["tcp", "quic", "pipe"]
+ - ref: error.type
+ requirement_level:
+ conditionally_required: If and only if the operation fails.
+ note: |
+ This attribute SHOULD be set to the string representation of the JSON-RPC
+ error code, if one is returned.
+
+ When JSON-RPC call is successful, but an error is returned within the
+ result payload, this attribute SHOULD be set to the low-cardinality
+ string representation of the error. When
+ [CallToolResult](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/9c8a44e47e16b789a1f9d47c89ea23ed13a37cf9/schema/2025-06-18/schema.ts#L715)
+ is returned with `isError` set to `true`, this attribute SHOULD be set to
+ `tool_error`.
+ - ref: mcp.method.name
+ requirement_level: required
+ - ref: mcp.protocol.version
+ - ref: rpc.response.status_code
+ brief: The error code from the JSON-RPC response.
+ requirement_level:
+ conditionally_required: If response contains an error code.
+ - ref: network.protocol.name
+ requirement_level:
+ recommended: When applicable.
+ examples:
+ - "http"
+ - "websocket"
+ - ref: network.protocol.version
+ note: "" # overriding the default note
+ requirement_level:
+ recommended: When applicable.
+ - ref: jsonrpc.protocol.version
+ requirement_level:
+ recommended: when it's not `2.0`.
diff --git a/model/mcp/metrics.yaml b/model/mcp/metrics.yaml
new file mode 100644
index 0000000000..68a482a9c3
--- /dev/null
+++ b/model/mcp/metrics.yaml
@@ -0,0 +1,90 @@
+groups:
+ - id: mcp.operation.metrics.attributes
+ type: attribute_group
+ brief: MCP request metrics attributes
+ extends: mcp.common.attributes
+ attributes:
+ - ref: mcp.resource.uri
+ requirement_level: opt_in
+
+ - id: mcp.session.metrics.attributes
+ type: attribute_group
+ brief: MCP session metrics attributes
+ attributes:
+ - ref: mcp.protocol.version
+ - ref: network.protocol.name
+ requirement_level:
+ recommended: When applicable.
+ examples:
+ - "http"
+ - "websocket"
+ - ref: network.protocol.version
+ note: "" # overriding the default note
+ requirement_level:
+ recommended: When applicable.
+ - ref: jsonrpc.protocol.version
+ requirement_level:
+ recommended: when it's not `2.0`.
+ - ref: network.transport
+ brief: The transport protocol used for the MCP session.
+ note: |
+ This attribute SHOULD be set to `tcp` or `quic` if the transport protocol
+ is HTTP. It SHOULD be set to `pipe` if the transport is stdio.
+ examples: ["tcp", "quic", "pipe"]
+ - ref: error.type
+ requirement_level:
+ conditionally_required: If and only if session ends with an error.
+
+ - id: metric.mcp.client.operation.duration
+ type: metric
+ metric_name: mcp.client.operation.duration
+ brief: >
+ The duration of the MCP request or notification as observed on the sender
+ from the time it was sent until the response or ack is received.
+ unit: s
+ instrument: histogram
+ stability: development
+ extends: mcp.operation.metrics.attributes
+ attributes:
+ - ref: server.address
+ requirement_level:
+ recommended: If applicable
+ - ref: server.port
+ requirement_level:
+ recommended: When `server.address` is set
+
+ - id: metric.mcp.server.operation.duration
+ type: metric
+ metric_name: mcp.server.operation.duration
+ brief: >
+ MCP request or notification duration as observed on the receiver
+ from the time it was received until the result or ack is sent.
+ unit: s
+ instrument: histogram
+ stability: development
+ extends: mcp.operation.metrics.attributes
+
+ - id: metric.mcp.client.session.duration
+ type: metric
+ metric_name: mcp.client.session.duration
+ brief: The duration of the MCP session as observed on the MCP client.
+ unit: s
+ instrument: histogram
+ stability: development
+ extends: mcp.session.metrics.attributes
+ attributes:
+ - ref: server.address
+ requirement_level:
+ recommended: If applicable
+ - ref: server.port
+ requirement_level:
+ recommended: When `server.address` is set
+
+ - id: metric.mcp.server.session.duration
+ type: metric
+ metric_name: mcp.server.session.duration
+ brief: The duration of the MCP session as observed on the MCP server.
+ unit: s
+ instrument: histogram
+ stability: development
+ extends: mcp.session.metrics.attributes
diff --git a/model/mcp/registry.yaml b/model/mcp/registry.yaml
new file mode 100644
index 0000000000..fa4455a7f8
--- /dev/null
+++ b/model/mcp/registry.yaml
@@ -0,0 +1,155 @@
+groups:
+ - id: registry.mcp
+ type: attribute_group
+ brief: >
+ [Model Context Protocol (MCP)](https://modelcontextprotocol.io) attributes
+ attributes:
+ - id: mcp.method.name
+ brief: The name of the request or notification method.
+ stability: development
+ type:
+ members:
+ - id: notifications_cancelled
+ value: notifications/cancelled
+ brief: >
+ Notification cancelling a previously-issued request.
+ stability: development
+ - id: initialize
+ value: initialize
+ brief: >
+ Request to initialize the MCP client.
+ stability: development
+ - id: notifications_initialized
+ value: notifications/initialized
+ brief: >
+ Notification indicating that the MCP client has been initialized.
+ stability: development
+ - id: notifications_progress
+ value: notifications/progress
+ brief: >
+ Notification indicating the progress for a long-running operation.
+ stability: development
+ - id: ping
+ value: ping
+ brief: >
+ Request to check that the other party is still alive.
+ stability: development
+ - id: resources_list
+ value: resources/list
+ brief: >
+ Request to list resources available on server.
+ stability: development
+ - id: resources_templates_list
+ value: resources/templates/list
+ brief: >
+ Request to list resource templates available on server.
+ stability: development
+ - id: resources_read
+ value: resources/read
+ brief: >
+ Request to read a resource.
+ stability: development
+ - id: notifications_resources_list_changed
+ value: notifications/resources/list_changed
+ brief: >
+ Notification indicating that the list of resources has changed.
+ stability: development
+ - id: resources_subscribe
+ value: resources/subscribe
+ brief: >
+ Request to subscribe to a resource.
+ stability: development
+ - id: resources_unsubscribe
+ value: resources/unsubscribe
+ brief: >
+ Request to unsubscribe from resource updates.
+ stability: development
+ - id: notifications_resources_updated
+ value: notifications/resources/updated
+ brief: >
+ Notification indicating that a resource has been updated.
+ stability: development
+ - id: prompts_list
+ value: prompts/list
+ brief: >
+ Request to list prompts available on server.
+ stability: development
+ - id: prompts_get
+ value: prompts/get
+ brief: >
+ Request to get a prompt.
+ stability: development
+ - id: notifications_prompts_list_changed
+ value: notifications/prompts/list_changed
+ brief: >
+ Notification indicating that the list of prompts has changed.
+ stability: development
+ - id: tools_list
+ value: tools/list
+ brief: >
+ Request to list tools available on server.
+ stability: development
+ - id: tools_call
+ value: tools/call
+ brief: >
+ Request to call a tool.
+ stability: development
+ - id: notifications_tools_list_changed
+ value: notifications/tools/list_changed
+ brief: >
+ Notification indicating that the list of tools has changed.
+ stability: development
+ - id: logging_set_level
+ value: logging/setLevel
+ brief: >
+ Request to set the logging level.
+ stability: development
+ - id: notifications_message
+ value: notifications/message
+ brief: >
+ Notification indicating that a message has been received.
+ stability: development
+ - id: sampling_create_message
+ value: sampling/createMessage
+ brief: >
+ Request to create a sampling message.
+ stability: development
+ - id: completion_complete
+ value: completion/complete
+ brief: >
+ Request to complete a prompt.
+ stability: development
+ - id: roots_list
+ value: roots/list
+ brief: >
+ Request to list roots available on server.
+ stability: development
+ - id: notifications_roots_list_changed
+ value: notifications/roots/list_changed
+ brief: >
+ Notification indicating that the list of roots has changed.
+ stability: development
+ - id: elicitation_create
+ value: elicitation/create
+ brief: >
+ Request from the server to elicit additional information from the
+ user via the client
+ stability: development
+ - id: mcp.session.id
+ type: string
+ brief: Identifies [MCP session](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#session-management).
+ stability: development
+ examples: ["191c4850af6c49e08843a3f6c80e5046"]
+ - id: mcp.resource.uri
+ type: string
+ brief: The value of the resource uri.
+ note: >
+ This is a URI of the resource provided in the following requests or notifications:
+ `resources/read`, `resources/subscribe`, `resources/unsubscribe`, or `notifications/resources/updated`.
+ stability: development
+ examples: ["postgres://database/customers/schema", "file:///home/user/documents/report.pdf"]
+ - id: mcp.protocol.version
+ type: string
+ brief: The [version](https://modelcontextprotocol.io/specification/versioning) of the Model Context Protocol used.
+ stability: development
+ examples: ["2025-06-18"]
diff --git a/model/mcp/spans.yaml b/model/mcp/spans.yaml
new file mode 100644
index 0000000000..bab682a14b
--- /dev/null
+++ b/model/mcp/spans.yaml
@@ -0,0 +1,95 @@
+groups:
+ - id: trace.mcp.common.attributes
+ type: attribute_group
+ extends: mcp.common.attributes
+ brief: MCP common span attributes
+ attributes:
+ - ref: mcp.session.id
+ requirement_level:
+ recommended: When the MCP request or notification is part of a session.
+ - ref: mcp.resource.uri
+ requirement_level:
+ conditionally_required: When the client executes a request type that includes a resource URI parameter.
+ - ref: jsonrpc.request.id
+ requirement_level:
+ conditionally_required: When the client executes a request.
+
+ - id: span.mcp.client
+ type: span
+ span_kind: client
+ brief: This span describes the MCP call from the client side.
+ note: |
+ It's reported by the MCP client when it initiates the request
+ or notification or by the MCP server when server initiates the operation.
+ It covers the time to receive the response or ack from the peer.
+
+ **Span name** SHOULD follow the format `{mcp.method.name} {target}`
+ where target SHOULD match `{gen_ai.tool.name}` or `{gen_ai.prompt.name}` when
+ applicable.
+ If there is no low-cardinality `target` available, the Span name SHOULD be `{mcp.method.name}`.
+
+ Instrumentation MAY allow users to opt into including `{mcp.resource.uri}`
+ as `target` in the span name when it is available but SHOULD NOT include it by default
+ to avoid high cardinality span names.
+
+ **Span status** SHOULD be set to `ERROR` when `error.type` attribute is present.
+ The status description SHOULD match the `JSONRPCError.message` if the message is available.
+
+ Refer to the [Recording Errors](/docs/general/recording-errors.md) document
+ for more details.
+
+ MCP tool call execution spans are compatible with GenAI [execute_tool spans](/docs/gen-ai/gen-ai-spans.md#execute-tool-span).
+
+ If the MCP instrumentation can reliably detect that outer GenAI instrumentation
+ is already tracing the tool execution, it SHOULD NOT create a separate span.
+ Instead, it SHOULD add MCP-specific attributes to the existing tool execution span.
+
+ Instrumentations that support this behavior MAY provide a configuration
+ option to enable it.
+ stability: development
+ extends: trace.mcp.common.attributes
+ attributes:
+ - ref: server.address
+ requirement_level:
+ recommended: If applicable
+ - ref: server.port
+ requirement_level:
+ recommended: When `server.address` is set
+ - ref: gen_ai.tool.call.arguments
+ requirement_level: opt_in
+ - ref: gen_ai.tool.call.result
+ requirement_level: opt_in
+
+ - id: span.mcp.server
+ type: span
+ span_kind: server
+ brief: This span describes the processing of the MCP request or notification
+ initiated by the peer.
+ note: |
+ It's reported by the MCP server when client initiates the request
+ (or notification) or by the MCP client when server initiates the operation.
+
+ **Span name** SHOULD follow the format `{mcp.method.name} {target}`
+ where target SHOULD match `{gen_ai.tool.name}` or `{gen_ai.prompt.name}` when
+ applicable.
+ If there is no low-cardinality `target` available, the Span name SHOULD be `{mcp.method.name}`.
+
+ Instrumentation MAY allow users to opt into including `{mcp.resource.uri}`
+ as `target` in the span name when it is available but SHOULD NOT include it by default
+ to avoid high cardinality span names.
+
+ **Span status** SHOULD be set to `ERROR` when `error.type` attribute is present.
+ The status description SHOULD match the `JSONRPCError.message` if the message is available.
+
+ Refer to the [Recording Errors](/docs/general/recording-errors.md) document
+ for more details.
+ stability: development
+ extends: trace.mcp.common.attributes
+ attributes:
+ - ref: client.address
+ requirement_level:
+ recommended: If applicable
+
+ - ref: client.port
+ requirement_level:
+ recommended: When `client.address` is set
diff --git a/templates/registry/markdown/weaver.yaml b/templates/registry/markdown/weaver.yaml
index 1471999c5a..656281f909 100644
--- a/templates/registry/markdown/weaver.yaml
+++ b/templates/registry/markdown/weaver.yaml
@@ -40,6 +40,7 @@ acronyms:
- HTTP
- iOS
- JVM
+ - MCP
- NFS
- NodeJS
- OCI