44using ModelContextProtocol . Utils . Json ;
55using Microsoft . Extensions . AI ;
66using System . Text . Json ;
7+ using System . Runtime . CompilerServices ;
78
89namespace ModelContextProtocol . Client ;
910
@@ -45,25 +46,25 @@ public static Task PingAsync(this IMcpClient client, CancellationToken cancellat
4546 }
4647
4748 /// <summary>
48- /// Retrieves a sequence of available tools from the server.
49+ /// Retrieves a list of available tools from the server.
4950 /// </summary>
5051 /// <param name="client">The client.</param>
5152 /// <param name="cancellationToken">A token to cancel the operation.</param>
52- /// <returns>An asynchronous sequence of tool information .</returns>
53+ /// <returns>A list of all available tools .</returns>
5354 public static async Task < IList < McpClientTool > > ListToolsAsync (
5455 this IMcpClient client , CancellationToken cancellationToken = default )
5556 {
5657 Throw . IfNull ( client ) ;
5758
58- List < McpClientTool > tools = [ ] ;
59-
59+ List < McpClientTool > ? tools = null ;
6060 string ? cursor = null ;
6161 do
6262 {
6363 var toolResults = await client . SendRequestAsync < ListToolsResult > (
6464 CreateRequest ( "tools/list" , CreateCursorDictionary ( cursor ) ) ,
6565 cancellationToken ) . ConfigureAwait ( false ) ;
6666
67+ tools ??= new List < McpClientTool > ( toolResults . Tools . Count ) ;
6768 foreach ( var tool in toolResults . Tools )
6869 {
6970 tools . Add ( new McpClientTool ( client , tool ) ) ;
@@ -76,12 +77,44 @@ public static async Task<IList<McpClientTool>> ListToolsAsync(
7677 return tools ;
7778 }
7879
80+ /// <summary>
81+ /// Creates an enumerable for asynchronously enumerating all available tools from the server.
82+ /// </summary>
83+ /// <param name="client">The client.</param>
84+ /// <param name="cancellationToken">A token to cancel the operation.</param>
85+ /// <returns>An asynchronous sequence of all available tools.</returns>
86+ /// <remarks>
87+ /// Every iteration through the returned <see cref="IAsyncEnumerable{McpClientTool}"/>
88+ /// will result in requerying the server and yielding the sequence of available tools.
89+ /// </remarks>
90+ public static async IAsyncEnumerable < McpClientTool > EnumerateToolsAsync (
91+ this IMcpClient client , [ EnumeratorCancellation ] CancellationToken cancellationToken = default )
92+ {
93+ Throw . IfNull ( client ) ;
94+
95+ string ? cursor = null ;
96+ do
97+ {
98+ var toolResults = await client . SendRequestAsync < ListToolsResult > (
99+ CreateRequest ( "tools/list" , CreateCursorDictionary ( cursor ) ) ,
100+ cancellationToken ) . ConfigureAwait ( false ) ;
101+
102+ foreach ( var tool in toolResults . Tools )
103+ {
104+ yield return new McpClientTool ( client , tool ) ;
105+ }
106+
107+ cursor = toolResults . NextCursor ;
108+ }
109+ while ( cursor is not null ) ;
110+ }
111+
79112 /// <summary>
80113 /// Retrieves a list of available prompts from the server.
81114 /// </summary>
82115 /// <param name="client">The client.</param>
83116 /// <param name="cancellationToken">A token to cancel the operation.</param>
84- /// <returns>An asynchronous sequence of prompt information .</returns>
117+ /// <returns>A list of all available prompts .</returns>
85118 public static async Task < IList < Prompt > > ListPromptsAsync (
86119 this IMcpClient client , CancellationToken cancellationToken = default )
87120 {
@@ -112,6 +145,38 @@ public static async Task<IList<Prompt>> ListPromptsAsync(
112145 return prompts ;
113146 }
114147
148+ /// <summary>
149+ /// Creates an enumerable for asynchronously enumerating all available prompts from the server.
150+ /// </summary>
151+ /// <param name="client">The client.</param>
152+ /// <param name="cancellationToken">A token to cancel the operation.</param>
153+ /// <returns>An asynchronous sequence of all available prompts.</returns>
154+ /// <remarks>
155+ /// Every iteration through the returned <see cref="IAsyncEnumerable{Prompt}"/>
156+ /// will result in requerying the server and yielding the sequence of available prompts.
157+ /// </remarks>
158+ public static async IAsyncEnumerable < Prompt > EnumeratePromptsAsync (
159+ this IMcpClient client , [ EnumeratorCancellation ] CancellationToken cancellationToken = default )
160+ {
161+ Throw . IfNull ( client ) ;
162+
163+ string ? cursor = null ;
164+ do
165+ {
166+ var promptResults = await client . SendRequestAsync < ListPromptsResult > (
167+ CreateRequest ( "prompts/list" , CreateCursorDictionary ( cursor ) ) ,
168+ cancellationToken ) . ConfigureAwait ( false ) ;
169+
170+ foreach ( var prompt in promptResults . Prompts )
171+ {
172+ yield return prompt ;
173+ }
174+
175+ cursor = promptResults . NextCursor ;
176+ }
177+ while ( cursor is not null ) ;
178+ }
179+
115180 /// <summary>
116181 /// Retrieves a specific prompt with optional arguments.
117182 /// </summary>
@@ -132,11 +197,11 @@ public static Task<GetPromptResult> GetPromptAsync(
132197 }
133198
134199 /// <summary>
135- /// Retrieves a sequence of available resource templates from the server.
200+ /// Retrieves a list of available resource templates from the server.
136201 /// </summary>
137202 /// <param name="client">The client.</param>
138203 /// <param name="cancellationToken">A token to cancel the operation.</param>
139- /// <returns>An asynchronous sequence of resource template information .</returns>
204+ /// <returns>A list of all available resource templates .</returns>
140205 public static async Task < IList < ResourceTemplate > > ListResourceTemplatesAsync (
141206 this IMcpClient client , CancellationToken cancellationToken = default )
142207 {
@@ -168,11 +233,43 @@ public static async Task<IList<ResourceTemplate>> ListResourceTemplatesAsync(
168233 }
169234
170235 /// <summary>
171- /// Retrieves a sequence of available resources from the server.
236+ /// Creates an enumerable for asynchronously enumerating all available resource templates from the server.
237+ /// </summary>
238+ /// <param name="client">The client.</param>
239+ /// <param name="cancellationToken">A token to cancel the operation.</param>
240+ /// <returns>An asynchronous sequence of all available resource templates.</returns>
241+ /// <remarks>
242+ /// Every iteration through the returned <see cref="IAsyncEnumerable{ResourceTemplate}"/>
243+ /// will result in requerying the server and yielding the sequence of available resource templates.
244+ /// </remarks>
245+ public static async IAsyncEnumerable < ResourceTemplate > EnumerateResourceTemplatesAsync (
246+ this IMcpClient client , [ EnumeratorCancellation ] CancellationToken cancellationToken = default )
247+ {
248+ Throw . IfNull ( client ) ;
249+
250+ string ? cursor = null ;
251+ do
252+ {
253+ var templateResults = await client . SendRequestAsync < ListResourceTemplatesResult > (
254+ CreateRequest ( "resources/templates/list" , CreateCursorDictionary ( cursor ) ) ,
255+ cancellationToken ) . ConfigureAwait ( false ) ;
256+
257+ foreach ( var template in templateResults . ResourceTemplates )
258+ {
259+ yield return template ;
260+ }
261+
262+ cursor = templateResults . NextCursor ;
263+ }
264+ while ( cursor is not null ) ;
265+ }
266+
267+ /// <summary>
268+ /// Retrieves a list of available resources from the server.
172269 /// </summary>
173270 /// <param name="client">The client.</param>
174271 /// <param name="cancellationToken">A token to cancel the operation.</param>
175- /// <returns>An asynchronous sequence of resource information .</returns>
272+ /// <returns>A list of all available resources .</returns>
176273 public static async Task < IList < Resource > > ListResourcesAsync (
177274 this IMcpClient client , CancellationToken cancellationToken = default )
178275 {
@@ -203,6 +300,38 @@ public static async Task<IList<Resource>> ListResourcesAsync(
203300 return resources ;
204301 }
205302
303+ /// <summary>
304+ /// Creates an enumerable for asynchronously enumerating all available resources from the server.
305+ /// </summary>
306+ /// <param name="client">The client.</param>
307+ /// <param name="cancellationToken">A token to cancel the operation.</param>
308+ /// <returns>An asynchronous sequence of all available resources.</returns>
309+ /// <remarks>
310+ /// Every iteration through the returned <see cref="IAsyncEnumerable{Resource}"/>
311+ /// will result in requerying the server and yielding the sequence of available resources.
312+ /// </remarks>
313+ public static async IAsyncEnumerable < Resource > EnumerateResourcesAsync (
314+ this IMcpClient client , [ EnumeratorCancellation ] CancellationToken cancellationToken = default )
315+ {
316+ Throw . IfNull ( client ) ;
317+
318+ string ? cursor = null ;
319+ do
320+ {
321+ var resourceResults = await client . SendRequestAsync < ListResourcesResult > (
322+ CreateRequest ( "resources/list" , CreateCursorDictionary ( cursor ) ) ,
323+ cancellationToken ) . ConfigureAwait ( false ) ;
324+
325+ foreach ( var resource in resourceResults . Resources )
326+ {
327+ yield return resource ;
328+ }
329+
330+ cursor = resourceResults . NextCursor ;
331+ }
332+ while ( cursor is not null ) ;
333+ }
334+
206335 /// <summary>
207336 /// Reads a resource from the server.
208337 /// </summary>
0 commit comments