Skip to content

Add Extensions support to ClientCapabilities and ServerCapabilities (SEP-2133)#1292

Open
Copilot wants to merge 6 commits intomainfrom
copilot/add-mcp-extensions-support
Open

Add Extensions support to ClientCapabilities and ServerCapabilities (SEP-2133)#1292
Copilot wants to merge 6 commits intomainfrom
copilot/add-mcp-extensions-support

Conversation

Copy link
Contributor

Copilot AI commented Feb 17, 2026

  • Update docs/list-of-diagnostics.md to include Extensions in MCPEXP001 description
  • Add Extensions property to ClientCapabilities with [Experimental] attribute using MCPEXP001
  • Add Extensions property to ServerCapabilities with [Experimental] attribute using MCPEXP001
  • Build and test to verify changes work correctly
  • Verify serialization/deserialization works correctly
  • Add dedicated Extensions constants (Extensions_DiagnosticId, Extensions_Message, Extensions_Url) that map to MCPEXP001
  • Add clarifying documentation explaining why Tasks and Extensions share the same diagnostic ID
  • Add comprehensive serialization roundtrip tests for Extensions property
  • Update Extensions_Message to clarify it's for an unratified spec version
  • Split capabilities tests into separate files (ClientCapabilitiesTests.cs and ServerCapabilitiesTests.cs)
Original prompt

Summary

Implement support for the MCP Extensions framework defined in SEP-2133. This SEP adds an extensions field to both ClientCapabilities and ServerCapabilities to allow clients and servers to advertise support for MCP extensions during the initialization handshake.

What changed in the spec

The last commit of SEP-2133 (f19398725c6ef464e1f3af0214cfde3ff4f80325) adds an extensions field to both ClientCapabilities and ServerCapabilities in the draft schema:

// In ClientCapabilities:
/**
 * Optional MCP extensions that the client supports. Keys are extension identifiers
 * (e.g., "io.modelcontextprotocol/oauth-client-credentials"), and values are
 * per-extension settings objects. An empty object indicates support with no settings.
 */
extensions?: { [key: string]: object };

// In ServerCapabilities:
/**
 * Optional MCP extensions that the server supports. Keys are extension identifiers
 * (e.g., "io.modelcontextprotocol/apps"), and values are per-extension settings
 * objects. An empty object indicates support with no settings.
 */
extensions?: { [key: string]: object };

What needs to be done in the C# SDK

1. Add Extensions_DiagnosticId, Extensions_Message, and Extensions_Url to src/Common/Experimentals.cs

Follow the existing pattern from Tasks. Use diagnostic ID MCPEXP002. The message should mention that the Extensions feature is experimental per the MCP specification. The URL should point to https://github.com/modelcontextprotocol/csharp-sdk/blob/main/docs/list-of-diagnostics.md#mcpexp002.

2. Update docs/list-of-diagnostics.md

Add a new row to the "Experimental APIs" table for MCPEXP002 describing the MCP Extensions feature and linking to the SEP-2133 PR.

3. Add Extensions property to ClientCapabilities (src/ModelContextProtocol.Core/Protocol/ClientCapabilities.cs)

Add the following property:

/// <summary>
/// Gets or sets optional MCP extensions that the client supports.
/// </summary>
/// <remarks>
/// <para>
/// Keys are extension identifiers in reverse domain notation with an extension name
/// (e.g., <c>"io.modelcontextprotocol/oauth-client-credentials"</c>), and values are
/// per-extension settings objects. An empty object indicates support with no additional settings.
/// </para>
/// <para>
/// Extensions provide a framework for extending the Model Context Protocol while maintaining
/// interoperability. Both clients and servers advertise extension support via this field during
/// the initialization handshake.
/// </para>
/// </remarks>
[JsonPropertyName("extensions")]
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)] // SEP-2133: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2133
public IDictionary<string, object>? Extensions { get; set; }

4. Add Extensions property to ServerCapabilities (src/ModelContextProtocol.Core/Protocol/ServerCapabilities.cs)

Add the following property:

/// <summary>
/// Gets or sets optional MCP extensions that the server supports.
/// </summary>
/// <remarks>
/// <para>
/// Keys are extension identifiers in reverse domain notation with an extension name
/// (e.g., <c>"io.modelcontextprotocol/apps"</c>), and values are per-extension settings
/// objects. An empty object indicates support with no additional settings.
/// </para>
/// <para>
/// Extensions provide a framework for extending the Model Context Protocol while maintaining
/// interoperability. Both clients and servers advertise extension support via this field during
/// the initialization handshake.
/// </para>
/// </remarks>
[JsonPropertyName("extensions")]
[Experimental(Experimentals.Extensions_DiagnosticId, UrlFormat = Experimentals.Extensions_Url)] // SEP-2133: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2133
public IDictionary<string, object>? Extensions { get; set; }

5. Suppress MCPEXP002 in project files that already suppress MCPEXP001

Add ;MCPEXP002 to the <NoWarn> in the following project files (these are the ones that already suppress MCPEXP001):

  • src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
  • src/ModelContextProtocol/ModelContextProtocol.csproj
  • src/ModelContextProtocol.AspNetCore/ModelContextProtocol.AspNetCore.csproj (if it suppresses MCPEXP001)
  • tests/ModelContextProtocol.AotCompatibility.TestApp/ModelContextProtocol.AotCompatibility.TestApp.csproj
  • samples/LongRunningTasks/LongRunningTasks.csproj

Important patterns to follow

  • The type for Extensions should be IDictionary<string, object>? — this matches the existing Experimental property on both classes.
  • The [Experimental] attribute uses constants from src/Common/Experimentals.cs — follow the same pattern as `Tasks_Diagno...

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement support for MCP Extensions framework Add Extensions support to ClientCapabilities and ServerCapabilities (SEP-2133) Feb 17, 2026
Copilot AI requested a review from stephentoub February 17, 2026 08:29
Copilot AI and others added 2 commits February 17, 2026 08:41
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
…message

Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
public static class CapabilitiesTests
{
[Fact]
public static void ClientCapabilities_ExtensionsProperty_SerializationRoundTrip()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot these should be split into test files by type, one for client, one for server

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in b19aefd. Split into ClientCapabilitiesTests.cs (5 tests) and ServerCapabilitiesTests.cs (5 tests).

@stephentoub stephentoub marked this pull request as ready for review February 17, 2026 09:15
Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com>
/// MCP features. Having separate constants improves code clarity while maintaining a
/// single diagnostic suppression point.
/// </remarks>
public const string Extensions_DiagnosticId = "MCPEXP001";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
public const string Extensions_DiagnosticId = "MCPEXP001";
public const string Extensions_DiagnosticId = "MCPEXP002";

Shouldn't we use a different diagnostic ID if we're going to have a different URL/message? There are more usages we'll have to fix. Are we going to wait for #1260 to get merged first before merging this? @MackinnonBuck

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the same url, just a different message. It's fine to have different messages for the dame diagnostic. I also don't want to proliferate diagnostics, or makes consumption super annoying.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments