From fa0744c366aac16f7c1813d5d17868527c0b121b Mon Sep 17 00:00:00 2001
From: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
Date: Mon, 17 Feb 2025 16:24:00 -0800
Subject: [PATCH 1/5] Add mcp-client-typescript quickstart guide
---
quickstart/client.mdx | 358 ++++++++++++++++++++++++++++++++++++++++++
quickstart/server.mdx | 2 +-
2 files changed, 359 insertions(+), 1 deletion(-)
diff --git a/quickstart/client.mdx b/quickstart/client.mdx
index a751bed..f7bcfe5 100644
--- a/quickstart/client.mdx
+++ b/quickstart/client.mdx
@@ -402,6 +402,364 @@ If you see:
+
+
+[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-typescript)
+
+## System Requirements
+
+Before starting, ensure your system meets these requirements:
+- Mac or Windows computer
+- Node.js 16 or higher installed
+- Latest version of `npm` installed
+- Anthropic API key (Claude)
+
+## Setting Up Your Environment
+
+First, let's create and set up our project:
+
+
+```bash MacOS/Linux
+# Create project directory
+mkdir mcp-client-typescript
+cd mcp-client-typescript
+
+# Initialize npm project
+npm init -y
+
+# Install dependencies
+npm install @anthropic-ai/sdk @modelcontextprotocol/sdk dotenv
+
+# Install dev dependencies
+npm install --save-dev @types/node
+
+# Initialize TypeScript configuration
+npx tsc --init
+
+# Create source file
+touch index.ts
+```
+
+```powershell Windows
+# Create project directory
+md mcp-client-typescript
+cd mcp-client-typescript
+
+# Initialize npm project
+npm init -y
+
+# Install dependencies
+npm install @anthropic-ai/sdk @modelcontextprotocol/sdk dotenv
+
+# Install dev dependencies
+npm install --save-dev @types/node
+
+# Initialize TypeScript configuration
+npx tsc --init
+
+# Create source file
+new-item index.ts
+```
+
+
+## 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 to store it:
+
+```bash
+echo "ANTHROPIC_API_KEY=" > .env
+```
+
+Add `.env` to your `.gitignore`:
+```bash
+echo ".env" >> .gitignore
+```
+
+
+Make sure you keep your `ANTHROPIC_API_KEY` secure!
+
+
+## Creating the Client
+
+### Basic Client Structure
+
+First, let's set up our imports and create the basic client class in `index.ts`:
+
+```typescript
+import { Anthropic } from "@anthropic-ai/sdk";
+import {
+ MessageParam,
+ Tool,
+} from "@anthropic-ai/sdk/resources/messages/messages.mjs";
+import { Client } from "@modelcontextprotocol/sdk/client/index.js";
+import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
+import readline from "readline/promises";
+import dotenv from "dotenv";
+
+dotenv.config();
+
+const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
+if (!ANTHROPIC_API_KEY) {
+ throw new Error("ANTHROPIC_API_KEY is not set");
+}
+
+class MCPClient {
+ private mcp: Client;
+ private anthropic: Anthropic;
+ private transport: StdioClientTransport | null = null;
+
+ constructor() {
+ this.anthropic = new Anthropic({
+ apiKey: ANTHROPIC_API_KEY,
+ });
+ this.mcp = new Client({ name: "mcp-client-cli", version: "1.0.0" });
+ }
+ // methods will go here
+}
+```
+
+### Server Connection Management
+
+Next, we'll implement the method to connect to an MCP server:
+
+```typescript
+async connectToServer(serverScriptPath: string) {
+ try {
+ const isJs = serverScriptPath.endsWith(".js");
+ const isPy = serverScriptPath.endsWith(".py");
+ if (!isJs && !isPy) {
+ throw new Error("Server script must be a .js or .py file");
+ }
+ const command = isPy
+ ? process.platform === "win32"
+ ? "python"
+ : "python3"
+ : process.execPath;
+ this.transport = new StdioClientTransport({
+ command,
+ args: [serverScriptPath],
+ });
+ this.mcp.connect(this.transport);
+ const toolsResult = await this.mcp.listTools();
+ const tools = toolsResult.tools.map((tool) => {
+ return {
+ name: tool.name,
+ description: tool.description,
+ input_schema: tool.inputSchema,
+ };
+ });
+ console.log(
+ "Connected to server with tools:",
+ tools.map(({ name }) => name)
+ );
+ } catch (e) {
+ console.log("Failed to connect to MCP server: ", e);
+ throw e;
+ }
+}
+```
+
+### Query Processing Logic
+
+Now let's add the core functionality for processing queries and handling tool calls:
+
+```typescript
+async processQuery(query: string) {
+ const messages: MessageParam[] = [
+ {
+ role: "user",
+ content: query,
+ },
+ ];
+
+ const toolsResult = await this.mcp.listTools();
+ const tools: Tool[] = toolsResult.tools.map((tool) => {
+ return {
+ name: tool.name,
+ description: tool.description,
+ input_schema: tool.inputSchema,
+ };
+ });
+ const response = await this.anthropic.messages.create({
+ model: "claude-3-5-sonnet-20241022",
+ max_tokens: 1000,
+ messages,
+ tools,
+ });
+
+ const finalText = [];
+ const toolResults = [];
+
+ for (const content of response.content) {
+ if (content.type === "text") {
+ finalText.push(content.text);
+ } else if (content.type === "tool_use") {
+ const toolName = content.name;
+ const toolArgs = content.input as { [x: string]: unknown } | undefined;
+
+ const result = await this.mcp.callTool({
+ name: toolName,
+ arguments: toolArgs,
+ });
+ toolResults.push(result);
+ finalText.push(
+ `[Calling tool ${toolName} with args ${JSON.stringify(toolArgs)}]`
+ );
+
+ messages.push({
+ role: "user",
+ content: result.content as string,
+ });
+
+ const response = await this.anthropic.messages.create({
+ model: "claude-3-5-sonnet-20241022",
+ max_tokens: 1000,
+ messages,
+ });
+
+ finalText.push(
+ response.content[0].type === "text" ? response.content[0].text : ""
+ );
+ }
+ }
+
+ return finalText.join("\n");
+}
+```
+
+### Interactive Chat Interface
+
+Now we'll add the chat loop and cleanup functionality:
+
+```typescript
+async chatLoop() {
+ const rl = readline.createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ });
+
+ console.log("\nMCP Client Started!");
+ console.log("Type your queries or 'quit' to exit.");
+
+ while (true) {
+ const message = await rl.question("\nQuery: ");
+ if (message === "quit") {
+ break;
+ }
+ const response = await this.processQuery(message);
+ console.log("\n" + response);
+ }
+}
+
+async cleanup() {
+ await this.mcp.close();
+}
+```
+
+### Main Entry Point
+
+Finally, we'll add the main execution logic:
+
+```typescript
+async function main() {
+ if (process.argv.length < 3) {
+ console.log("Usage: node index.ts ");
+ return;
+ }
+ const mcpClient = new MCPClient();
+ try {
+ await mcpClient.connectToServer(process.argv[2]);
+ await mcpClient.chatLoop();
+ } finally {
+ await mcpClient.cleanup();
+ process.exit(0);
+ }
+}
+
+main();
+```
+
+## Running the Client
+
+To run your client with any MCP server:
+
+```bash
+# Build TypeScript
+npx tsc
+
+# Run the client
+node build/index.js path/to/server.py # python server
+node build/index.js path/to/build/index.js # node server
+```
+
+
+If you're continuing the weather tutorial from the server quickstart, your command might look something like this: `node build/index.js .../quickstart-resources/weather-server-typescript/build/index.js`
+
+
+## Key Components Explained
+
+### 1. Client Initialization
+- Uses TypeScript classes for better type safety
+- Initializes Anthropic client with API key
+- Creates MCP client with version information
+
+### 2. Server Connection
+- Supports both Python and Node.js servers
+- Platform-aware Python command selection
+- Establishes stdio transport connection
+
+### 3. Query Processing
+- Strong typing for messages and tools
+- Handles Claude's tool calls
+- Manages conversation context
+- Processes tool results
+
+### 4. Resource Management
+- Proper cleanup of resources
+- Type-safe error handling
+- Graceful shutdown procedures
+
+## Best Practices
+
+1. **Type Safety**
+ - Use TypeScript interfaces for tool schemas
+ - Leverage type checking for API responses
+ - Define clear types for message structures
+
+2. **Error Handling**
+ - Implement proper try-catch blocks
+ - Type-check API responses
+ - Validate server connections
+
+3. **Security**
+ - Store API keys in environment variables
+ - Validate server paths
+ - Check tool permissions
+
+## Troubleshooting
+
+### Common Issues
+
+1. **TypeScript Build Errors**
+ - Ensure `tsconfig.json` is properly configured
+ - Check import paths are correct
+ - Verify all dependencies are installed
+
+2. **Runtime Errors**
+ - Check API key is properly set
+ - Verify server path is correct
+ - Ensure proper Node.js version
+
+3. **Server Connection Issues**
+ - Verify server script exists
+ - Check file permissions
+ - Ensure correct Python/Node command
+
+
+
+
diff --git a/quickstart/server.mdx b/quickstart/server.mdx
index dfa5e29..6203294 100644
--- a/quickstart/server.mdx
+++ b/quickstart/server.mdx
@@ -316,7 +316,7 @@ This tells Claude for Desktop:
Save the file, and restart **Claude for Desktop**.
-
+
Let's get started with building our weather server! [You can find the complete code for what we'll be building here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/weather-server-typescript)
### Prerequisite knowledge
From 7f3c508c6a7383cad83a1dc0ac6efe5a7b75bc2c Mon Sep 17 00:00:00 2001
From: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
Date: Mon, 17 Feb 2025 16:47:27 -0800
Subject: [PATCH 2/5] Improve client running explanation, best practices, etc.
---
quickstart/client.mdx | 106 +++++++++++++++++++++++-------------------
1 file changed, 59 insertions(+), 47 deletions(-)
diff --git a/quickstart/client.mdx b/quickstart/client.mdx
index f7bcfe5..0015f4f 100644
--- a/quickstart/client.mdx
+++ b/quickstart/client.mdx
@@ -405,13 +405,12 @@ If you see:
[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-typescript)
-
## System Requirements
Before starting, ensure your system meets these requirements:
- Mac or Windows computer
- Node.js 16 or higher installed
-- Latest version of `npm` installed
+- Latest version of `npm` and `npx` installed
- Anthropic API key (Claude)
## Setting Up Your Environment
@@ -698,64 +697,77 @@ node build/index.js path/to/build/index.js # node server
If you're continuing the weather tutorial from the server quickstart, your command might look something like this: `node build/index.js .../quickstart-resources/weather-server-typescript/build/index.js`
-## Key Components Explained
+**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
-### 1. Client Initialization
-- Uses TypeScript classes for better type safety
-- Initializes Anthropic client with API key
-- Creates MCP client with version information
+## How It Works
-### 2. Server Connection
-- Supports both Python and Node.js servers
-- Platform-aware Python command selection
-- Establishes stdio transport connection
+When you submit a query:
-### 3. Query Processing
-- Strong typing for messages and tools
-- Handles Claude's tool calls
-- Manages conversation context
-- Processes tool results
+1. The client gets the list of available tools from the server
+2. Your query is sent to Claude along with tool descriptions
+3. Claude decides which tools (if any) to use
+4. The client executes any requested tool calls through the server
+5. Results are sent back to Claude
+6. Claude provides a natural language response
+7. The response is displayed to you
-### 4. Resource Management
-- Proper cleanup of resources
-- Type-safe error handling
-- Graceful shutdown procedures
+## Best practices
+
+1. **Error Handling**
+ - Use TypeScript's type system for better error detection
+ - Wrap tool calls in try-catch blocks
+ - Provide meaningful error messages
+ - Gracefully handle connection issues
-## Best Practices
+2. **Security**
+ - Store API keys securely in `.env`
+ - Validate server responses
+ - Be cautious with tool permissions
-1. **Type Safety**
- - Use TypeScript interfaces for tool schemas
- - Leverage type checking for API responses
- - Define clear types for message structures
+## Troubleshooting
-2. **Error Handling**
- - Implement proper try-catch blocks
- - Type-check API responses
- - Validate server connections
+### Server Path Issues
+- Double-check the path to your server script is correct
+- Use the absolute path if the relative path isn't working
+- For Windows users, make sure to use forward slashes (/) or escaped backslashes (\\) in the path
+- Verify the server file has the correct extension (.js for Node.js or .py for Python)
-3. **Security**
- - Store API keys in environment variables
- - Validate server paths
- - Check tool permissions
+Example of correct path usage:
+```bash
+# Relative path
+node build/index.js ./server/build/index.js
-## Troubleshooting
+# Absolute path
+node build/index.js /Users/username/projects/mcp-server/build/index.js
-### Common Issues
+# Windows path (either format works)
+node build/index.js C:/projects/mcp-server/build/index.js
+node build/index.js C:\\projects\\mcp-server\\build\\index.js
+```
-1. **TypeScript Build Errors**
- - Ensure `tsconfig.json` is properly configured
- - Check import paths are correct
- - Verify all dependencies are installed
+### Response Timing
+- The first response might take up to 30 seconds to return
+- This is normal and happens while:
+ - The server initializes
+ - Claude processes the query
+ - Tools are being executed
+- Subsequent responses are typically faster
+- Don't interrupt the process during this initial waiting period
-2. **Runtime Errors**
- - Check API key is properly set
- - Verify server path is correct
- - Ensure proper Node.js version
+### Common Error Messages
-3. **Server Connection Issues**
- - Verify server script exists
- - Check file permissions
- - Ensure correct Python/Node command
+If you see:
+- `Error: Cannot find module`: Check your build folder and ensure TypeScript compilation succeeded
+- `Connection refused`: Ensure the server is running and the path is correct
+- `Tool execution failed`: Verify the tool's required environment variables are set
+- `ANTHROPIC_API_KEY is not set`: Check your .env file and environment variables
+- `TypeError`: Ensure you're using the correct types for tool arguments
From f707436cb643e4ca0e7cb6a14132516cf87514c7 Mon Sep 17 00:00:00 2001
From: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
Date: Mon, 17 Feb 2025 16:47:56 -0800
Subject: [PATCH 3/5] Set new python mcp client github link
---
quickstart/client.mdx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/quickstart/client.mdx b/quickstart/client.mdx
index 0015f4f..4cd100f 100644
--- a/quickstart/client.mdx
+++ b/quickstart/client.mdx
@@ -8,7 +8,7 @@ In this tutorial, you'll learn how to build a LLM-powered chatbot client that co
-[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client)
+[You can find the complete code for this tutorial here.](https://github.com/modelcontextprotocol/quickstart-resources/tree/main/mcp-client-python)
## System Requirements
From 046c593da9b63641e64b2ca497d91211774f86f8 Mon Sep 17 00:00:00 2001
From: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
Date: Mon, 17 Feb 2025 17:03:17 -0800
Subject: [PATCH 4/5] Only call list tools at initialization
---
quickstart/client.mdx | 37 ++++++++++++++++++-------------------
1 file changed, 18 insertions(+), 19 deletions(-)
diff --git a/quickstart/client.mdx b/quickstart/client.mdx
index 4cd100f..2601760 100644
--- a/quickstart/client.mdx
+++ b/quickstart/client.mdx
@@ -508,6 +508,7 @@ class MCPClient {
private mcp: Client;
private anthropic: Anthropic;
private transport: StdioClientTransport | null = null;
+ private tools: Tool[] = [];
constructor() {
this.anthropic = new Anthropic({
@@ -536,13 +537,15 @@ async connectToServer(serverScriptPath: string) {
? "python"
: "python3"
: process.execPath;
+
this.transport = new StdioClientTransport({
command,
args: [serverScriptPath],
});
this.mcp.connect(this.transport);
+
const toolsResult = await this.mcp.listTools();
- const tools = toolsResult.tools.map((tool) => {
+ this.tools = toolsResult.tools.map((tool) => {
return {
name: tool.name,
description: tool.description,
@@ -551,7 +554,7 @@ async connectToServer(serverScriptPath: string) {
});
console.log(
"Connected to server with tools:",
- tools.map(({ name }) => name)
+ this.tools.map(({ name }) => name)
);
} catch (e) {
console.log("Failed to connect to MCP server: ", e);
@@ -573,19 +576,11 @@ async processQuery(query: string) {
},
];
- const toolsResult = await this.mcp.listTools();
- const tools: Tool[] = toolsResult.tools.map((tool) => {
- return {
- name: tool.name,
- description: tool.description,
- input_schema: tool.inputSchema,
- };
- });
const response = await this.anthropic.messages.create({
model: "claude-3-5-sonnet-20241022",
max_tokens: 1000,
messages,
- tools,
+ tools: this.tools,
});
const finalText = [];
@@ -639,16 +634,20 @@ async chatLoop() {
output: process.stdout,
});
- console.log("\nMCP Client Started!");
- console.log("Type your queries or 'quit' to exit.");
+ try {
+ console.log("\nMCP Client Started!");
+ console.log("Type your queries or 'quit' to exit.");
- while (true) {
- const message = await rl.question("\nQuery: ");
- if (message === "quit") {
- break;
+ while (true) {
+ const message = await rl.question("\nQuery: ");
+ if (message.toLowerCase() === "quit") {
+ break;
+ }
+ const response = await this.processQuery(message);
+ console.log("\n" + response);
}
- const response = await this.processQuery(message);
- console.log("\n" + response);
+ } finally {
+ rl.close();
}
}
From b03bc0d87c8b2ccfa88416d2dfafa6d95833cb6e Mon Sep 17 00:00:00 2001
From: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
Date: Wed, 19 Feb 2025 10:23:44 -0800
Subject: [PATCH 5/5] Add package.json and tsconfig.json setup section
---
quickstart/client.mdx | 45 +++++++++++++++++++++++++++++++++----------
1 file changed, 35 insertions(+), 10 deletions(-)
diff --git a/quickstart/client.mdx b/quickstart/client.mdx
index 2601760..a32e969 100644
--- a/quickstart/client.mdx
+++ b/quickstart/client.mdx
@@ -410,7 +410,7 @@ If you see:
Before starting, ensure your system meets these requirements:
- Mac or Windows computer
- Node.js 16 or higher installed
-- Latest version of `npm` and `npx` installed
+- Latest version of `npm` installed
- Anthropic API key (Claude)
## Setting Up Your Environment
@@ -430,10 +430,7 @@ npm init -y
npm install @anthropic-ai/sdk @modelcontextprotocol/sdk dotenv
# Install dev dependencies
-npm install --save-dev @types/node
-
-# Initialize TypeScript configuration
-npx tsc --init
+npm install -D @types/node typescript
# Create source file
touch index.ts
@@ -451,16 +448,44 @@ npm init -y
npm install @anthropic-ai/sdk @modelcontextprotocol/sdk dotenv
# Install dev dependencies
-npm install --save-dev @types/node
-
-# Initialize TypeScript configuration
-npx tsc --init
+npm install -D @types/node typescript
# Create source file
new-item index.ts
```
+Update your `package.json` to set `type: "module"` and a build script:
+
+```json package.json
+{
+ "type": "module",
+ "scripts": {
+ "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
+ }
+}
+```
+
+Create a `tsconfig.json` in the root of your project:
+
+```json tsconfig.json
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "Node16",
+ "moduleResolution": "Node16",
+ "outDir": "./build",
+ "rootDir": "./",
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "include": ["index.ts"],
+ "exclude": ["node_modules"]
+}
+```
+
## Setting Up Your API Key
You'll need an Anthropic API key from the [Anthropic Console](https://console.anthropic.com/settings/keys).
@@ -685,7 +710,7 @@ To run your client with any MCP server:
```bash
# Build TypeScript
-npx tsc
+npm run build
# Run the client
node build/index.js path/to/server.py # python server