Skip to content

Commit 4443cfc

Browse files
Merge main branch and resolve conflicts (PR #976 integration)
Co-authored-by: MackinnonBuck <[email protected]>
1 parent 2decb2d commit 4443cfc

File tree

71 files changed

+4803
-399
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+4803
-399
lines changed

.github/dependabot.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ updates:
1717
patterns:
1818
- "xunit.*"
1919
- "Microsoft.NET.Test.Sdk"
20-
- "Microsoft.Testing.*"
2120
- "coverlet.*"
2221
- "GitHubActionsTestLogger"
2322
- "Moq"

Directory.Build.props

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@
2929
</PropertyGroup>
3030

3131
<PropertyGroup>
32-
<UseMicrosoftTestingPlatformRunner>true</UseMicrosoftTestingPlatformRunner>
33-
<_MTPResultsDirectory>$(ArtifactsTestResultsDir)</_MTPResultsDirectory>
34-
<TestingPlatformCommandLineArguments>$(TestingPlatformCommandLineArguments) --results-directory $(_MTPResultsDirectory) --report-trx --report-trx-filename $(MSBuildProjectName).$(TargetFramework).$(OS).trx</TestingPlatformCommandLineArguments>
32+
<VSTestLogger Condition="'$(VSTestLogger)' == ''">trx%3bLogFileName=$(MSBuildProjectName).$(TargetFramework).$(OS).trx</VSTestLogger>
33+
<VSTestResultsDirectory Condition="'$(VSTestResultsDirectory)' == ''">$(ArtifactsTestResultsDir)</VSTestResultsDirectory>
3534
</PropertyGroup>
3635

3736
<PropertyGroup Condition="'$(GITHUB_ACTIONS)' == 'true'">

Directory.Packages.props

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
<System8Version>8.0.22</System8Version>
55
<System9Version>9.0.11</System9Version>
66
<System10Version>10.0.0</System10Version>
7-
<MicrosoftTestingPlatformVersion>2.0.2</MicrosoftTestingPlatformVersion>
87
</PropertyGroup>
98

109
<!-- Product dependencies shared -->
@@ -47,23 +46,33 @@
4746
<PackageVersion Include="Microsoft.IdentityModel.Tokens" Version="8.14.0" />
4847
</ItemGroup>
4948

49+
<!-- Source Generator & Analyzer dependencies -->
50+
<ItemGroup>
51+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.8.0" />
52+
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
53+
</ItemGroup>
54+
55+
<!-- Build Infra & Packaging dependencies-->
5056
<ItemGroup>
51-
<!-- Build Infra & Packaging -->
5257
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="8.0.0" />
58+
</ItemGroup>
5359

54-
<!-- Testing dependencies -->
60+
<!-- Testing dependencies -->
61+
<ItemGroup>
5562
<PackageVersion Include="Anthropic.SDK" Version="5.8.0" />
56-
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.1.0" />
57-
<PackageVersion Include="Microsoft.Testing.Extensions.HangDump" Version="$(MicrosoftTestingPlatformVersion)" />
58-
<PackageVersion Include="Microsoft.Testing.Extensions.CrashDump" Version="$(MicrosoftTestingPlatformVersion)" />
59-
<PackageVersion Include="Microsoft.Testing.Extensions.TrxReport" Version="$(MicrosoftTestingPlatformVersion)" />
63+
<PackageVersion Include="coverlet.collector" Version="6.0.4">
64+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
65+
<PrivateAssets>all</PrivateAssets>
66+
</PackageVersion>
67+
<PackageVersion Include="GitHubActionsTestLogger" Version="2.4.1" />
6068
<PackageVersion Include="Microsoft.Extensions.AI.OpenAI" Version="10.0.0-preview.1.25559.3" />
6169
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(System10Version)" />
6270
<PackageVersion Include="Microsoft.Extensions.Hosting" Version="$(System10Version)" />
6371
<PackageVersion Include="Microsoft.Extensions.Logging" Version="$(System10Version)" />
6472
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="$(System10Version)" />
6573
<PackageVersion Include="Microsoft.Extensions.Options" Version="$(System10Version)" />
6674
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="$(System10Version)" />
75+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
6776
<PackageVersion Include="Moq" Version="4.20.72" />
6877
<PackageVersion Include="OpenTelemetry" Version="1.14.0" />
6978
<PackageVersion Include="OpenTelemetry.Exporter.InMemory" Version="1.14.0" />
@@ -72,13 +81,14 @@
7281
<PackageVersion Include="OpenTelemetry.Extensions.Hosting" Version="1.14.0" />
7382
<PackageVersion Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.14.0" />
7483
<PackageVersion Include="Serilog.Extensions.Hosting" Version="9.0.0" />
75-
<PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.1" />
76-
<PackageVersion Include="Serilog.Sinks.Console" Version="6.0.0" />
84+
<PackageVersion Include="Serilog.Extensions.Logging" Version="9.0.2" />
85+
<PackageVersion Include="Serilog.Sinks.Console" Version="6.1.1" />
7786
<PackageVersion Include="Serilog.Sinks.Debug" Version="3.0.0" />
7887
<PackageVersion Include="Serilog.Sinks.File" Version="7.0.0" />
7988
<PackageVersion Include="Serilog" Version="4.3.0" />
8089
<PackageVersion Include="System.Linq.AsyncEnumerable" Version="$(System10Version)" />
81-
<PackageVersion Include="xunit.v3.mtp-v2" Version="3.2.0" />
90+
<PackageVersion Include="xunit.v3" Version="3.2.0" />
91+
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
8292
<PackageVersion Include="System.Net.Http" Version="4.3.4" />
8393
<PackageVersion Include="JsonSchema.Net" Version="7.4.0" />
8494
</ItemGroup>

Makefile

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@ build: restore
1818
test: build
1919
dotnet test \
2020
--no-build \
21-
--no-progress \
2221
--configuration $(CONFIGURATION) \
23-
--filter-not-trait 'Execution=Manual' \
24-
--crashdump \
25-
--hangdump \
26-
--hangdump-timeout 7m \
27-
--coverage \
28-
--coverage-output-format cobertura \
29-
-p:_MTPResultsDirectory=$(ARTIFACT_PATH)/testresults \
22+
--filter '(Execution!=Manual)' \
23+
--blame \
24+
--blame-crash \
25+
--blame-hang-timeout 7m \
26+
--diag "$(ARTIFACT_PATH)/diag.txt" \
27+
--logger "trx" \
28+
--logger "GitHubActions;summary.includePassedTests=true;summary.includeSkippedTests=true" \
29+
--collect "XPlat Code Coverage" \
30+
--results-directory $(ARTIFACT_PATH)/testresults \
31+
-- \
32+
RunConfiguration.CollectSourceInformation=true
3033

3134
pack: restore
3235
dotnet pack --no-restore --configuration $(CONFIGURATION)

ModelContextProtocol.slnx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,13 @@
6262
</Folder>
6363
<Folder Name="/src/">
6464
<File Path="src/Directory.Build.props" />
65+
<Project Path="src/ModelContextProtocol.Analyzers/ModelContextProtocol.Analyzers.csproj" />
6566
<Project Path="src/ModelContextProtocol.AspNetCore/ModelContextProtocol.AspNetCore.csproj" />
6667
<Project Path="src/ModelContextProtocol.Core/ModelContextProtocol.Core.csproj" />
6768
<Project Path="src/ModelContextProtocol/ModelContextProtocol.csproj" />
6869
</Folder>
6970
<Folder Name="/tests/">
71+
<Project Path="tests/ModelContextProtocol.Analyzers.Tests/ModelContextProtocol.Analyzers.Tests.csproj" />
7072
<Project Path="tests/ModelContextProtocol.AspNetCore.Tests/ModelContextProtocol.AspNetCore.Tests.csproj" />
7173
<Project Path="tests/ModelContextProtocol.TestOAuthServer/ModelContextProtocol.TestOAuthServer.csproj" />
7274
<Project Path="tests/ModelContextProtocol.Tests/ModelContextProtocol.Tests.csproj" />

README.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ To get started writing a client, the `McpClient.CreateAsync` method is used to i
4141
to a server. Once you have an `McpClient`, you can interact with it, such as to enumerate all available tools and invoke tools.
4242

4343
```csharp
44+
using ModelContextProtocol.Client;
45+
using ModelContextProtocol.Protocol;
46+
4447
var clientTransport = new StdioClientTransport(new StdioClientTransportOptions
4548
{
4649
Name = "Everything",
@@ -63,7 +66,7 @@ var result = await client.CallToolAsync(
6366
cancellationToken:CancellationToken.None);
6467

6568
// echo always returns one and only one text content object
66-
Console.WriteLine(result.Content.First(c => c.Type == "text").Text);
69+
Console.WriteLine(result.Content.OfType<TextContentBlock>().First().Text);
6770
```
6871

6972
You can find samples demonstrating how to use ModelContextProtocol with an LLM SDK in the [samples](samples) directory, and also refer to the [tests](tests/ModelContextProtocol.Tests) project for more examples. Additional examples and documentation will be added as in the near future.
@@ -225,6 +228,11 @@ await using McpServer server = McpServer.Create(new StdioServerTransport("MyServ
225228
await server.RunAsync();
226229
```
227230

231+
Descriptions can be added to tools, prompts, and resources in a variety of ways, including via the `[Description]` attribute from `System.ComponentModel`.
232+
This attribute may be placed on a method to provide for the tool, prompt, or resource, or on individual parameters to describe each's purpose.
233+
XML comments may also be used; if an `[McpServerTool]`, `[McpServerPrompt]`, or `[McpServerResource]`-attributed method is marked as `partial`,
234+
XML comments placed on the method will be used automatically to generate `[Description]` attributes for the method and its parameters.
235+
228236
## Acknowledgements
229237

230238
The starting point for this library was a project called [mcpdotnet](https://github.com/PederHP/mcpdotnet), initiated by [Peder Holdgaard Pedersen](https://github.com/PederHP). We are grateful for the work done by Peder and other contributors to that repository, which created a solid foundation for this library.

docs/concepts/elicitation/elicitation.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,16 @@ The C# SDK registers an instance of <xref:ModelContextProtocol.Server.McpServer>
1616
so tools can simply add a parameter of type <xref:ModelContextProtocol.Server.McpServer> to their method signature to access it.
1717

1818
The MCP Server must specify the schema of each input value it is requesting from the user.
19-
Only primitive types (string, number, boolean) are supported for elicitation requests.
19+
Primitive types (string, number, boolean) and enum types are supported for elicitation requests.
2020
The schema may include a description to help the user understand what is being requested.
2121

22+
For enum types, the SDK supports several schema formats:
23+
- **UntitledSingleSelectEnumSchema**: A single-select enum where the enum values serve as both the value and display text
24+
- **TitledSingleSelectEnumSchema**: A single-select enum with separate display titles for each option (using JSON Schema `oneOf` with `const` and `title`)
25+
- **UntitledMultiSelectEnumSchema**: A multi-select enum allowing multiple values to be selected
26+
- **TitledMultiSelectEnumSchema**: A multi-select enum with display titles for each option
27+
- **LegacyTitledEnumSchema** (deprecated): The legacy enum schema using `enumNames` for backward compatibility
28+
2229
The server can request a single input or multiple inputs at once.
2330
To help distinguish multiple inputs, each input has a unique name.
2431

docs/concepts/elicitation/samples/server/Tools/InteractiveTools.cs

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,152 @@ CancellationToken token
123123
}
124124
}
125125
}
126+
127+
// <snippet_EnumExamples>
128+
[McpServerTool, Description("Example tool demonstrating various enum schema types")]
129+
public async Task<string> EnumExamples(
130+
McpServer server,
131+
CancellationToken token
132+
)
133+
{
134+
// Example 1: UntitledSingleSelectEnumSchema - Simple enum without display titles
135+
var prioritySchema = new RequestSchema
136+
{
137+
Properties =
138+
{
139+
["Priority"] = new UntitledSingleSelectEnumSchema
140+
{
141+
Title = "Priority Level",
142+
Description = "Select the priority level",
143+
Enum = ["low", "medium", "high", "critical"],
144+
Default = "medium"
145+
}
146+
}
147+
};
148+
149+
var priorityResponse = await server.ElicitAsync(new ElicitRequestParams
150+
{
151+
Message = "Select a priority level:",
152+
RequestedSchema = prioritySchema
153+
}, token);
154+
155+
if (priorityResponse.Action != "accept")
156+
{
157+
return "Operation cancelled";
158+
}
159+
160+
string? priority = priorityResponse.Content?["Priority"].GetString();
161+
162+
// Example 2: TitledSingleSelectEnumSchema - Enum with custom display titles
163+
var severitySchema = new RequestSchema
164+
{
165+
Properties =
166+
{
167+
["Severity"] = new TitledSingleSelectEnumSchema
168+
{
169+
Title = "Issue Severity",
170+
Description = "Select the issue severity level",
171+
OneOf =
172+
[
173+
new EnumSchemaOption { Const = "p0", Title = "P0 - Critical (Immediate attention required)" },
174+
new EnumSchemaOption { Const = "p1", Title = "P1 - High (Urgent, within 24 hours)" },
175+
new EnumSchemaOption { Const = "p2", Title = "P2 - Medium (Within a week)" },
176+
new EnumSchemaOption { Const = "p3", Title = "P3 - Low (As time permits)" }
177+
],
178+
Default = "p2"
179+
}
180+
}
181+
};
182+
183+
var severityResponse = await server.ElicitAsync(new ElicitRequestParams
184+
{
185+
Message = "Select the issue severity:",
186+
RequestedSchema = severitySchema
187+
}, token);
188+
189+
if (severityResponse.Action != "accept")
190+
{
191+
return "Operation cancelled";
192+
}
193+
194+
string? severity = severityResponse.Content?["Severity"].GetString();
195+
196+
// Example 3: UntitledMultiSelectEnumSchema - Select multiple values
197+
var tagsSchema = new RequestSchema
198+
{
199+
Properties =
200+
{
201+
["Tags"] = new UntitledMultiSelectEnumSchema
202+
{
203+
Title = "Tags",
204+
Description = "Select one or more tags",
205+
MinItems = 1,
206+
MaxItems = 3,
207+
Items = new UntitledEnumItemsSchema
208+
{
209+
Type = "string",
210+
Enum = ["bug", "feature", "documentation", "enhancement", "question"]
211+
},
212+
Default = ["bug"]
213+
}
214+
}
215+
};
216+
217+
var tagsResponse = await server.ElicitAsync(new ElicitRequestParams
218+
{
219+
Message = "Select up to 3 tags:",
220+
RequestedSchema = tagsSchema
221+
}, token);
222+
223+
if (tagsResponse.Action != "accept")
224+
{
225+
return "Operation cancelled";
226+
}
227+
228+
// For multi-select, the value is an array
229+
var tags = tagsResponse.Content?["Tags"].EnumerateArray()
230+
.Select(e => e.GetString())
231+
.ToArray();
232+
233+
// Example 4: TitledMultiSelectEnumSchema - Multi-select with custom titles
234+
var featuresSchema = new RequestSchema
235+
{
236+
Properties =
237+
{
238+
["Features"] = new TitledMultiSelectEnumSchema
239+
{
240+
Title = "Features",
241+
Description = "Select desired features",
242+
Items = new TitledEnumItemsSchema
243+
{
244+
AnyOf =
245+
[
246+
new EnumSchemaOption { Const = "auth", Title = "Authentication & Authorization" },
247+
new EnumSchemaOption { Const = "api", Title = "RESTful API" },
248+
new EnumSchemaOption { Const = "ui", Title = "Modern UI Components" },
249+
new EnumSchemaOption { Const = "db", Title = "Database Integration" }
250+
]
251+
}
252+
}
253+
}
254+
};
255+
256+
var featuresResponse = await server.ElicitAsync(new ElicitRequestParams
257+
{
258+
Message = "Select desired features:",
259+
RequestedSchema = featuresSchema
260+
}, token);
261+
262+
if (featuresResponse.Action != "accept")
263+
{
264+
return "Operation cancelled";
265+
}
266+
267+
var features = featuresResponse.Content?["Features"].EnumerateArray()
268+
.Select(e => e.GetString())
269+
.ToArray();
270+
271+
return $"Selected: Priority={priority}, Severity={severity}, Tags=[{string.Join(", ", tags ?? [])}], Features=[{string.Join(", ", features ?? [])}]";
272+
}
273+
// </snippet_EnumExamples>
126274
}

docs/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ For more information about MCP:
1818

1919
For how-to guides, tutorials, and additional guidance, refer to the [official MCP documentation](https://modelcontextprotocol.io/).
2020

21+
## Official SDK packages
22+
23+
The official C# SDK packages for stable and pre-release versions are published to the [NuGet Gallery](https://www.nuget.org) under the [ModelContextProtocolOfficial](https://www.nuget.org/profiles/ModelContextProtocolOfficial) profile.
24+
25+
Continuous integration builds are published to the modelcontextprotocol organization's [GitHub NuGet package registry](https://github.com/orgs/modelcontextprotocol/packages?ecosystem=nuget).
26+
2127
## License
2228

2329
This project is licensed under the [MIT License](https://github.com/modelcontextprotocol/csharp-sdk/blob/main/LICENSE).

docs/toc.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,7 @@ items:
33
href: concepts/index.md
44
- name: API Reference
55
href: api/ModelContextProtocol.yml
6-
- name: Github
7-
href: https://github.com/ModelContextProtocol/csharp-sdk
6+
- name: Versioning
7+
href: versioning.md
8+
- name: GitHub
9+
href: https://github.com/ModelContextProtocol/csharp-sdk

0 commit comments

Comments
 (0)