Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/concepts/tasks/tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -424,8 +424,8 @@ Task operations may throw <xref:ModelContextProtocol.McpException> with these er

| Error Code | Scenario |
|------------|----------|
| `InvalidParams` | Invalid or nonexistent task ID |
| `InvalidRequest` | Tool with `taskSupport: forbidden` called with task metadata, or tool with `taskSupport: required` called without task metadata |
| `InvalidParams` | Invalid or nonexistent task ID or invalid cursor |
| `InvalidParams` | Tool with `taskSupport: forbidden` called with task metadata, or tool with `taskSupport: required` called without task metadata |
| `InternalError` | Task execution failure or result unavailable |

Example error handling:
Expand Down
25 changes: 19 additions & 6 deletions src/ModelContextProtocol.Core/McpErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,19 @@ public enum McpErrorCode
InvalidRequest = -32600,

/// <summary>
/// Indicates that the requested method does not exist or is not available on the server.
/// Indicates that the requested method does not exist or is not available.
/// </summary>
/// <remarks>
/// This error is returned when the method name specified in the request cannot be found.
/// <para>
/// In MCP, this error is returned when a request is made for a method that requires a capability
/// that has not been declared. This can occur in either direction:
/// </para>
/// <list type="bullet">
/// <item><description>A server returning this error when the client requests a capability it doesn't support
/// (for example, requesting completions when the <c>completions</c> capability was not advertised).</description></item>
/// <item><description>A client returning this error when the server requests a capability it doesn't support
/// (for example, requesting roots when the client did not declare the <c>roots</c> capability).</description></item>
/// </list>
/// </remarks>
MethodNotFound = -32601,

Expand All @@ -51,12 +60,16 @@ public enum McpErrorCode
/// </summary>
/// <remarks>
/// <para>
/// This error is returned for protocol-level parameter issues, such as:
Comment thread
stephentoub marked this conversation as resolved.
/// In MCP, this error is returned in various contexts when request parameters fail validation:
/// </para>
/// <list type="bullet">
/// <item><description>Malformed requests that fail to satisfy the request schema (for example, CallToolRequest)</description></item>
/// <item><description>Unknown or unrecognized primitive names (for example, tool, prompt, or resource names)</description></item>
/// <item><description>Missing required protocol-level parameters</description></item>
/// <item><description><b>Tools</b>: Unknown tool name or invalid tool arguments.</description></item>
/// <item><description><b>Prompts</b>: Unknown prompt name or missing required arguments.</description></item>
/// <item><description><b>Pagination</b>: Invalid or expired cursor values.</description></item>
/// <item><description><b>Logging</b>: Invalid log level.</description></item>
/// <item><description><b>Tasks</b>: Invalid or nonexistent task ID or invalid cursor.</description></item>
/// <item><description><b>Elicitation</b>: Server requests an elicitation mode not declared in client capabilities.</description></item>
/// <item><description><b>Sampling</b>: Missing tool result or tool results mixed with other content.</description></item>
/// </list>
/// <para>
/// Note: Input validation errors within tool/prompt/resource arguments should be reported as execution errors
Expand Down
4 changes: 2 additions & 2 deletions src/ModelContextProtocol.Core/Server/McpServerImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,7 @@ await originalListToolsHandler(request, cancellationToken).ConfigureAwait(false)
{
throw new McpProtocolException(
$"Tool '{tool.ProtocolTool.Name}' does not support task-augmented execution.",
McpErrorCode.MethodNotFound);
McpErrorCode.InvalidParams);
}

// Task augmentation requested - return CreateTaskResult
Expand All @@ -604,7 +604,7 @@ await originalListToolsHandler(request, cancellationToken).ConfigureAwait(false)
throw new McpProtocolException(
$"Tool '{tool.ProtocolTool.Name}' requires task-augmented execution. " +
"Include a 'task' parameter with the request.",
McpErrorCode.MethodNotFound);
McpErrorCode.InvalidParams);
}

// Normal synchronous execution
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ await client.CallToolAsync(
TestContext.Current.CancellationToken));

Assert.Contains("does not support task-augmented execution", exception.Message, StringComparison.OrdinalIgnoreCase);
Assert.Equal(McpErrorCode.MethodNotFound, exception.ErrorCode);
Assert.Equal(McpErrorCode.InvalidParams, exception.ErrorCode);
}

[Fact]
Expand Down Expand Up @@ -227,7 +227,7 @@ await client.CallToolAsync(
TestContext.Current.CancellationToken));

Assert.Contains("requires task-augmented execution", exception.Message, StringComparison.OrdinalIgnoreCase);
Assert.Equal(McpErrorCode.MethodNotFound, exception.ErrorCode);
Assert.Equal(McpErrorCode.InvalidParams, exception.ErrorCode);
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ public async Task CompletedTask_CannotTransitionToOtherStatus()

Assert.Equal(McpTaskStatus.Completed, taskStatus.Status);

// Act - Try to cancel a completed task
// Act - Try to cancel a completed task (should be idempotent)
var cancelResult = await client.CancelTaskAsync(taskId, cancellationToken: TestContext.Current.CancellationToken);

// Assert - Status should still be completed (not cancelled)
Expand Down Expand Up @@ -500,7 +500,7 @@ public async Task FailedTask_CannotTransitionToOtherStatus()

Assert.Equal(McpTaskStatus.Failed, taskStatus.Status);

// Act - Try to cancel a failed task
// Act - Try to cancel a failed task (should be idempotent)
var cancelResult = await client.CancelTaskAsync(taskId, cancellationToken: TestContext.Current.CancellationToken);

// Assert - Status should still be failed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -526,8 +526,8 @@ public async Task SyncTool_WithRequiredTaskSupport_CannotBeCalledDirectly()
arguments: new Dictionary<string, object?> { ["input"] = "test" },
cancellationToken: TestContext.Current.CancellationToken).AsTask());

// The server returns MethodNotFound because direct invocation is not allowed for required-task tools
Assert.Equal(McpErrorCode.MethodNotFound, exception.ErrorCode);
// The server returns InvalidParams because direct invocation is not allowed for required-task tools
Assert.Equal(McpErrorCode.InvalidParams, exception.ErrorCode);
Assert.Contains("task", exception.Message, StringComparison.OrdinalIgnoreCase);
}

Expand Down
Loading