Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion docs/list-of-diagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ If you use experimental APIs, you will get one of the diagnostics shown below. T

| Diagnostic ID | Description |
| :------------ | :---------- |
| `MCPEXP001` | Experimental APIs for features in the MCP specification itself, including Tasks and Extensions. Tasks provide a mechanism for asynchronous long-running operations that can be polled for status and results (see [SEP-2663](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2663-tasks-extension.md)). Extensions provide a framework for extending the Model Context Protocol while maintaining interoperability (see [SEP-2133](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2133)). |
| `MCPEXP001` | Experimental APIs tied to MCP specification features. Reuse this ID for newly introduced experimental spec features, and add feature-specific messages/URLs in `Experimentals`. |
| `MCPEXP002` | Experimental SDK APIs unrelated to the MCP specification itself, including subclassing `McpClient`/`McpServer` (see [#1363](https://github.com/modelcontextprotocol/csharp-sdk/pull/1363)) and `RunSessionHandler`, which may be removed or change signatures in a future release (consider using `ConfigureSessionOptions` instead). |

## Obsolete APIs
Expand Down
40 changes: 8 additions & 32 deletions src/Common/Experimentals.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ namespace ModelContextProtocol;
/// Experimental diagnostic IDs are grouped by category:
/// <list type="bullet">
/// <item><description>
/// <c>MCPEXP001</c> covers APIs related to experimental features in the MCP specification itself,
/// such as Extensions. These APIs may change as the specification evolves.
/// <c>MCPEXP001</c> covers APIs related to experimental features in the MCP specification itself.
/// These APIs may change as the specification evolves.
/// </description></item>
/// <item><description>
/// <c>MCPEXP002</c> covers experimental SDK APIs that are unrelated to the MCP specification,
Expand All @@ -36,19 +36,13 @@ namespace ModelContextProtocol;
internal static class Experimentals
{
/// <summary>
/// Diagnostic ID for the experimental MCP Extensions feature.
/// Diagnostic ID for experimental MCP specification features.
/// </summary>
public const string Extensions_DiagnosticId = "MCPEXP001";

/// <summary>
/// Message for the experimental MCP Extensions feature.
/// </summary>
public const string Extensions_Message = "The Extensions feature is part of a future MCP specification version that has not yet been ratified and is subject to change.";

/// <summary>
/// URL for the experimental MCP Extensions feature.
/// </summary>
public const string Extensions_Url = "https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#mcpexp001";
/// <remarks>
/// When introducing a new experimental specification feature, add feature-specific message
/// and URL constants that use this diagnostic ID.
/// </remarks>
public const string SpecificationFeature_DiagnosticId = "MCPEXP001";

/// <summary>
/// Diagnostic ID for experimental SDK APIs unrelated to the MCP specification,
Expand Down Expand Up @@ -90,22 +84,4 @@ internal static class Experimentals
/// </summary>
public const string RunSessionHandler_Url = "https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#mcpexp002";

/// <summary>
/// Diagnostic ID for the experimental Multi Round-Trip Requests (MRTR) feature.
/// </summary>
/// <remarks>
/// This uses the same diagnostic ID as <see cref="Extensions_DiagnosticId"/> because MRTR
/// is an experimental feature in the MCP specification (SEP-2322).
/// </remarks>
public const string Mrtr_DiagnosticId = "MCPEXP001";

/// <summary>
/// Message for the experimental MRTR feature.
/// </summary>
public const string Mrtr_Message = "The Multi Round-Trip Requests (MRTR) feature is experimental per the MCP specification (SEP-2322) and is subject to change.";

/// <summary>
/// URL for the experimental MRTR feature.
/// </summary>
public const string Mrtr_Url = "https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#mcpexp001";
}
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Protocol/ClientCapabilities.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using ModelContextProtocol.Client;
using ModelContextProtocol.Server;
Expand Down Expand Up @@ -82,7 +81,6 @@ public sealed class ClientCapabilities
/// interoperability. Clients advertise extension support via this field during the initialization handshake.
/// </para>
/// </remarks>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
[JsonIgnore]
public IDictionary<string, object>? Extensions
{
Expand Down
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Protocol/InputRequest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;

Expand All @@ -20,7 +19,6 @@ namespace ModelContextProtocol.Protocol;
/// parameters can be accessed via the typed accessor properties.
/// </para>
/// </remarks>
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
[JsonConverter(typeof(Converter))]
public sealed class InputRequest
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Diagnostics.CodeAnalysis;

namespace ModelContextProtocol.Protocol;

/// <summary>
Expand Down Expand Up @@ -54,7 +52,6 @@ namespace ModelContextProtocol.Protocol;
/// }
/// </code>
/// </example>
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
public class InputRequiredException : Exception
{
/// <summary>
Expand Down
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Protocol/InputRequiredResult.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;

namespace ModelContextProtocol.Protocol;
Expand All @@ -22,7 +21,6 @@ namespace ModelContextProtocol.Protocol;
/// This type is part of the Multi Round-Trip Requests (MRTR) mechanism defined in SEP-2322.
/// </para>
/// </remarks>
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
public sealed class InputRequiredResult : Result
{
/// <summary>
Expand Down
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Protocol/InputResponse.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.Json.Serialization.Metadata;
Expand All @@ -21,7 +20,6 @@ namespace ModelContextProtocol.Protocol;
/// the corresponding <see cref="InputRequest.Method"/> key in the <see cref="InputRequiredResult.InputRequests"/> map.
/// </para>
/// </remarks>
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
[JsonConverter(typeof(Converter))]
public sealed class InputResponse
{
Expand Down
3 changes: 0 additions & 3 deletions src/ModelContextProtocol.Core/Protocol/RequestParams.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Nodes;
using System.Text.Json.Serialization;

Expand Down Expand Up @@ -36,7 +35,6 @@ private protected RequestParams()
/// the value is the client's response to that input request.
/// </para>
/// </remarks>
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
[JsonIgnore]
public IDictionary<string, InputResponse>? InputResponses
{
Expand All @@ -59,7 +57,6 @@ public IDictionary<string, InputResponse>? InputResponses
/// exact value without modification.
/// </para>
/// </remarks>
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
[JsonIgnore]
public string? RequestState
{
Expand Down
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Protocol/ServerCapabilities.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
using ModelContextProtocol.Server;

Expand Down Expand Up @@ -81,7 +80,6 @@ public sealed class ServerCapabilities
/// interoperability. Servers advertise extension support via this field during the initialization handshake.
/// </para>
/// </remarks>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
[JsonIgnore]
public IDictionary<string, object>? Extensions
{
Expand Down
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Server/IMcpTaskStore.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using ModelContextProtocol.Protocol;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;

namespace ModelContextProtocol.Server;
Expand Down Expand Up @@ -31,7 +30,6 @@ namespace ModelContextProtocol.Server;
/// specification for details on the tasks extension.
/// </para>
/// </remarks>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
public interface IMcpTaskStore
{
/// <summary>
Expand Down
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Server/InMemoryMcpTaskStore.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using ModelContextProtocol.Protocol;
using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;

namespace ModelContextProtocol.Server;
Expand All @@ -20,7 +19,6 @@ namespace ModelContextProtocol.Server;
/// implement a custom <see cref="IMcpTaskStore"/>.
/// </para>
/// </remarks>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
public class InMemoryMcpTaskStore : IMcpTaskStore
{
private readonly ConcurrentDictionary<string, McpTaskInfo> _tasks = new();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using ModelContextProtocol.Protocol;
using System.Diagnostics.CodeAnalysis;

namespace ModelContextProtocol.Server;

/// <summary>
/// Provides data for the <see cref="IMcpTaskStore.InputResponseReceived"/> event.
/// </summary>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
public sealed class InputResponseReceivedEventArgs
{
/// <summary>
Expand Down
1 change: 0 additions & 1 deletion src/ModelContextProtocol.Core/Server/McpServer.Methods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,6 @@ private void ThrowIfRootsUnsupported()
/// <param name="taskId">The task ID in the store.</param>
/// <param name="store">The task store to write input requests to.</param>
/// <returns>An <see cref="IDisposable"/> that restores the previous context when disposed.</returns>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
public IDisposable CreateMcpTaskScope(
string taskId,
IMcpTaskStore store)
Expand Down
1 change: 0 additions & 1 deletion src/ModelContextProtocol.Core/Server/McpServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ protected McpServer()
/// the required feature) instead of throwing <see cref="Protocol.InputRequiredException"/>.
/// </para>
/// </remarks>
[Experimental(Experimentals.Mrtr_DiagnosticId, UrlFormat = Experimentals.Mrtr_Url)]
public virtual bool IsMrtrSupported => false;

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using System.Diagnostics.CodeAnalysis;

namespace ModelContextProtocol.Server;

/// <summary>
Expand All @@ -9,7 +7,6 @@ namespace ModelContextProtocol.Server;
/// and <see cref="McpServer.RequestRootsAsync(ModelContextProtocol.Protocol.ListRootsRequestParams, CancellationToken)"/>
/// are redirected through the task store as input requests rather than sent directly to the client.
/// </summary>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
internal sealed class McpTaskExecutionContext
{
internal static readonly AsyncLocal<McpTaskExecutionContext?> Current = new();
Expand Down
2 changes: 0 additions & 2 deletions src/ModelContextProtocol.Core/Server/McpTaskInfo.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using ModelContextProtocol.Protocol;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json;

namespace ModelContextProtocol.Server;
Expand All @@ -14,7 +13,6 @@ namespace ModelContextProtocol.Server;
/// types (<see cref="CreateTaskResult"/>, <see cref="GetTaskResult"/>) when communicating with clients.
/// </para>
/// </remarks>
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)]
public sealed record McpTaskInfo(
string TaskId,
McpTaskStatus Status,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Reflection;
using System.Text.Json.Serialization;
using ModelContextProtocol.Server;
using ModelContextProtocol.Protocol;

namespace ModelContextProtocol.Tests;
Expand All @@ -15,6 +16,29 @@ namespace ModelContextProtocol.Tests;
/// </remarks>
public class ExperimentalInternalPropertyTests
{
[Fact]
public void OfficialExtensionsTasksAndMrtrApis_AreNotExperimental()
{
static bool HasExperimentalAttribute(ICustomAttributeProvider provider) =>
provider.GetCustomAttributes(inherit: false).Any(a => a.GetType().Name == "ExperimentalAttribute");

Assert.False(HasExperimentalAttribute(typeof(InputRequest)));
Assert.False(HasExperimentalAttribute(typeof(InputResponse)));
Assert.False(HasExperimentalAttribute(typeof(InputRequiredResult)));
Assert.False(HasExperimentalAttribute(typeof(InputRequiredException)));
Assert.False(HasExperimentalAttribute(typeof(IMcpTaskStore)));
Assert.False(HasExperimentalAttribute(typeof(InMemoryMcpTaskStore)));
Assert.False(HasExperimentalAttribute(typeof(InputResponseReceivedEventArgs)));
Assert.False(HasExperimentalAttribute(typeof(McpTaskInfo)));

Assert.False(HasExperimentalAttribute(typeof(ClientCapabilities).GetProperty(nameof(ClientCapabilities.Extensions))!));
Assert.False(HasExperimentalAttribute(typeof(ServerCapabilities).GetProperty(nameof(ServerCapabilities.Extensions))!));
Assert.False(HasExperimentalAttribute(typeof(RequestParams).GetProperty(nameof(RequestParams.InputResponses))!));
Assert.False(HasExperimentalAttribute(typeof(RequestParams).GetProperty(nameof(RequestParams.RequestState))!));
Assert.False(HasExperimentalAttribute(typeof(McpServer).GetProperty(nameof(McpServer.IsMrtrSupported))!));
Assert.False(HasExperimentalAttribute(typeof(McpServer).GetMethod(nameof(McpServer.CreateMcpTaskScope))!));
}

[Fact]
public void ExperimentalProperties_MustBeHiddenFromSourceGenerator()
{
Expand Down
Loading