From 01d55d04914b8d18bdde427aca0eee51b9b41acb Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Wed, 18 Feb 2026 17:02:19 -0800 Subject: [PATCH 1/3] Add docs for working with experimental APIs --- docs/concepts/tasks/tasks.md | 2 +- docs/experimental.md | 65 ++++++++++++++++++++++++++++++++++++ docs/toc.yml | 2 ++ 3 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 docs/experimental.md diff --git a/docs/concepts/tasks/tasks.md b/docs/concepts/tasks/tasks.md index 9b67e119b..1b312d9c5 100644 --- a/docs/concepts/tasks/tasks.md +++ b/docs/concepts/tasks/tasks.md @@ -8,7 +8,7 @@ uid: tasks # MCP Tasks > [!WARNING] -> Tasks are an **experimental feature** in the MCP specification (version 2025-11-25). The API may change in future releases. +> Tasks are an **experimental feature** in the MCP specification (version 2025-11-25). The API may change in future releases. See the [Experimental APIs](../../experimental.md) documentation for details on working with experimental APIs. The Model Context Protocol (MCP) supports [task-based execution] for long-running operations. Tasks enable a "call-now, fetch-later" pattern where clients can initiate operations that may take significant time to complete, then poll for status and retrieve results when ready. diff --git a/docs/experimental.md b/docs/experimental.md new file mode 100644 index 000000000..70a131a7c --- /dev/null +++ b/docs/experimental.md @@ -0,0 +1,65 @@ +--- +title: Experimental APIs +author: MackinnonBuck +description: Working with experimental APIs in the MCP C# SDK +uid: experimental +--- + +The Model Context Protocol C# SDK uses the [`[Experimental]`](https://learn.microsoft.com/dotnet/api/system.diagnostics.codeanalysis.experimentalattribute) attribute to mark APIs that are still in development and may change without notice. For more details on the SDK's versioning policy around experimental APIs, see the [Versioning](versioning.md) documentation. + +## Suppressing experimental diagnostics + +When you use an experimental API, the compiler produces a diagnostic (e.g., `MCPEXP001`) to ensure you're aware the API may change. If you want to use the API, suppress the diagnostic in one of these ways: + +### Project-wide suppression + +Add the diagnostic ID to `` in your project file: + +```xml + + $(NoWarn);MCPEXP001 + +``` + +### Per-call suppression + +Use `#pragma warning disable` around specific call sites: + +```csharp +#pragma warning disable MCPEXP001 +tool.Execution = new ToolExecution { ... }; +#pragma warning restore MCPEXP001 +``` + +For a full list of experimental diagnostic IDs and their descriptions, see the [list of diagnostics](list-of-diagnostics.md#experimental-apis). + +## Serialization behavior + +Experimental properties on protocol types are fully serialized and deserialized when using the SDK's built-in serialization via . This means experimental data is transmitted on the wire even if your application code doesn't directly interact with it, preserving protocol compatibility. + +### Custom `JsonSerializerContext` + +If you define your own `JsonSerializerContext` that includes MCP protocol types, experimental properties will not be included in your context's serialization contract. This is by design, as it protects your compiled code against binary breaking changes to experimental APIs. + +To ensure consistent serialization behavior that always includes experimental properties, configure a `TypeInfoResolverChain` so the SDK's resolver handles MCP types: + +```csharp +using ModelContextProtocol; + +JsonSerializerOptions options = new() +{ + TypeInfoResolverChain = + { + McpJsonUtilities.DefaultOptions.TypeInfoResolver!, + MyCustomContext.Default, + } +}; +``` + +By placing the SDK's resolver first, MCP types are serialized using the SDK's contract (which includes experimental properties), while your custom context handles your own types. This is recommended even if you aren't currently using experimental APIs, since it ensures your serialization configuration remains correct as new experimental properties are introduced or as you adopt experimental features in the future. + +## See also + +- [Versioning](versioning.md) +- [List of diagnostics](list-of-diagnostics.md#experimental-apis) +- [Tasks](concepts/tasks/tasks.md) (an experimental feature) diff --git a/docs/toc.yml b/docs/toc.yml index 84cf4de03..9b70938f2 100644 --- a/docs/toc.yml +++ b/docs/toc.yml @@ -5,5 +5,7 @@ items: href: api/ModelContextProtocol.yml - name: Versioning href: versioning.md +- name: Experimental APIs + href: experimental.md - name: GitHub href: https://github.com/ModelContextProtocol/csharp-sdk From ad7869ddaf4d58d2f0d6ccb2f7150d7b1277eaac Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Thu, 19 Feb 2026 07:32:57 -0800 Subject: [PATCH 2/3] Update docs/experimental.md Co-authored-by: Jeff Handley --- docs/experimental.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/experimental.md b/docs/experimental.md index 70a131a7c..018d221a9 100644 --- a/docs/experimental.md +++ b/docs/experimental.md @@ -26,7 +26,7 @@ Add the diagnostic ID to `` in your project file: Use `#pragma warning disable` around specific call sites: ```csharp -#pragma warning disable MCPEXP001 +#pragma warning disable MCPEXP001 // The Tasks feature is experimental per the MCP specification and is subject to change. tool.Execution = new ToolExecution { ... }; #pragma warning restore MCPEXP001 ``` From abca27f46832d25c2b0114050513d561cafe66cb Mon Sep 17 00:00:00 2001 From: Mackinnon Buck Date: Thu, 19 Feb 2026 07:48:13 -0800 Subject: [PATCH 3/3] PR feedback: differentiate between reflection and SG --- docs/experimental.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/docs/experimental.md b/docs/experimental.md index 018d221a9..1ad75a9b4 100644 --- a/docs/experimental.md +++ b/docs/experimental.md @@ -37,11 +37,16 @@ For a full list of experimental diagnostic IDs and their descriptions, see the [ Experimental properties on protocol types are fully serialized and deserialized when using the SDK's built-in serialization via . This means experimental data is transmitted on the wire even if your application code doesn't directly interact with it, preserving protocol compatibility. -### Custom `JsonSerializerContext` +The behavior of experimental properties differs depending on whether you use [reflection-based or source-generated](https://learn.microsoft.com/dotnet/standard/serialization/system-text-json/source-generation) serialization: + +- **Reflection-based serialization** (the default when no `JsonSerializerContext` is used): Experimental properties are included. No special configuration is needed. +- **Source-generated serialization** (using a custom `JsonSerializerContext`): Experimental properties are **not** included in your context's serialization contract. This is by design, as it protects your compiled code against binary breaking changes to experimental APIs. -If you define your own `JsonSerializerContext` that includes MCP protocol types, experimental properties will not be included in your context's serialization contract. This is by design, as it protects your compiled code against binary breaking changes to experimental APIs. +This means that switching between reflection-based and source-generated serialization can silently change which properties are serialized. To avoid this, source-generation users should configure a `TypeInfoResolverChain` as described below. + +### Custom `JsonSerializerContext` -To ensure consistent serialization behavior that always includes experimental properties, configure a `TypeInfoResolverChain` so the SDK's resolver handles MCP types: +If you define your own `JsonSerializerContext` that includes MCP protocol types, configure a `TypeInfoResolverChain` so the SDK's resolver handles MCP types: ```csharp using ModelContextProtocol;