Skip to content
Merged
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
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ dotnet add package ModelContextProtocol --prerelease

## Getting Started (Client)

To get started writing a client, the `McpClientFactory.CreateAsync` method is used to instantiate and connect an `IMcpClient`
to a server. Once you have an `IMcpClient`, you can interact with it, such as to enumerate all available tools and invoke tools.
To get started writing a client, the `McpClient.CreateAsync` method is used to instantiate and connect an `McpClient`
to a server. Once you have an `McpClient`, you can interact with it, such as to enumerate all available tools and invoke tools.

```csharp
var clientTransport = new StdioClientTransport(new StdioClientTransportOptions
Expand All @@ -48,7 +48,7 @@ var clientTransport = new StdioClientTransport(new StdioClientTransportOptions
Arguments = ["-y", "@modelcontextprotocol/server-everything"],
});

var client = await McpClientFactory.CreateAsync(clientTransport);
var client = await McpClient.CreateAsync(clientTransport);

// Print the list of tools available from the server.
foreach (var tool in await client.ListToolsAsync())
Expand Down Expand Up @@ -122,14 +122,14 @@ public static class EchoTool
}
```

Tools can have the `IMcpServer` representing the server injected via a parameter to the method, and can use that for interaction with
Tools can have the `McpServer` representing the server injected via a parameter to the method, and can use that for interaction with
the connected client. Similarly, arguments may be injected via dependency injection. For example, this tool will use the supplied
`IMcpServer` to make sampling requests back to the client in order to summarize content it downloads from the specified url via
`McpServer` to make sampling requests back to the client in order to summarize content it downloads from the specified url via
an `HttpClient` injected via dependency injection.
```csharp
[McpServerTool(Name = "SummarizeContentFromUrl"), Description("Summarizes content downloaded from a specific URI")]
public static async Task<string> SummarizeDownloadedContent(
IMcpServer thisServer,
McpServer thisServer,
HttpClient httpClient,
[Description("The url from which to download the content to summarize")] string url,
CancellationToken cancellationToken)
Expand Down Expand Up @@ -224,7 +224,7 @@ McpServerOptions options = new()
},
};

await using IMcpServer server = McpServerFactory.Create(new StdioServerTransport("MyServer"), options);
await using McpServer server = McpServer.Create(new StdioServerTransport("MyServer"), options);
await server.RunAsync();
```

Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/elicitation/samples/client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

var endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? "http://localhost:3001";

