Skip to content
Open
Show file tree
Hide file tree
Changes from 3 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