Restructure IMcpEndpoint, IMcpClient, and IMcpServer (#723)

* Remove `McpEndpoint` & `IMcpClient`

* Revise naming, add abstract classes

* Fix missing renames

* Move extension methods to instance methods

* Add back old API, but obsoleted

* Add back obsoleted factory classes

* Move deprecation attributes

* `SseClientTransport` -> `HttpClientTransport`

* Update src/ModelContextProtocol.Core/Server/AugmentedServiceProvider.cs

Co-authored-by: Stephen Halter <halter73@gmail.com>

* PR feedback

* PR feedback

* Add back dispose lock

* Fix docs projects

* PR feedback

* Undo `docs/*.md` changes

---------

Co-authored-by: Stephen Halter <halter73@gmail.com>
This commit is contained in:
Mackinnon Buck 2025-09-16 13:22:10 -04:00 • committed by GitHub
commit 38b4a26998
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -1,11 +1,9 @@
using Microsoft.Extensions.AI;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Primitives;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using Moq;
using System.ComponentModel;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.Json;
@ -43,11 +41,11 @@ public class McpServerPromptTests
}
[Fact]
public async Task SupportsIMcpServer()
public async Task SupportsMcpServer()
{
Mock<IMcpServer> mockServer = new();
Mock<McpServer> mockServer = new();
McpServerPrompt prompt = McpServerPrompt.Create((IMcpServer server) =>
McpServerPrompt prompt = McpServerPrompt.Create((McpServer server) =>
{
Assert.Same(mockServer.Object, server);
return new ChatMessage(ChatRole.User, "Hello");
@ -73,7 +71,7 @@ public class McpServerPromptTests
sc.AddSingleton(expectedMyService);
IServiceProvider services = sc.BuildServiceProvider();
Mock<IMcpServer> mockServer = new();
Mock<McpServer> mockServer = new();
mockServer.SetupGet(s => s.Services).Returns(services);
MethodInfo? testMethod = typeof(HasCtorWithSpecialParameters).GetMethod(nameof(HasCtorWithSpecialParameters.TestPrompt));
@ -96,11 +94,11 @@ public class McpServerPromptTests
private sealed class HasCtorWithSpecialParameters
{
private readonly MyService _ms;
private readonly IMcpServer _server;
private readonly McpServer _server;
private readonly RequestContext<GetPromptRequestParams> _request;
private readonly IProgress<ProgressNotificationValue> _progress;
public HasCtorWithSpecialParameters(MyService ms, IMcpServer server, RequestContext<GetPromptRequestParams> request, IProgress<ProgressNotificationValue> progress)
public HasCtorWithSpecialParameters(MyService ms, McpServer server, RequestContext<GetPromptRequestParams> request, IProgress<ProgressNotificationValue> progress)
{
Assert.NotNull(ms);
Assert.NotNull(server);
@ -135,11 +133,11 @@ public class McpServerPromptTests
Assert.DoesNotContain("actualMyService", prompt.ProtocolPrompt.Arguments?.Select(a => a.Name) ?? []);
await Assert.ThrowsAnyAsync<ArgumentException>(async () => await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken));
var result = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()) { Services = services },
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()) { Services = services },
TestContext.Current.CancellationToken);
Assert.Equal("Hello", Assert.IsType<TextContentBlock>(result.Messages[0].Content).Text);
}
@ -160,7 +158,7 @@ public class McpServerPromptTests
}, new() { Services = services });
var result = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("Hello", Assert.IsType<TextContentBlock>(result.Messages[0].Content).Text);
}
@ -173,7 +171,7 @@ public class McpServerPromptTests
_ => new DisposablePromptType());
var result = await prompt1.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("disposals:1", Assert.IsType<TextContentBlock>(result.Messages[0].Content).Text);
}
@ -186,7 +184,7 @@ public class McpServerPromptTests
_ => new AsyncDisposablePromptType());
var result = await prompt1.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("asyncDisposals:1", Assert.IsType<TextContentBlock>(result.Messages[0].Content).Text);
}
@ -199,7 +197,7 @@ public class McpServerPromptTests
_ => new AsyncDisposableAndDisposablePromptType());
var result = await prompt1.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Equal("disposals:0, asyncDisposals:1", Assert.IsType<TextContentBlock>(result.Messages[0].Content).Text);
}
@ -215,7 +213,7 @@ public class McpServerPromptTests
});
var actual = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.Same(expected, actual);
@ -232,7 +230,7 @@ public class McpServerPromptTests
});
var actual = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@ -258,7 +256,7 @@ public class McpServerPromptTests
});
var actual = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@ -290,7 +288,7 @@ public class McpServerPromptTests
});
var actual = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@ -317,7 +315,7 @@ public class McpServerPromptTests
});
var actual = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@ -349,7 +347,7 @@ public class McpServerPromptTests
});
var actual = await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken);
Assert.NotNull(actual);
@ -370,7 +368,7 @@ public class McpServerPromptTests
});
await Assert.ThrowsAsync<InvalidOperationException>(async () => await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken));
}
@ -383,7 +381,7 @@ public class McpServerPromptTests
});
await Assert.ThrowsAsync<InvalidOperationException>(async () => await prompt.GetAsync(
new RequestContext<GetPromptRequestParams>(new Mock<IMcpServer>().Object, CreateTestJsonRpcRequest()),
new RequestContext<GetPromptRequestParams>(new Mock<McpServer>().Object, CreateTestJsonRpcRequest()),
TestContext.Current.CancellationToken));
}