Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
24 changes: 7 additions & 17 deletions .github/workflows/ci-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,25 +66,15 @@ jobs:
- name: Install dependencies for tests
run: npm install @modelcontextprotocol/server-memory

- name: Build
run: dotnet build --configuration ${{ matrix.configuration }}
- name: Build & Test
run: make build test CONFIGURATION=${{ matrix.configuration }}

- name: Pack
run: dotnet pack --configuration ${{ matrix.configuration }}

- name: Test
run: >-
dotnet test
--filter '(Execution!=Manual)'
--no-build
--configuration ${{ matrix.configuration }}
--logger "trx"
--logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true"
--blame
--blame-hang-timeout 7m
--blame-crash
--results-directory testresults
--collect "XPlat Code Coverage" -- RunConfiguration.CollectSourceInformation=true
if: matrix.configuration == 'Release'
run: make pack CONFIGURATION=${{ matrix.configuration }}

- name: Generate docs
run: make generate-docs CONFIGURATION=${{ matrix.configuration }}

- name: Upload test results artifact
if: always()
Expand Down
12 changes: 9 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,22 @@ test: build
--configuration $(CONFIGURATION) \
--filter '(Execution!=Manual)' \
--blame \
--blame-crash \
--blame-hang-timeout 7m \
--diag "$(ARTIFACT_PATH)/diag.txt" \
--logger "trx" \
--logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true" \
--collect "Code Coverage;Format=cobertura" \
--results-directory $(ARTIFACT_PATH)/test-results \
--results-directory $(ARTIFACT_PATH)/testresults \
-- \
RunConfiguration.CollectSourceInformation=true

generate-docs: clean restore
pack: restore
dotnet pack --no-restore --configuration $(CONFIGURATION)

generate-docs: restore
dotnet build --no-restore --configuration Release
dotnet docfx $(DOCS_PATH)/docfx.json
dotnet docfx $(DOCS_PATH)/docfx.json --warningsAsErrors true

serve-docs: generate-docs
dotnet docfx serve $(ARTIFACT_PATH)/_site --port 8080
Expand Down
77 changes: 77 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Documentation Guidelines

This directory contains the conceptual documentation for the MCP C# SDK, built using [DocFX](https://dotnet.github.io/docfx/).

## Referencing API Types

When referencing types from the MCP C# SDK API in markdown documentation, **always use DocFX xref syntax** instead of direct URLs to API documentation pages. This ensures that:

1. Links remain valid even when API documentation structure changes
2. DocFX can validate that referenced types exist during build
3. Links work correctly in offline documentation
4. DocFX generates proper warnings if referenced types are obsolete or missing

### xref Syntax

Use the `<xref:>` tag to reference types, methods, and properties:

```markdown
<!-- Reference a type -->
<xref:ModelContextProtocol.Client.McpClient>

<!-- Reference a method (use * for overloads) -->
<xref:ModelContextProtocol.McpSession.SendNotificationAsync*>

<!-- Reference a specific property -->
<xref:ModelContextProtocol.Client.McpClient.ServerCapabilities>

<!-- Reference a property on a different type -->
<xref:ModelContextProtocol.Protocol.ServerCapabilities.Logging>

<!-- Reference types from external libraries -->
<xref:System.Progress`1>
<xref:Microsoft.Extensions.Logging.ILogger>
```

### Common Types to Reference

When updating documentation, use these type names instead of obsolete interfaces:

| Obsolete Interface | Current Type | xref |
|--------------------|--------------|------|
| `IMcpEndpoint` | `McpSession` | `<xref:ModelContextProtocol.McpSession>` |
| `IMcpClient` | `McpClient` | `<xref:ModelContextProtocol.Client.McpClient>` |
| `IMcpServer` | `McpServer` | `<xref:ModelContextProtocol.Server.McpServer>` |

Note: `IMcpServerBuilder` is NOT obsolete and should still be referenced.

### Building Documentation

To build the documentation locally and verify xref links:

```bash
make generate-docs
```

This will:
1. Clean previous builds
2. Build the project
3. Generate API documentation
4. Build the DocFX site to `artifacts/_site`

To serve the documentation locally:

```bash
make serve-docs
```

Then navigate to `http://localhost:8080` to view the documentation.

## External Links

For links to external documentation (e.g., Microsoft Learn, MCP specification), regular markdown links are acceptable:

```markdown
[Model Context Protocol](https://modelcontextprotocol.io/)
[ILogger](https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger)
```
10 changes: 5 additions & 5 deletions docs/concepts/elicitation/elicitation.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ Servers request structured data from users with the [ElicitAsync] extension meth
The C# SDK registers an instance of [IMcpServer] with the dependency injection container,
so tools can simply add a parameter of type [IMcpServer] to their method signature to access it.

