diff --git a/tutorials/building-a-client-node.mdx b/tutorials/building-a-client-node.mdx
new file mode 100644
index 0000000..9cc5ccc
--- /dev/null
+++ b/tutorials/building-a-client-node.mdx
@@ -0,0 +1,463 @@
+
+## System Requirements
+
+Before starting, ensure your system meets these requirements:
+- Mac or Windows computer
+- Node.js version 16 or higher installed
+- npm (comes with Node.js)
+
+## Setting Up Your Environment
+
+First, create a new Node.js project:
+
+```bash
+# Create project directory
+mkdir mcp-client
+cd mcp-client
+
+# Initialize npm project
+npm init -y
+
+# Install dependencies
+npm install @modelcontextprotocol/sdk @anthropic-ai/sdk dotenv
+npm install -D typescript @types/node
+
+# Create TypeScript config
+npx tsc --init
+
+# Create necessary files
+mkdir src
+touch src/client.ts
+touch .env
+```
+
+Update your `package.json` to add necessary configuration:
+
+```json
+{
+ "type": "module",
+ "scripts": {
+ "build": "tsc",
+ "start": "node build/client.js"
+ }
+}
+```
+
+Update your `tsconfig.json` with appropriate settings:
+
+```json
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "Node16",
+ "moduleResolution": "Node16",
+ "outDir": "./build",
+ "rootDir": "./src",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "include": ["src/**/*"]
+}
+```
+
+## Setting Up Your API Key
+
+You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
+
+Create a `.env` file:
+```bash
+ANTHROPIC_API_KEY=your_key_here
+```
+
+Add `.env` to your `.gitignore`:
+```bash
+echo ".env" >> .gitignore
+```
+
+## Creating the Client
+
+First, let's set up our imports and create the basic client class in `src/client.ts`:
+
+```typescript
+import { Client } from "@modelcontextprotocol/sdk/client/index.js";
+import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
+import Anthropic from "@anthropic-ai/sdk";
+import dotenv from "dotenv";
+import { Tool } from "@anthropic-ai/sdk/resources/messages.js";
+import {
+ CallToolResultSchema,
+ ListToolsResultSchema,
+} from "@modelcontextprotocol/sdk/types.js";
+import * as readline from "node:readline";
+
+dotenv.config();
+
+interface MCPClientConfig {
+ name?: string;
+ version?: string;
+}
+
+class MCPClient {
+ private client: Client | null = null;
+ private anthropic: Anthropic;
+ private transport: StdioClientTransport | null = null;
+
+ constructor(config: MCPClientConfig = {}) {
+ this.anthropic = new Anthropic();
+ }
+
+ // Methods will go here
+}
+```
+
+## Server Connection Management
+
+Next, implement the method to connect to an MCP server:
+
+```typescript
+ async connectToServer(serverScriptPath: string): Promise {
+ const isPython = serverScriptPath.endsWith(".py");
+ const isJs = serverScriptPath.endsWith(".js");
+
+ if (!isPython && !isJs) {
+ throw new Error("Server script must be a .py or .js file");
+ }
+
+ const command = isPython ? "python" : "node";
+
+ this.transport = new StdioClientTransport({
+ command,
+ args: [serverScriptPath],
+ });
+
+ this.client = new Client(
+ {
+ name: "mcp-client",
+ version: "1.0.0",
+ },
+ {
+ capabilities: {},
+ }
+ );
+
+ await this.client.connect(this.transport);
+
+ // List available tools
+ const response = await this.client.request(
+ { method: "tools/list" },
+ ListToolsResultSchema
+ );
+
+ console.log(
+ "\nConnected to server with tools:",
+ response.tools.map((tool: any) => tool.name)
+ );
+ }
+```
+
+## Query Processing Logic
+
+Now add the core functionality for processing queries and handling tool calls:
+
+```typescript
+ async processQuery(query: string): Promise {
+ if (!this.client) {
+ throw new Error("Client not connected");
+ }
+
+ // Initialize messages array with user query
+ let messages: Anthropic.MessageParam[] = [
+ {
+ role: "user",
+ content: query,
+ },
+ ];
+
+ // Get available tools
+ const toolsResponse = await this.client.request(
+ { method: "tools/list" },
+ ListToolsResultSchema
+ );
+
+ const availableTools: Tool[] = toolsResponse.tools.map((tool: any) => ({
+ name: tool.name,
+ description: tool.description,
+ input_schema: tool.inputSchema,
+ }));
+
+ const finalText: string[] = [];
+ let currentResponse = await this.anthropic.messages.create({
+ model: "claude-3-5-sonnet-20241022",
+ max_tokens: 1000,
+ messages,
+ tools: availableTools,
+ });
+
+ // Process the response and any tool calls
+ while (true) {
+ // Add Claude's response to final text and messages
+ for (const content of currentResponse.content) {
+ if (content.type === "text") {
+ finalText.push(content.text);
+ } else if (content.type === "tool_use") {
+ const toolName = content.name;
+ const toolArgs = content.input;
+
+ // Execute tool call
+ const result = await this.client.request(
+ {
+ method: "tools/call",
+ params: {
+ name: toolName,
+ args: toolArgs,
+ },
+ },
+ CallToolResultSchema
+ );
+
+ finalText.push(
+ `[Calling tool ${toolName} with args ${JSON.stringify(toolArgs)}]`
+ );
+
+ // Add Claude's response (including tool use) to messages
+ messages.push({
+ role: "assistant",
+ content: currentResponse.content,
+ });
+
+ // Add tool result to messages
+ messages.push({
+ role: "user",
+ content: [
+ {
+ type: "tool_result",
+ tool_use_id: content.id,
+ content: [
+ { type: "text", text: JSON.stringify(result.content) },
+ ],
+ },
+ ],
+ });
+
+ // Get next response from Claude with tool results
+ currentResponse = await this.anthropic.messages.create({
+ model: "claude-3-5-sonnet-20241022",
+ max_tokens: 1000,
+ messages,
+ tools: availableTools,
+ });
+
+ // Add Claude's interpretation of the tool results to final text
+ if (currentResponse.content[0]?.type === "text") {
+ finalText.push(currentResponse.content[0].text);
+ }
+
+ // Continue the loop to process any additional tool calls
+ continue;
+ }
+ }
+
+ // If we reach here, there were no tool calls in the response
+ break;
+ }
+
+ return finalText.join("\n");
+ }
+
+```
+
+## Interactive Chat Interface
+
+Add the chat loop and cleanup functionality:
+
+```typescript
+ async chatLoop(): Promise {
+ console.log("\nMCP Client Started!");
+ console.log("Type your queries or 'quit' to exit.");
+
+ // Using Node's readline for console input
+ const rl = readline.createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ });
+
+ const askQuestion = () => {
+ rl.question("\nQuery: ", async (query: string) => {
+ try {
+ if (query.toLowerCase() === "quit") {
+ await this.cleanup();
+ rl.close();
+ return;
+ }
+
+ const response = await this.processQuery(query);
+ console.log("\n" + response);
+ askQuestion();
+ } catch (error) {
+ console.error("\nError:", error);
+ askQuestion();
+ }
+ });
+ };
+
+ askQuestion();
+ }
+
+ async cleanup(): Promise {
+ if (this.transport) {
+ await this.transport.close();
+ }
+ }
+```
+
+## Main Entry Point
+
+Finally, add the main execution logic outside the class:
+
+```typescript
+// Main execution
+async function main() {
+ if (process.argv.length < 3) {
+ console.log("Usage: ts-node client.ts ");
+ process.exit(1);
+ }
+
+ const client = new MCPClient();
+ try {
+ await client.connectToServer(process.argv[2]);
+ await client.chatLoop();
+ } catch (error) {
+ console.error("Error:", error);
+ await client.cleanup();
+ process.exit(1);
+ }
+}
+
+// Run main if this is the main module
+if (import.meta.url === new URL(process.argv[1], "file:").href) {
+ main();
+}
+
+export default MCPClient;
+```
+
+## Running the Client
+
+To run your client with any MCP server:
+
+```bash
+# Build the TypeScript code. Make sure to rerun this every time you update `client.ts`!
+npm run build
+
+# Run the client
+node build/client.js path/to/server.py # for Python servers
+node build/client.js path/to/server.js # for Node.js servers
+```
+
+The client will:
+1. Connect to the specified server
+2. List available tools
+3. Start an interactive chat session where you can:
+ - Enter queries
+ - See tool executions
+ - Get responses from Claude
+
+## Key Components Explained
+
+#### 1. Client Initialization
+- The `MCPClient` class initializes with session management and API clients
+- Sets up the MCP client with basic capabilities
+- Configures the Anthropic client for Claude interactions
+
+#### 2. Server Connection
+- Supports both Python and Node.js servers
+- Validates server script type
+- Sets up proper communication channels
+- Lists available tools on connection
+
+#### 3. Query Processing
+- Maintains conversation context
+- Handles Claude's responses and tool calls
+- Manages the message flow between Claude and tools
+- Combines results into a coherent response
+
+#### 4. Interactive Interface
+- Provides a simple command-line interface
+- Handles user input and displays responses
+- Includes basic error handling
+- Allows graceful exit
+
+#### 5. Resource Management
+- Proper cleanup of resources
+- Error handling for connection issues
+- Graceful shutdown procedures
+
+### Common Customization Points
+
+1. **Tool Handling**
+ - Modify `processQuery()` to handle specific tool types
+ - Add custom error handling for tool calls
+ - Implement tool-specific response formatting
+
+2. **Response Processing**
+ - Customize how tool results are formatted
+ - Add response filtering or transformation
+ - Implement custom logging
+
+3. **User Interface**
+ - Add a GUI or web interface
+ - Implement rich console output
+ - Add command history or auto-completion
+
+### Best Practices
+
+1. **Error Handling**
+ - Always wrap tool calls in try-catch blocks
+ - Provide meaningful error messages
+ - Gracefully handle connection issues
+
+2. **Resource Management**
+ - Use proper cleanup methods
+ - Close connections when done
+ - Handle server disconnections
+
+3. **Security**
+ - Store API keys securely in `.env`
+ - Validate server responses
+ - Be cautious with tool permissions
+
+### Troubleshooting
+
+#### Server Path Issues
+- Double-check the path to your server script
+- Use absolute paths if relative paths aren't working
+- For Windows users, use forward slashes (/) or escaped backslashes (\\)
+- Verify the server file has the correct extension (.py or .js)
+
+Example of correct path usage:
+```bash
+# Relative path
+node build/client.js ./server/weather.js
+
+# Absolute path
+node build/client.js /Users/username/projects/mcp-server/weather.js
+
+# Windows path (either format works)
+node build/client.js C:/projects/mcp-server/weather.js
+node build/client.js C:\\projects\\mcp-server\\weather.js
+```
+
+#### Connection Issues
+- Verify the server script exists and has correct permissions
+- Check that the server script is executable
+- Ensure the server script's dependencies are installed
+- Try running the server script directly to check for errors
+
+#### Tool Execution Issues
+- Check server logs for error messages
+- Verify tool input arguments match the schema
+- Ensure tool dependencies are available
+- Add debug logging to track execution flow
+
\ No newline at end of file
diff --git a/tutorials/building-a-client.mdx b/tutorials/building-a-client.mdx
index ac0f642..7e1b5dc 100644
--- a/tutorials/building-a-client.mdx
+++ b/tutorials/building-a-client.mdx
@@ -387,469 +387,7 @@ If you see:
- `Timeout error`: Consider increasing the timeout in your client configuration
-
-## System Requirements
-Before starting, ensure your system meets these requirements:
-- Mac or Windows computer
-- Node.js version 16 or higher installed
-- npm (comes with Node.js)
-
-## Setting Up Your Environment
-
-First, create a new Node.js project:
-
-```bash
-# Create project directory
-mkdir mcp-client
-cd mcp-client
-
-# Initialize npm project
-npm init -y
-
-# Install dependencies
-npm install @modelcontextprotocol/sdk @anthropic-ai/sdk dotenv
-npm install -D typescript @types/node
-
-# Create TypeScript config
-npx tsc --init
-
-# Create necessary files
-mkdir src
-touch src/client.ts
-touch .env
-```
-
-Update your `package.json` to add necessary configuration:
-
-```json
-{
- "type": "module",
- "scripts": {
- "build": "tsc",
- "start": "node build/client.js"
- }
-}
-```
-
-Update your `tsconfig.json` with appropriate settings:
-
-```json
-{
- "compilerOptions": {
- "target": "ES2022",
- "module": "Node16",
- "moduleResolution": "Node16",
- "outDir": "./build",
- "rootDir": "./src",
- "strict": true,
- "esModuleInterop": true,
- "skipLibCheck": true,
- "forceConsistentCasingInFileNames": true
- },
- "include": ["src/**/*"]
-}
-```
-
-## Setting Up Your API Key
-
-You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
-
-Create a `.env` file:
-```bash
-ANTHROPIC_API_KEY=your_key_here
-```
-
-Add `.env` to your `.gitignore`:
-```bash
-echo ".env" >> .gitignore
-```
-
-## Creating the Client
-
-First, let's set up our imports and create the basic client class in `src/client.ts`:
-
-```typescript
-import { Client } from "@modelcontextprotocol/sdk/client/index.js";
-import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
-import Anthropic from "@anthropic-ai/sdk";
-import dotenv from "dotenv";
-import { Tool } from "@anthropic-ai/sdk/resources/messages.js";
-import {
- CallToolResultSchema,
- ListToolsResultSchema,
-} from "@modelcontextprotocol/sdk/types.js";
-import * as readline from "node:readline";
-
-dotenv.config();
-
-interface MCPClientConfig {
- name?: string;
- version?: string;
-}
-
-class MCPClient {
- private client: Client | null = null;
- private anthropic: Anthropic;
- private transport: StdioClientTransport | null = null;
-
- constructor(config: MCPClientConfig = {}) {
- this.anthropic = new Anthropic();
- }
-
- // Methods will go here
-}
-```
-
-## Server Connection Management
-
-Next, implement the method to connect to an MCP server:
-
-```typescript
- async connectToServer(serverScriptPath: string): Promise {
- const isPython = serverScriptPath.endsWith(".py");
- const isJs = serverScriptPath.endsWith(".js");
-
- if (!isPython && !isJs) {
- throw new Error("Server script must be a .py or .js file");
- }
-
- const command = isPython ? "python" : "node";
-
- this.transport = new StdioClientTransport({
- command,
- args: [serverScriptPath],
- });
-
- this.client = new Client(
- {
- name: "mcp-client",
- version: "1.0.0",
- },
- {
- capabilities: {},
- }
- );
-
- await this.client.connect(this.transport);
-
- // List available tools
- const response = await this.client.request(
- { method: "tools/list" },
- ListToolsResultSchema
- );
-
- console.log(
- "\nConnected to server with tools:",
- response.tools.map((tool: any) => tool.name)
- );
- }
-```
-
-## Query Processing Logic
-
-Now add the core functionality for processing queries and handling tool calls:
-
-```typescript
- async processQuery(query: string): Promise {
- if (!this.client) {
- throw new Error("Client not connected");
- }
-
- // Initialize messages array with user query
- let messages: Anthropic.MessageParam[] = [
- {
- role: "user",
- content: query,
- },
- ];
-
- // Get available tools
- const toolsResponse = await this.client.request(
- { method: "tools/list" },
- ListToolsResultSchema
- );
-
- const availableTools: Tool[] = toolsResponse.tools.map((tool: any) => ({
- name: tool.name,
- description: tool.description,
- input_schema: tool.inputSchema,
- }));
-
- const finalText: string[] = [];
- let currentResponse = await this.anthropic.messages.create({
- model: "claude-3-5-sonnet-20241022",
- max_tokens: 1000,
- messages,
- tools: availableTools,
- });
-
- // Process the response and any tool calls
- while (true) {
- // Add Claude's response to final text and messages
- for (const content of currentResponse.content) {
- if (content.type === "text") {
- finalText.push(content.text);
- } else if (content.type === "tool_use") {
- const toolName = content.name;
- const toolArgs = content.input;
-
- // Execute tool call
- const result = await this.client.request(
- {
- method: "tools/call",
- params: {
- name: toolName,
- args: toolArgs,
- },
- },
- CallToolResultSchema
- );
-
- finalText.push(
- `[Calling tool ${toolName} with args ${JSON.stringify(toolArgs)}]`
- );
-
- // Add Claude's response (including tool use) to messages
- messages.push({
- role: "assistant",
- content: currentResponse.content,
- });
-
- // Add tool result to messages
- messages.push({
- role: "user",
- content: [
- {
- type: "tool_result",
- tool_use_id: content.id,
- content: [
- { type: "text", text: JSON.stringify(result.content) },
- ],
- },
- ],
- });
-
- // Get next response from Claude with tool results
- currentResponse = await this.anthropic.messages.create({
- model: "claude-3-5-sonnet-20241022",
- max_tokens: 1000,
- messages,
- tools: availableTools,
- });
-
- // Add Claude's interpretation of the tool results to final text
- if (currentResponse.content[0]?.type === "text") {
- finalText.push(currentResponse.content[0].text);
- }
-
- // Continue the loop to process any additional tool calls
- continue;
- }
- }
-
- // If we reach here, there were no tool calls in the response
- break;
- }
-
- return finalText.join("\n");
- }
-
-```
-
-## Interactive Chat Interface
-
-Add the chat loop and cleanup functionality:
-
-```typescript
- async chatLoop(): Promise {
- console.log("\nMCP Client Started!");
- console.log("Type your queries or 'quit' to exit.");
-
- // Using Node's readline for console input
- const rl = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- });
-
- const askQuestion = () => {
- rl.question("\nQuery: ", async (query: string) => {
- try {
- if (query.toLowerCase() === "quit") {
- await this.cleanup();
- rl.close();
- return;
- }
-
- const response = await this.processQuery(query);
- console.log("\n" + response);
- askQuestion();
- } catch (error) {
- console.error("\nError:", error);
- askQuestion();
- }
- });
- };
-
- askQuestion();
- }
-
- async cleanup(): Promise {
- if (this.transport) {
- await this.transport.close();
- }
- }
-```
-
-## Main Entry Point
-
-Finally, add the main execution logic outside the class:
-
-```typescript
-// Main execution
-async function main() {
- if (process.argv.length < 3) {
- console.log("Usage: ts-node client.ts ");
- process.exit(1);
- }
-
- const client = new MCPClient();
- try {
- await client.connectToServer(process.argv[2]);
- await client.chatLoop();
- } catch (error) {
- console.error("Error:", error);
- await client.cleanup();
- process.exit(1);
- }
-}
-
-// Run main if this is the main module
-if (import.meta.url === new URL(process.argv[1], "file:").href) {
- main();
-}
-
-export default MCPClient;
-```
-
-## Running the Client
-
-To run your client with any MCP server:
-
-```bash
-# Build the TypeScript code. Make sure to rerun this every time you update `client.ts`!
-npm run build
-
-# Run the client
-node build/client.js path/to/server.py # for Python servers
-node build/client.js path/to/server.js # for Node.js servers
-```
-
-The client will:
-1. Connect to the specified server
-2. List available tools
-3. Start an interactive chat session where you can:
- - Enter queries
- - See tool executions
- - Get responses from Claude
-
-## Key Components Explained
-
-#### 1. Client Initialization
-- The `MCPClient` class initializes with session management and API clients
-- Sets up the MCP client with basic capabilities
-- Configures the Anthropic client for Claude interactions
-
-#### 2. Server Connection
-- Supports both Python and Node.js servers
-- Validates server script type
-- Sets up proper communication channels
-- Lists available tools on connection
-
-#### 3. Query Processing
-- Maintains conversation context
-- Handles Claude's responses and tool calls
-- Manages the message flow between Claude and tools
-- Combines results into a coherent response
-
-#### 4. Interactive Interface
-- Provides a simple command-line interface
-- Handles user input and displays responses
-- Includes basic error handling
-- Allows graceful exit
-
-#### 5. Resource Management
-- Proper cleanup of resources
-- Error handling for connection issues
-- Graceful shutdown procedures
-
-### Common Customization Points
-
-1. **Tool Handling**
- - Modify `processQuery()` to handle specific tool types
- - Add custom error handling for tool calls
- - Implement tool-specific response formatting
-
-2. **Response Processing**
- - Customize how tool results are formatted
- - Add response filtering or transformation
- - Implement custom logging
-
-3. **User Interface**
- - Add a GUI or web interface
- - Implement rich console output
- - Add command history or auto-completion
-
-### Best Practices
-
-1. **Error Handling**
- - Always wrap tool calls in try-catch blocks
- - Provide meaningful error messages
- - Gracefully handle connection issues
-
-2. **Resource Management**
- - Use proper cleanup methods
- - Close connections when done
- - Handle server disconnections
-
-3. **Security**
- - Store API keys securely in `.env`
- - Validate server responses
- - Be cautious with tool permissions
-
-### Troubleshooting
-
-#### Server Path Issues
-- Double-check the path to your server script
-- Use absolute paths if relative paths aren't working
-- For Windows users, use forward slashes (/) or escaped backslashes (\\)
-- Verify the server file has the correct extension (.py or .js)
-
-Example of correct path usage:
-```bash
-# Relative path
-node build/client.js ./server/weather.js
-
-# Absolute path
-node build/client.js /Users/username/projects/mcp-server/weather.js
-
-# Windows path (either format works)
-node build/client.js C:/projects/mcp-server/weather.js
-node build/client.js C:\\projects\\mcp-server\\weather.js
-```
-
-#### Connection Issues
-- Verify the server script exists and has correct permissions
-- Check that the server script is executable
-- Ensure the server script's dependencies are installed
-- Try running the server script directly to check for errors
-
-#### Tool Execution Issues
-- Check server logs for error messages
-- Verify tool input arguments match the schema
-- Ensure tool dependencies are available
-- Add debug logging to track execution flow
-
## Next steps