Skip to content

Commit e06f0c1

Browse files
committed
Remove the hosting and options dependencies from the ModelContextProtocol package
1 parent 63df451 commit e06f0c1

26 files changed

+99
-123
lines changed

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
<!-- Product dependencies netstandard -->
99
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
1010
<PackageVersion Include="Microsoft.Bcl.Memory" Version="9.0.4" />
11-
<PackageVersion Include="Microsoft.Extensions.Hosting.Abstractions" Version="8.0.0" />
1211
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.3" />
1312
<PackageVersion Include="System.IO.Pipelines" Version="8.0.0" />
1413
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
1514
<PackageVersion Include="System.Threading.Channels" Version="8.0.0" />
15+
<PackageVersion Include="System.Diagnostics.DiagnosticSource" Version="9.0.1" />
1616
</ItemGroup>
1717

1818
<!-- Product dependencies LTS -->

samples/EverythingServer/EverythingServer.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
</ItemGroup>
1616

1717
<ItemGroup>
18-
<ProjectReference Include="..\..\src\ModelContextProtocol\ModelContextProtocol.csproj" />
18+
<ProjectReference Include="..\..\src\ModelContextProtocol.AspNetCore\ModelContextProtocol.AspNetCore.csproj" />
1919
</ItemGroup>
2020

2121
</Project>

samples/QuickstartWeatherServer/QuickstartWeatherServer.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
</ItemGroup>
1414

1515
<ItemGroup>
16-
<ProjectReference Include="..\..\src\ModelContextProtocol\ModelContextProtocol.csproj" />
16+
<ProjectReference Include="..\..\src\ModelContextProtocol.AspNetCore\ModelContextProtocol.AspNetCore.csproj" />
1717
</ItemGroup>
1818

1919
</Project>

samples/TestServerWithHosting/TestServerWithHosting.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<OutputType>Exe</OutputType>
5-
<TargetFrameworks>net9.0;net8.0;net472</TargetFrameworks>
5+
<TargetFrameworks>net9.0;net8.0</TargetFrameworks>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<Nullable>enable</Nullable>
88
<!--
@@ -23,7 +23,7 @@
2323
</ItemGroup>
2424

2525
<ItemGroup>
26-
<ProjectReference Include="..\..\src\ModelContextProtocol\ModelContextProtocol.csproj" />
26+
<ProjectReference Include="..\..\src\ModelContextProtocol.AspNetCore\ModelContextProtocol.AspNetCore.csproj" />
2727
</ItemGroup>
2828

2929
</Project>

src/ModelContextProtocol/Configuration/DefaultMcpServerBuilder.cs renamed to src/ModelContextProtocol.AspNetCore/Configuration/DefaultMcpServerBuilder.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
using ModelContextProtocol;
2-
31
namespace Microsoft.Extensions.DependencyInjection;
42

53
/// <summary>
@@ -21,7 +19,7 @@ internal sealed class DefaultMcpServerBuilder : IMcpServerBuilder
2119
/// <exception cref="ArgumentNullException">Thrown when <paramref name="services"/> is null.</exception>
2220
public DefaultMcpServerBuilder(IServiceCollection services)
2321
{
24-
Throw.IfNull(services);
22+
ArgumentNullException.ThrowIfNull(services);
2523

2624
Services = services;
2725
}

src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs renamed to src/ModelContextProtocol.AspNetCore/Configuration/McpServerBuilderExtensions.cs

