@@ -43,7 +43,7 @@ const (
4343)
4444
4545// WithSentryTracing wraps an MCP tool handler with Sentry tracing.
46- // It creates spans following OpenTelemetry MCP semantic conventions and
46+ // It creates transactions following OpenTelemetry MCP semantic conventions and
4747// captures tool execution results and errors.
4848//
4949// Example usage:
@@ -56,56 +56,62 @@ const (
5656// }))
5757func WithSentryTracing [In , Out any ](toolName string , handler mcp.ToolHandlerFor [In , Out ]) mcp.ToolHandlerFor [In , Out ] {
5858 return func (ctx context.Context , req * mcp.CallToolRequest , args In ) (* mcp.CallToolResult , Out , error ) {
59- // Create span for tool execution
60- span := sentry .StartSpan (ctx , OpMCPServer )
61- defer span .Finish ()
59+ // Get the current hub from context or create a new one
60+ hub := sentry .GetHubFromContext (ctx )
61+ if hub == nil {
62+ hub = sentry .CurrentHub ().Clone ()
63+ ctx = sentry .SetHubOnContext (ctx , hub )
64+ }
6265
63- // Set span name following MCP conventions: "tools/call {tool_name}"
64- span .Description = fmt .Sprintf ("tools/call %s" , toolName )
66+ // Create transaction for tool execution following MCP conventions
67+ // Transaction name: "tools/call {tool_name}" (e.g., "tools/call get_action_parameters")
68+ transactionName := fmt .Sprintf ("tools/call %s" , toolName )
69+ transaction := sentry .StartTransaction (ctx ,
70+ transactionName ,
71+ sentry .WithOpName (OpMCPServer ),
72+ sentry .WithTransactionSource (sentry .SourceCustom ),
73+ )
74+ defer transaction .Finish ()
6575
6676 // Set common MCP attributes
67- span .SetData (AttrMCPMethodName , "tools/call" )
68- span .SetData (AttrMCPToolName , toolName )
69- span .SetData (AttrMCPTransport , TransportStdio )
70- span .SetData (AttrNetworkTransport , NetworkTransportPipe )
71- span .SetData (AttrNetworkProtocolVer , JSONRPCVersion )
77+ transaction .SetData (AttrMCPMethodName , "tools/call" )
78+ transaction .SetData (AttrMCPToolName , toolName )
79+ transaction .SetData (AttrMCPTransport , TransportStdio )
80+ transaction .SetData (AttrNetworkTransport , NetworkTransportPipe )
81+ transaction .SetData (AttrNetworkProtocolVer , JSONRPCVersion )
7282
7383 // Set Sentry-specific attributes
74- span .SetData ("sentry.origin" , OriginMCPFunction )
75- span .SetData ("sentry.source" , SourceMCPRoute )
84+ transaction .SetData ("sentry.origin" , OriginMCPFunction )
85+ transaction .SetData ("sentry.source" , SourceMCPRoute )
7686
7787 // Extract and set request ID if available
7888 if req != nil {
7989 // The CallToolRequest may have metadata we can extract
8090 // For now, we'll use reflection to check if there's an ID field
81- setRequestMetadata (span , req )
91+ setRequestMetadata (transaction , req )
8292 }
8393
8494 // Extract and set tool arguments
85- setToolArguments (span , args )
95+ setToolArguments (transaction , args )
8696
87- // Execute the handler with the span 's context
88- ctx = span .Context ()
97+ // Execute the handler with the transaction 's context
98+ ctx = transaction .Context ()
8999 result , data , err := handler (ctx , req , args )
90100
91101 // Capture error if present
92102 if err != nil {
93- span .Status = sentry .SpanStatusInternalError
94- span .SetData (AttrMCPToolResultIsError , true )
103+ transaction .Status = sentry .SpanStatusInternalError
104+ transaction .SetData (AttrMCPToolResultIsError , true )
95105
96106 // Capture the error to Sentry with context
97- hub := sentry .GetHubFromContext (ctx )
98- if hub == nil {
99- hub = sentry .CurrentHub ()
100- }
101107 hub .CaptureException (err )
102108 } else {
103- span .Status = sentry .SpanStatusOK
104- span .SetData (AttrMCPToolResultIsError , false )
109+ transaction .Status = sentry .SpanStatusOK
110+ transaction .SetData (AttrMCPToolResultIsError , false )
105111
106112 // Extract result metadata
107113 if result != nil {
108- setResultMetadata (span , result )
114+ setResultMetadata (transaction , result )
109115 }
110116 }
111117
0 commit comments