[ElicitAsync]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Server.McpServerExtensions.html#ModelContextProtocol_Server_McpServerExtensions_ElicitAsync_ModelContextProtocol_Server_IMcpServer_ModelContextProtocol_Protocol_ElicitRequestParams_System_Threading_CancellationToken_
[IMcpServer]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Server.IMcpServer.html
[ElicitAsync]: xref:ModelContextProtocol.Server.McpServer.ElicitAsync*
[IMcpServer]: xref:ModelContextProtocol.Server.McpServer

The MCP Server must specify the schema of each input value it is requesting from the user.
Only primitive types (string, number, boolean) are supported for elicitation requests.
Expand All @@ -33,8 +33,8 @@ The following example demonstrates how a server could request a boolean response

Elicitation is an optional feature so clients declare their support for it in their capabilities as part of the `initialize` request. In the MCP C# SDK, this is done by configuring an [ElicitationHandler] in the [McpClientOptions]:

[ElicitationHandler]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Protocol.ElicitationCapability.html#ModelContextProtocol_Protocol_ElicitationCapability_ElicitationHandler
[McpClientOptions]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Client.McpClientOptions.html
[ElicitationHandler]: xref:ModelContextProtocol.Client.McpClientHandlers.ElicitationHandler
[McpClientOptions]: xref:ModelContextProtocol.Client.McpClientOptions

[!code-csharp[](samples/client/Program.cs?name=snippet_McpInitialize)]

