Skip to content

Commit da912e9

Browse files
committed
Change request/notification delegates to return ValueTask
1 parent fccff04 commit da912e9

Some content is hidden

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

43 files changed

+242
-238
lines changed

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ root = true
44
# C# files
55
[*.cs]
66

7+
# Compiler
8+
dotnet_diagnostic.CS1998.severity = suggestion # CS1998: Missing awaits
9+
710
# Code Analysis
811
dotnet_diagnostic.CA1002.severity = none # CA1002: Do not expose generic lists
912
dotnet_diagnostic.CA1031.severity = none # CA1031: Do not catch general exception types

samples/EverythingServer/Program.cs

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
using ModelContextProtocol.Protocol.Types;
1010
using ModelContextProtocol.Server;
1111

12+
#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously
13+
1214
var builder = Host.CreateApplicationBuilder(args);
1315
builder.Logging.AddConsole(consoleLogOptions =>
1416
{
@@ -31,17 +33,17 @@
3133
.WithTools<TinyImageTool>()
3234
.WithPrompts<ComplexPromptType>()
3335
.WithPrompts<SimplePromptType>()
34-
.WithListResourceTemplatesHandler((ctx, ct) =>
36+
.WithListResourceTemplatesHandler(async (ctx, ct) =>
3537
{
36-
return Task.FromResult(new ListResourceTemplatesResult
38+
return new ListResourceTemplatesResult
3739
{
3840
ResourceTemplates =
3941
[
4042
new ResourceTemplate { Name = "Static Resource", Description = "A static resource with a numeric ID", UriTemplate = "test://static/resource/{id}" }
4143
]
42-
});
44+
};
4345
})
44-
.WithReadResourceHandler((ctx, ct) =>
46+
.WithReadResourceHandler(async (ctx, ct) =>
4547
{
4648
var uri = ctx.Params?.Uri;
4749

@@ -61,27 +63,27 @@
6163

6264
if (resource.MimeType == "text/plain")
6365
{
64-
return Task.FromResult(new ReadResourceResult
66+
return new ReadResourceResult
6567
{
6668
Contents = [new TextResourceContents
6769
{
6870
Text = resource.Description!,
6971
MimeType = resource.MimeType,
7072
Uri = resource.Uri,
7173
}]
72-
});
74+
};
7375
}
7476
else
7577
{
76-
return Task.FromResult(new ReadResourceResult
78+
return new ReadResourceResult
7779
{
7880
Contents = [new BlobResourceContents
7981
{
8082
Blob = resource.Description!,
8183
MimeType = resource.MimeType,
8284
Uri = resource.Uri,
8385
}]
84-
});
86+
};
8587
}
8688
})
8789
.WithSubscribeToResourcesHandler(async (ctx, ct) =>
@@ -106,16 +108,16 @@ await ctx.Server.RequestSamplingAsync([
106108

107109
return new EmptyResult();
108110
})
109-
.WithUnsubscribeFromResourcesHandler((ctx, ct) =>
111+
.WithUnsubscribeFromResourcesHandler(async (ctx, ct) =>
110112
{
111113
var uri = ctx.Params?.Uri;
112114
if (uri is not null)
113115
{
114116
subscriptions.Remove(uri);
115117
}
116-
return Task.FromResult(new EmptyResult());
118+
return new EmptyResult();
117119
})
118-
.WithCompleteHandler((ctx, ct) =>
120+
.WithCompleteHandler(async (ctx, ct) =>
119121
{
120122
var exampleCompletions = new Dictionary<string, IEnumerable<string>>
121123
{
@@ -128,7 +130,7 @@ await ctx.Server.RequestSamplingAsync([
128130
{
129131
throw new NotSupportedException($"Params are required.");
130132
}
131-
133+
132134
var @ref = @params.Ref;
133135
var argument = @params.Argument;
134136

@@ -138,15 +140,15 @@ await ctx.Server.RequestSamplingAsync([
138140

139141
if (resourceId is null)
140142
{
141-
return Task.FromResult(new CompleteResult());
143+
return new CompleteResult();
142144
}
143145

144146
var values = exampleCompletions["resourceId"].Where(id => id.StartsWith(argument.Value));
145147

146-
return Task.FromResult(new CompleteResult
148+
return new CompleteResult
147149
{
148-
Completion = new Completion { Values = [..values], HasMore = false, Total = values.Count() }
149-
});
150+
Completion = new Completion { Values = [.. values], HasMore = false, Total = values.Count() }
151+
};
150152
}
151153

152154
if (@ref.Type == "ref/prompt")
@@ -157,10 +159,10 @@ await ctx.Server.RequestSamplingAsync([
157159
}
158160

159161
var values = value.Where(value => value.StartsWith(argument.Value));
160-
return Task.FromResult(new CompleteResult
162+
return new CompleteResult
161163
{
162-
Completion = new Completion { Values = [..values], HasMore = false, Total = values.Count() }
163-
});
164+
Completion = new Completion { Values = [.. values], HasMore = false, Total = values.Count() }
165+
};
164166
}
165167

166168
throw new NotSupportedException($"Unknown reference type: {@ref.Type}");
@@ -175,15 +177,14 @@ await ctx.Server.RequestSamplingAsync([
175177
_minimumLoggingLevel = ctx.Params.Level;
176178

177179
await ctx.Server.SendNotificationAsync("notifications/message", new
178-
{
179-
Level = "debug",
180-
Logger = "test-server",
181-
Data = $"Logging level set to {_minimumLoggingLevel}",
182-
}, cancellationToken: ct);
180+
{
181+
Level = "debug",
182+
Logger = "test-server",
183+
Data = $"Logging level set to {_minimumLoggingLevel}",
184+
}, cancellationToken: ct);
183185

184186
return new EmptyResult();
185-
})
186-
;
187+
});
187188

188189
builder.Services.AddSingleton(subscriptions);
189190
builder.Services.AddHostedService<SubscriptionMessageSender>();

src/ModelContextProtocol/Client/McpClientExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,7 @@ internal static CreateMessageResult ToCreateMessageResult(this ChatResponse chat
948948
/// </para>
949949
/// </remarks>
950950
/// <exception cref="ArgumentNullException"><paramref name="chatClient"/> is <see langword="null"/>.</exception>
951-
public static Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, Task<CreateMessageResult>> CreateSamplingHandler(
951+
public static Func<CreateMessageRequestParams?, IProgress<ProgressNotificationValue>, CancellationToken, ValueTask<CreateMessageResult>> CreateSamplingHandler(
952952
this IChatClient chatClient)
953953
{
954954
Throw.IfNull(chatClient);

src/ModelContextProtocol/Configuration/McpServerBuilderExtensions.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ where t.GetCustomAttribute<McpServerPromptTypeAttribute>() is not null
275275
/// resource system where templates define the URI patterns and the read handler provides the actual content.
276276
/// </para>
277277
/// </remarks>
278-
public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServerBuilder builder, Func<RequestContext<ListResourceTemplatesRequestParams>, CancellationToken, Task<ListResourceTemplatesResult>> handler)
278+
public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServerBuilder builder, Func<RequestContext<ListResourceTemplatesRequestParams>, CancellationToken, ValueTask<ListResourceTemplatesResult>> handler)
279279
{
280280
Throw.IfNull(builder);
281281

@@ -308,7 +308,7 @@ public static IMcpServerBuilder WithListResourceTemplatesHandler(this IMcpServer
308308
/// executes them when invoked by clients.
309309
/// </para>
310310
/// </remarks>
311-
public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder builder, Func<RequestContext<ListToolsRequestParams>, CancellationToken, Task<ListToolsResult>> handler)
311+
public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder builder, Func<RequestContext<ListToolsRequestParams>, CancellationToken, ValueTask<ListToolsResult>> handler)
312312
{
313313
Throw.IfNull(builder);
314314

@@ -328,7 +328,7 @@ public static IMcpServerBuilder WithListToolsHandler(this IMcpServerBuilder buil
328328
/// This method is typically paired with <see cref="WithListToolsHandler"/> to provide a complete tools implementation,
329329
/// where <see cref="WithListToolsHandler"/> advertises available tools and this handler executes them.
330330
/// </remarks>
331-
public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder builder, Func<RequestContext<CallToolRequestParams>, CancellationToken, Task<CallToolResponse>> handler)
331+
public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder builder, Func<RequestContext<CallToolRequestParams>, CancellationToken, ValueTask<CallToolResponse>> handler)
332332
{
333333
Throw.IfNull(builder);
334334

@@ -361,7 +361,7 @@ public static IMcpServerBuilder WithCallToolHandler(this IMcpServerBuilder build
361361
/// produces them when invoked by clients.
362362
/// </para>
363363
/// </remarks>
364-
public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder builder, Func<RequestContext<ListPromptsRequestParams>, CancellationToken, Task<ListPromptsResult>> handler)
364+
public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder builder, Func<RequestContext<ListPromptsRequestParams>, CancellationToken, ValueTask<ListPromptsResult>> handler)
365365
{
366366
Throw.IfNull(builder);
367367

@@ -376,7 +376,7 @@ public static IMcpServerBuilder WithListPromptsHandler(this IMcpServerBuilder bu
376376
/// <param name="handler">The handler function that processes prompt requests.</param>
377377
/// <returns>The builder provided in <paramref name="builder"/>.</returns>
378378
/// <exception cref="ArgumentNullException"><paramref name="builder"/> is <see langword="null"/>.</exception>
379-
public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder builder, Func<RequestContext<GetPromptRequestParams>, CancellationToken, Task<GetPromptResult>> handler)
379+
public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder builder, Func<RequestContext<GetPromptRequestParams>, CancellationToken, ValueTask<GetPromptResult>> handler)
380380
{
381381
Throw.IfNull(builder);
382382

@@ -397,7 +397,7 @@ public static IMcpServerBuilder WithGetPromptHandler(this IMcpServerBuilder buil
397397
/// where this handler advertises available resources and the read handler provides their content when requested.
398398
/// </para>
399399
/// </remarks>
400-
public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<ListResourcesRequestParams>, CancellationToken, Task<ListResourcesResult>> handler)
400+
public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<ListResourcesRequestParams>, CancellationToken, ValueTask<ListResourcesResult>> handler)
401401
{
402402
Throw.IfNull(builder);
403403

@@ -416,7 +416,7 @@ public static IMcpServerBuilder WithListResourcesHandler(this IMcpServerBuilder
416416
/// This handler is typically paired with <see cref="WithListResourcesHandler"/> to provide a complete resources implementation,
417417
/// where the list handler advertises available resources and the read handler provides their content when requested.
418418
/// </remarks>
419-
public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder builder, Func<RequestContext<ReadResourceRequestParams>, CancellationToken, Task<ReadResourceResult>> handler)
419+
public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder builder, Func<RequestContext<ReadResourceRequestParams>, CancellationToken, ValueTask<ReadResourceResult>> handler)
420420
{
421421
Throw.IfNull(builder);
422422

@@ -435,7 +435,7 @@ public static IMcpServerBuilder WithReadResourceHandler(this IMcpServerBuilder b
435435
/// The completion handler is invoked when clients request suggestions for argument values.
436436
/// This enables auto-complete functionality for both prompt arguments and resource references.
437437
/// </remarks>
438-
public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder builder, Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>> handler)
438+
public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder builder, Func<RequestContext<CompleteRequestParams>, CancellationToken, ValueTask<CompleteResult>> handler)
439439
{
440440
Throw.IfNull(builder);
441441

@@ -465,7 +465,7 @@ public static IMcpServerBuilder WithCompleteHandler(this IMcpServerBuilder build
465465
/// resources and to send appropriate notifications through the connection when resources change.
466466
/// </para>
467467
/// </remarks>
468-
public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<SubscribeRequestParams>, CancellationToken, Task<EmptyResult>> handler)
468+
public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<SubscribeRequestParams>, CancellationToken, ValueTask<EmptyResult>> handler)
469469
{
470470
Throw.IfNull(builder);
471471

@@ -495,7 +495,7 @@ public static IMcpServerBuilder WithSubscribeToResourcesHandler(this IMcpServerB
495495
/// to the specified resource.
496496
/// </para>
497497
/// </remarks>
498-
public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<UnsubscribeRequestParams>, CancellationToken, Task<EmptyResult>> handler)
498+
public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpServerBuilder builder, Func<RequestContext<UnsubscribeRequestParams>, CancellationToken, ValueTask<EmptyResult>> handler)
499499
{
500500
Throw.IfNull(builder);
501501

@@ -522,7 +522,7 @@ public static IMcpServerBuilder WithUnsubscribeFromResourcesHandler(this IMcpSer
522522
/// most recently set level.
523523
/// </para>
524524
/// </remarks>
525-
public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilder builder, Func<RequestContext<SetLevelRequestParams>, CancellationToken, Task<EmptyResult>> handler)
525+
public static IMcpServerBuilder WithSetLoggingLevelHandler(this IMcpServerBuilder builder, Func<RequestContext<SetLevelRequestParams>, CancellationToken, ValueTask<EmptyResult>> handler)
526526
{
527527
Throw.IfNull(builder);
528528

src/ModelContextProtocol/IMcpEndpoint.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,5 @@ public interface IMcpEndpoint : IAsyncDisposable
6969
/// <param name="method">The notification method.</param>
7070
/// <param name="handler">The handler to be invoked.</param>
7171
/// <returns>An <see cref="IDisposable"/> that will remove the registered handler when disposed.</returns>
72-
IAsyncDisposable RegisterNotificationHandler(string method, Func<JsonRpcNotification, CancellationToken, Task> handler);
72+
IAsyncDisposable RegisterNotificationHandler(string method, Func<JsonRpcNotification, CancellationToken, ValueTask> handler);
7373
}

src/ModelContextProtocol/Protocol/Types/ClientCapabilities.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,5 +77,5 @@ public class ClientCapabilities
7777
/// </para>
7878
/// </remarks>
7979
[JsonIgnore]
80-
public IEnumerable<KeyValuePair<string, Func<JsonRpcNotification, CancellationToken, Task>>>? NotificationHandlers { get; set; }
80+
public IEnumerable<KeyValuePair<string, Func<JsonRpcNotification, CancellationToken, ValueTask>>>? NotificationHandlers { get; set; }
8181
}

src/ModelContextProtocol/Protocol/Types/CompletionsCapability.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,5 @@ public class CompletionsCapability
3333
/// and should return appropriate completion suggestions.
3434
/// </remarks>
3535
[JsonIgnore]
36-
public Func<RequestContext<CompleteRequestParams>, CancellationToken, Task<CompleteResult>>? CompleteHandler { get; set; }
36+
public Func<RequestContext<CompleteRequestParams>, CancellationToken, ValueTask<CompleteResult>>? CompleteHandler { get; set; }
3737
}

src/ModelContextProtocol/Protocol/Types/EmptyResult.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@ namespace ModelContextProtocol.Protocol.Types;
99
public class EmptyResult
1010
{
1111
[JsonIgnore]
12-
internal static Task<EmptyResult> CompletedTask { get; } = Task.FromResult(new EmptyResult());
12+
internal static EmptyResult Instance { get; } = new();
1313
}

src/ModelContextProtocol/Protocol/Types/LoggingCapability.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,5 @@ public class LoggingCapability
1919
/// Gets or sets the handler for set logging level requests from clients.
2020
/// </summary>
2121
[JsonIgnore]
22-
public Func<RequestContext<SetLevelRequestParams>, CancellationToken, Task<EmptyResult>>? SetLoggingLevelHandler { get; set; }
22+
public Func<RequestContext<SetLevelRequestParams>, CancellationToken, ValueTask<EmptyResult>>? SetLoggingLevelHandler { get; set; }
2323
}

src/ModelContextProtocol/Protocol/Types/PromptsCapability.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public class PromptsCapability
4141
/// along with any prompts defined in <see cref="PromptCollection"/>.
4242
/// </remarks>
4343
[JsonIgnore]
44-
public Func<RequestContext<ListPromptsRequestParams>, CancellationToken, Task<ListPromptsResult>>? ListPromptsHandler { get; set; }
44+
public Func<RequestContext<ListPromptsRequestParams>, CancellationToken, ValueTask<ListPromptsResult>>? ListPromptsHandler { get; set; }
4545

4646
/// <summary>
4747
/// Gets or sets the handler for <see cref="RequestMethods.PromptsGet"/> requests.
@@ -58,7 +58,7 @@ public class PromptsCapability
5858
/// </para>
5959
/// </remarks>
6060
[JsonIgnore]
61-
public Func<RequestContext<GetPromptRequestParams>, CancellationToken, Task<GetPromptResult>>? GetPromptHandler { get; set; }
61+
public Func<RequestContext<GetPromptRequestParams>, CancellationToken, ValueTask<GetPromptResult>>? GetPromptHandler { get; set; }
6262

6363
/// <summary>
6464
/// Gets or sets a collection of prompts that will be served by the server.

src/ModelContextProtocol/Protocol/Types/ResourcesCapability.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ public class ResourcesCapability
4040
/// allowing clients to discover available resource types and their access patterns.
4141
/// </remarks>
4242
[JsonIgnore]
43-
public Func<RequestContext<ListResourceTemplatesRequestParams>, CancellationToken, Task<ListResourceTemplatesResult>>? ListResourceTemplatesHandler { get; set; }
43+
public Func<RequestContext<ListResourceTemplatesRequestParams>, CancellationToken, ValueTask<ListResourceTemplatesResult>>? ListResourceTemplatesHandler { get; set; }
4444

4545
/// <summary>
4646
/// Gets or sets the handler for <see cref="RequestMethods.ResourcesList"/> requests.
@@ -50,7 +50,7 @@ public class ResourcesCapability
5050
/// The implementation should return a <see cref="ListResourcesResult"/> with the matching resources.
5151
/// </remarks>
5252
[JsonIgnore]
53-
public Func<RequestContext<ListResourcesRequestParams>, CancellationToken, Task<ListResourcesResult>>? ListResourcesHandler { get; set; }
53+
public Func<RequestContext<ListResourcesRequestParams>, CancellationToken, ValueTask<ListResourcesResult>>? ListResourcesHandler { get; set; }
5454

5555
/// <summary>
5656
/// Gets or sets the handler for <see cref="RequestMethods.ResourcesRead"/> requests.
@@ -62,7 +62,7 @@ public class ResourcesCapability
6262
/// its contents in a ReadResourceResult object.
6363
/// </remarks>
6464
[JsonIgnore]
65-
public Func<RequestContext<ReadResourceRequestParams>, CancellationToken, Task<ReadResourceResult>>? ReadResourceHandler { get; set; }
65+
public Func<RequestContext<ReadResourceRequestParams>, CancellationToken, ValueTask<ReadResourceResult>>? ReadResourceHandler { get; set; }
6666

6767
/// <summary>
6868
/// Gets or sets the handler for <see cref="RequestMethods.ResourcesSubscribe"/> requests.
@@ -75,7 +75,7 @@ public class ResourcesCapability
7575
/// requiring polling.
7676
/// </remarks>
7777
[JsonIgnore]
78-
public Func<RequestContext<SubscribeRequestParams>, CancellationToken, Task<EmptyResult>>? SubscribeToResourcesHandler { get; set; }
78+
public Func<RequestContext<SubscribeRequestParams>, CancellationToken, ValueTask<EmptyResult>>? SubscribeToResourcesHandler { get; set; }
7979

8080
/// <summary>
8181
/// Gets or sets the handler for <see cref="RequestMethods.ResourcesUnsubscribe"/> requests.
@@ -86,5 +86,5 @@ public class ResourcesCapability
8686
/// about the specified resource.
8787
/// </remarks>
8888
[JsonIgnore]
89-
public Func<RequestContext<UnsubscribeRequestParams>, CancellationToken, Task<EmptyResult>>? UnsubscribeFromResourcesHandler { get; set; }
89+
public Func<RequestContext<UnsubscribeRequestParams>, CancellationToken, ValueTask<EmptyResult>>? UnsubscribeFromResourcesHandler { get; set; }
9090
}

src/ModelContextProtocol/Protocol/Types/RootsCapability.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,5 @@ public class RootsCapability
4141
/// The handler receives request parameters and should return a <see cref="ListRootsResult"/> containing the collection of available roots.
4242
/// </remarks>
4343
[JsonIgnore]
44-
public Func<ListRootsRequestParams?, CancellationToken, Task<ListRootsResult>>? RootsHandler { get; set; }
44+
public Func<ListRootsRequestParams?, CancellationToken, ValueTask<ListRootsResult>>? RootsHandler { get; set; }
4545
}

0 commit comments

Comments
 (0)