@@ -50,7 +50,7 @@ public static Task PingAsync(this IMcpClient client, CancellationToken cancellat
5050 parameters : null ,
5151 McpJsonUtilities . JsonContext . Default . Object ! ,
5252 McpJsonUtilities . JsonContext . Default . Object ,
53- cancellationToken : cancellationToken ) ;
53+ cancellationToken : cancellationToken ) . AsTask ( ) ;
5454 }
5555
5656 /// <summary>
@@ -92,7 +92,7 @@ public static Task PingAsync(this IMcpClient client, CancellationToken cancellat
9292 /// </code>
9393 /// </example>
9494 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
95- public static async Task < IList < McpClientTool > > ListToolsAsync (
95+ public static async ValueTask < IList < McpClientTool > > ListToolsAsync (
9696 this IMcpClient client ,
9797 JsonSerializerOptions ? serializerOptions = null ,
9898 CancellationToken cancellationToken = default )
@@ -205,7 +205,7 @@ public static async IAsyncEnumerable<McpClientTool> EnumerateToolsAsync(
205205 /// </para>
206206 /// </remarks>
207207 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
208- public static async Task < IList < McpClientPrompt > > ListPromptsAsync (
208+ public static async ValueTask < IList < McpClientPrompt > > ListPromptsAsync (
209209 this IMcpClient client , CancellationToken cancellationToken = default )
210210 {
211211 Throw . IfNull ( client ) ;
@@ -311,7 +311,7 @@ public static async IAsyncEnumerable<McpClientPrompt> EnumeratePromptsAsync(
311311 /// </remarks>
312312 /// <exception cref="McpException">Thrown when the prompt does not exist, when required arguments are missing, or when the server encounters an error processing the prompt.</exception>
313313 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
314- public static Task < GetPromptResult > GetPromptAsync (
314+ public static ValueTask < GetPromptResult > GetPromptAsync (
315315 this IMcpClient client ,
316316 string name ,
317317 IReadOnlyDictionary < string , object ? > ? arguments = null ,
@@ -349,12 +349,12 @@ public static Task<GetPromptResult> GetPromptAsync(
349349 /// </para>
350350 /// </remarks>
351351 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
352- public static async Task < IList < ResourceTemplate > > ListResourceTemplatesAsync (
352+ public static async ValueTask < IList < McpClientResourceTemplate > > ListResourceTemplatesAsync (
353353 this IMcpClient client , CancellationToken cancellationToken = default )
354354 {
355355 Throw . IfNull ( client ) ;
356356
357- List < ResourceTemplate > ? templates = null ;
357+ List < McpClientResourceTemplate > ? resourceTemplates = null ;
358358
359359 string ? cursor = null ;
360360 do
@@ -366,20 +366,17 @@ public static async Task<IList<ResourceTemplate>> ListResourceTemplatesAsync(
366366 McpJsonUtilities . JsonContext . Default . ListResourceTemplatesResult ,
367367 cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
368368
369- if ( templates is null )
370- {
371- templates = templateResults . ResourceTemplates ;
372- }
373- else
369+ resourceTemplates ??= new List < McpClientResourceTemplate > ( templateResults . ResourceTemplates . Count ) ;
370+ foreach ( var template in templateResults . ResourceTemplates )
374371 {
375- templates . AddRange ( templateResults . ResourceTemplates ) ;
372+ resourceTemplates . Add ( new McpClientResourceTemplate ( client , template ) ) ;
376373 }
377374
378375 cursor = templateResults . NextCursor ;
379376 }
380377 while ( cursor is not null ) ;
381378
382- return templates ;
379+ return resourceTemplates ;
383380 }
384381
385382 /// <summary>
@@ -395,7 +392,7 @@ public static async Task<IList<ResourceTemplate>> ListResourceTemplatesAsync(
395392 /// with cursors if the server responds with templates split across multiple responses.
396393 /// </para>
397394 /// <para>
398- /// Every iteration through the returned <see cref="IAsyncEnumerable{ResourceTemplate }"/>
395+ /// Every iteration through the returned <see cref="IAsyncEnumerable{McpClientResourceTemplate }"/>
399396 /// will result in re-querying the server and yielding the sequence of available resource templates.
400397 /// </para>
401398 /// </remarks>
@@ -409,7 +406,7 @@ public static async Task<IList<ResourceTemplate>> ListResourceTemplatesAsync(
409406 /// </code>
410407 /// </example>
411408 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
412- public static async IAsyncEnumerable < ResourceTemplate > EnumerateResourceTemplatesAsync (
409+ public static async IAsyncEnumerable < McpClientResourceTemplate > EnumerateResourceTemplatesAsync (
413410 this IMcpClient client , [ EnumeratorCancellation ] CancellationToken cancellationToken = default )
414411 {
415412 Throw . IfNull ( client ) ;
@@ -424,9 +421,9 @@ public static async IAsyncEnumerable<ResourceTemplate> EnumerateResourceTemplate
424421 McpJsonUtilities . JsonContext . Default . ListResourceTemplatesResult ,
425422 cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
426423
427- foreach ( var template in templateResults . ResourceTemplates )
424+ foreach ( var templateResult in templateResults . ResourceTemplates )
428425 {
429- yield return template ;
426+ yield return new McpClientResourceTemplate ( client , templateResult ) ;
430427 }
431428
432429 cursor = templateResults . NextCursor ;
@@ -463,12 +460,12 @@ public static async IAsyncEnumerable<ResourceTemplate> EnumerateResourceTemplate
463460 /// </code>
464461 /// </example>
465462 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
466- public static async Task < IList < Resource > > ListResourcesAsync (
463+ public static async ValueTask < IList < McpClientResource > > ListResourcesAsync (
467464 this IMcpClient client , CancellationToken cancellationToken = default )
468465 {
469466 Throw . IfNull ( client ) ;
470467
471- List < Resource > ? resources = null ;
468+ List < McpClientResource > ? resources = null ;
472469
473470 string ? cursor = null ;
474471 do
@@ -480,13 +477,10 @@ public static async Task<IList<Resource>> ListResourcesAsync(
480477 McpJsonUtilities . JsonContext . Default . ListResourcesResult ,
481478 cancellationToken : cancellationToken ) . ConfigureAwait ( false ) ;
482479
483- if ( resources is null )
484- {
485- resources = resourceResults . Resources ;
486- }
487- else
480+ resources ??= new List < McpClientResource > ( resourceResults . Resources . Count ) ;
481+ foreach ( var resource in resourceResults . Resources )
488482 {
489- resources . AddRange ( resourceResults . Resources ) ;
483+ resources . Add ( new McpClientResource ( client , resource ) ) ;
490484 }
491485
492486 cursor = resourceResults . NextCursor ;
@@ -509,7 +503,7 @@ public static async Task<IList<Resource>> ListResourcesAsync(
509503 /// with cursors if the server responds with resources split across multiple responses.
510504 /// </para>
511505 /// <para>
512- /// Every iteration through the returned <see cref="IAsyncEnumerable{Resource }"/>
506+ /// Every iteration through the returned <see cref="IAsyncEnumerable{McpClientResource }"/>
513507 /// will result in re-querying the server and yielding the sequence of available resources.
514508 /// </para>
515509 /// </remarks>
@@ -523,7 +517,7 @@ public static async Task<IList<Resource>> ListResourcesAsync(
523517 /// </code>
524518 /// </example>
525519 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
526- public static async IAsyncEnumerable < Resource > EnumerateResourcesAsync (
520+ public static async IAsyncEnumerable < McpClientResource > EnumerateResourcesAsync (
527521 this IMcpClient client , [ EnumeratorCancellation ] CancellationToken cancellationToken = default )
528522 {
529523 Throw . IfNull ( client ) ;
@@ -540,7 +534,7 @@ public static async IAsyncEnumerable<Resource> EnumerateResourcesAsync(
540534
541535 foreach ( var resource in resourceResults . Resources )
542536 {
543- yield return resource ;
537+ yield return new McpClientResource ( client , resource ) ;
544538 }
545539
546540 cursor = resourceResults . NextCursor ;
@@ -557,7 +551,7 @@ public static async IAsyncEnumerable<Resource> EnumerateResourcesAsync(
557551 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
558552 /// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
559553 /// <exception cref="ArgumentException"><paramref name="uri"/> is empty or composed entirely of whitespace.</exception>
560- public static Task < ReadResourceResult > ReadResourceAsync (
554+ public static ValueTask < ReadResourceResult > ReadResourceAsync (
561555 this IMcpClient client , string uri , CancellationToken cancellationToken = default )
562556 {
563557 Throw . IfNull ( client ) ;
@@ -579,7 +573,7 @@ public static Task<ReadResourceResult> ReadResourceAsync(
579573 /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
580574 /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
581575 /// <exception cref="ArgumentNullException"><paramref name="uri"/> is <see langword="null"/>.</exception>
582- public static Task < ReadResourceResult > ReadResourceAsync (
576+ public static ValueTask < ReadResourceResult > ReadResourceAsync (
583577 this IMcpClient client , Uri uri , CancellationToken cancellationToken = default )
584578 {
585579 Throw . IfNull ( client ) ;
@@ -588,6 +582,31 @@ public static Task<ReadResourceResult> ReadResourceAsync(
588582 return ReadResourceAsync ( client , uri . ToString ( ) , cancellationToken ) ;
589583 }
590584
585+ /// <summary>
586+ /// Reads a resource from the server.
587+ /// </summary>
588+ /// <param name="client">The client instance used to communicate with the MCP server.</param>
589+ /// <param name="uriTemplate">The uri template of the resource.</param>
590+ /// <param name="arguments">Arguments to use to format <paramref name="uriTemplate"/>.</param>
591+ /// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
592+ /// <exception cref="ArgumentNullException"><paramref name="client"/> is <see langword="null"/>.</exception>
593+ /// <exception cref="ArgumentNullException"><paramref name="uriTemplate"/> is <see langword="null"/>.</exception>
594+ /// <exception cref="ArgumentException"><paramref name="uriTemplate"/> is empty or composed entirely of whitespace.</exception>
595+ public static ValueTask < ReadResourceResult > ReadResourceAsync (
596+ this IMcpClient client , string uriTemplate , IReadOnlyDictionary < string , object ? > arguments , CancellationToken cancellationToken = default )
597+ {
598+ Throw . IfNull ( client ) ;
599+ Throw . IfNullOrWhiteSpace ( uriTemplate ) ;
600+ Throw . IfNull ( arguments ) ;
601+
602+ return client . SendRequestAsync (
603+ RequestMethods . ResourcesRead ,
604+ new ( ) { Uri = UriTemplate . FormatUri ( uriTemplate , arguments ) } ,
605+ McpJsonUtilities . JsonContext . Default . ReadResourceRequestParams ,
606+ McpJsonUtilities . JsonContext . Default . ReadResourceResult ,
607+ cancellationToken : cancellationToken ) ;
608+ }
609+
591610 /// <summary>
592611 /// Requests completion suggestions for a prompt argument or resource reference.
593612 /// </summary>
@@ -617,7 +636,7 @@ public static Task<ReadResourceResult> ReadResourceAsync(
617636 /// <exception cref="ArgumentNullException"><paramref name="argumentName"/> is <see langword="null"/>.</exception>
618637 /// <exception cref="ArgumentException"><paramref name="argumentName"/> is empty or composed entirely of whitespace.</exception>
619638 /// <exception cref="McpException">The server returned an error response.</exception>
620- public static Task < CompleteResult > CompleteAsync ( this IMcpClient client , Reference reference , string argumentName , string argumentValue , CancellationToken cancellationToken = default )
639+ public static ValueTask < CompleteResult > CompleteAsync ( this IMcpClient client , Reference reference , string argumentName , string argumentValue , CancellationToken cancellationToken = default )
621640 {
622641 Throw . IfNull ( client ) ;
623642 Throw . IfNull ( reference ) ;
@@ -675,7 +694,7 @@ public static Task SubscribeToResourceAsync(this IMcpClient client, string uri,
675694 new ( ) { Uri = uri } ,
676695 McpJsonUtilities . JsonContext . Default . SubscribeRequestParams ,
677696 McpJsonUtilities . JsonContext . Default . EmptyResult ,
678- cancellationToken : cancellationToken ) ;
697+ cancellationToken : cancellationToken ) . AsTask ( ) ;
679698 }
680699
681700 /// <summary>
@@ -744,7 +763,7 @@ public static Task UnsubscribeFromResourceAsync(this IMcpClient client, string u
744763 new ( ) { Uri = uri } ,
745764 McpJsonUtilities . JsonContext . Default . UnsubscribeRequestParams ,
746765 McpJsonUtilities . JsonContext . Default . EmptyResult ,
747- cancellationToken : cancellationToken ) ;
766+ cancellationToken : cancellationToken ) . AsTask ( ) ;
748767 }
749768
750769 /// <summary>
@@ -813,7 +832,7 @@ public static Task UnsubscribeFromResourceAsync(this IMcpClient client, Uri uri,
813832 /// });
814833 /// </code>
815834 /// </example>
816- public static Task < CallToolResponse > CallToolAsync (
835+ public static ValueTask < CallToolResponse > CallToolAsync (
817836 this IMcpClient client ,
818837 string toolName ,
819838 IReadOnlyDictionary < string , object ? > ? arguments = null ,
@@ -842,7 +861,7 @@ public static Task<CallToolResponse> CallToolAsync(
842861 McpJsonUtilities . JsonContext . Default . CallToolResponse ,
843862 cancellationToken : cancellationToken ) ;
844863
845- static async Task < CallToolResponse > SendRequestWithProgressAsync (
864+ static async ValueTask < CallToolResponse > SendRequestWithProgressAsync (
846865 IMcpClient client ,
847866 string toolName ,
848867 IReadOnlyDictionary < string , object ? > ? arguments ,
@@ -1061,7 +1080,7 @@ public static Task SetLoggingLevel(this IMcpClient client, LoggingLevel level, C
10611080 new ( ) { Level = level } ,
10621081 McpJsonUtilities . JsonContext . Default . SetLevelRequestParams ,
10631082 McpJsonUtilities . JsonContext . Default . EmptyResult ,
1064- cancellationToken : cancellationToken ) ;
1083+ cancellationToken : cancellationToken ) . AsTask ( ) ;
10651084 }
10661085
10671086 /// <summary>
0 commit comments