Skip to content

Commit 7aed07f

Browse files
authored
Merge branch 'main' into copilot/add-description-property-client-server
2 parents 178f620 + 4b241e7 commit 7aed07f

File tree

4 files changed

+81
-16
lines changed

4 files changed

+81
-16
lines changed

src/ModelContextProtocol.Core/McpErrorCode.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,22 @@ public enum McpErrorCode
3030
MethodNotFound = -32601,
3131

3232
/// <summary>
33-
/// Indicates that one or more parameters provided in the request are invalid.
33+
/// Indicates that the request parameters are invalid at the protocol level.
3434
/// </summary>
3535
/// <remarks>
36-
/// This error is returned when the parameters do not match the expected method signature or constraints.
37-
/// This includes cases where required parameters are missing or not understood, such as when a name for
38-
/// a tool or prompt is not recognized.
36+
/// <para>
37+
/// This error is returned for protocol-level parameter issues, such as:
38+
/// </para>
39+
/// <list type="bullet">
40+
/// <item><description>Malformed requests that fail to satisfy the request schema (e.g., CallToolRequest)</description></item>
41+
/// <item><description>Unknown or unrecognized primitive names (e.g., tool, prompt, or resource names)</description></item>
42+
/// <item><description>Missing required protocol-level parameters</description></item>
43+
/// </list>
44+
/// <para>
45+
/// Note: Input validation errors within tool/prompt/resource arguments should be reported as execution errors
46+
/// (e.g., via <see cref="Protocol.CallToolResult.IsError"/>) rather than as protocol errors, allowing language
47+
/// models to receive error feedback and self-correct.
48+
/// </para>
3949
/// </remarks>
4050
InvalidParams = -32602,
4151

src/ModelContextProtocol.Core/McpProtocolException.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
namespace ModelContextProtocol;
22

