Skip to content

Commit e1ebbc7

Browse files
committed
Make opentelemetry-api a mandatory dependency
Simplify _otel.py by removing the ImportError fallback and lru_cache since opentelemetry-api is now always available.
1 parent bbdd99b commit e1ebbc7

File tree

4 files changed

+13
-46
lines changed

4 files changed

+13
-46
lines changed

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,13 @@ dependencies = [
4040
"pyjwt[crypto]>=2.10.1",
4141
"typing-extensions>=4.13.0",
4242
"typing-inspection>=0.4.1",
43+
"opentelemetry-api>=1.28.0",
4344
]
4445

4546
[project.optional-dependencies]
4647
rich = ["rich>=13.9.4"]
4748
cli = ["typer>=0.16.0", "python-dotenv>=1.0.0"]
4849
ws = ["websockets>=15.0.1"]
49-
otel = ["opentelemetry-api>=1.28.0"]
5050

5151
[project.scripts]
5252
mcp = "mcp.cli:app [cli]"
@@ -58,7 +58,7 @@ required-version = ">=0.9.5"
5858
[dependency-groups]
5959
dev = [
6060
# We add mcp[cli,ws] so `uv sync` considers the extras.
61-
"mcp[cli,ws,otel]",
61+
"mcp[cli,ws]",
6262
"pyright>=1.1.400",
6363
"pytest>=8.3.4",
6464
"ruff>=0.8.5",

src/mcp/shared/_otel.py

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,14 @@
1-
"""OpenTelemetry helpers for MCP.
2-
3-
Provides a context manager that creates an OpenTelemetry span when
4-
``opentelemetry-api`` is installed, or acts as a no-op otherwise.
5-
"""
1+
"""OpenTelemetry helpers for MCP."""
62

73
from __future__ import annotations
84

9-
import functools
105
from collections.abc import Iterator
116
from contextlib import contextmanager
127
from typing import Any
138

9+
from opentelemetry.trace import SpanKind, get_tracer
1410

15-
@functools.lru_cache(maxsize=1)
16-
def _get_tracer() -> Any:
17-
"""Return the OTel tracer for ``mcp``, or ``None``."""
18-
try:
19-
from opentelemetry.trace import get_tracer
20-
21-
return get_tracer("mcp-python-sdk")
22-
except ImportError:
23-
return None
11+
_tracer = get_tracer("mcp-python-sdk")
2412

2513

2614
@contextmanager
@@ -30,14 +18,7 @@ def otel_span(
3018
kind: str = "INTERNAL",
3119
attributes: dict[str, Any] | None = None,
3220
) -> Iterator[Any]:
33-
"""Create an OTel span if ``opentelemetry-api`` is installed, else no-op."""
34-
tracer = _get_tracer()
35-
if tracer is None:
36-
yield None
37-
return
38-
39-
from opentelemetry.trace import SpanKind
40-
21+
"""Create an OTel span."""
4122
span_kind = getattr(SpanKind, kind, SpanKind.INTERNAL)
42-
with tracer.start_as_current_span(name, kind=span_kind, attributes=attributes) as span:
23+
with _tracer.start_as_current_span(name, kind=span_kind, attributes=attributes) as span:
4324
yield span

tests/shared/test_otel.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,12 @@
11
from __future__ import annotations
22

3-
from unittest.mock import patch
4-
53
import pytest
64

7-
from mcp.shared._otel import _get_tracer, otel_span
5+
from mcp.shared._otel import otel_span
86

97
pytestmark = pytest.mark.anyio
108

119

1210
def test_otel_span_creates_span():
13-
_get_tracer.cache_clear()
1411
with otel_span("test.span", kind="CLIENT", attributes={"key": "value"}) as span:
1512
assert span is not None
16-
17-
18-
def test_otel_span_noop_when_unavailable():
19-
_get_tracer.cache_clear()
20-
with patch.dict("sys.modules", {"opentelemetry": None, "opentelemetry.trace": None}):
21-
_get_tracer.cache_clear()
22-
with otel_span("test.span") as span:
23-
assert span is None
24-
_get_tracer.cache_clear()

uv.lock

Lines changed: 5 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)