Lines changed: 68 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
using Microsoft.Extensions.DependencyInjection.Extensions;
22
using Microsoft.Extensions.Logging;
33
using Microsoft.Extensions.Options;
4-
using ModelContextProtocol;
4+
using ModelContextProtocol.AspNetCore;
5+
using ModelContextProtocol.AspNetCore.Configuration;
56
using ModelContextProtocol.Protocol;
67
using ModelContextProtocol.Server;
78
using System.Diagnostics.CodeAnalysis;
@@ -38,7 +39,7 @@ public static partial class McpServerBuilderExtensions
3839
this IMcpServerBuilder builder,
3940
JsonSerializerOptions? serializerOptions = null)
4041
{
41-
Throw.IfNull(builder);
42+
ArgumentNullException.ThrowIfNull(builder);
4243

4344
foreach (var toolMethod in typeof(TToolType).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
4445
{
@@ -61,8 +62,8 @@ public static partial class McpServerBuilderExtensions
6162
/// <exception cref="ArgumentNullException"><paramref name="tools"/> is <see langword="null"/>.</exception>
6263
public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, IEnumerable<McpServerTool> tools)
6364
{
64-
Throw.IfNull(builder);
65-
Throw.IfNull(tools);
65+
ArgumentNullException.ThrowIfNull(builder);
66+
ArgumentNullException.ThrowIfNull(tools);
6667

6768
foreach (var tool in tools)
6869
{
@@ -90,8 +91,8 @@ public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, IEnume
9091
[RequiresUnreferencedCode(WithToolsRequiresUnreferencedCodeMessage)]
9192
public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, IEnumerable<Type> toolTypes, JsonSerializerOptions? serializerOptions = null)
9293
{
93-
Throw.IfNull(builder);
94-
Throw.IfNull(toolTypes);
94+
ArgumentNullException.ThrowIfNull(builder);
95+
ArgumentNullException.ThrowIfNull(toolTypes);
9596

9697
foreach (var toolType in toolTypes)
9798
{
@@ -143,7 +144,7 @@ public static IMcpServerBuilder WithTools(this IMcpServerBuilder builder, IEnume
143144
[RequiresUnreferencedCode(WithToolsRequiresUnreferencedCodeMessage)]
144145
public static IMcpServerBuilder WithToolsFromAssembly(this IMcpServerBuilder builder, Assembly? toolAssembly = null, JsonSerializerOptions? serializerOptions = null)
145146
{
146-
Throw.IfNull(builder);
147+
ArgumentNullException.ThrowIfNull(builder);
147148

148149
toolAssembly ??= Assembly.GetCallingAssembly();
149150

@@ -178,7 +179,7 @@ where t.GetCustomAttribute<McpServerToolTypeAttribute>() is not null
178179
this IMcpServerBuilder builder,
179180
JsonSerializerOptions? serializerOptions = null)
180181
{
181-
Throw.IfNull(builder);
182+
ArgumentNullException.ThrowIfNull(builder);
182183

183184
foreach (var promptMethod in typeof(TPromptType).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
184185
{
@@ -201,8 +202,8 @@ where t.GetCustomAttribute<McpServerToolTypeAttribute>() is not null
201202
/// <exception cref="ArgumentNullException"><paramref name="prompts"/> is <see langword="null"/>.</exception>
202203
public static IMcpServerBuilder WithPrompts(this IMcpServerBuilder builder, IEnumerable<McpServerPrompt> prompts)
203204
{
204-
Throw.IfNull(builder);
205-
Throw.IfNull(prompts);
205+
ArgumentNullException.ThrowIfNull(builder);
206+
ArgumentNullException.ThrowIfNull(prompts);
206207

207208
foreach (var prompt in prompts)
208209
{
@@ -230,8 +231,8 @@ public static IMcpServerBuilder WithPrompts(this IMcpServerBuilder builder, IEnu
230231
[RequiresUnreferencedCode(WithPromptsRequiresUnreferencedCodeMessage)]
231232
public static IMcpServerBuilder WithPrompts(this IMcpServerBuilder builder, IEnumerable<Type> promptTypes, JsonSerializerOptions? serializerOptions = null)
232233
{
233-
Throw.IfNull(builder);
234-
Throw.IfNull(promptTypes);
234+
ArgumentNullException.ThrowIfNull(builder);
235+
ArgumentNullException.ThrowIfNull(promptTypes);
235236

236237
foreach (var promptType in promptTypes)
237238
{
@@ -283,7 +284,7 @@ public static IMcpServerBuilder WithPrompts(this IMcpServerBuilder builder, IEnu
283284
[RequiresUnreferencedCode(WithPromptsRequiresUnreferencedCodeMessage)]
284285
public static IMcpServerBuilder WithPromptsFromAssembly(this IMcpServerBuilder builder, Assembly? promptAssembly = null, JsonSerializerOptions? serializerOptions = null)
285286
{
286-
Throw.IfNull(builder);
287+
ArgumentNullException.ThrowIfNull(builder);
287288

288289
promptAssembly ??= Assembly.GetCallingAssembly();
289290

@@ -315,7 +316,7 @@ where t.GetCustomAttribute<McpServerPromptTypeAttribute>() is not null
315316
DynamicallyAccessedMemberTypes.PublicConstructors)] TResourceType>(
316317
this IMcpServerBuilder builder)
317318
{
318-
Throw.IfNull(builder);
319+
ArgumentNullException.ThrowIfNull(builder);
319320

320321
foreach (var resourceTemplateMethod in typeof(TResourceType).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance))
321322
{
@@ -338,8 +339,8 @@ where t.GetCustomAttribute<McpServerPromptTypeAttribute>() is not null
338339
/// <exception cref="ArgumentNullException"><paramref name="resourceTemplates"/> is <see langword="null"/>.</exception>
339340
public static IMcpServerBuilder WithResources(this IMcpServerBuilder builder, IEnumerable<McpServerResource> resourceTemplates)
340341
{
341-
Throw.IfNull(builder);
342-
Throw.IfNull(resourceTemplates);
342+
ArgumentNullException.ThrowIfNull(builder);
343+
ArgumentNullException.ThrowIfNull(resourceTemplates);
343344

344345
foreach (var resourceTemplate in resourceTemplates)
345346
{
@@ -366,8 +367,8 @@ public static IMcpServerBuilder WithResources(this IMcpServerBuilder builder, IE
366367
[RequiresUnreferencedCode(WithResourcesRequiresUnreferencedCodeMessage)]
367368
public static IMcpServerBuilder WithResources(this IMcpServerBuilder builder, IEnumerable<Type> resourceTemplateTypes)
368369
{
369-
Throw.IfNull(builder);
370-
Throw.IfNull(resourceTemplateTypes);
370+
ArgumentNullException.ThrowIfNull(builder);
371+
ArgumentNullException.ThrowIfNull(resourceTemplateTypes);
371372

372373
foreach (var resourceTemplateType in resourceTemplateTypes)
373374
{
@@ -418,7 +419,7 @@ public static IMcpServerBuilder WithResources(this IMcpServerBuilder builder, IE
418419
[RequiresUnreferencedCode(WithResourcesRequiresUnreferencedCodeMessage)]
419420
public static IMcpServerBuilder WithResourcesFromAssembly(this IMcpServerBuilder builder, Assembly? resourceAssembly = null)
420421
{
421-
Throw.IfNull(builder);
422+
ArgumentNullException.ThrowIfNull(builder);
422423

423424
resourceAssembly ??= Assembly.GetCallingAssembly();
424425

@@ -453,7 +454,7 @@ where t.GetCustomAttribute<McpServerResourceTypeAttribute>() is not null
453454
/// </remarks>
454455
public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServerBuilder builder, Func<RequestContext<ListResourceTemplatesRequestParams>, CancellationToken, ValueTask<ListResourceTemplatesResult>> handler)
455456
{
456-
Throw.IfNull(builder);
457+
ArgumentNullException.ThrowIfNull(builder);
457458

458459
builder.Services.Configure<McpServerHandlers>(s => s.ListResourceTemplatesHandler = handler);
459460
return builder;
@@ -486,7 +487,7 @@ public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServer
486487
/// </remarks>
487488
public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder builder, Func<RequestContext<ListToolsRequestParams>, CancellationToken, ValueTask<ListToolsResult>> handler)
488489
{
489-
Throw.IfNull(builder);
490+
ArgumentNullException.ThrowIfNull(builder);
490491

491492
builder.Services.Configure<McpServerHandlers>(s => s.ListToolsHandler = handler);
492493
return builder;
@@ -506,7 +507,7 @@ public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder buil
506507
/// </remarks>
507508
public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder builder, Func<RequestContext<CallToolRequestParams>, CancellationToken, ValueTask<CallToolResponse>> handler)
508509
{
509-
Throw.IfNull(builder);
510+
ArgumentNullException.ThrowIfNull(builder);
510511

511512
builder.Services.Configure<McpServerHandlers>(s => s.CallToolHandler = handler);
512513
return builder;
@@ -539,7 +540,7 @@ public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder build
539540
/// </remarks>
540541
public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder builder, Func<RequestContext<ListPromptsRequestParams>, CancellationToken, ValueTask<ListPromptsResult>> handler)
541542
{
542-
Throw.IfNull(builder);
543+
ArgumentNullException.ThrowIfNull(builder);
543544

544545
builder.Services.Configure<McpServerHandlers>(s => s.ListPromptsHandler = handler);
545546
return builder;
@@ -554,7 +555,7 @@ public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder bu
554555
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
555556
public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder builder, Func<RequestContext<GetPromptRequestParams>, CancellationToken, ValueTask<GetPromptResult>> handler)
556557
{
557-
Throw.IfNull(builder);
558+
ArgumentNullException.ThrowIfNull(builder);
558559

559560
builder.Services.Configure<McpServerHandlers>(s => s.GetPromptHandler = handler);
560561
return builder;
@@ -575,7 +576,7 @@ public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder buil
575576
/// </remarks>
576577
public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<ListResourcesRequestParams>, CancellationToken, ValueTask<ListResourcesResult>> handler)
577578
{
578-
Throw.IfNull(builder);
579+
ArgumentNullException.ThrowIfNull(builder);
579580

580581
builder.Services.Configure<McpServerHandlers>(s => s.ListResourcesHandler = handler);
581582
return builder;
@@ -594,7 +595,7 @@ public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder
594595
/// </remarks>
595596
public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder builder, Func<RequestContext<ReadResourceRequestParams>, CancellationToken, ValueTask<ReadResourceResult>> handler)
596597
{
597-
Throw.IfNull(builder);
598+
ArgumentNullException.ThrowIfNull(builder);
598599

599600
builder.Services.Configure<McpServerHandlers>(s => s.ReadResourceHandler = handler);
600601
return builder;
@@ -613,7 +614,7 @@ public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder b
613614
/// </remarks>
614615
public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder builder, Func<RequestContext<CompleteRequestParams>, CancellationToken, ValueTask<CompleteResult>> handler)
615616
{
616-
Throw.IfNull(builder);
617+
ArgumentNullException.ThrowIfNull(builder);
617618

618619
builder.Services.Configure<McpServerHandlers>(s => s.CompleteHandler = handler);
619620
return builder;
@@ -643,7 +644,7 @@ public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder build
643644
/// </remarks>
644645
public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<SubscribeRequestParams>, CancellationToken, ValueTask<EmptyResult>> handler)
645646
{
646-
Throw.IfNull(builder);
647+
ArgumentNullException.ThrowIfNull(builder);
647648

648649
builder.Services.Configure<McpServerHandlers>(s => s.SubscribeToResourcesHandler = handler);
649650
return builder;
@@ -673,7 +674,7 @@ public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerB
673674
/// </remarks>
674675
public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<UnsubscribeRequestParams>, CancellationToken, ValueTask<EmptyResult>> handler)
675676
{
676-
Throw.IfNull(builder);
677+
ArgumentNullException.ThrowIfNull(builder);
677678

678679
builder.Services.Configure<McpServerHandlers>(s => s.UnsubscribeFromResourcesHandler = handler);
679680
return builder;
@@ -700,7 +701,7 @@ public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpSer
700701
/// </remarks>
701702
public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilder builder, Func<RequestContext<SetLevelRequestParams>, CancellationToken, ValueTask<EmptyResult>> handler)
702703
{
703-
Throw.IfNull(builder);
704+
ArgumentNullException.ThrowIfNull(builder);
704705

705706
builder.Services.Configure<McpServerHandlers>(s => s.SetLoggingLevelHandler = handler);
706707
return builder;
@@ -728,10 +729,15 @@ public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilde
728729
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
729730
public static IMcpServerBuilder WithStdioServerTransport(this IMcpServerBuilder builder)
730731
{
731-
Throw.IfNull(builder);
732+
ArgumentNullException.ThrowIfNull(builder);
732733

733734
AddSingleSessionServerDependencies(builder.Services);
734-
builder.Services.AddSingleton<ITransport, StdioServerTransport>();
735+
builder.Services.AddSingleton<ITransport>(sp =>
736+
{
737+
var serverOptions = sp.GetRequiredService<IOptions<McpServerOptions>>();
738+
var loggerFactory = sp.GetService<ILoggerFactory>();
739+
return new StdioServerTransport(serverOptions.Value, loggerFactory);
740+
});
735741

736742
return builder;
737743
}
@@ -751,16 +757,43 @@ public static IMcpServerBuilder WithStreamServerTransport(
751757
Stream inputStream,
752758
Stream outputStream)
753759
{
754-
Throw.IfNull(builder);
755-
Throw.IfNull(inputStream);
756-
Throw.IfNull(outputStream);
760+
ArgumentNullException.ThrowIfNull(builder);
761+
ArgumentNullException.ThrowIfNull(inputStream);
762+
ArgumentNullException.ThrowIfNull(outputStream);
757763

758764
AddSingleSessionServerDependencies(builder.Services);
759765
builder.Services.AddSingleton<ITransport>(new StreamServerTransport(inputStream, outputStream));
760766

761767
return builder;
762768
}
763769

770+
/// <summary>
771+
/// Adds the services necessary for <see cref="M:McpEndpointRouteBuilderExtensions.MapMcp"/>
772+
/// to handle MCP requests and sessions using the MCP Streamable HTTP transport. For more information on configuring the underlying HTTP server
773+
/// to control things like port binding custom TLS certificates, see the <see href="https://learn.microsoft.com/aspnet/core/fundamentals/minimal-apis">Minimal APIs quick reference</see>.
774+
/// </summary>
775+
/// <param name="builder">The builder instance.</param>
776+
/// <param name="configureOptions">Configures options for the Streamable HTTP transport. This allows configuring per-session
777+
/// <see cref="McpServerOptions"/> and running logic before and after a session.</param>
778+
/// <returns>The builder provided in <paramref name="builder"/>.</returns>
779+
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
780+
public static IMcpServerBuilder WithHttpTransport(this IMcpServerBuilder builder, Action<HttpServerTransportOptions>? configureOptions = null)
781+
{
782+
ArgumentNullException.ThrowIfNull(builder);
783+
784+
builder.Services.TryAddSingleton<StreamableHttpHandler>();
785+
builder.Services.TryAddSingleton<SseHandler>();
786+
builder.Services.AddHostedService<IdleTrackingBackgroundService>();
787+
builder.Services.AddDataProtection();
788+
789+
if (configureOptions is not null)
790+
{
791+
builder.Services.Configure(configureOptions);
792+
}
793+
794+
return builder;
795+
}
796+
764797
private static void AddSingleSessionServerDependencies(IServiceCollection services)
765798
{
766799
services.AddHostedService<SingleSessionMcpServerHostedService>();

src/ModelContextProtocol/Configuration/McpServerOptionsSetup.cs renamed to src/ModelContextProtocol.AspNetCore/Configuration/McpServerOptionsSetup.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
using Microsoft.Extensions.Options;
2-
using ModelContextProtocol;
32
using ModelContextProtocol.Server;
43

5-
namespace Microsoft.Extensions.DependencyInjection;
4+
namespace ModelContextProtocol.AspNetCore.Configuration;
65

76
/// <summary>
87
/// Configures the McpServerOptions using addition services from DI.
@@ -24,7 +23,7 @@ internal sealed class McpServerOptionsSetup(
2423
/// <param name="options">The options instance to be configured.</param>
2524
public void Configure(McpServerOptions options)
2625
{
27-
Throw.IfNull(options);
26+
ArgumentNullException.ThrowIfNull(options);
2827

2928
// Collect all of the provided tools into a tools collection. If the options already has
3029
// a collection, add to it, otherwise create a new one. We want to maintain the identity

src/ModelContextProtocol/Configuration/McpServerServiceCollectionExtensions.cs renamed to src/ModelContextProtocol.AspNetCore/Configuration/McpServerServiceCollectionExtensions.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using Microsoft.Extensions.DependencyInjection.Extensions;
22
using Microsoft.Extensions.Options;
3+
using ModelContextProtocol.AspNetCore.Configuration;
34
using ModelContextProtocol.Server;
45

56
namespace Microsoft.Extensions.DependencyInjection;

0 commit comments

Comments
 (0)