Expand All @@ -45,7 +45,7 @@ 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 [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 [ElicitResult] with the action set to "reject" and no content.

[ElicitResult]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Protocol.ElicitResult.html
[ElicitResult]: xref:ModelContextProtocol.Protocol.ElicitResult

Below is an example of how a console application might handle elicitation requests.
Here's an example implementation:
Expand Down
20 changes: 10 additions & 10 deletions docs/concepts/logging/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ server to perform any special logic it wants to perform when a client sets the l
SDK already takes care of setting the [LoggingLevel] in the [IMcpServer], so most servers will not need to
implement this.

[IMcpServer]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Server.IMcpServer.html
[IMcpServerBuilder]: https://modelcontextprotocol.github.io/csharp-sdk/api/Microsoft.Extensions.DependencyInjection.IMcpServerBuilder.html
[WithSetLoggingLevelHandler]: https://modelcontextprotocol.github.io/csharp-sdk/api/Microsoft.Extensions.DependencyInjection.McpServerBuilderExtensions.html#Microsoft_Extensions_DependencyInjection_McpServerBuilderExtensions_WithSetLoggingLevelHandler_Microsoft_Extensions_DependencyInjection_IMcpServerBuilder_System_Func_ModelContextProtocol_Server_RequestContext_ModelContextProtocol_Protocol_SetLevelRequestParams__System_Threading_CancellationToken_System_Threading_Tasks_ValueTask_ModelContextProtocol_Protocol_EmptyResult___
[LoggingLevel]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Server.IMcpServer.html#ModelContextProtocol_Server_IMcpServer_LoggingLevel
[IMcpServer]: xref:ModelContextProtocol.Server.McpServer
[IMcpServerBuilder]: xref:Microsoft.Extensions.DependencyInjection.IMcpServerBuilder
[WithSetLoggingLevelHandler]: xref:Microsoft.Extensions.DependencyInjection.McpServerBuilderExtensions.WithSetLoggingLevelHandler*
[LoggingLevel]: xref:ModelContextProtocol.Server.McpServer.LoggingLevel

MCP Servers using the MCP C# SDK can obtain an [ILoggerProvider] from the IMcpServer [AsClientLoggerProvider] extension method,
and from that can create an [ILogger] instance for logging messages that should be sent to the MCP client.

[!code-csharp[](samples/server/Tools/LoggingTools.cs?name=snippet_LoggingConfiguration)]

[ILoggerProvider]: https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.iloggerprovider
[AsClientLoggerProvider]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Server.McpServerExtensions.html#ModelContextProtocol_Server_McpServerExtensions_AsClientLoggerProvider_ModelContextProtocol_Server_IMcpServer_
[AsClientLoggerProvider]: xref:ModelContextProtocol.Server.McpServer.AsClientLoggerProvider*
[ILogger]: https://learn.microsoft.com/dotnet/api/microsoft.extensions.logging.ilogger

### Client support for logging
Expand All @@ -75,9 +75,9 @@ the logging level to specify which messages the server should send to the client

Clients should check if the server supports logging by checking the [Logging] property of the [ServerCapabilities] field of [IMcpClient].

[IMcpClient]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Client.IMcpClient.html
[ServerCapabilities]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Client.IMcpClient.html#ModelContextProtocol_Client_IMcpClient_ServerCapabilities
[Logging]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Protocol.ServerCapabilities.html#ModelContextProtocol_Protocol_ServerCapabilities_Logging
[IMcpClient]: xref:ModelContextProtocol.Client.McpClient
[ServerCapabilities]: xref:ModelContextProtocol.Client.McpClient.ServerCapabilities
[Logging]: xref:ModelContextProtocol.Protocol.ServerCapabilities.Logging

[!code-csharp[](samples/client/Program.cs?name=snippet_LoggingCapabilities)]

Expand All @@ -89,13 +89,13 @@ sets a logging level to ensure it receives the desired log messages and only tho
The `loggingLevel` set by the client is an MCP logging level.
See the [Logging Levels](#logging-levels) section above for the mapping between MCP and .NET logging levels.

[SetLoggingLevel]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Client.McpClientExtensions.html#ModelContextProtocol_Client_McpClientExtensions_SetLoggingLevel_ModelContextProtocol_Client_IMcpClient_Microsoft_Extensions_Logging_LogLevel_System_Threading_CancellationToken_
[SetLoggingLevel]: xref:ModelContextProtocol.Client.McpClient.SetLoggingLevel*

[!code-csharp[](samples/client/Program.cs?name=snippet_LoggingLevel)]

Lastly, the client must configure a notification handler for [NotificationMethods.LoggingMessageNotification] notifications.
The following example simply writes the log messages to the console.

[NotificationMethods.LoggingMessageNotification]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Protocol.NotificationMethods.html#ModelContextProtocol_Protocol_NotificationMethods_LoggingMessageNotification
[NotificationMethods.LoggingMessageNotification]: xref:ModelContextProtocol.Protocol.NotificationMethods.LoggingMessageNotification

[!code-csharp[](samples/client/Program.cs?name=snippet_LoggingHandler)]
14 changes: 7 additions & 7 deletions docs/concepts/progress/progress.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ The C# SDK registers an instance of [IMcpServer] with the dependency injection c
so tools can simply add a parameter of type [IMcpServer] to their method signature to access it.
The parameters passed to [sendNotificationAsync] should be an instance of [ProgressNotificationParams], which includes the current progress, total steps, and an optional message.

[sendNotificationAsync]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.McpEndpointExtensions.html#ModelContextProtocol_McpEndpointExtensions_SendNotificationAsync_ModelContextProtocol_IMcpEndpoint_System_String_System_Threading_CancellationToken_
[IMcpServer]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Server.IMcpServer.html
[ProgressNotificationParams]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Protocol.ProgressNotificationParams.html
[sendNotificationAsync]: xref:ModelContextProtocol.McpSession.SendNotificationAsync*
[IMcpServer]: xref:ModelContextProtocol.Server.McpServer
[ProgressNotificationParams]: xref:ModelContextProtocol.Protocol.ProgressNotificationParams

The server must verify that the caller provided a `progressToken` in the request and include it in the call to [sendNotificationAsync]. The following example demonstrates how a server can send a progress notification:

Expand All @@ -40,8 +40,8 @@ In the MCP C# SDK, clients can specify a `progressToken` in the request paramete
The client should also provide a notification handler to process "notifications/progress" notifications.
There are two way to do this. The first is to register a notification handler using the [RegisterNotificationHandler] method on the [IMcpClient] instance. A handler registered this way will receive all progress notifications sent by the server.

[IMcpClient]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.Client.IMcpClient.html
[RegisterNotificationHandler]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.IMcpEndpoint.html#ModelContextProtocol_IMcpEndpoint_RegisterNotificationHandler_System_String_System_Func_ModelContextProtocol_Protocol_JsonRpcNotification_System_Threading_CancellationToken_System_Threading_Tasks_ValueTask__
[IMcpClient]: xref:ModelContextProtocol.Client.McpClient
[RegisterNotificationHandler]: xref:ModelContextProtocol.McpSession.RegisterNotificationHandler*

```csharp
mcpClient.RegisterNotificationHandler(NotificationMethods.ProgressNotification,
Expand All @@ -63,7 +63,7 @@ The MCP C# SDK will automatically handle progress notifications and report them
This notification handler will only receive progress updates for the specific request that was made,
rather than all progress notifications from the server.

[Progress`<T>`]: https://learn.microsoft.com/en-us/dotnet/api/system.progress-1
[ProgressNotificationValue]: https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.ProgressNotificationValue.html
[Progress`<T>`]: https://learn.microsoft.com/dotnet/api/system.progress-1
[ProgressNotificationValue]: xref:ModelContextProtocol.ProgressNotificationValue

[!code-csharp[](samples/client/Program.cs?name=snippet_ProgressHandler)]
Loading