Skip to content

Add ModelContextProtocol.Core package #428

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jun 2, 2025
Merged
Show file tree
Hide file tree
Changes from 4 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
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<PackageVersion Include="Microsoft.Bcl.Memory" Version="9.0.4" />
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="8.0.1" />
<PackageVersion Include="System.IO.Pipelines" Version="8.0.0" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="System.Threading.Channels" Version="8.0.0" />
Expand Down
9 changes: 8 additions & 1 deletion ModelContextProtocol.sln
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.13.35507.96
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol", "src\ModelContextProtocol\ModelContextProtocol.csproj", "{12260CD2-AFFC-4B2E-8898-F442CAA1FA0F}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol.Core", "src\ModelContextProtocol.Core\ModelContextProtocol.Core.csproj", "{12260CD2-AFFC-4B2E-8898-F442CAA1FA0F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol.Tests", "tests\ModelContextProtocol.Tests\ModelContextProtocol.Tests.csproj", "{FF41F619-833D-4FA2-8C53-04D0A1D5AA61}"
EndProject
Expand Down Expand Up @@ -54,6 +54,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EverythingServer", "samples
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol.AspNetCore", "src\ModelContextProtocol.AspNetCore\ModelContextProtocol.AspNetCore.csproj", "{37B6A5E0-9995-497D-8B43-3BC6870CC716}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol", "src\ModelContextProtocol\ModelContextProtocol.csproj", "{3F5C7E8A-F123-4D2B-8B9A-1E2F3D4C5B6A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ModelContextProtocol.AspNetCore.Tests", "tests\ModelContextProtocol.AspNetCore.Tests\ModelContextProtocol.AspNetCore.Tests.csproj", "{85557BA6-3D29-4C95-A646-2A972B1C2F25}"
EndProject
Global
Expand Down Expand Up @@ -106,6 +108,10 @@ Global
{37B6A5E0-9995-497D-8B43-3BC6870CC716}.Debug|Any CPU.Build.0 = Debug|Any CPU
{37B6A5E0-9995-497D-8B43-3BC6870CC716}.Release|Any CPU.ActiveCfg = Release|Any CPU
{37B6A5E0-9995-497D-8B43-3BC6870CC716}.Release|Any CPU.Build.0 = Release|Any CPU
{3F5C7E8A-F123-4D2B-8B9A-1E2F3D4C5B6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3F5C7E8A-F123-4D2B-8B9A-1E2F3D4C5B6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F5C7E8A-F123-4D2B-8B9A-1E2F3D4C5B6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F5C7E8A-F123-4D2B-8B9A-1E2F3D4C5B6A}.Release|Any CPU.Build.0 = Release|Any CPU
{85557BA6-3D29-4C95-A646-2A972B1C2F25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{85557BA6-3D29-4C95-A646-2A972B1C2F25}.Debug|Any CPU.Build.0 = Debug|Any CPU
{85557BA6-3D29-4C95-A646-2A972B1C2F25}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -127,6 +133,7 @@ Global
{0D1552DC-E6ED-4AAC-5562-12F8352F46AA} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{17B8453F-AB72-99C5-E5EA-D0B065A6AE65} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
{37B6A5E0-9995-497D-8B43-3BC6870CC716} = {A2F1F52A-9107-4BF8-8C3F-2F6670E7D0AD}
{3F5C7E8A-F123-4D2B-8B9A-1E2F3D4C5B6A} = {A2F1F52A-9107-4BF8-8C3F-2F6670E7D0AD}
{85557BA6-3D29-4C95-A646-2A972B1C2F25} = {2A77AF5C-138A-4EBB-9A13-9205DCD67928}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@

The official C# SDK for the [Model Context Protocol](https://modelcontextprotocol.io/), enabling .NET applications, services, and libraries to implement and interact with MCP clients and servers. Please visit our [API documentation](https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.html) for more details on available functionality.

## Packages

This SDK consists of three main packages:

- **[ModelContextProtocol](https://www.nuget.org/packages/ModelContextProtocol/absoluteLatest)** [![NuGet preview version](https://img.shields.io/nuget/vpre/ModelContextProtocol.svg)](https://www.nuget.org/packages/ModelContextProtocol/absoluteLatest) - The main package with hosting and dependency injection extensions. This is the right fit for most projects that don't need HTTP server capabilities. This README serves as documentation for this package.

- **[ModelContextProtocol.AspNetCore](https://www.nuget.org/packages/ModelContextProtocol.AspNetCore/absoluteLatest)** [![NuGet preview version](https://img.shields.io/nuget/vpre/ModelContextProtocol.AspNetCore.svg)](https://www.nuget.org/packages/ModelContextProtocol.AspNetCore/absoluteLatest) - The library for HTTP-based MCP servers. [Documentation](src/ModelContextProtocol.AspNetCore/README.md)

- **[ModelContextProtocol.Core](https://www.nuget.org/packages/ModelContextProtocol.Core/absoluteLatest)** [![NuGet preview version](https://img.shields.io/nuget/vpre/ModelContextProtocol.Core.svg)](https://www.nuget.org/packages/ModelContextProtocol.Core/absoluteLatest) - For people who only need to use the client or low-level server APIs and want the minimum number of dependencies. [Documentation](src/ModelContextProtocol.Core/README.md)

> [!NOTE]
> This project is in preview; breaking changes can be introduced without prior notice.

Expand Down
1 change: 0 additions & 1 deletion samples/AspNetCoreSseServer/AspNetCoreSseServer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ModelContextProtocol\ModelContextProtocol.csproj" />
<ProjectReference Include="..\..\src\ModelContextProtocol.AspNetCore\ModelContextProtocol.AspNetCore.csproj" />
</ItemGroup>

Expand Down
2 changes: 1 addition & 1 deletion samples/ChatWithTools/ChatWithTools.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ModelContextProtocol\ModelContextProtocol.csproj" />
<ProjectReference Include="..\..\src\ModelContextProtocol.Core\ModelContextProtocol.Core.csproj" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion samples/QuickstartClient/QuickstartClient.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\ModelContextProtocol\ModelContextProtocol.csproj" />
<ProjectReference Include="..\..\src\ModelContextProtocol.Core\ModelContextProtocol.Core.csproj" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.DependencyInjection.Extensions;
using ModelContextProtocol.AspNetCore;
using ModelContextProtocol.Server;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<ItemGroup>
<None Include="README.md" pack="true" PackagePath="\" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\ModelContextProtocol\ModelContextProtocol.csproj" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,17 +57,13 @@ public SseClientTransport(SseClientTransportOptions transportOptions, HttpClient
/// <inheritdoc />
public async Task<ITransport> ConnectAsync(CancellationToken cancellationToken = default)
{
switch (_options.TransportMode)
return _options.TransportMode switch
{
case HttpTransportMode.AutoDetect:
return new AutoDetectingClientSessionTransport(_options, _httpClient, _loggerFactory, Name);
case HttpTransportMode.StreamableHttp:
return new StreamableHttpClientSessionTransport(Name, _options, _httpClient, messageChannel: null, _loggerFactory);
case HttpTransportMode.Sse:
return await ConnectSseTransportAsync(cancellationToken).ConfigureAwait(false);
default:
throw new InvalidOperationException($"Unsupported transport mode: {_options.TransportMode}");
}
HttpTransportMode.AutoDetect => new AutoDetectingClientSessionTransport(_options, _httpClient, _loggerFactory, Name),
HttpTransportMode.StreamableHttp => new StreamableHttpClientSessionTransport(Name, _options, _httpClient, messageChannel: null, _loggerFactory),
HttpTransportMode.Sse => await ConnectSseTransportAsync(cancellationToken).ConfigureAwait(false),
_ => throw new InvalidOperationException($"Unsupported transport mode: {_options.TransportMode}"),
};
}

private async Task<ITransport> ConnectSseTransportAsync(CancellationToken cancellationToken)
Expand Down
46 changes: 46 additions & 0 deletions src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net9.0;net8.0;netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<IsPackable>true</IsPackable>
<PackageId>ModelContextProtocol.Core</PackageId>
<Description>Core .NET SDK for the Model Context Protocol (MCP)</Description>
<PackageReadmeFile>README.md</PackageReadmeFile>
<LangVersion>preview</LangVersion>
</PropertyGroup>

<PropertyGroup Condition="'$(TargetFramework)' != 'netstandard2.0'">
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\Common\Throw.cs" Link="Throw.cs" />
</ItemGroup>

<!-- Dependencies only needed by netstandard2.0 -->
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Compile Include="..\Common\Polyfills\**\*.cs" />
<PackageReference Include="Microsoft.Bcl.Memory" />
<PackageReference Include="System.Diagnostics.DiagnosticSource" />
<PackageReference Include="System.Text.Json" />
<PackageReference Include="System.Threading.Channels" />
</ItemGroup>

<!-- Dependencies only needed by netstandard2.0 or net8.0 -->
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'net8.0'">
<PackageReference Include="System.IO.Pipelines" />
</ItemGroup>

<!-- Dependencies needed by all -->
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.AI.Abstractions" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" />
<PackageReference Include="System.Net.ServerSentEvents" />
</ItemGroup>

<ItemGroup>
<None Include="README.md" pack="true" PackagePath="\" />
</ItemGroup>

</Project>
112 changes: 112 additions & 0 deletions src/ModelContextProtocol.Core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
# MCP C# SDK Core

[![NuGet preview version](https://img.shields.io/nuget/vpre/ModelContextProtocol.Core.svg)](https://www.nuget.org/packages/ModelContextProtocol.Core/absoluteLatest)

Core .NET SDK for the [Model Context Protocol](https://modelcontextprotocol.io/), enabling .NET applications, services, and libraries to implement and interact with MCP clients and servers. Please visit our [API documentation](https://modelcontextprotocol.github.io/csharp-sdk/api/ModelContextProtocol.html) for more details on available functionality.

> [!NOTE]
> This project is in preview; 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:

- [Official Documentation](https://modelcontextprotocol.io/)
- [Protocol Specification](https://spec.modelcontextprotocol.io/)
- [GitHub Organization](https://github.com/modelcontextprotocol)

## Installation

To get started, install the core package from NuGet

```
dotnet add package ModelContextProtocol.Core --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.

```csharp
var clientTransport = new StdioClientTransport(new StdioClientTransportOptions
{
Name = "Everything",
Command = "npx",
Arguments = ["-y", "@modelcontextprotocol/server-everything"],
});

var client = await McpClientFactory.CreateAsync(clientTransport);

// Print the list of tools available from the server.
foreach (var tool in await 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 Dictionary<string, object?>() { ["message"] = "Hello MCP!" },
cancellationToken:CancellationToken.None);

// echo always returns one and only one text content object
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);
```

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 easily exposed for immediate use by `IChatClient`s, because `McpClientTool` inherits from `AIFunction`.

```csharp
// Get available functions.
IList<McpClientTool> tools = await client.ListToolsAsync();

// Call the chat client using the tools.
IChatClient chatClient = ...;
var response = await chatClient.GetResponseAsync(
"your prompt here",
new() { Tools = [.. tools] },
```

## Getting Started (Server)

The core package provides the basic server functionality. Here's an example of creating a simple MCP server without dependency injection:

```csharp
using ModelContextProtocol.Server;
using System.ComponentModel;

// Create server options
var serverOptions = new McpServerOptions();

// Add tools directly
serverOptions.Capabilities.Tools = new()
{
ListChanged = true,
ToolCollection = [
McpServerTool.Create((string message) => $"hello {message}", new()
{
Name = "echo",
Description = "Echoes the message back to the client."
})
]
};

// Create and run server with stdio transport
var server = new McpServer(serverOptions);
using var stdioTransport = new StdioServerTransport();
await server.RunAsync(stdioTransport, CancellationToken.None);
```

For more advanced scenarios with dependency injection, hosting, and automatic tool discovery, see the `ModelContextProtocol` package.

## Acknowledgements

The MCP C# SDK builds upon the excellent work from the [mcpdotnet](https://github.com/ReallyLiri/mcpdotnet) project by [Liri](https://github.com/ReallyLiri). We extend our gratitude for providing a foundational implementation that inspired this SDK.

## License

This project is licensed under the MIT License. See the [LICENSE](../../LICENSE) file for details.
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,7 @@ namespace ModelContextProtocol.Server;
/// <para>
/// Most commonly, <see cref="McpServerPrompt"/> instances are created using the static <see cref="M:McpServerPrompt.Create"/> methods.
/// These methods enable creating an <see cref="McpServerPrompt"/> for a method, specified via a <see cref="Delegate"/> or
/// <see cref="MethodInfo"/>, and are what are used implicitly by <see cref="McpServerBuilderExtensions.WithPromptsFromAssembly"/> and
/// <see cref="M:McpServerBuilderExtensions.WithPrompts"/>. The <see cref="M:McpServerPrompt.Create"/> methods
/// <see cref="MethodInfo"/>, and are what are used implicitly by WithPromptsFromAssembly and WithPrompts. The <see cref="M:McpServerPrompt.Create"/> methods
/// create <see cref="McpServerPrompt"/> instances capable of working with a large variety of .NET method signatures, automatically handling
/// how parameters are marshaled into the method from the JSON received from the MCP client, and how the return value is marshaled back
/// into the <see cref="GetPromptResult"/> that's then serialized and sent back to the client.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace ModelContextProtocol.Server;
/// <remarks>
/// <para>
/// This attribute is applied to methods that should be exposed as prompts in the Model Context Protocol. When a class
/// containing methods marked with this attribute is registered with <see cref="McpServerBuilderExtensions"/>,
/// containing methods marked with this attribute is registered with McpServerBuilderExtensions,
/// these methods become available as prompts that can be called by MCP clients.
/// </para>
/// <para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ namespace ModelContextProtocol.Server;
/// <para>
/// This attribute is used to mark a class containing methods that should be automatically
/// discovered and registered as <see cref="McpServerPrompt"/>s. When combined with discovery methods like
/// <see cref="McpServerBuilderExtensions.WithPromptsFromAssembly"/>, it enables automatic registration
/// of prompts without explicitly listing each prompt class. The attribute is not necessary when a reference
/// to the type is provided directly to a method like <see cref="McpServerBuilderExtensions.WithPrompts{T}"/>.
/// WithPromptsFromAssembly, it enables automatic registration of prompts without explicitly listing each prompt class.
/// The attribute is not necessary when a reference to the type is provided directly to a method like WithPrompts.
/// </para>
/// <para>
/// Within a class marked with this attribute, individual methods that should be exposed as
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace ModelContextProtocol.Server;
/// <para>
/// Most commonly, <see cref="McpServerResource"/> instances are created using the static <see cref="M:McpServerResource.Create"/> methods.
/// These methods enable creating an <see cref="McpServerResource"/> for a method, specified via a <see cref="Delegate"/> or
/// <see cref="MethodInfo"/>, and are what are used implicitly by <see cref="McpServerBuilderExtensions.WithResourcesFromAssembly"/> and
/// <see cref="MethodInfo"/>, and are what are used implicitly by WithResourcesFromAssembly and
/// <see cref="M:McpServerBuilderExtensions.WithResources"/>. The <see cref="M:McpServerResource.Create"/> methods
/// create <see cref="McpServerResource"/> instances capable of working with a large variety of .NET method signatures, automatically handling
/// how parameters are marshaled into the method from the URI received from the MCP client, and how the return value is marshaled back
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace ModelContextProtocol.Server;
/// <remarks>
/// <para>
/// This attribute is applied to methods or properties that should be exposed as resources in the Model Context Protocol. When a class
/// containing methods marked with this attribute is registered with <see cref="McpServerBuilderExtensions"/>,
/// containing methods marked with this attribute is registered with McpServerBuilderExtensions,
/// these methods or properties become available as resources that can be called by MCP clients.
/// </para>
/// <para>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ namespace ModelContextProtocol.Server;
/// <para>
/// This attribute is used to mark a class containing members that should be automatically
/// discovered and registered as <see cref="McpServerResource"/>s. When combined with discovery methods like
/// <see cref="McpServerBuilderExtensions.WithResourcesFromAssembly"/>, it enables automatic registration
/// of resources without explicitly listing each resource class. The attribute is not necessary when a reference
/// to the type is provided directly to a method like <see cref="McpServerBuilderExtensions.WithResources{T}"/>.
/// WithResourcesFromAssembly, it enables automatic registration of resources without explicitly listing each
/// resource class. The attribute is not necessary when a reference to the type is provided directly to a method
/// like McpServerBuilderExtensions.WithResources.
/// </para>
/// <para>
/// Within a class marked with this attribute, individual members that should be exposed as
Expand Down
Loading
Loading