@@ -10,7 +10,7 @@ import readline from "readline/promises";
1010
1111import dotenv from "dotenv" ;
1212
13- dotenv . config ( ) ;
13+ dotenv . config ( ) ; // load environment variables from .env
1414
1515const ANTHROPIC_API_KEY = process . env . ANTHROPIC_API_KEY ;
1616if ( ! ANTHROPIC_API_KEY ) {
@@ -23,14 +23,21 @@ class MCPClient {
2323 private transport : StdioClientTransport | null = null ;
2424
2525 constructor ( ) {
26+ // Initialize Anthropic client and MCP client
2627 this . anthropic = new Anthropic ( {
2728 apiKey : ANTHROPIC_API_KEY ,
2829 } ) ;
2930 this . mcp = new Client ( { name : "mcp-client-cli" , version : "1.0.0" } ) ;
3031 }
3132
3233 async connectToServer ( serverScriptPath : string ) {
34+ /**
35+ * Connect to an MCP server
36+ *
37+ * @param serverScriptPath - Path to the server script (.py or .js)
38+ */
3339 try {
40+ // Determine script type and appropriate command
3441 const isJs = serverScriptPath . endsWith ( ".js" ) ;
3542 const isPy = serverScriptPath . endsWith ( ".py" ) ;
3643 if ( ! isJs && ! isPy ) {
@@ -41,11 +48,15 @@ class MCPClient {
4148 ? "python"
4249 : "python3"
4350 : process . execPath ;
51+
52+ // Initialize transport and connect to server
4453 this . transport = new StdioClientTransport ( {
4554 command,
4655 args : [ serverScriptPath ] ,
4756 } ) ;
4857 this . mcp . connect ( this . transport ) ;
58+
59+ // List available tools
4960 const toolsResult = await this . mcp . listTools ( ) ;
5061 const tools = toolsResult . tools . map ( ( tool ) => {
5162 return {
@@ -65,13 +76,20 @@ class MCPClient {
6576 }
6677
6778 async processQuery ( query : string ) {
79+ /**
80+ * Process a query using Claude and available tools
81+ *
82+ * @param query - The user's input query
83+ * @returns Processed response as a string
84+ */
6885 const messages : MessageParam [ ] = [
6986 {
7087 role : "user" ,
7188 content : query ,
7289 } ,
7390 ] ;
7491
92+ // Get available tools
7593 const toolsResult = await this . mcp . listTools ( ) ;
7694 const tools : Tool [ ] = toolsResult . tools . map ( ( tool ) => {
7795 return {
@@ -80,20 +98,24 @@ class MCPClient {
8098 input_schema : tool . inputSchema ,
8199 } ;
82100 } ) ;
101+
102+ // Initial Claude API call
83103 const response = await this . anthropic . messages . create ( {
84104 model : "claude-3-5-sonnet-20241022" ,
85105 max_tokens : 1000 ,
86106 messages,
87107 tools,
88108 } ) ;
89109
110+ // Process response and handle tool calls
90111 const finalText = [ ] ;
91112 const toolResults = [ ] ;
92113
93114 for ( const content of response . content ) {
94115 if ( content . type === "text" ) {
95116 finalText . push ( content . text ) ;
96117 } else if ( content . type === "tool_use" ) {
118+ // Execute tool call
97119 const toolName = content . name ;
98120 const toolArgs = content . input as { [ x : string ] : unknown } | undefined ;
99121
@@ -106,11 +128,13 @@ class MCPClient {
106128 `[Calling tool ${ toolName } with args ${ JSON . stringify ( toolArgs ) } ]`
107129 ) ;
108130
131+ // Continue conversation with tool results
109132 messages . push ( {
110133 role : "user" ,
111134 content : result . content as string ,
112135 } ) ;
113136
137+ // Get next response from Claude
114138 const response = await this . anthropic . messages . create ( {
115139 model : "claude-3-5-sonnet-20241022" ,
116140 max_tokens : 1000 ,
@@ -127,6 +151,9 @@ class MCPClient {
127151 }
128152
129153 async chatLoop ( ) {
154+ /**
155+ * Run an interactive chat loop
156+ */
130157 const rl = readline . createInterface ( {
131158 input : process . stdin ,
132159 output : process . stdout ,
@@ -146,9 +173,13 @@ class MCPClient {
146173 }
147174
148175 async cleanup ( ) {
176+ /**
177+ * Clean up resources
178+ */
149179 await this . mcp . close ( ) ;
150180 }
151181}
182+
152183async function main ( ) {
153184 if ( process . argv . length < 3 ) {
154185 console . log ( "Usage: node index.ts <path_to_server_script>" ) ;
0 commit comments