var clientTransport = new SseClientTransport(new()
var clientTransport = new HttpClientTransport(new()
{
Endpoint = new Uri(endpoint),
TransportMode = HttpTransportMode.StreamableHttp,
Expand All @@ -27,7 +27,7 @@
}
};

await using var mcpClient = await McpClientFactory.CreateAsync(clientTransport, options);
await using var mcpClient = await McpClient.CreateAsync(clientTransport, options);
// </snippet_McpInitialize>

var tools = await mcpClient.ListToolsAsync();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public sealed class InteractiveTools
// <snippet_GuessTheNumber>
[McpServerTool, Description("A simple game where the user has to guess a number between 1 and 10.")]
public async Task<string> GuessTheNumber(
IMcpServer server, // Get the McpServer from DI container
McpServer server, // Get the McpServer from DI container
CancellationToken token
)
{
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/logging/samples/client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,13 @@

var endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? "http://localhost:3001";

var clientTransport = new SseClientTransport(new()
var clientTransport = new HttpClientTransport(new()
{
Endpoint = new Uri(endpoint),
TransportMode = HttpTransportMode.StreamableHttp,
});

await using var mcpClient = await McpClientFactory.CreateAsync(clientTransport);
await using var mcpClient = await McpClient.CreateAsync(clientTransport);

// <snippet_LoggingCapabilities>
// Verify that the server supports logging
Expand Down
4 changes: 2 additions & 2 deletions docs/concepts/progress/samples/client/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

var endpoint = Environment.GetEnvironmentVariable("ENDPOINT") ?? "http://localhost:3001";

var clientTransport = new SseClientTransport(new()
var clientTransport = new HttpClientTransport(new()
{
Endpoint = new Uri(endpoint),
TransportMode = HttpTransportMode.StreamableHttp,
Expand All @@ -20,7 +20,7 @@
}
};

await using var mcpClient = await McpClientFactory.CreateAsync(clientTransport, options);
await using var mcpClient = await McpClient.CreateAsync(clientTransport, options);

var tools = await mcpClient.ListToolsAsync();
foreach (var tool in tools)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class LongRunningTools
{
[McpServerTool, Description("Demonstrates a long running tool with progress updates")]
public static async Task<string> LongRunningTool(
IMcpServer server,
McpServer server,
RequestContext<CallToolRequestParams> context,
int duration = 10,
int steps = 5)
Expand Down
2 changes: 1 addition & 1 deletion samples/AspNetCoreMcpServer/Tools/SampleLlmTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public sealed class SampleLlmTool
{
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
public static async Task<string> SampleLLM(
IMcpServer thisServer,
McpServer thisServer,
[Description("The prompt to send to the LLM")] string prompt,
[Description("Maximum number of tokens to generate")] int maxTokens,
CancellationToken cancellationToken)
Expand Down
2 changes: 1 addition & 1 deletion samples/ChatWithTools/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
.UseOpenTelemetry(loggerFactory: loggerFactory, configure: o => o.EnableSensitiveData = true)
.Build();

var mcpClient = await McpClientFactory.CreateAsync(
var mcpClient = await McpClient.CreateAsync(
new StdioClientTransport(new()
{
Command = "npx",
Expand Down
2 changes: 1 addition & 1 deletion samples/EverythingServer/LoggingUpdateMessageSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace EverythingServer;

public class LoggingUpdateMessageSender(IMcpServer server, Func<LoggingLevel> getMinLevel) : BackgroundService
public class LoggingUpdateMessageSender(McpServer server, Func<LoggingLevel> getMinLevel) : BackgroundService
{
readonly Dictionary<LoggingLevel, string> _loggingLevelMap = new()
{
Expand Down
2 changes: 1 addition & 1 deletion samples/EverythingServer/SubscriptionMessageSender.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using ModelContextProtocol;
using ModelContextProtocol.Server;

internal class SubscriptionMessageSender(IMcpServer server, HashSet<string> subscriptions) : BackgroundService
internal class SubscriptionMessageSender(McpServer server, HashSet<string> subscriptions) : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
Expand Down
2 changes: 1 addition & 1 deletion samples/EverythingServer/Tools/LongRunningTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class LongRunningTool
{
[McpServerTool(Name = "longRunningOperation"), Description("Demonstrates a long running operation with progress updates")]
public static async Task<string> LongRunningOperation(
IMcpServer server,
McpServer server,
RequestContext<CallToolRequestParams> context,
int duration = 10,
int steps = 5)
Expand Down
2 changes: 1 addition & 1 deletion samples/EverythingServer/Tools/SampleLlmTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class SampleLlmTool
{
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
public static async Task<string> SampleLLM(
IMcpServer server,
McpServer server,
[Description("The prompt to send to the LLM")] string prompt,
[Description("Maximum number of tokens to generate")] int maxTokens,
CancellationToken cancellationToken)
Expand Down
4 changes: 2 additions & 2 deletions samples/InMemoryTransport/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Pipe clientToServerPipe = new(), serverToClientPipe = new();

// Create a server using a stream-based transport over an in-memory pipe.
await using IMcpServer server = McpServerFactory.Create(
await using McpServer server = McpServer.Create(
new StreamServerTransport(clientToServerPipe.Reader.AsStream(), serverToClientPipe.Writer.AsStream()),
new McpServerOptions()
{
Expand All @@ -21,7 +21,7 @@
_ = server.RunAsync();

// Connect a client using a stream-based transport over the same in-memory pipe.
await using IMcpClient client = await McpClientFactory.CreateAsync(
await using McpClient client = await McpClient.CreateAsync(
new StreamClientTransport(clientToServerPipe.Writer.AsStream(), serverToClientPipe.Reader.AsStream()));

// List all tools.
Expand Down
4 changes: 2 additions & 2 deletions samples/ProtectedMcpClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
builder.AddConsole();
});

var transport = new SseClientTransport(new()
var transport = new HttpClientTransport(new()
{
Endpoint = new Uri(serverUrl),
Name = "Secure Weather Client",
Expand All @@ -40,7 +40,7 @@
}
}, httpClient, consoleLoggerFactory);

var client = await McpClientFactory.CreateAsync(transport, loggerFactory: consoleLoggerFactory);
var client = await McpClient.CreateAsync(transport, loggerFactory: consoleLoggerFactory);

var tools = await client.ListToolsAsync();
if (tools.Count == 0)
Expand Down
6 changes: 3 additions & 3 deletions samples/QuickstartClient/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
if (command == "http")
{
// make sure AspNetCoreMcpServer is running
clientTransport = new SseClientTransport(new()
clientTransport = new HttpClientTransport(new()
{
Endpoint = new Uri("http://localhost:3001")
});
Expand All @@ -33,7 +33,7 @@
Arguments = arguments,
});
}
await using var mcpClient = await McpClientFactory.CreateAsync(clientTransport!);
await using var mcpClient = await McpClient.CreateAsync(clientTransport!);

var tools = await mcpClient.ListToolsAsync();
foreach (var tool in tools)
Expand Down Expand Up @@ -62,7 +62,7 @@
var sb = new StringBuilder();

PromptForInput();
while(Console.ReadLine() is string query && !"exit".Equals(query, StringComparison.OrdinalIgnoreCase))
while (Console.ReadLine() is string query && !"exit".Equals(query, StringComparison.OrdinalIgnoreCase))
{
if (string.IsNullOrWhiteSpace(query))
{
Expand Down
2 changes: 1 addition & 1 deletion samples/TestServerWithHosting/Tools/SampleLlmTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public sealed class SampleLlmTool
{
[McpServerTool(Name = "sampleLLM"), Description("Samples from an LLM using MCP's sampling feature")]
public static async Task<string> SampleLLM(
IMcpServer thisServer,
McpServer thisServer,
[Description("The prompt to send to the LLM")] string prompt,
[Description("Maximum number of tokens to generate")] int maxTokens,
CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ private async ValueTask<AuthorizationResult> GetAuthorizationResultAsync(
if (requestServices is null)
{
// The IAuthorizationPolicyProvider service must be non-null to get to this line, so it's very unexpected for RequestContext.Services to not be set.
throw new InvalidOperationException("RequestContext.Services is not set! The IMcpServer must be initialized with a non-null IServiceProvider.");
throw new InvalidOperationException("RequestContext.Services is not set! The McpServer must be initialized with a non-null IServiceProvider.");
}

// ASP.NET Core's AuthorizationMiddleware resolves the IAuthorizationService from scoped request services, so we do the same.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class HttpServerTransportOptions
/// Gets or sets an optional asynchronous callback for running new MCP sessions manually.
/// This is useful for running logic before a sessions starts and after it completes.
/// </summary>
public Func<HttpContext, IMcpServer, CancellationToken, Task>? RunSessionHandler { get; set; }
public Func<HttpContext, McpServer, CancellationToken, Task>? RunSessionHandler { get; set; }

/// <summary>
/// Gets or sets whether the server should run in a stateless mode that does not require all requests for a given session
Expand Down
2 changes: 1 addition & 1 deletion src/ModelContextProtocol.AspNetCore/SseHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public async Task HandleSseRequestAsync(HttpContext context)

try
{
await using var mcpServer = McpServerFactory.Create(transport, mcpServerOptions, loggerFactory, context.RequestServices);
await using var mcpServer = McpServer.Create(transport, mcpServerOptions, loggerFactory, context.RequestServices);
context.Features.Set(mcpServer);

var runSessionAsync = httpMcpServerOptions.Value.RunSessionHandler ?? StreamableHttpHandler.RunSessionAsync;
Expand Down
4 changes: 2 additions & 2 deletions src/ModelContextProtocol.AspNetCore/StreamableHttpHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ private async ValueTask<StreamableHttpSession> CreateSessionAsync(
}
}

var server = McpServerFactory.Create(transport, mcpServerOptions, loggerFactory, mcpServerServices);
var server = McpServer.Create(transport, mcpServerOptions, loggerFactory, mcpServerServices);
context.Features.Set(server);

var userIdClaim = statelessId?.UserIdClaim ?? GetUserIdClaim(context.User);
Expand Down Expand Up @@ -307,7 +307,7 @@ private void ScheduleStatelessSessionIdWrite(HttpContext context, StreamableHttp
};
}

internal static Task RunSessionAsync(HttpContext httpContext, IMcpServer session, CancellationToken requestAborted)
internal static Task RunSessionAsync(HttpContext httpContext, McpServer session, CancellationToken requestAborted)
=> session.RunAsync(requestAborted);

// SignalR only checks for ClaimTypes.NameIdentifier in HttpConnectionDispatcher, but AspNetCore.Antiforgery checks that plus the sub and UPN claims.
Expand Down
4 changes: 2 additions & 2 deletions src/ModelContextProtocol.AspNetCore/StreamableHttpSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ namespace ModelContextProtocol.AspNetCore;
internal sealed class StreamableHttpSession(
string sessionId,
StreamableHttpServerTransport transport,
IMcpServer server,
McpServer server,
UserIdClaim? userId,
StatefulSessionManager sessionManager) : IAsyncDisposable
{
Expand All @@ -20,7 +20,7 @@ internal sealed class StreamableHttpSession(

public string Id => sessionId;
public StreamableHttpServerTransport Transport => transport;
public IMcpServer Server => server;
public McpServer Server => server;
private StatefulSessionManager SessionManager => sessionManager;

public CancellationToken SessionClosed => _disposeCts.Token;
Expand Down
9 changes: 9 additions & 0 deletions src/ModelContextProtocol.Core/AssemblyNameHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System.Reflection;

namespace ModelContextProtocol;

internal static class AssemblyNameHelper
{
/// <summary>Cached naming information used for MCP session name/version when none is specified.</summary>
public static AssemblyName DefaultAssemblyName { get; } = (Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly()).GetName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@ namespace ModelContextProtocol.Client;
/// </summary>
internal sealed partial class AutoDetectingClientSessionTransport : ITransport
{
private readonly SseClientTransportOptions _options;
private readonly HttpClientTransportOptions _options;
private readonly McpHttpClient _httpClient;
private readonly ILoggerFactory? _loggerFactory;
private readonly ILogger _logger;
private readonly string _name;
private readonly Channel<JsonRpcMessage> _messageChannel;

public AutoDetectingClientSessionTransport(string endpointName, SseClientTransportOptions transportOptions, McpHttpClient httpClient, ILoggerFactory? loggerFactory)
public AutoDetectingClientSessionTransport(string endpointName, HttpClientTransportOptions transportOptions, McpHttpClient httpClient, ILoggerFactory? loggerFactory)
{
Throw.IfNull(transportOptions);
Throw.IfNull(httpClient);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,26 +13,26 @@ namespace ModelContextProtocol.Client;
/// Unlike the <see cref="StdioClientTransport"/>, this transport connects to an existing server
/// rather than launching a new process.
/// </remarks>
public sealed class SseClientTransport : IClientTransport, IAsyncDisposable
public sealed class HttpClientTransport : IClientTransport, IAsyncDisposable
{
private readonly SseClientTransportOptions _options;
private readonly HttpClientTransportOptions _options;
private readonly McpHttpClient _mcpHttpClient;
private readonly ILoggerFactory? _loggerFactory;

private readonly HttpClient? _ownedHttpClient;

/// <summary>
/// Initializes a new instance of the <see cref="SseClientTransport"/> class.
/// Initializes a new instance of the <see cref="HttpClientTransport"/> class.
/// </summary>
/// <param name="transportOptions">Configuration options for the transport.</param>
/// <param name="loggerFactory">Logger factory for creating loggers used for diagnostic output during transport operations.</param>
public SseClientTransport(SseClientTransportOptions transportOptions, ILoggerFactory? loggerFactory = null)
public HttpClientTransport(HttpClientTransportOptions transportOptions, ILoggerFactory? loggerFactory = null)
: this(transportOptions, new HttpClient(), loggerFactory, ownsHttpClient: true)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="SseClientTransport"/> class with a provided HTTP client.
/// Initializes a new instance of the <see cref="HttpClientTransport"/> class with a provided HTTP client.
/// </summary>
/// <param name="transportOptions">Configuration options for the transport.</param>
/// <param name="httpClient">The HTTP client instance used for requests.</param>
Expand All @@ -41,7 +41,7 @@ public SseClientTransport(SseClientTransportOptions transportOptions, ILoggerFac
/// <see langword="true"/> to dispose of <paramref name="httpClient"/> when the transport is disposed;
/// <see langword="false"/> if the caller is retaining ownership of the <paramref name="httpClient"/>'s lifetime.
/// </param>
public SseClientTransport(SseClientTransportOptions transportOptions, HttpClient httpClient, ILoggerFactory? loggerFactory = null, bool ownsHttpClient = false)
public HttpClientTransport(HttpClientTransportOptions transportOptions, HttpClient httpClient, ILoggerFactory? loggerFactory = null, bool ownsHttpClient = false)
{
Throw.IfNull(transportOptions);
Throw.IfNull(httpClient);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
namespace ModelContextProtocol.Client;

/// <summary>
/// Provides options for configuring <see cref="SseClientTransport"/> instances.
/// Provides options for configuring <see cref="HttpClientTransport"/> instances.
/// </summary>
public sealed class SseClientTransportOptions
public sealed class HttpClientTransportOptions
{
/// <summary>
/// Gets or sets the base address of the server for SSE connections.
Expand Down
Loading
Loading