33
/// <summary>
4-
/// Represents an exception that is thrown when an Model Context Protocol (MCP) error occurs.
4+
/// Represents an exception that is thrown when a Model Context Protocol (MCP) protocol-level error occurs.
55
/// </summary>
66
/// <remarks>
7-
/// This exception is used to represent failures to do with protocol-level concerns, such as invalid JSON-RPC requests,
8-
/// invalid parameters, or internal errors. It is not intended to be used for application-level errors.
7+
/// <para>
8+
/// This exception is used to represent failures related to protocol-level concerns, such as malformed
9+
/// JSON-RPC requests, unknown methods, unknown primitive names (tools/prompts/resources), or internal
10+
/// server errors. It is not intended to be used for tool execution errors, including input validation failures.
11+
/// </para>
12+
/// <para>
13+
/// Tool execution errors (including input validation errors, API failures, and business logic errors)
14+
/// should be returned in the result object with <c>IsError</c> set to <see langword="true"/>, allowing
15+
/// language models to see error details and self-correct. Only protocol-level issues should throw
16+
/// <see cref="McpProtocolException"/>.
17+
/// </para>
18+
/// <para>
919
/// <see cref="Exception.Message"/> or <see cref="ErrorCode"/> from a <see cref="McpProtocolException"/> may be
1020
/// propagated to the remote endpoint; sensitive information should not be included. If sensitive details need
1121
/// to be included, a different exception type should be used.
22+
/// </para>
1223
/// </remarks>
1324
public sealed class McpProtocolException : McpException
1425
{
@@ -65,7 +76,7 @@ public McpProtocolException(string message, Exception? innerException, McpErrorC
6576
/// <item><description>-32700: Parse error - Invalid JSON received</description></item>
6677
/// <item><description>-32600: Invalid request - The JSON is not a valid Request object</description></item>
6778
/// <item><description>-32601: Method not found - The method does not exist or is not available</description></item>
68-
/// <item><description>-32602: Invalid params - Invalid method parameters</description></item>
79+
/// <item><description>-32602: Invalid params - Malformed request or unknown primitive name (tool/prompt/resource)</description></item>
6980
/// <item><description>-32603: Internal error - Internal JSON-RPC error</description></item>
7081
/// </list>
7182
/// </remarks>

src/ModelContextProtocol.Core/Protocol/CallToolResult.cs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ namespace ModelContextProtocol.Protocol;
88
/// </summary>
99
/// <remarks>
1010
/// <para>
11-
/// Any errors that originate from the tool should be reported inside the result
12-
/// object, with <see cref="IsError"/> set to true, rather than as a <see cref="JsonRpcError"/>.
11+
/// Tool execution errors (including input validation errors, API failures, and business logic errors)
12+
/// should be reported inside the result object with <see cref="IsError"/> set to <see langword="true"/>,
13+
/// rather than as a <see cref="JsonRpcError"/>. This allows language models to see error details
14+
/// and potentially self-correct in subsequent requests.
1315
/// </para>
1416
/// <para>
15-
/// However, any errors in finding the tool, an error indicating that the
16-
/// server does not support tool calls, or any other exceptional conditions,
17-
/// should be reported as an MCP error response.
17+
/// Protocol-level errors (such as unknown tool names, malformed requests that fail schema validation,
18+
/// or server errors) should be reported as MCP protocol error responses using <see cref="McpErrorCode"/>.
1819
/// </para>
1920
/// <para>
2021
/// See the <see href="https://github.com/modelcontextprotocol/specification/blob/main/schema/">schema</see> for details.
@@ -38,10 +39,18 @@ public sealed class CallToolResult : Result
3839
/// Gets or sets an indication of whether the tool call was unsuccessful.
3940
/// </summary>
4041
/// <remarks>
42+
/// <para>
4143
/// When set to <see langword="true"/>, it signifies that the tool execution failed.
42-
/// Tool errors are reported with this property set to <see langword="true"/> and details in the <see cref="Content"/>
43-
/// property, rather than as protocol-level errors. This allows LLMs to see that an error occurred
44-
/// and potentially self-correct in subsequent requests.
44+
/// Tool execution errors (including input validation errors, API failures, and business logic errors)
45+
/// are reported with this property set to <see langword="true"/> and details in the <see cref="Content"/>
46+
/// property, rather than as protocol-level errors.
47+
/// </para>
48+
/// <para>
49+
/// This allows language models to receive detailed error feedback and potentially self-correct
50+
/// in subsequent requests. For example, if a date parameter is in the wrong format or out of range,
51+
/// the error message in <see cref="Content"/> can explain the issue, enabling the model to retry
52+
/// with corrected parameters.
53+
/// </para>
4554
/// </remarks>
4655
[JsonPropertyName("isError")]
4756
public bool? IsError { get; set; }

tests/ModelContextProtocol.Tests/Server/McpServerTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,41 @@ await Can_Handle_Requests(
591591
});
592592
}
593593

594+
[Fact]
595+
public async Task Can_Handle_Call_Tool_Requests_With_InputValidationException()
596+
{
597+
// Test that input validation errors (like ArgumentException from JSON deserialization)
598+
// are returned as tool execution errors (IsError=true) rather than protocol errors, per SEP-1303.
599+
const string errorMessage = "Input validation failed: invalid date format";
600+
601+
await Can_Handle_Requests(
602+
new ServerCapabilities
603+
{
604+
Tools = new()
605+
},
606+
method: RequestMethods.ToolsCall,
607+
configureOptions: options =>
608+
{
609+
options.Handlers.CallToolHandler = async (request, ct) =>
610+
{
611+
// Simulate an input validation error (like what would happen with wrong argument types)
612+
throw new ArgumentException(errorMessage);
613+
};
614+
options.Handlers.ListToolsHandler = (request, ct) => throw new NotImplementedException();
615+
},
616+
assertResult: (_, response) =>
617+
{
618+
var result = JsonSerializer.Deserialize<CallToolResult>(response, McpJsonUtilities.DefaultOptions);
619+
Assert.NotNull(result);
620+
Assert.True(result.IsError, "Input validation errors should be returned as tool execution errors (IsError=true), not protocol errors");
621+
Assert.NotEmpty(result.Content);
622+
var textContent = Assert.IsType<TextContentBlock>(result.Content[0]);
623+
// ArgumentException should result in a generic error message that doesn't expose the exception details
624+
Assert.DoesNotContain(errorMessage, textContent.Text);
625+
Assert.Contains("An error occurred", textContent.Text);
626+
});
627+
}
628+
594629
[Fact]
595630
public async Task Can_Handle_Call_Tool_Requests_With_McpProtocolException()
596631
{

0 commit comments

Comments
 (0)