Skip to content

Commit effe0e8

Browse files
fix(mcp): Added support for newer version of MCP (#2956)
Signed-off-by: fali007 <[email protected]> Co-authored-by: ellipsis-dev[bot] <65095814+ellipsis-dev[bot]@users.noreply.github.com>
1 parent 1648905 commit effe0e8

File tree

1 file changed

+49
-2
lines changed
  • packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp

1 file changed

+49
-2
lines changed

packages/opentelemetry-instrumentation-mcp/opentelemetry/instrumentation/mcp/instrumentation.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
from dataclasses import dataclass
33
from typing import Any, AsyncGenerator, Callable, Collection, Tuple, cast
44
import json
5+
import logging
6+
import traceback
57

68
from opentelemetry import context, propagate
79
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
@@ -18,6 +20,35 @@
1820
_instruments = ("mcp >= 1.6.0",)
1921

2022

23+
class Config:
24+
exception_logger = None
25+
26+
27+
def dont_throw(func):
28+
"""
29+
A decorator that wraps the passed in function and logs exceptions instead of throwing them.
30+
31+
@param func: The function to wrap
32+
@return: The wrapper function
33+
"""
34+
# Obtain a logger specific to the function's module
35+
logger = logging.getLogger(func.__module__)
36+
37+
def wrapper(*args, **kwargs):
38+
try:
39+
return func(*args, **kwargs)
40+
except Exception as e:
41+
logger.debug(
42+
"OpenLLMetry failed to trace in %s, error: %s",
43+
func.__name__,
44+
traceback.format_exc(),
45+
)
46+
if Config.exception_logger:
47+
Config.exception_logger(e)
48+
49+
return wrapper
50+
51+
2152
class McpInstrumentor(BaseInstrumentor):
2253
def instrumentation_dependencies(self) -> Collection[str]:
2354
return _instruments
@@ -106,6 +137,7 @@ def traced_method(
106137
return traced_method
107138

108139
def patch_mcp_client(self, tracer):
140+
@dont_throw
109141
async def traced_method(wrapped, instance, args, kwargs):
110142
import mcp.types
111143

@@ -206,11 +238,18 @@ async def __aenter__(self) -> Any:
206238
async def __aexit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any:
207239
return await self.__wrapped__.__aexit__(exc_type, exc_value, traceback)
208240

241+
@dont_throw
209242
async def __aiter__(self) -> AsyncGenerator[Any, None]:
210243
from mcp.types import JSONRPCMessage, JSONRPCRequest
244+
from mcp.shared.message import SessionMessage
211245

212246
async for item in self.__wrapped__:
213-
request = cast(JSONRPCMessage, item).root
247+
if isinstance(item, SessionMessage):
248+
request = cast(JSONRPCMessage, item.message).root
249+
elif type(item) is JSONRPCMessage:
250+
request = cast(JSONRPCMessage, item).root
251+
else:
252+
return
214253
if not isinstance(request, JSONRPCRequest):
215254
yield item
216255
continue
@@ -240,10 +279,17 @@ async def __aenter__(self) -> Any:
240279
async def __aexit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any:
241280
return await self.__wrapped__.__aexit__(exc_type, exc_value, traceback)
242281

282+
@dont_throw
243283
async def send(self, item: Any) -> Any:
244284
from mcp.types import JSONRPCMessage, JSONRPCRequest
285+
from mcp.shared.message import SessionMessage
245286

246-
request = cast(JSONRPCMessage, item).root
287+
if isinstance(item, SessionMessage):
288+
request = cast(JSONRPCMessage, item.message).root
289+
elif type(item) is JSONRPCMessage:
290+
request = cast(JSONRPCMessage, item).root
291+
else:
292+
return
247293

248294
with self._tracer.start_as_current_span("ResponseStreamWriter") as span:
249295
if hasattr(request, "result"):
@@ -287,6 +333,7 @@ async def __aenter__(self) -> Any:
287333
async def __aexit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> Any:
288334
return await self.__wrapped__.__aexit__(exc_type, exc_value, traceback)
289335

336+
@dont_throw
290337
async def send(self, item: Any) -> Any:
291338
with self._tracer.start_as_current_span("RequestStreamWriter") as span:
292339
if hasattr(item, "request_id"):

0 commit comments

Comments
 (0)