1
1
using Microsoft . Extensions . AI ;
2
2
using Microsoft . Extensions . DependencyInjection ;
3
+ using Microsoft . Extensions . Logging ;
4
+ using Microsoft . Extensions . Logging . Abstractions ;
3
5
using ModelContextProtocol . Protocol ;
4
6
using System . ComponentModel ;
5
7
using System . Diagnostics . CodeAnalysis ;
9
11
namespace ModelContextProtocol . Server ;
10
12
11
13
/// <summary>Provides an <see cref="McpServerTool"/> that's implemented via an <see cref="AIFunction"/>.</summary>
12
- internal sealed class AIFunctionMcpServerTool : McpServerTool
14
+ internal sealed partial class AIFunctionMcpServerTool : McpServerTool
13
15
{
16
+ private readonly ILogger _logger ;
17
+
14
18
/// <summary>
15
19
/// Creates an <see cref="McpServerTool"/> instance for a method, specified via a <see cref="Delegate"/> instance.
16
20
/// </summary>
@@ -194,7 +198,7 @@ options.OpenWorld is not null ||
194
198
}
195
199
}
196
200
197
- return new AIFunctionMcpServerTool ( function , tool ) ;
201
+ return new AIFunctionMcpServerTool ( function , tool , options ? . Services ) ;
198
202
}
199
203
200
204
private static McpServerToolCreateOptions DeriveOptions ( MethodInfo method , McpServerToolCreateOptions ? options )
@@ -239,10 +243,11 @@ private static McpServerToolCreateOptions DeriveOptions(MethodInfo method, McpSe
239
243
internal AIFunction AIFunction { get ; }
240
244
241
245
/// <summary>Initializes a new instance of the <see cref="McpServerTool"/> class.</summary>
242
- private AIFunctionMcpServerTool ( AIFunction function , Tool tool )
246
+ private AIFunctionMcpServerTool ( AIFunction function , Tool tool , IServiceProvider ? serviceProvider )
243
247
{
244
248
AIFunction = function ;
245
249
ProtocolTool = tool ;
250
+ _logger = serviceProvider ? . GetService < ILoggerFactory > ( ) ? . CreateLogger < McpServerTool > ( ) ?? ( ILogger ) NullLogger . Instance ;
246
251
}
247
252
248
253
/// <inheritdoc />
@@ -277,6 +282,8 @@ public override async ValueTask<CallToolResponse> InvokeAsync(
277
282
}
278
283
catch ( Exception e ) when ( e is not OperationCanceledException )
279
284
{
285
+ ToolCallError ( request . Params ? . Name ?? string . Empty , e ) ;
286
+
280
287
string errorMessage = e is McpException ?
281
288
$ "An error occurred invoking '{ request . Params ? . Name } ': { e . Message } " :
282
289
$ "An error occurred invoking '{ request . Params ? . Name } '.";
@@ -359,4 +366,7 @@ private static CallToolResponse ConvertAIContentEnumerableToCallToolResponse(IEn
359
366
IsError = allErrorContent && hasAny
360
367
} ;
361
368
}
369
+
370
+ [ LoggerMessage ( Level = LogLevel . Error , Message = "\" {ToolName}\" threw an unhandled exception." ) ]
371
+ private partial void ToolCallError ( string toolName , Exception exception ) ;
362
372
}
0 commit comments