@@ -13,10 +13,17 @@ import { debug } from "./utils";
1313
1414type ToolName = string ;
1515
16+ export interface ChatCompletionInputMessageTool extends ChatCompletionInputMessage {
17+ role : "tool" ;
18+ tool_call_id : string ;
19+ content : string ;
20+ name ?: string ;
21+ }
22+
1623export class McpClient {
17- private client : InferenceClient ;
18- private provider : string ;
19- private model : string ;
24+ protected client : InferenceClient ;
25+ protected provider : string ;
26+ protected model : string ;
2027 private clients : Map < ToolName , Client > = new Map ( ) ;
2128 public readonly availableTools : ChatCompletionInputTool [ ] = [ ] ;
2229
@@ -62,13 +69,10 @@ export class McpClient {
6269 ) ;
6370 }
6471
65- async processQuery ( query : string ) : Promise < ChatCompletionOutput > {
66- const messages : ChatCompletionInputMessage [ ] = [
67- {
68- role : "user" ,
69- content : query ,
70- } ,
71- ] ;
72+ async * processSingleTurnWithTools (
73+ messages : ChatCompletionInputMessage [ ]
74+ ) : AsyncGenerator < ChatCompletionOutput | ChatCompletionInputMessageTool > {
75+ debug ( "start of single turn" ) ;
7276
7377 const response = await this . client . chatCompletion ( {
7478 provider : this . provider ,
@@ -80,43 +84,41 @@ export class McpClient {
8084
8185 const toolCalls = response . choices [ 0 ] . message . tool_calls ;
8286 if ( ! toolCalls || toolCalls . length === 0 ) {
83- return response ;
87+ messages . push ( {
88+ role : response . choices [ 0 ] . message . role ,
89+ content : response . choices [ 0 ] . message . content ,
90+ } ) ;
91+ return yield response ;
8492 }
8593 for ( const toolCall of toolCalls ) {
8694 const toolName = toolCall . function . name ;
8795 const toolArgs = JSON . parse ( toolCall . function . arguments ) ;
8896
97+ const message : ChatCompletionInputMessageTool = {
98+ role : "tool" ,
99+ tool_call_id : toolCall . id ,
100+ content : "" ,
101+ name : toolName ,
102+ } ;
89103 /// Get the appropriate session for this tool
90104 const client = this . clients . get ( toolName ) ;
91105 if ( client ) {
92106 const result = await client . callTool ( { name : toolName , arguments : toolArgs } ) ;
93- messages . push ( {
94- tool_call_id : toolCall . id ,
95- role : "tool" ,
96- name : toolName ,
97- content : ( result . content as Array < { text : string } > ) [ 0 ] . text ,
98- } ) ;
107+ message . content = ( result . content as Array < { text : string } > ) [ 0 ] . text ;
99108 } else {
100- messages . push ( {
101- tool_call_id : toolCall . id ,
102- role : "tool" ,
103- name : toolName ,
104- content : `Error: No session found for tool: ${ toolName } ` ,
105- } ) ;
109+ message . content = `Error: No session found for tool: ${ toolName } ` ;
106110 }
111+ messages . push ( message ) ;
112+ yield message ;
107113 }
108-
109- const enrichedResponse = await this . client . chatCompletion ( {
110- provider : this . provider ,
111- model : this . model ,
112- messages,
113- } ) ;
114-
115- return enrichedResponse ;
116114 }
117115
118116 async cleanup ( ) : Promise < void > {
119117 const clients = new Set ( this . clients . values ( ) ) ;
120118 await Promise . all ( [ ...clients ] . map ( ( client ) => client . close ( ) ) ) ;
121119 }
120+
121+ async [ Symbol . dispose ] ( ) : Promise < void > {
122+ return this . cleanup ( ) ;
123+ }
122124}
0 commit comments