Propagate tool call exceptions through filters (#844)
* Add McpProtocolException specifically for JSON-RPC errors
This commit is contained in:
parent
2c9558cf21
commit
3255adb4d6
1 changed files with 334 additions and 163 deletions
|
|
@ -36,7 +36,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.CallToolAsync(
|
||||
"authorized_tool",
|
||||
new Dictionary<string, object?> { ["message"] = "test" },
|
||||
|
|
@ -101,7 +101,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.CallToolAsync(
|
||||
"admin_tool",
|
||||
new Dictionary<string, object?> { ["message"] = "test" },
|
||||
|
|
@ -188,7 +188,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.GetPromptAsync(
|
||||
"authorized_prompt",
|
||||
new Dictionary<string, object?> { ["message"] = "test" },
|
||||
|
|
@ -235,7 +235,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.ReadResourceAsync(
|
||||
"resource://authorized",
|
||||
cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
|
@ -277,7 +277,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
await using var app = await StartServerWithoutAuthFilters(builder => builder.WithTools<AuthorizationTestTools>());
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.ListToolsAsync(cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
||||
Assert.Equal("Request failed (remote): An error occurred.", exception.Message);
|
||||
|
|
@ -289,21 +289,23 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CallTool_WithoutAuthFilters_ThrowsInvalidOperationException()
|
||||
public async Task CallTool_WithoutAuthFilters_ReturnsError()
|
||||
{
|
||||
_mockLoggerProvider.LogMessages.Clear();
|
||||
await using var app = await StartServerWithoutAuthFilters(builder => builder.WithTools<AuthorizationTestTools>());
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
await client.CallToolAsync(
|
||||
var toolResult = await client.CallToolAsync(
|
||||
"authorized_tool",
|
||||
new Dictionary<string, object?> { ["message"] = "test" },
|
||||
cancellationToken: TestContext.Current.CancellationToken));
|
||||
cancellationToken: TestContext.Current.CancellationToken);
|
||||
|
||||
Assert.Equal("Request failed (remote): An error occurred.", exception.Message);
|
||||
Assert.True(toolResult.IsError);
|
||||
|
||||
var errorContent = Assert.IsType<TextContentBlock>(Assert.Single(toolResult.Content));
|
||||
Assert.Equal("An error occurred invoking 'authorized_tool'.", errorContent.Text);
|
||||
Assert.Contains(_mockLoggerProvider.LogMessages, log =>
|
||||
log.LogLevel == LogLevel.Warning &&
|
||||
log.LogLevel == LogLevel.Error &&
|
||||
log.Exception is InvalidOperationException &&
|
||||
log.Exception.Message.Contains("Authorization filter was not invoked for tools/call operation") &&
|
||||
log.Exception.Message.Contains("Ensure that AddAuthorizationFilters() is called"));
|
||||
|
|
@ -316,7 +318,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
await using var app = await StartServerWithoutAuthFilters(builder => builder.WithPrompts<AuthorizationTestPrompts>());
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.ListPromptsAsync(cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
||||
Assert.Equal("Request failed (remote): An error occurred.", exception.Message);
|
||||
|
|
@ -334,7 +336,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
await using var app = await StartServerWithoutAuthFilters(builder => builder.WithPrompts<AuthorizationTestPrompts>());
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.GetPromptAsync(
|
||||
"authorized_prompt",
|
||||
new Dictionary<string, object?> { ["message"] = "test" },
|
||||
|
|
@ -355,7 +357,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
await using var app = await StartServerWithoutAuthFilters(builder => builder.WithResources<AuthorizationTestResources>());
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.ListResourcesAsync(cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
||||
Assert.Equal("Request failed (remote): An error occurred.", exception.Message);
|
||||
|
|
@ -373,7 +375,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
await using var app = await StartServerWithoutAuthFilters(builder => builder.WithResources<AuthorizationTestResources>());
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.ReadResourceAsync(
|
||||
"resource://authorized",
|
||||
cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
|
@ -393,7 +395,7 @@ public class AuthorizeAttributeTests(ITestOutputHelper testOutputHelper) : Kestr
|
|||
await using var app = await StartServerWithoutAuthFilters(builder => builder.WithResources<AuthorizationTestResources>());
|
||||
var client = await ConnectAsync();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<McpException>(async () =>
|
||||
var exception = await Assert.ThrowsAsync<McpProtocolException>(async () =>
|
||||
await client.ListResourceTemplatesAsync(cancellationToken: TestContext.Current.CancellationToken));
|
||||
|
||||
Assert.Equal("Request failed (remote): An error occurred.", exception.Message);
|
||||
|
|
|
|||
Loading…
Reference in a new issue