Log tool invocation errors (#447)

* Log tool errors
* add test and implement source generated logging
This commit is contained in:
кɵɵѕнī 2025-05-23 16:48:47 -05:00 • committed by GitHub
commit adb2098e4d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,7 +1,9 @@
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using ModelContextProtocol.Tests.Utils;
using Moq;
using System.Reflection;
using System.Text.Json;
@ -381,6 +383,45 @@ public partial class McpServerToolTests
);
}
[Fact]
public async Task ToolCallError_LogsErrorMessage()
{
// Arrange
var mockLoggerProvider = new MockLoggerProvider();
var loggerFactory = new LoggerFactory(new[] { mockLoggerProvider });
var services = new ServiceCollection();
services.AddSingleton<ILoggerFactory>(loggerFactory);
var serviceProvider = services.BuildServiceProvider();
var toolName = "tool-that-throws";
var exceptionMessage = "Test exception message";
McpServerTool tool = McpServerTool.Create(() =>
{
throw new InvalidOperationException(exceptionMessage);
}, new() { Name = toolName, Services = serviceProvider });
var mockServer = new Mock<IMcpServer>();
var request = new RequestContext<CallToolRequestParams>(mockServer.Object)
{
Params = new CallToolRequestParams() { Name = toolName },
Services = serviceProvider
};
// Act
var result = await tool.InvokeAsync(request, TestContext.Current.CancellationToken);
// Assert
Assert.True(result.IsError);
Assert.Single(result.Content);
Assert.Equal($"An error occurred invoking '{toolName}'.", result.Content[0].Text);
var errorLog = Assert.Single(mockLoggerProvider.LogMessages, m => m.LogLevel == LogLevel.Error);
Assert.Equal($"\"{toolName}\" threw an unhandled exception.", errorLog.Message);
Assert.IsType<InvalidOperationException>(errorLog.Exception);
Assert.Equal(exceptionMessage, errorLog.Exception.Message);
}
private sealed class MyService;
private class DisposableToolType : IDisposable