Propagate tool call exceptions through filters #844
Merged
+334
−163
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
I thought I added tests that verified that tool call exceptions propagated through filters before getting converted to a CallToolResult with
IsError = true
when I originally added the filter pipeline in #733, but I did not. If I had, I would have noticed that I put the exception catching logic immediately around the call to McpServerTool.InvokeAsync or the custom CallToolHandler without letting it propagate through the entire filter pipeline which was not my intention.This PR adds a new Exception type, McpServerToolException, because authorization filters still need the ability to throw an McpException to produce a JsonRpcError like it does in other handler types. McpServerToolException allows McpServerTool implementations to retain the ability to produce an CallToolResult with
IsError = true
and a custom message with an exception like before. However, I think even if not for the authorization filters, this change makes sense considering that McpException is "not intended to be used for application-level errors.", and it includes details irrelevant to the CallToolResult like the McpErrorCode.csharp-sdk/src/ModelContextProtocol.Core/McpException.cs
Line 8 in f286391
Technically, it isn't strictly necessary for McpServerToolException to exist considering any McpServerTool or CallToolHandler can just return a CallToolResult with
IsError = true
, but that might be inconvenient.Fixes #820
This doesn't fix #830, since ArgumentException's from ReflectionAIFunctionDescriptor.GetParameterMarshaller will still get turned into generic errors without further intervention. But least after this change, developers will be able to add a tool call filter that observes the ArgumentException and turns it into a McpServerToolException (to produce a CallToolResult with IsError = true) or McpException (to produce a JsonRpcError with an McpErrorCode) depending on their needs.