Skip to content

Conversation

halter73
Copy link
Contributor

@halter73 halter73 commented Oct 9, 2025

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.

/// invalid parameters, or internal errors. It is not intended to be used for application-level errors.

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.

@Jaben
Copy link

Jaben commented Oct 10, 2025

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.

FIne by me -- Just need a way to handle. My plan was to dump ex.Message in most cases. Thank you!

McpProtocolException derives from McpException which can still be used
to control the JsonRpcErrorDetail set by McpSessionHandler and the
CallToolResult error content set by McpServerImpl making this change
non-breaking unless you were previously setting an ErrorCode
@halter73 halter73 merged commit 3255adb into main Oct 15, 2025
14 of 18 checks passed
@halter73 halter73 deleted the halter73/820 branch October 15, 2025 02:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parameter Argument Errors Aren't Communicated AddCallToolFilter does not allow to catch exceptions

5 participants