Publish multi-version documentation site (#1727)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: bb4b44f0-f505-49c5-9878-76e2b40c7a15
Copilot-Session: 8eac1204-10ae-4319-9333-aee5dd43dcc8
This commit is contained in:
Jeff Handley 2026-07-24 15:55:35 -07:00 • committed by GitHub
commit ae36026695
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -14,7 +14,7 @@ The MCP Server provides two levels of filters for intercepting and modifying req
The filters are stored in `McpServerOptions.Filters`.
## Available Request-Specific Filter Methods
## Available request-specific filter methods
The following request filter methods are available on `IMcpRequestFilterBuilder` inside `WithRequestFilters(...)`:
@ -32,23 +32,13 @@ The following request filter methods are available on `IMcpRequestFilterBuilder`
| `AddUnsubscribeFromResourcesFilter` | Resource unsubscription handlers |
| `AddSetLoggingLevelFilter` | Logging level handlers |
The Tasks extension and ASP.NET Core tool authorization use alternate-result `tools/call` filters.
Alternate-result filters run in registration order outside the ordinary `AddCallToolFilter`
pipeline. The Tasks filter creates a task at its position in that order and runs its remaining
pipeline in the background. Consequently, alternate-result filters registered before Tasks run
before task creation, while those registered after Tasks run in the background before the
ordinary filters and tool. ASP.NET Core authorization is registered before Tasks, so an
unauthorized call is rejected without creating a task.
The Tasks extension and ASP.NET Core tool authorization use alternate-result `tools/call` filters. Alternate-result filters run in registration order outside the ordinary `AddCallToolFilter` pipeline. The Tasks filter creates a task at its position in that order and runs its remaining pipeline in the background. Consequently, alternate-result filters registered before Tasks run before task creation, while those registered after Tasks run in the background before the ordinary filters and tool. ASP.NET Core authorization is registered before Tasks, so an unauthorized call is rejected without creating a task.
Ordinary call-tool filters run exactly once after all alternate-result filters and before the tool.
For task-backed calls, ordinary filters execute in the background after task creation. An explicit
`CallToolWithAlternateHandler` remains a full replacement and cannot be combined with ordinary
call-tool filters.
Ordinary call-tool filters run exactly once after all alternate-result filters and before the tool. For task-backed calls, ordinary filters execute in the background after task creation. An explicit `CallToolWithAlternateHandler` remains a full replacement and cannot be combined with ordinary call-tool filters.
Configure `WithTasks` before adding ordinary call-tool filters. Tasks validates this ordering when
its filter is installed because it must execute outside the ordinary call-tool pipeline.
Configure `WithTasks` before adding ordinary call-tool filters. Tasks validates this ordering when its filter is installed because it must execute outside the ordinary call-tool pipeline.
## Message Filters
## Message filters
In addition to the request-specific filters above, there are low-level message filters that intercept all JSON-RPC messages before they are routed to specific handlers.
Configure these on `IMcpMessageFilterBuilder` inside `WithMessageFilters(...)`:
@ -56,7 +46,7 @@ Configure these on `IMcpMessageFilterBuilder` inside `WithMessageFilters(...)`:
- `AddIncomingFilter` - Filter for all incoming JSON-RPC messages (requests and notifications)
- `AddOutgoingFilter` - Filter for all outgoing JSON-RPC messages (responses and notifications)
### When to Use Message Filters
### When to use message filters
Message filters operate at a lower level than request-specific filters and are useful when you need to:
@ -66,7 +56,7 @@ Message filters operate at a lower level than request-specific filters and are u
- Modify or skip messages before they reach handlers
- Send additional messages in response to specific events
### Incoming Message Filter
### Incoming message filter
`AddIncomingFilter` intercepts all incoming JSON-RPC messages before they are dispatched to request-specific handlers:
@ -100,7 +90,7 @@ Inside an incoming message filter, you have access to:
- `context.Services` - The request's service provider
- `context.Items` - A dictionary for passing data between filters
#### Skipping Default Handlers
#### Skipping default handlers
You can skip the default handler by not calling `next`. This is useful for implementing custom protocol methods:
@ -126,7 +116,7 @@ You can skip the default handler by not calling `next`. This is useful for imple
})
```
### Outgoing Message Filter
### Outgoing message filter
`AddOutgoingFilter` intercepts all outgoing JSON-RPC messages before they are sent to the client:
@ -155,7 +145,7 @@ services.AddMcpServer()
.WithTools<MyTools>();
```
#### Skipping Outgoing Messages
#### Skipping outgoing messages
You can suppress outgoing messages by not calling `next`:
@ -176,7 +166,7 @@ You can suppress outgoing messages by not calling `next`:
})
```
#### Sending Additional Messages
#### Sending additional messages
Outgoing message filters can send additional messages by calling `next` with a new `MessageContext`:
@ -207,7 +197,7 @@ Outgoing message filters can send additional messages by calling `next` with a n
})
```
### Message Filter Execution Order
### Message filter execution order
Message filters execute in registration order, with the first registered filter being the outermost:
@ -253,7 +243,7 @@ OutgoingFilter2 (after next)
OutgoingFilter1 (after next)
```
### Passing Data Between Filters
### Passing data between filters
The `Items` dictionary allows you to pass data between filters processing the same message:
@ -309,7 +299,7 @@ services.AddMcpServer()
});
```
## Filter Execution Order
## Filter execution order
```csharp
services.AddMcpServer()
@ -324,7 +314,7 @@ services.AddMcpServer()
Execution flow: `filter1 -> filter2 -> filter3 -> baseHandler -> filter3 -> filter2 -> filter1`
## Common Use Cases
## Common use cases
Filters are commonly used for [logging](#logging), [error handling](#error-handling), [performance monitoring](#performance-monitoring), and [caching](#caching).
@ -345,7 +335,7 @@ Filters are commonly used for [logging](#logging), [error handling](#error-handl
});
```
### Error Handling
### Error handling
```csharp
.WithRequestFilters(requestFilters =>
@ -371,7 +361,7 @@ Filters are commonly used for [logging](#logging), [error handling](#error-handl
});
```
### Performance Monitoring
### Performance monitoring
```csharp
.WithRequestFilters(requestFilters =>
@ -411,11 +401,11 @@ Filters are commonly used for [logging](#logging), [error handling](#error-handl
});
```
## Built-in Authorization Request Filters
## Built-in authorization request filters
When using the ASP.NET Core integration (`ModelContextProtocol.AspNetCore`), you can add authorization filters to support `[Authorize]` and `[AllowAnonymous]` attributes on MCP server tools, prompts, and resources by calling `AddAuthorizationFilters()` on your MCP server builder.
### Enabling Authorization Request Filters
### Enabling authorization request filters
To enable authorization support, call `AddAuthorizationFilters()` when configuring your MCP server:
@ -428,7 +418,7 @@ services.AddMcpServer()
**Important**: If you want to use authorization attributes like `[Authorize]` on your MCP server tools, prompts, or resources, you should always call `AddAuthorizationFilters()` when using ASP.NET Core integration.
### Authorization Attributes Support
### Authorization attributes support
The MCP server automatically respects the following authorization attributes:
@ -437,7 +427,7 @@ The MCP server automatically respects the following authorization attributes:
- **`[Authorize(Policy = "PolicyName")]`** - Requires specific authorization policies
- **`[AllowAnonymous]`** - Explicitly allows anonymous access (overrides `[Authorize]`)
### Tool Authorization
### Tool authorization
Tools can be decorated with authorization attributes to control access:
@ -467,7 +457,7 @@ public class WeatherTools
}
```
### Class-Level Authorization
### Class-level authorization
You can apply authorization at the class level, which affects all tools in the class:
@ -491,19 +481,19 @@ public class RestrictedTools
}
```
### How Authorization Filters Work
### How authorization filters work
The authorization filters work differently for list operations versus individual operations:
#### List Operations (ListTools, ListPrompts, ListResources)
#### List operations (`ListTools`, `ListPrompts`, `ListResources`)
For list operations, the filters automatically remove unauthorized items from the results. Users only see tools, prompts, or resources they have permission to access.
#### Individual Operations (CallTool, GetPrompt, ReadResource)
#### Individual operations (`CallTool`, `GetPrompt`, `ReadResource`)
For individual operations, the filters throw an `McpException` with "Access forbidden" message. These get turned into JSON-RPC errors if uncaught by middleware.
### Filter Execution Order and Authorization
### Filter execution order and authorization
Authorization filters are applied automatically when you call `AddAuthorizationFilters()`. These filters run at a specific point in the filter pipeline, which means:
@ -551,7 +541,7 @@ services.AddMcpServer()
.WithTools<WeatherTools>();
```
### Setup Requirements
### Setup requirements
To use authorization features, you must configure authentication and authorization in your ASP.NET Core application and call `AddAuthorizationFilters()`:
@ -585,7 +575,7 @@ app.MapMcp();
app.Run();
```
### Custom Authorization Filters
### Custom authorization filters
You can also create custom authorization filters using the filter methods: