1- using System ;
1+ using System ;
22using System . Threading ;
33using System . Threading . Tasks ;
44using Microsoft . Extensions . Hosting ;
55using Microsoft . Extensions . Logging ;
66using ModelContextProtocol . Server ;
77using Resgrid . Config ;
8+ using Sentry ;
89
910namespace Resgrid . Web . Mcp
1011{
@@ -35,6 +36,9 @@ public Task StartAsync(CancellationToken cancellationToken)
3536 {
3637 _logger . LogInformation ( "Starting Resgrid MCP Server..." ) ;
3738
39+ // Add Sentry breadcrumb for startup
40+ SentrySdk . AddBreadcrumb ( "MCP Server starting" , "server.lifecycle" , level : BreadcrumbLevel . Info ) ;
41+
3842 _stoppingCts = CancellationTokenSource . CreateLinkedTokenSource ( cancellationToken ) ;
3943
4044 try
@@ -49,7 +53,20 @@ public Task StartAsync(CancellationToken cancellationToken)
4953 // Register all tools from the registry
5054 _toolRegistry . RegisterTools ( _mcpServer ) ;
5155
52- _logger . LogInformation ( "MCP Server initialized with {ToolCount} tools" , _toolRegistry . GetToolCount ( ) ) ;
56+ var toolCount = _toolRegistry . GetToolCount ( ) ;
57+ _logger . LogInformation ( "MCP Server initialized with {ToolCount} tools" , toolCount ) ;
58+
59+ // Add Sentry breadcrumb for successful initialization
60+ SentrySdk . AddBreadcrumb (
61+ $ "MCP Server initialized with { toolCount } tools",
62+ "server.lifecycle" ,
63+ data : new System . Collections . Generic . Dictionary < string , string >
64+ {
65+ { "server_name" , serverName } ,
66+ { "server_version" , serverVersion } ,
67+ { "tool_count" , toolCount . ToString ( ) }
68+ } ,
69+ level : BreadcrumbLevel . Info ) ;
5370
5471 // Start the server execution
5572 _executingTask = ExecuteAsync ( _stoppingCts . Token ) ;
@@ -60,10 +77,20 @@ public Task StartAsync(CancellationToken cancellationToken)
6077 }
6178
6279 _logger . LogInformation ( "Resgrid MCP Server started successfully" ) ;
80+ SentrySdk . AddBreadcrumb ( "MCP Server started successfully" , "server.lifecycle" , level : BreadcrumbLevel . Info ) ;
6381 }
6482 catch ( Exception ex )
6583 {
6684 _logger . LogError ( ex , "Failed to start MCP Server" ) ;
85+
86+ // Capture exception in Sentry
87+ SentrySdk . CaptureException ( ex , scope =>
88+ {
89+ scope . SetTag ( "component" , "McpServerHost" ) ;
90+ scope . SetTag ( "operation" , "StartAsync" ) ;
91+ scope . Level = SentryLevel . Fatal ;
92+ } ) ;
93+
6794 throw ;
6895 }
6996
@@ -73,6 +100,7 @@ public Task StartAsync(CancellationToken cancellationToken)
73100 public async Task StopAsync ( CancellationToken cancellationToken )
74101 {
75102 _logger . LogInformation ( "Stopping Resgrid MCP Server..." ) ;
103+ SentrySdk . AddBreadcrumb ( "MCP Server stopping" , "server.lifecycle" , level : BreadcrumbLevel . Info ) ;
76104
77105 if ( _executingTask == null )
78106 {
@@ -92,25 +120,57 @@ public async Task StopAsync(CancellationToken cancellationToken)
92120 }
93121
94122 _logger . LogInformation ( "Resgrid MCP Server stopped" ) ;
123+ SentrySdk . AddBreadcrumb ( "MCP Server stopped" , "server.lifecycle" , level : BreadcrumbLevel . Info ) ;
95124 }
96125
97126 private async Task ExecuteAsync ( CancellationToken stoppingToken )
98127 {
128+ // Start a Sentry transaction for the MCP server execution
129+ var transaction = SentrySdk . StartTransaction ( "mcp.server.execution" , "mcp.lifecycle" ) ;
130+ var transactionFinished = false ;
131+
99132 try
100133 {
101134 _logger . LogInformation ( "MCP Server listening on stdio transport..." ) ;
135+ SentrySdk . AddBreadcrumb ( "MCP Server started listening" , "server.lifecycle" , level : BreadcrumbLevel . Info ) ;
102136
103137 // Run the server - this will handle stdio communication
104138 await _mcpServer . RunAsync ( stoppingToken ) ;
139+
140+ transaction . Status = SpanStatus . Ok ;
105141 }
106142 catch ( OperationCanceledException )
107143 {
108144 _logger . LogInformation ( "MCP Server execution was cancelled" ) ;
145+ SentrySdk . AddBreadcrumb ( "MCP Server execution cancelled" , "server.lifecycle" , level : BreadcrumbLevel . Info ) ;
146+ transaction . Status = SpanStatus . Cancelled ;
109147 }
110148 catch ( Exception ex )
111149 {
112150 _logger . LogError ( ex , "Unexpected error in MCP Server execution" ) ;
151+
152+ // Capture exception in Sentry with context
153+ SentrySdk . CaptureException ( ex , scope =>
154+ {
155+ scope . SetTag ( "component" , "McpServerHost" ) ;
156+ scope . SetTag ( "operation" , "ExecuteAsync" ) ;
157+ scope . Level = SentryLevel . Fatal ;
158+ scope . AddBreadcrumb ( "Server execution failed" , "server.error" , level : BreadcrumbLevel . Error ) ;
159+ } ) ;
160+
161+ transaction . Status = SpanStatus . InternalError ;
162+ transaction . Finish ( ex ) ;
163+ transactionFinished = true ;
164+
113165 _applicationLifetime . StopApplication ( ) ;
166+ return ;
167+ }
168+ finally
169+ {
170+ if ( ! transactionFinished )
171+ {
172+ transaction . Finish ( ) ;
173+ }
114174 }
115175 }
116176
0 commit comments