Add OpenTelemetry instrumentation for Model Context Protocol (MCP)#3822
Add OpenTelemetry instrumentation for Model Context Protocol (MCP)#3822lukeina2z wants to merge 6 commits intoopen-telemetry:mainfrom
Conversation
0775d46 to
ba43d31
Compare
bba04fc to
36a82f4
Compare
4bcb845 to
10f1f8f
Compare
This commit introduces a new instrumentation package for the Model Context Protocol (MCP), enabling automatic distributed tracing for MCP client-server interactions. Key Features: - Automatic instrumentation of MCP client sessions and server handlers - Support for both stdio and HTTP/SSE transports - W3C trace context propagation across MCP messages - Comprehensive span attributes following semantic conventions - Tool calls, resource reads, prompt handling, and session lifecycle tracing Package Structure: - Core instrumentation: McpInstrumentor with automatic wrapping - Semantic attributes: MCP-specific span attributes and conventions - Test coverage: Unit tests for instrumentor, server, and session wrappers - Examples: stdio (simple-client-server) and HTTP/SSE transport demos - Documentation: README, CHANGELOG, and example-specific guides Technical Implementation: - Wraps mcp.ClientSession and mcp.server.Server classes - Injects trace context into message metadata - Extracts and propagates context across transport boundaries - Records exceptions and sets span status appropriately - Requires Python >=3.10 (MCP SDK requirement) CI/CD Updates: - Added MCP instrumentation to test workflows - Updated lint configuration for new package - Disabled pypy3 tests (Python 3.10+ requirement) - Integrated into eachdist.ini and bootstrap generation Examples: - simple-client-server: stdio transport with tool calls and resources - http-transport: HTTP/SSE transport with distributed tracing - Both include Jaeger trace visualizations and setup instructions"
| "Intended Audience :: Developers", | ||
| "License :: OSI Approved :: Apache Software License", | ||
| "Programming Language :: Python", | ||
| "Programming Language :: Python :: 3", |
There was a problem hiding this comment.
We drop python version 6 months after they have been EOL'ed. So Python 3.9 should be there.
There was a problem hiding this comment.
The MCP Python SDK does not support Python 3.9. Should the instrumentation library support Python 3.9?
https://github.com/modelcontextprotocol/python-sdk/blob/main/pyproject.toml#L18
xrmx
left a comment
There was a problem hiding this comment.
Are you in touch with the genai WG people? From a quick look it looks like this needs semantic conventions attributes that are not spec'ed it.
...enai/opentelemetry-instrumentation-mcp/src/opentelemetry/instrumentation/mcp/instrumentor.py
Show resolved
Hide resolved
| _CLIENT_SPAN_NAME = "mcp.client" | ||
| _SERVER_SPAN_NAME = "mcp.server" |
There was a problem hiding this comment.
are these defined by MCP semconv? shoud these be moved to attributes.py as well?
There was a problem hiding this comment.
These two constants are used to build span names, but they are not span names.
https://github.com/lmolkova/semantic-conventions/blob/mcp/docs/gen-ai/mcp.md
| tracer_provider: Optional tracer provider to use | ||
| propagators: Optional propagators for context injection/extraction | ||
| """ | ||
| _LOG.info("Initializing MCP instrumentor xyxyxy") |
There was a problem hiding this comment.
is this info logging needed? if yes, need to fix logging message content
|
|
||
| def instrumentation_dependencies(self) -> Collection[str]: | ||
| """Return the dependencies required for this instrumentation.""" | ||
| return ("mcp >= 1.8.1",) |
There was a problem hiding this comment.
any reason why the support starts from this version
There was a problem hiding this comment.
That's the start of the new protocol:
https://github.com/modelcontextprotocol/python-sdk/releases/tag/v1.8.0
This is the first release supporting the new Streamable HTTP transport from protocol version 2025-03-26, which supersedes the SSE transport from protocol version 2024-11-05. 🎉
| message_json = message.model_dump( | ||
| by_alias=True, mode="json", exclude_none=True | ||
| ) |
There was a problem hiding this comment.
is a try/catch error handling required to not interupt the original request?
There was a problem hiding this comment.
It's in try-except block now. Original call will be invoked explicitly if exception happens.
This is their PR: |
|
@lukeina2z Any timelines for this PR? |
| def hook(_module: Any) -> None: | ||
| wrap_function_wrapper(module, target, wrapper) | ||
|
|
||
| register_post_import_hook(hook, module) |
There was a problem hiding this comment.
question: Hi @lukeina2z, I’m still new to the repo and trying to learn the patterns here. I noticed that in other places wrap_function_wrapper is used directly, while here it’s combined with register_post_import_hook. Could you help me understand why this approach is preferred in this case? Thanks!
|
|
||
| class McpInstrumentor(BaseInstrumentor): | ||
| """ | ||
| Instrumentor for MCP (Model Context Protocol). |
There was a problem hiding this comment.
nit: I noticed the Instrumentor class has many methods (~450 lines). Other instrumentations like openai-v2 split wrapper logic into separate files (e.g., patch.py, utils.py). Would it make sense to follow that pattern here for consistency?
|
@lukeina2z are you still working on this PR? Any reason to open this separate PR when #3678 is already open? |
Description
This commit introduces a new instrumentation package for the Model Context
Protocol (MCP), enabling automatic distributed tracing for MCP client-server
interactions.
Key Features:
Package Structure:
Technical Implementation:
MCP semantic conventions
open-telemetry/semantic-conventions#2083
https://github.com/lmolkova/semantic-conventions/blob/mcp/docs/gen-ai/mcp.md
Examples:
Type of change
Please delete options that are not relevant.
How Has This Been Tested?
Unit tests added.
tox -e py310-test-instrumentation-mcp-oldest
tox -e py310-test-instrumentation-mcp-latest
tox -e py311-test-instrumentation-mcp-oldest
tox -e py311-test-instrumentation-mcp-latest
tox -e py312-test-instrumentation-mcp-oldest
tox -e py312-test-instrumentation-mcp-latest
tox -e py313-test-instrumentation-mcp-oldest
tox -e py313-test-instrumentation-mcp-latest
tox -e pypy3-test-instrumentation-mcp-oldest
tox -e pypy3-test-instrumentation-mcp-latest
tox -e lint-instrumentation-mcp
tox -e spellcheck
tox -e ruff
End to end testing with two applications in the examples folder.
Does This PR Require a Core Repo Change?
Checklist:
See contributing.md for styleguide, changelog guidelines, and more.