Releases: modelcontextprotocol/csharp-sdk
v0.1.0-preview.4
This release introduces the ModelContextProtocol.AspNetCore package for hosting MCP servers in ASP.NET Core applications with SSE transport support.
Breaking Changes
Refer to the C# SDK Versioning documentation for details on versioning and breaking change policies.
- Add ModelContextProtocol.AspNetCore #160
HttpListenerSseServerTransportremovedIServerTransportinterface removedMapMcpSserenamed toMapMcpand moved to the newModelContextProtocol.AspNetCorepackage
What's Changed
- Add ModelContextProtocol.AspNetCore #160 by @halter73 (co-authored by @eiriktsarpalis @jeffhandley)
Repository Infrastructure Updates
- Bump package version #167 by @eiriktsarpalis
Acknowledgements
- @stephentoub reviewed pull requests
Full Changelog: v0.1.0-preview.3...v0.1.0-preview.4
v0.1.0-preview.3
This release overhauls the resource system, refactors transports for graceful shutdown, introduces prompt support with McpServerPrompt and McpClientPrompt, and adds progress reporting and annotation support.
Breaking Changes
Refer to the C# SDK Versioning documentation for details on versioning and breaking change policies.
- Add ToolAnnotations support #124
McpServerToolAttributeconstructor no longer accepts a positional string; must useName = "..."instead
- Overhaul of Resources #125
ResourceContentschanged to an abstract class;TextandBlobproperties removed- Must use
TextResourceContentsorBlobResourceContentssubclasses instead
- Add [McpServerPrompt] support #126
ListPromptsAsyncreturn type changedGetPromptAsyncparameter type changedIMcpServerBuildernamespace moved- All
With*Handlerextension methods deleted
- Add missing Annotations #138
Annotatedabstract record base class deletedAnnotationsproperty inlined intoContent,Resource, andResourceTemplate
- Refactor transports to help enable graceful shutdown #142
McpServerHostedServicedeletedIClientTransport.ConnectAsyncnow returnsITransportinstead of the previous typeStartAsyncreplaced byRunAsync
- Improve progress reporting #145
OperationNamesclass deleted; replaced byRequestMethods
What's Changed
- Fix some issues with Native AOT #130 by @stephentoub
- Add ToolAnnotations support #124 by @stephentoub
- Add missing Annotations #138 by @stephentoub
- Remove Assembly.GetCallingAssembly #133 by @stephentoub
- Refactor transports to help enable graceful shutdown #142 by @halter73 (co-authored by @stephentoub)
- Overhaul of Resources #125 by @aaronpowell (co-authored by @stephentoub @PederHP)
- Fix binding to wrong overload in WithTools #152 by @stephentoub
- Improve progress reporting #145 by @stephentoub
- Add
[McpServerPrompt]support #126 by @stephentoub - Implement cancellation notifications #146 by @stephentoub
Documentation Updates
- Fix sample in README #136 by @BrennanConroy
Repository Infrastructure Updates
- Bump version to 0.1.0-preview.3 #162 by @jeffhandley
Acknowledgements
- @BrennanConroy made their first contribution in #136
- @stvansolano reviewed pull requests
Full Changelog: v0.1.0-preview.2...v0.1.0-preview.3
v0.1.0-preview.2
This release overhauls tool handling, makes options types fully mutable, adds logging capability, and improves serialization.
Breaking Changes
Refer to the C# SDK Versioning documentation for details on versioning and breaking change policies.
- Overhaul tool handling #89
McpToolAttributerenamed toMcpServerToolAttribute;McpToolTypeAttributerenamed toMcpServerToolTypeAttributeWithTools()renamed toWithToolsFromAssembly()ListToolsAsyncreturn type changed fromIAsyncEnumerable<Tool>toTask<IList<McpClientTool>>CallToolAsyncparameter changed fromDictionary<string, object>toIReadOnlyDictionary<string, object?>
- Make options types fully mutable #107
McpClientOptions,Implementation, and all capability types changed fromrecordtoclassinit-only setters changed toset;withexpressions on these types will no longer compile
- Fix enum serialization #61
Role,LoggingLevel, andContextInclusionenums now useJsonStringEnumConverterwith[JsonStringEnumMemberName]instead of[JsonPropertyName]- This is a serialization format change; any code depending on the previous serialized form needs to be updated
- List tools from DI once #115
ServerInstructionsproperty removed fromMcpServerMcpServerHostedServiceis no longer public
What's Changed
- Logging Capability #53 by @PederHP (co-authored by @stephentoub)
- Fix enum serialization #61 by @zaevi (co-authored by @eiriktsarpalis)
- Make client config optional to McpClientFactory.CreateAsync #65 by @stephentoub (co-authored by @eiriktsarpalis)
- Fix stdio encoding issue: Enforce explicit UTF-8 for correct Unicode handling #73 by @willibrandon (co-authored by @stephentoub)
- Overhaul tool handling #89 by @stephentoub
- Avoid race starting SseResponseStreamTransport #91 by @halter73
- Adding a base class for request params that exposes the progressToken #99 by @aaronpowell (co-authored by @stephentoub)
- Add
[McpServerTool]support for instance methods #100 by @stephentoub - complete fix for SampleLlmTool discovery #102 by @NeverMorewd (co-authored by @stephentoub)
- Make options types fully mutable #107 by @halter73
- Configurable messages endpoint for SSE transport #109 by @edis-uipath
- Use different logger categories for client and server in McpJsonRpcEndpoint #110 by @halter73
- List tools from DI once #115 by @halter73
- Adding support for returning collections from tools #116 by @aaronpowell
Documentation Updates
- Add nuget badge to README #58 by @stephentoub
- docs: update McpToolAttribute name comment #63 by @WeihanLi
- docs: add McpServerOptionsSetup code comment #77 by @JaneConan
- Update documentation configuration #86 by @localden (co-authored by @eiriktsarpalis)
- Add acknowledgements to README #94 by @mikekistler (co-authored by @stephentoub)
- Add links to API docs from README.md #96 by @eiriktsarpalis
- Add package installation to README #101 by @timheuer
- Samples for quickstart docs #104 by @aaronpowell
Test Improvements
- Run integration test SSE server in process #56 by @halter73
- Remove reflection from Connect test #57 by @jaredpar (co-authored by @stephentoub)
- Fix private reflection #60 by @jaredpar
- Add XunitLoggerProvider #81 by @halter73
Repository Infrastructure Updates
- Adding code coverage to tests in workflow #75 by @aaronpowell (co-authored by @stephentoub @eiriktsarpalis)
- Adding merge files to gitignore #78 by @aaronpowell
- Add gitattributes #98 by @halter73
- Set up package publishing for daily, manual, and release builds #118 by @jeffhandley (co-authored by @Copilot)
Acknowledgements
- @PederHP made their first contribution in #53
- @jaredpar made their first contribution in #57
- @zaevi made their first contribution in #61
- @WeihanLi made their first contribution in #63
- @willibrandon made their first contribution in #73
- @aaronpowell made their first contribution in #75
- @JaneConan made their first contribution in #77
- @localden made their first contribution in #86
- @timheuer made their first contribution in #101
- @NeverMorewd made their first contribution in #102
- @edis-uipath made their first contribution in #109
- @colombod @Meir017 reviewed pull requests
Full Changelog: v0.1.0-preview.1.25171.12...v0.1.0-preview.2
v0.1.0-preview.1.25171.12
MCP C# SDK
https://www.nuget.org/packages/ModelContextProtocol/0.1.0-preview.1.25171.12
The official C# SDK for the Model Context Protocol, enabling .NET applications, services, and libraries to implement and interact with MCP clients and servers.
Note
This is a preview release. Breaking changes can be introduced without prior notice.
About MCP
The Model Context Protocol (MCP) is an open protocol that standardizes how applications provide context to Large Language Models (LLMs). It enables secure integration between LLMs and various data sources and tools.
For more information about MCP:
Getting Started (Client)
To get started writing a client, the McpClientFactory.CreateAsync method is used to instantiate and connect an IMcpClient
to a server, with details about the client and server specified in McpClientOptions and McpServerConfig objects.
Once you have an IMcpClient, you can interact with it, such as to enumerate all available tools and invoke tools.
McpClientOptions options = new()
{
ClientInfo = new() { Name = "TestClient", Version = "1.0.0" }
};
McpServerConfig config = new()
{
Id = "everything",
Name = "Everything",
TransportType = TransportTypes.StdIo,
TransportOptions = new()
{
["command"] = "npx",
["arguments"] = "-y @modelcontextprotocol/server-everything",
}
};
var client = await McpClientFactory.CreateAsync(config, options);
// Print the list of tools available from the server.
await foreach (var tool in client.ListToolsAsync())
{
Console.WriteLine($"{tool.Name} ({tool.Description})");
}
// Execute a tool (this would normally be driven by LLM tool invocations).
var result = await client.CallToolAsync(
"echo",
new() { ["message"] = "Hello MCP!" },
CancellationToken.None);
// echo always returns one and only one text content object
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);You can find samples demonstrating how to use ModelContextProtocol with an LLM SDK in the samples directory, and also refer to the tests project for more examples. Additional examples and documentation will be added as in the near future.
Clients can connect to any MCP server, not just ones created using this library. The protocol is designed to be server-agnostic, so you can use this library to connect to any compliant server.
Tools can be exposed easily as AIFunction instances so that they are immediately usable with IChatClients.
// Get available functions.
IList<AIFunction> tools = await client.GetAIFunctionsAsync();
// Call the chat client using the tools.
IChatClient chatClient = ...;
var response = await chatClient.GetResponseAsync(
"your prompt here",
new()
{
Tools = [.. tools],
});Getting Started (Server)
Here is an example of how to create an MCP server and register all tools from the current application.
It includes a simple echo tool as an example (this is included in the same file here for easy of copy and paste, but it needn't be in the same file...
the employed overload of WithTools examines the current assembly for classes with the McpToolType attribute, and registers all methods with the
McpTool attribute as tools.)
using ModelContextProtocol;
using ModelContextProtocol.Server;
using Microsoft.Extensions.Hosting;
using System.ComponentModel;
var builder = Host.CreateEmptyApplicationBuilder(settings: null);
builder.Services
.AddMcpServer()
.WithStdioServerTransport()
.WithTools();
await builder.Build().RunAsync();
[McpToolType]
public static class EchoTool
{
[McpTool, Description("Echoes the message back to the client.")]
public static string Echo(string message) => $"hello {message}";
}More control is also available, with fine-grained control over configuring the server and how it should handle client requests. For example:
using ModelContextProtocol.Protocol.Transport;
using ModelContextProtocol.Protocol.Types;
using ModelContextProtocol.Server;
using Microsoft.Extensions.Logging.Abstractions;
McpServerOptions options = new()
{
ServerInfo = new() { Name = "MyServer", Version = "1.0.0" },
Capabilities = new()
{
Tools = new()
{
ListToolsHandler = async (request, cancellationToken) =>
{
return new ListToolsResult()
{
Tools =
[
new Tool()
{
Name = "echo",
Description = "Echoes the input back to the client.",
InputSchema = new JsonSchema()
{
Type = "object",
Properties = new Dictionary<string, JsonSchemaProperty>()
{
["message"] = new JsonSchemaProperty() { Type = "string", Description = "The input to echo back." }
}
},
}
]
};
},
CallToolHandler = async (request, cancellationToken) =>
{
if (request.Params?.Name == "echo")
{
if (request.Params.Arguments?.TryGetValue("message", out var message) is not true)
{
throw new McpServerException("Missing required argument 'message'");
}
return new CallToolResponse()
{
Content = [new Content() { Text = $"Echo: {message}", Type = "text" }]
};
}
throw new McpServerException($"Unknown tool: '{request.Params?.Name}'");
},
}
},
};
await using IMcpServer server = McpServerFactory.Create(new StdioServerTransport("MyServer"), options);
await server.StartAsync();
// Run until process is stopped by the client (parent process)
await Task.Delay(Timeout.Infinite);License
This project is licensed under the MIT License.