Writing style edits (#1024)
This commit is contained in:
parent
820821fa0c
commit
e2a802ebdc
5 changed files with 54 additions and 46 deletions
|
|
@ -15,21 +15,22 @@ Servers request structured data from users with the <xref:ModelContextProtocol.S
|
|||
The C# SDK registers an instance of <xref:ModelContextProtocol.Server.McpServer> with the dependency injection container,
|
||||
so tools can simply add a parameter of type <xref:ModelContextProtocol.Server.McpServer> to their method signature to access it.
|
||||
|
||||
The MCP Server must specify the schema of each input value it is requesting from the user.
|
||||
Primitive types (string, number, boolean) and enum types are supported for elicitation requests.
|
||||
The schema may include a description to help the user understand what is being requested.
|
||||
The MCP Server must specify the schema of each input value it's requesting from the user.
|
||||
Primitive types (string, number, Boolean) and enum types are supported for elicitation requests.
|
||||
The schema might include a description to help the user understand what's being requested.
|
||||
|
||||
For enum types, the SDK supports several schema formats:
|
||||
- **UntitledSingleSelectEnumSchema**: A single-select enum where the enum values serve as both the value and display text
|
||||
- **TitledSingleSelectEnumSchema**: A single-select enum with separate display titles for each option (using JSON Schema `oneOf` with `const` and `title`)
|
||||
- **UntitledMultiSelectEnumSchema**: A multi-select enum allowing multiple values to be selected
|
||||
- **TitledMultiSelectEnumSchema**: A multi-select enum with display titles for each option
|
||||
- **LegacyTitledEnumSchema** (deprecated): The legacy enum schema using `enumNames` for backward compatibility
|
||||
|
||||
- **UntitledSingleSelectEnumSchema**: A single-select enum where the enum values serve as both the value and display text.
|
||||
- **TitledSingleSelectEnumSchema**: A single-select enum with separate display titles for each option (using JSON Schema `oneOf` with `const` and `title`).
|
||||
- **UntitledMultiSelectEnumSchema**: A multi-select enum allowing multiple values to be selected.
|
||||
- **TitledMultiSelectEnumSchema**: A multi-select enum with display titles for each option.
|
||||
- **LegacyTitledEnumSchema** (deprecated): The legacy enum schema using `enumNames` for backward compatibility.
|
||||
|
||||
The server can request a single input or multiple inputs at once.
|
||||
To help distinguish multiple inputs, each input has a unique name.
|
||||
|
||||
The following example demonstrates how a server could request a boolean response from the user.
|
||||
The following example demonstrates how a server could request a Boolean response from the user.
|
||||
|
||||
[!code-csharp[](samples/server/Tools/InteractiveTools.cs?name=snippet_GuessTheNumber)]
|
||||
|
||||
|
|
@ -46,7 +47,6 @@ This will be highly dependent on the client application and how it interacts wit
|
|||
If the user provides the requested information, the ElicitationHandler should return an <xref:ModelContextProtocol.Protocol.ElicitResult> with the action set to "accept" and the content containing the user's input.
|
||||
If the user does not provide the requested information, the ElicitationHandler should return an [<xref:ModelContextProtocol.Protocol.ElicitResult> with the action set to "reject" and no content.
|
||||
|
||||
Below is an example of how a console application might handle elicitation requests.
|
||||
Here's an example implementation:
|
||||
Here's an example implementation of how a console application might handle elicitation requests:
|
||||
|
||||
[!code-csharp[](samples/client/Program.cs?name=snippet_ElicitationHandler)]
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ Execution flow: `filter1 -> filter2 -> filter3 -> baseHandler -> filter3 -> filt
|
|||
## Common Use Cases
|
||||
|
||||
### Logging
|
||||
|
||||
```csharp
|
||||
.AddListToolsFilter(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -79,6 +80,7 @@ Execution flow: `filter1 -> filter2 -> filter3 -> baseHandler -> filter3 -> filt
|
|||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
```csharp
|
||||
.AddCallToolFilter(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -98,6 +100,7 @@ Execution flow: `filter1 -> filter2 -> filter3 -> baseHandler -> filter3 -> filt
|
|||
```
|
||||
|
||||
### Performance Monitoring
|
||||
|
||||
```csharp
|
||||
.AddListToolsFilter(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -112,6 +115,7 @@ Execution flow: `filter1 -> filter2 -> filter3 -> baseHandler -> filter3 -> filt
|
|||
```
|
||||
|
||||
### Caching
|
||||
|
||||
```csharp
|
||||
.AddListResourcesFilter(next => async (context, cancellationToken) =>
|
||||
{
|
||||
|
|
@ -214,9 +218,11 @@ public class RestrictedTools
|
|||
The authorization filters work differently for list operations versus individual operations:
|
||||
|
||||
#### 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)
|
||||
|
||||
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
|
||||
|
|
@ -224,12 +230,14 @@ For individual operations, the filters throw an `McpException` with "Access forb
|
|||
Authorization filters are applied automatically when you call `AddAuthorizationFilters()`. These filters run at a specific point in the filter pipeline, which means:
|
||||
|
||||
**Filters added before authorization filters** can see:
|
||||
- Unauthorized requests for operations before they are rejected by the authorization filters
|
||||
- Complete listings for unauthorized primitives before they are filtered out by the authorization filters
|
||||
|
||||
- Unauthorized requests for operations before they are rejected by the authorization filters.
|
||||
- Complete listings for unauthorized primitives before they are filtered out by the authorization filters.
|
||||
|
||||
**Filters added after authorization filters** will only see:
|
||||
- Authorized requests that passed authorization checks
|
||||
- Filtered listings containing only authorized primitives
|
||||
|
||||
- Authorized requests that passed authorization checks.
|
||||
- Filtered listings containing only authorized primitives.
|
||||
|
||||
This allows you to implement logging, metrics, or other cross-cutting concerns that need to see all requests, while still maintaining proper authorization:
|
||||
|
||||
|
|
@ -312,6 +320,6 @@ You can also create custom authorization filters using the filter methods:
|
|||
|
||||
Within filters, you have access to:
|
||||
|
||||
- `context.User` - The current user's `ClaimsPrincipal`
|
||||
- `context.Services` - The request's service provider for resolving authorization services
|
||||
- `context.MatchedPrimitive` - The matched tool/prompt/resource with its metadata including authorization attributes via `context.MatchedPrimitive.Metadata`
|
||||
- `context.User` - The current user's `ClaimsPrincipal`.
|
||||
- `context.Services` - The request's service provider for resolving authorization services.
|
||||
- `context.MatchedPrimitive` - The matched tool/prompt/resource with its metadata including authorization attributes via `context.MatchedPrimitive.Metadata`.
|
||||
|
|
|
|||
|
|
@ -7,11 +7,11 @@ uid: httpcontext
|
|||
|
||||
## HTTP Context
|
||||
|
||||
When using the Streamable HTTP transport, an MCP server may need to access the underlying [HttpContext] for a request.
|
||||
When using the Streamable HTTP transport, an MCP server might need to access the underlying [HttpContext] for a request.
|
||||
The [HttpContext] contains request metadata such as the HTTP headers, authorization context, and the actual path and query string for the request.
|
||||
|
||||
To access the [HttpContext], the MCP server should add the [IHttpContextAccessor] service to the application service collection (typically in Program.cs).
|
||||
Then any classes, e.g. a class containing MCP tools, should accept an [IHttpContextAccessor] in their constructor and store this for use by its methods.
|
||||
Then any classes, for example, a class containing MCP tools, should accept an [IHttpContextAccessor] in their constructor and store this for use by its methods.
|
||||
Methods then use the [HttpContext property][IHttpContextAccessor.HttpContext] of the accessor to get the current context.
|
||||
|
||||
[HttpContext]: https://learn.microsoft.com/dotnet/api/microsoft.aspnetcore.http.httpcontext
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ uid: logging
|
|||
|
||||
## Logging
|
||||
|
||||
MCP servers may expose log messages to clients through the [Logging utility].
|
||||
MCP servers can expose log messages to clients through the [Logging utility].
|
||||
|
||||
[Logging utility]: https://modelcontextprotocol.io/specification/2025-06-18/server/utilities/logging
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ This document describes how to implement logging in MCP servers and how clients
|
|||
MCP uses the logging levels defined in [RFC 5424](https://tools.ietf.org/html/rfc5424).
|
||||
|
||||
The MCP C# SDK uses the standard .NET [ILogger] and [ILoggerProvider] abstractions, which support a slightly
|
||||
different set of logging levels. Here's the levels and how they map to standard .NET logging levels.
|
||||
different set of logging levels. The following table shows the levels and how they map to standard .NET logging levels.
|
||||
|
||||
| Level | .NET | Description | Example Use Case |
|
||||
|-----------|------|-----------------------------------|------------------------------|
|
||||
|
|
@ -46,8 +46,8 @@ MCP servers that implement the Logging utility must declare this in the capabili
|
|||
[Initialization]: https://modelcontextprotocol.io/specification/2025-06-18/basic/lifecycle#initialization
|
||||
|
||||
Servers built with the C# SDK always declare the logging capability. Doing so does not obligate the server
|
||||
to send log messages -- only allows it. Note that stateless MCP servers may not be capable of sending log
|
||||
messages as there may not be an open connection to the client on which the log messages could be sent.
|
||||
to send log messages—only allows it. Note that stateless MCP servers might not be capable of sending log
|
||||
messages as there might not be an open connection to the client on which the log messages could be sent.
|
||||
|
||||
The C# SDK provides an extension method <xref:Microsoft.Extensions.DependencyInjection.McpServerBuilderExtensions.WithSetLoggingLevelHandler*> on <xref:Microsoft.Extensions.DependencyInjection.IMcpServerBuilder> to allow the
|
||||
server to perform any special logic it wants to perform when a client sets the logging level. However, the
|
||||
|
|
@ -70,7 +70,7 @@ Clients should check if the server supports logging by checking the <xref:ModelC
|
|||
|
||||
If the server supports logging, the client should set the level of log messages it wishes to receive with
|
||||
the <xref:ModelContextProtocol.Client.McpClient.SetLoggingLevel*> method on <xref:ModelContextProtocol.Client.McpClient>. If the client does not set a logging level, the server might choose
|
||||
to send all log messages or none -- this is not specified in the protocol -- so it is important that the client
|
||||
to send all log messages or none—this is not specified in the protocol. So it's important that the client
|
||||
sets a logging level to ensure it receives the desired log messages and only those messages.
|
||||
|
||||
The `loggingLevel` set by the client is an MCP logging level.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ The Model Context Protocol (MCP) supports [progress tracking] for long-running o
|
|||
[progress tracking]: https://modelcontextprotocol.io/specification/2025-06-18/basic/utilities/progress
|
||||
|
||||
Typically progress tracking is supported by server tools that perform operations that take a significant amount of time to complete, such as image generation or complex calculations.
|
||||
However, progress tracking is defined in the MCP specification as a general feature that can be implemented for any request that is handled by either a server or a client.
|
||||
However, progress tracking is defined in the MCP specification as a general feature that can be implemented for any request that's handled by either a server or a client.
|
||||
This project illustrates the common case of a server tool that performs a long-running operation and sends progress updates to the client.
|
||||
|
||||
### Server Implementation
|
||||
|
|
@ -30,7 +30,7 @@ The server must verify that the caller provided a `progressToken` in the request
|
|||
### Client Implementation
|
||||
|
||||
Clients request progress updates by including a `progressToken` in the parameters of a request.
|
||||
Note that servers are not required to support progress tracking, so clients should not depend on receiving progress updates.
|
||||
Note that servers aren't required to support progress tracking, so clients should not depend on receiving progress updates.
|
||||
|
||||
In the MCP C# SDK, clients can specify a `progressToken` in the request parameters when calling a tool method.
|
||||
The client should also provide a notification handler to process "notifications/progress" notifications.
|
||||
|
|
|
|||
Loading…
Reference in a new issue