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