{"id":28932329,"url":"https://github.com/juspay/bedrock-mcp-connector","last_synced_at":"2026-03-07T11:02:29.042Z","repository":{"id":284353217,"uuid":"954623420","full_name":"juspay/Bedrock-MCP-Connector","owner":"juspay","description":"A connector to connect agentic models to MCP tools","archived":false,"fork":false,"pushed_at":"2025-08-25T13:15:01.000Z","size":83,"stargazers_count":2,"open_issues_count":0,"forks_count":6,"subscribers_count":5,"default_branch":"release","last_synced_at":"2025-11-03T14:25:59.528Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/juspay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-03-25T11:16:05.000Z","updated_at":"2025-08-25T13:15:05.000Z","dependencies_parsed_at":"2025-08-25T15:14:14.450Z","dependency_job_id":null,"html_url":"https://github.com/juspay/Bedrock-MCP-Connector","commit_stats":null,"previous_names":["juspay/bedrock-mcp-connector"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/juspay/Bedrock-MCP-Connector","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juspay%2FBedrock-MCP-Connector","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juspay%2FBedrock-MCP-Connector/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juspay%2FBedrock-MCP-Connector/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juspay%2FBedrock-MCP-Connector/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/juspay","download_url":"https://codeload.github.com/juspay/Bedrock-MCP-Connector/tar.gz/refs/heads/release","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/juspay%2FBedrock-MCP-Connector/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30212103,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T09:02:10.694Z","status":"ssl_error","status_checked_at":"2026-03-07T09:02:08.429Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-22T16:41:26.839Z","updated_at":"2026-03-07T11:02:29.035Z","avatar_url":"https://github.com/juspay.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Bedrock MCP Connector\n\nA TypeScript client for interacting with AWS Bedrock and MCP (Model Context Protocol) servers.\n\n## Features\n\n- Seamless integration with AWS Bedrock's Converse API\n- Support for Claude and other Bedrock models\n- Connect to MCP servers to discover and use available tools\n- Register custom tool handlers\n- Event-based architecture for streaming responses\n- TypeScript support with full type definitions\n- Command-line interface for interactive usage\n- Modular design for easy integration into other projects\n\n## Installation\n\n```bash\nnpm install @juspay/bedrock-mcp-connector\n```\n\n## Usage\n\n### Basic Usage\n\n```typescript\nimport { BedrockMCPClient, LogLevel } from \"@juspay/bedrock-mcp-connector\";\n\n// Create a client\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  systemPrompt: \"You are a helpful assistant.\",\n  mcpServerUrl: \"http://localhost:5713/sse\", // Optional\n});\n\n// Set the log level (optional)\n// LogLevel.INFO - Default, shows important information\n// LogLevel.DEBUG - Shows detailed debugging information\n// LogLevel.WARN - Shows only warnings and errors\n// LogLevel.ERROR - Shows only errors\n// LogLevel.NONE - Suppresses all logs\nclient.setLogLevel(LogLevel.INFO);\n\n// Connect to MCP server (if URL is provided)\nif (client.mcpServerUrl) {\n  await client.connect();\n}\n\n// Send a prompt\nconst response = await client.sendPrompt(\"What is the capital of France?\");\nconsole.log(\"Response:\", response);\n\n// Disconnect when done\nif (client.isConnectedToMCP()) {\n  await client.disconnect();\n}\n```\n\n### Using Redis for Persistent Storage\n\nThe package supports both in-memory and Redis storage for conversation history:\n\n```typescript\nimport { BedrockMCPClient } from \"@juspay/bedrock-mcp-connector\";\n\n// Using Redis storage for persistent conversations\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  sessionId: \"user-session-123\", // Unique session identifier\n  userId: \"user-456\", // Optional user identifier\n  storage: {\n    type: \"redis\",\n    config: {\n      host: \"localhost\",\n      port: 6379,\n      password: \"your-redis-password\", // Optional\n      db: 0, // Redis database number\n      keyPrefix: \"bedrock-mcp:\", // Key prefix for Redis keys\n      ttl: 86400, // TTL in seconds (24 hours)\n      connectionOptions: {\n        connectTimeout: 5000,\n        lazyConnect: true\n      }\n    }\n  }\n});\n\n// Conversations are now persistent across client restarts\nconst response = await client.sendPrompt(\"Remember this: my favorite color is blue\");\nconsole.log(\"Response:\", response);\n\n// Later, in a new client instance with the same sessionId...\nconst newClient = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  sessionId: \"user-session-123\", // Same session ID\n  storage: { type: \"redis\", config: { /* same config */ } }\n});\n\nconst response2 = await newClient.sendPrompt(\"What's my favorite color?\");\n// The model will remember the previous conversation!\n```\n\n### Storage Configuration Options\n\n#### In-Memory Storage (Default)\n```typescript\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  // No storage config = in-memory storage\n  // OR explicitly specify:\n  storage: { type: \"memory\" }\n});\n```\n\n#### Redis Storage\n```typescript\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  storage: {\n    type: \"redis\",\n    config: {\n      host: \"localhost\",        // Redis host (default: 'localhost')\n      port: 6379,              // Redis port (default: 6379)\n      password: \"password\",    // Redis password (optional)\n      db: 0,                   // Redis database (default: 0)\n      keyPrefix: \"myapp:\",     // Key prefix (default: 'bedrock-mcp:conversation:')\n      ttl: 3600,              // TTL in seconds (default: 86400 - 24 hours)\n      connectionOptions: {     // Additional Redis connection options\n        connectTimeout: 5000,\n        lazyConnect: true,\n        retryDelayOnFailover: 100,\n        maxRetriesPerRequest: 3\n      }\n    }\n  }\n});\n```\n\n### With Event Listeners\n\n```typescript\nimport { BedrockMCPClient, LogLevel } from \"@juspay/bedrock-mcp-connector\";\n\n// Create a client\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n});\n\n// Set the log level (optional)\nclient.setLogLevel(LogLevel.INFO);\n\n// Set up event listeners\nconst emitter = client.getEmitter();\n\nemitter.on(\"message\", (message) =\u003e {\n  console.log(`Message: ${message}`);\n});\n\nemitter.on(\"error\", (error) =\u003e {\n  console.error(`Error: ${error.message}`);\n});\n\nemitter.on(\"tool:start\", (toolName, input) =\u003e {\n  console.log(`Tool started: ${toolName}`);\n});\n\nemitter.on(\"tool:end\", (toolName, result) =\u003e {\n  console.log(`Tool completed: ${toolName}`);\n});\n\nemitter.on(\"response:start\", () =\u003e {\n  console.log(\"Response started\");\n});\n\nemitter.on(\"response:chunk\", (chunk) =\u003e {\n  console.log(`Response chunk: ${chunk.substring(0, 50)}...`);\n});\n\nemitter.on(\"response:end\", (fullResponse) =\u003e {\n  console.log(\"Response completed\");\n});\n\n// Send a prompt\nconst response = await client.sendPrompt(\"What is the capital of France?\");\n```\n\n## Creating and Registering Tools\n\nTools are a powerful feature that allow the LLM to perform actions and access external data. This section provides detailed guidance on how to create and register tools effectively.\n\n### Tool Registration Basics\n\nThe `registerTool` method takes four parameters:\n\n```typescript\nclient.registerTool(\n  name, // String: Unique identifier for the tool\n  handler, // Function: Async function that implements the tool\n  description, // String: Human-readable description of what the tool does\n  inputSchema // Object: JSON Schema defining the tool's parameters\n);\n```\n\n### Best Practices for Tool Design\n\n1. **Single Responsibility**: Each tool should do one thing well\n2. **Clear Naming**: Use descriptive, action-oriented names (e.g., `getCurrentTime`, `searchDatabase`)\n3. **Comprehensive Descriptions**: Provide detailed descriptions that help the LLM understand when to use the tool\n4. **Thorough Input Validation**: Always validate inputs to prevent errors\n5. **Informative Error Messages**: Return clear error messages when something goes wrong\n6. **Consistent Return Format**: Always return results in the same format\n7. **Appropriate Logging**: Include logging to help with debugging\n\n### Detailed Tool Registration Example\n\n```typescript\nimport { BedrockMCPClient, LogLevel } from \"@juspay/bedrock-mcp-connector\";\n\n// Create a client\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n});\n\n// Set the log level (optional)\nclient.setLogLevel(LogLevel.INFO);\n\n// Register a custom tool\nclient.registerTool(\n  // Name: Use a clear, descriptive name\n  \"getCurrentTime\",\n\n  // Handler: Implement the tool's functionality\n  async (name, input) =\u003e {\n    // Input validation with default values\n    const timezone = input.timezone || \"UTC\";\n\n    try {\n      // Core functionality\n      const date = new Date().toLocaleString(\"en-US\", { timeZone: timezone });\n\n      // Return successful result\n      return {\n        content: [{ text: `The current time is ${date} in ${timezone}` }],\n      };\n    } catch (error) {\n      // Error handling\n      return {\n        content: [{ text: `Error getting time: ${error.message}` }],\n        isError: true,\n      };\n    }\n  },\n\n  // Description: Clearly explain what the tool does\n  \"Get the current time in the specified timezone. This tool returns the current date and time formatted according to US locale conventions.\",\n\n  // Input Schema: Define the parameters using JSON Schema\n  {\n    type: \"object\",\n    properties: {\n      timezone: {\n        type: \"string\",\n        description:\n          \"The timezone to get the time for (e.g., UTC, America/New_York, Europe/London)\",\n        examples: [\"UTC\", \"America/New_York\", \"Europe/Paris\", \"Asia/Tokyo\"],\n      },\n    },\n    required: [], // Empty array means no parameters are required\n  }\n);\n\n// Send a prompt that might use the tool\nconst response = await client.sendPrompt(\"What time is it now in Tokyo?\");\n```\n\n### Input Schema Design\n\nThe input schema uses JSON Schema format to define the parameters your tool accepts:\n\n```typescript\n{\n  type: \"object\",\n  properties: {\n    // Define each parameter\n    paramName: {\n      type: \"string\" | \"number\" | \"boolean\" | \"array\" | \"object\",\n      description: \"Clear description of the parameter\",\n      examples: [\"example1\", \"example2\"], // Optional but helpful\n      enum: [\"option1\", \"option2\"],       // For parameters with fixed options\n      minimum: 1,                         // For number validation\n      maximum: 100,                       // For number validation\n      pattern: \"^[a-z]+$\",                // For string validation with regex\n      // Additional JSON Schema properties as needed\n    },\n    // More parameters...\n  },\n  required: [\"paramName1\", \"paramName2\"],  // List required parameters\n  additionalProperties: false              // Prevent extra parameters (optional)\n}\n```\n\n### Error Handling in Tools\n\nProper error handling is crucial for tools:\n\n```typescript\nclient.registerTool(\n  \"divideNumbers\",\n  async (name, input) =\u003e {\n    // Parameter validation\n    if (typeof input.dividend !== \"number\") {\n      return {\n        content: [{ text: \"Error: dividend must be a number\" }],\n        isError: true,\n      };\n    }\n\n    if (typeof input.divisor !== \"number\") {\n      return {\n        content: [{ text: \"Error: divisor must be a number\" }],\n        isError: true,\n      };\n    }\n\n    // Business logic validation\n    if (input.divisor === 0) {\n      return {\n        content: [{ text: \"Error: Cannot divide by zero\" }],\n        isError: true,\n      };\n    }\n\n    try {\n      // Perform the operation\n      const result = input.dividend / input.divisor;\n\n      return {\n        content: [\n          {\n            text: `${input.dividend} divided by ${input.divisor} equals ${result}`,\n          },\n        ],\n      };\n    } catch (error) {\n      return {\n        content: [{ text: `Calculation error: ${error.message}` }],\n        isError: true,\n      };\n    }\n  },\n  \"Divide two numbers\",\n  {\n    type: \"object\",\n    properties: {\n      dividend: {\n        type: \"number\",\n        description: \"The number to be divided\",\n      },\n      divisor: {\n        type: \"number\",\n        description: \"The number to divide by (cannot be zero)\",\n      },\n    },\n    required: [\"dividend\", \"divisor\"],\n  }\n);\n```\n\n### Examples of Different Tool Types\n\n#### 1. Data Retrieval Tool\n\n```typescript\nclient.registerTool(\n  \"getWeatherForecast\",\n  async (name, input) =\u003e {\n    const { city, days = 3 } = input;\n\n    if (!city) {\n      return {\n        content: [{ text: \"Error: city parameter is required\" }],\n        isError: true,\n      };\n    }\n\n    try {\n      // In a real implementation, this would call a weather API\n      const forecast = await weatherService.getForecast(city, days);\n\n      return {\n        content: [\n          {\n            text: `Weather forecast for ${city} for the next ${days} days:\\n\\n${forecast}`,\n          },\n        ],\n      };\n    } catch (error) {\n      return {\n        content: [{ text: `Error getting weather forecast: ${error.message}` }],\n        isError: true,\n      };\n    }\n  },\n  \"Get weather forecast for a city\",\n  {\n    type: \"object\",\n    properties: {\n      city: {\n        type: \"string\",\n        description: \"The city to get the weather forecast for\",\n      },\n      days: {\n        type: \"number\",\n        description: \"Number of days to forecast (default: 3)\",\n        minimum: 1,\n        maximum: 10,\n      },\n    },\n    required: [\"city\"],\n  }\n);\n```\n\n#### 2. Computational Tool\n\n```typescript\nclient.registerTool(\n  \"calculateStatistics\",\n  async (name, input) =\u003e {\n    const { numbers } = input;\n\n    if (!Array.isArray(numbers) || numbers.length === 0) {\n      return {\n        content: [\n          { text: \"Error: numbers must be a non-empty array of numbers\" },\n        ],\n        isError: true,\n      };\n    }\n\n    if (!numbers.every((n) =\u003e typeof n === \"number\")) {\n      return {\n        content: [{ text: \"Error: all elements in numbers must be numbers\" }],\n        isError: true,\n      };\n    }\n\n    try {\n      const sum = numbers.reduce((a, b) =\u003e a + b, 0);\n      const mean = sum / numbers.length;\n      const sortedNumbers = [...numbers].sort((a, b) =\u003e a - b);\n      const median =\n        sortedNumbers.length % 2 === 0\n          ? (sortedNumbers[sortedNumbers.length / 2 - 1] +\n              sortedNumbers[sortedNumbers.length / 2]) /\n            2\n          : sortedNumbers[Math.floor(sortedNumbers.length / 2)];\n\n      return {\n        content: [\n          {\n            text: `Statistics for [${numbers.join(\n              \", \"\n            )}]:\\n- Sum: ${sum}\\n- Mean: ${mean}\\n- Median: ${median}\\n- Min: ${Math.min(\n              ...numbers\n            )}\\n- Max: ${Math.max(...numbers)}`,\n          },\n        ],\n      };\n    } catch (error) {\n      return {\n        content: [{ text: `Error calculating statistics: ${error.message}` }],\n        isError: true,\n      };\n    }\n  },\n  \"Calculate basic statistics for an array of numbers\",\n  {\n    type: \"object\",\n    properties: {\n      numbers: {\n        type: \"array\",\n        items: {\n          type: \"number\",\n        },\n        description: \"Array of numbers to calculate statistics for\",\n      },\n    },\n    required: [\"numbers\"],\n  }\n);\n```\n\n#### 3. External API Tool\n\n```typescript\nclient.registerTool(\n  \"searchWikipedia\",\n  async (name, input) =\u003e {\n    const { query, limit = 3 } = input;\n\n    if (!query || typeof query !== \"string\") {\n      return {\n        content: [\n          { text: \"Error: query parameter is required and must be a string\" },\n        ],\n        isError: true,\n      };\n    }\n\n    try {\n      // In a real implementation, this would call the Wikipedia API\n      const searchUrl = `https://en.wikipedia.org/w/api.php?action=opensearch\u0026search=${encodeURIComponent(\n        query\n      )}\u0026limit=${limit}\u0026namespace=0\u0026format=json`;\n      const response = await fetch(searchUrl);\n      const [searchTerm, titles, descriptions, urls] = await response.json();\n\n      let resultText = `Wikipedia search results for \"${query}\":\\n\\n`;\n\n      for (let i = 0; i \u003c titles.length; i++) {\n        resultText += `${i + 1}. ${titles[i]}\\n`;\n        resultText += `   ${descriptions[i]}\\n`;\n        resultText += `   ${urls[i]}\\n\\n`;\n      }\n\n      return {\n        content: [{ text: resultText }],\n      };\n    } catch (error) {\n      return {\n        content: [{ text: `Error searching Wikipedia: ${error.message}` }],\n        isError: true,\n      };\n    }\n  },\n  \"Search Wikipedia for information on a topic\",\n  {\n    type: \"object\",\n    properties: {\n      query: {\n        type: \"string\",\n        description: \"The search query\",\n      },\n      limit: {\n        type: \"number\",\n        description: \"Maximum number of results to return (default: 3)\",\n        minimum: 1,\n        maximum: 10,\n      },\n    },\n    required: [\"query\"],\n  }\n);\n```\n\n### Tips for Effective Tool Usage\n\n1. **Provide Clear Instructions in System Prompt**: Guide the LLM on when and how to use tools\n2. **Use Descriptive Tool Names**: Names should clearly indicate the tool's purpose\n3. **Include Detailed Parameter Descriptions**: Help the LLM understand what each parameter does\n4. **Add Examples in Parameter Descriptions**: Show valid values for parameters\n5. **Implement Thorough Validation**: Check all inputs before processing\n6. **Return Structured Data**: Format tool results consistently\n7. **Handle Errors Gracefully**: Provide clear error messages\n8. **Test Tools Thoroughly**: Ensure they work with various inputs\n\n### Advanced Tool Registration\n\nFor more complex tools, you can structure your code to make it more maintainable:\n\n```typescript\n// Define tool handlers in separate files\nimport { searchDatabase } from \"./tools/database.js\";\nimport { processImage } from \"./tools/image.js\";\nimport { translateText } from \"./tools/translation.js\";\n\n// Import tool schemas\nimport {\n  searchDatabaseSchema,\n  processImageSchema,\n  translateTextSchema,\n} from \"./schemas/toolSchemas.js\";\n\n// Register tools\nclient.registerTool(\n  \"searchDatabase\",\n  searchDatabase,\n  \"Search the database for records matching the query\",\n  searchDatabaseSchema\n);\n\nclient.registerTool(\n  \"processImage\",\n  processImage,\n  \"Process and analyze an image\",\n  processImageSchema\n);\n\nclient.registerTool(\n  \"translateText\",\n  translateText,\n  \"Translate text between languages\",\n  translateTextSchema\n);\n```\n\nBy following these best practices, you can create tools that are easy for the LLM to understand and use effectively, resulting in better responses for your users.\n\n### Command Line Interface\n\nThe package includes a command-line interface for interactive usage:\n\n```bash\nnpx @juspay/bedrock-mcp-connector\n```\n\nOr install globally:\n\n```bash\nnpm install -g @juspay/bedrock-mcp-connector\n@juspay/bedrock-mcp-connector\n```\n\n#### CLI Options\n\n```\nOptions:\n  -m, --model \u003cid\u003e           AWS Bedrock model ID (default: anthropic.claude-3-sonnet-20240229-v1:0)\n  -r, --region \u003cregion\u003e      AWS region (default: us-east-1)\n  -s, --system-prompt \u003ctext\u003e System prompt for the model\n  -u, --mcp-url \u003curl\u003e        MCP server URL\n  -n, --name \u003cname\u003e          Client name\n  -v, --version \u003cversion\u003e    Client version\n  -h, --help                 Show this help message\n```\n\n## Session Management and Multi-User Support\n\nThe package supports sophisticated session management for multi-user applications:\n\n### Session Isolation\n```typescript\n// User 1's conversation\nconst user1Client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  sessionId: \"session-user1-chat1\",\n  userId: \"user1\",\n  storage: { type: \"redis\", config: { /* redis config */ } }\n});\n\n// User 2's conversation (completely isolated)\nconst user2Client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  sessionId: \"session-user2-chat1\",\n  userId: \"user2\",\n  storage: { type: \"redis\", config: { /* redis config */ } }\n});\n```\n\n### Storage Health Monitoring\n```typescript\n// Check if storage is healthy\nconst isHealthy = await client.isStorageHealthy();\nif (!isHealthy) {\n  console.log(\"Storage connection issues detected\");\n}\n\n// Get storage information\nconst storageInfo = client.getStorageInfo();\nconsole.log(\"Storage type:\", storageInfo.type); // 'memory' or 'redis'\n```\n\n### Redis Key Management\n\nWhen using Redis storage, keys are structured as follows:\n- Pattern: `{keyPrefix}{userId}:{sessionId}` or `{keyPrefix}{sessionId}`\n- Default prefix: `bedrock-mcp:conversation:`\n- Example keys:\n  - `bedrock-mcp:conversation:user123:session456`\n  - `bedrock-mcp:conversation:anonymous-session789`\n\n### Storage Migration\n\nYou can migrate between storage types by copying conversation history:\n\n```typescript\n// Get history from in-memory client\nconst memoryClient = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  storage: { type: \"memory\" }\n});\n\nconst history = await memoryClient.getConversationHistory();\n\n// Create Redis client and restore history\nconst redisClient = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  storage: { type: \"redis\", config: { /* config */ } }\n});\n\n// Note: Direct history restoration requires custom implementation\n// The storage layer handles this automatically for same-session clients\n```\n\n## API Reference\n\n### BedrockMCPClient\n\n#### Constructor\n\n```typescript\nnew BedrockMCPClient(config: {\n  modelId: string;\n  region?: string;\n  systemPrompt?: string;\n  mcpServerUrl?: string;\n  clientName?: string;\n  clientVersion?: string;\n  maxTokens?: number;\n  temperature?: number;\n  responseOutputTags?: [string, string];\n  storage?: StorageConfig;\n  sessionId?: string;\n  userId?: string;\n})\n```\n\n#### Methods\n\n- `connect(): Promise\u003cvoid\u003e` - Connect to the MCP server\n- `disconnect(): Promise\u003cvoid\u003e` - Disconnect from the MCP server and close storage\n- `isConnectedToMCP(): boolean` - Check if the client is connected to the MCP server\n- `sendPrompt(prompt: string): Promise\u003cstring\u003e` - Send a prompt to the agent\n- `registerTool(name: string, handler: ToolHandler, description?: string, inputSchema?: Record\u003cstring, any\u003e): void` - Register a custom tool\n- `getTools(): Array\u003c{ name: string; description?: string }\u003e` - Get all registered tools\n- `getEmitter(): BedrockMCPClientEmitter` - Get the event emitter\n- `getAgent(): ConverseAgent` - Get the agent\n- `getConversationHistory(): Promise\u003cMessage[]\u003e` - Get the conversation history\n- `clearConversationHistory(): Promise\u003cvoid\u003e` - Clear the conversation history\n- `setLogLevel(level: LogLevel): void` - Set the log level for the client and its components\n- `isStorageHealthy(): Promise\u003cboolean\u003e` - Check if storage is healthy\n- `getStorageInfo(): { type: string; isHealthy?: boolean }` - Get storage type information\n\n### Storage Types\n\n#### StorageConfig\n```typescript\ntype StorageConfig =\n  | { type: 'memory' }\n  | { type: 'redis'; config: RedisStorageConfig };\n```\n\n#### RedisStorageConfig\n```typescript\ninterface RedisStorageConfig {\n  host?: string;                    // Redis host (default: 'localhost')\n  port?: number;                    // Redis port (default: 6379)\n  password?: string;                // Redis password\n  db?: number;                      // Redis database number (default: 0)\n  keyPrefix?: string;               // Key prefix (default: 'bedrock-mcp:conversation:')\n  ttl?: number;                     // TTL in seconds (default: 86400)\n  connectionOptions?: {             // Additional Redis connection options\n    connectTimeout?: number;\n    lazyConnect?: boolean;\n    retryDelayOnFailover?: number;\n    maxRetriesPerRequest?: number;\n    [key: string]: any;\n  };\n}\n```\n\n#### SessionIdentifier\n```typescript\ninterface SessionIdentifier {\n  sessionId: string;                // Unique session ID\n  userId?: string;                  // Optional user ID for multi-user scenarios\n}\n```\n\n### Events\n\n- `message` - Emitted when a message is logged\n- `error` - Emitted when an error occurs\n- `tool:start` - Emitted when a tool starts executing\n- `tool:end` - Emitted when a tool finishes executing\n- `response:start` - Emitted when a response starts\n- `response:chunk` - Emitted when a response chunk is received\n- `response:end` - Emitted when a response ends\n- `connected` - Emitted when connected to the MCP server\n- `disconnected` - Emitted when disconnected from the MCP server\n\n## Logging System\n\nThe package includes a comprehensive logging system that allows you to control the verbosity of logs and debug information.\n\n### Log Levels\n\nThe following log levels are available (from most to least verbose):\n\n- `LogLevel.DEBUG` (0) - Detailed debugging information\n- `LogLevel.INFO` (1) - General information messages (default)\n- `LogLevel.WARN` (2) - Warning messages\n- `LogLevel.ERROR` (3) - Error messages\n- `LogLevel.NONE` (4) - No logging\n\n### Setting the Log Level\n\nYou can set the log level for the client and all its components:\n\n```typescript\nimport { BedrockMCPClient, LogLevel } from \"@juspay/bedrock-mcp-connector\";\n\n// Create a client\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n});\n\n// Set the log level\nclient.setLogLevel(LogLevel.INFO); // Default level\n// or\nclient.setLogLevel(LogLevel.DEBUG); // For detailed debugging\n```\n\n### What Gets Logged at Each Level\n\n- **DEBUG**: All messages, including detailed API responses, tool execution details, and internal state changes\n- **INFO**: General operational information, tool requests, connection status, and important events\n- **WARN**: Potential issues that don't prevent operation but might need attention\n- **ERROR**: Errors that affect operation but don't necessarily crash the application\n- **NONE**: No logs will be output (except for unhandled exceptions)\n\n### Use Cases\n\n#### Development and Debugging (LogLevel.DEBUG)\n\nUse the DEBUG level when:\n\n- Developing new features or tools\n- Troubleshooting issues with API responses\n- Debugging tool execution problems\n- Understanding the flow of data through the system\n\n```typescript\n// Enable detailed debugging\nclient.setLogLevel(LogLevel.DEBUG);\n\n// Now you'll see detailed information about:\n// - Full API responses from Bedrock\n// - Tool input and output details\n// - Message content and processing\n```\n\n#### Production Usage (LogLevel.INFO or LogLevel.WARN)\n\nFor production environments:\n\n- Use INFO to keep track of normal operations\n- Use WARN to only see potential issues\n\n```typescript\n// For normal operation with important information\nclient.setLogLevel(LogLevel.INFO);\n\n// Or for minimal logging (only warnings and errors)\nclient.setLogLevel(LogLevel.WARN);\n```\n\n#### Audit and Monitoring (LogLevel.INFO)\n\nWhen you need to track tool usage and interactions:\n\n```typescript\nclient.setLogLevel(LogLevel.INFO);\n\n// This will log:\n// - When tools are requested and executed\n// - Connection events\n// - Response start/end events\n```\n\n#### Silent Operation (LogLevel.NONE)\n\nWhen you want to suppress all logs:\n\n```typescript\nclient.setLogLevel(LogLevel.NONE);\n```\n\n## Conversation Management\n\nThe package maintains conversation history automatically, allowing for natural back-and-forth interactions with the model. This enables the model to remember context from previous messages and provide coherent responses throughout a conversation.\n\n### How Conversation History Works\n\n1. Each message sent to and received from the model is stored in memory\n2. The full conversation history is included with each new request to the model\n3. This allows the model to reference previous messages and maintain context\n\n### Managing Conversation History\n\nYou can access and manage the conversation history using these methods:\n\n```typescript\n// Get the current conversation history\nconst history = client.getConversationHistory();\nconsole.log(\"Current conversation:\", history);\n\n// Clear the conversation history to start a new conversation\nclient.clearConversationHistory();\nconsole.log(\"Started a new conversation\");\n```\n\n### Example: Multi-turn Conversation\n\n```typescript\nimport { BedrockMCPClient } from \"@juspay/bedrock-mcp-connector\";\n\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n});\n\n// First message\nlet response = await client.sendPrompt(\"What are the three primary colors?\");\nconsole.log(\"Response 1:\", response);\n\n// Follow-up question (model remembers the context)\nresponse = await client.sendPrompt(\n  \"And what colors do you get when you mix them?\"\n);\nconsole.log(\"Response 2:\", response);\n\n// Start a new conversation\nclient.clearConversationHistory();\n\n// This is now a completely new conversation with no memory of the previous exchange\nresponse = await client.sendPrompt(\"What's the tallest mountain in the world?\");\nconsole.log(\"New conversation response:\", response);\n```\n\n### Tool Results Across Multiple API Calls\n\nThe package maintains tool results across multiple API calls, ensuring that all tool results are included in the final response. This is particularly useful when the model needs to use multiple tools to answer a complex question.\n\n### Handling Missing Required Parameters\n\nWhen using tools that require specific parameters, you can implement an interactive flow where the model asks for missing information. There are two key approaches to handling missing parameters:\n\n#### 1. Using a Specialized System Prompt\n\nYou can guide the model's behavior with a specialized system prompt that instructs it on how to handle missing parameters:\n\n```typescript\nconst client = new BedrockMCPClient({\n  modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n  region: \"us-east-1\",\n  systemPrompt: `You are a helpful assistant with access to external tools.\n                  - Use available tools **only when necessary** to provide accurate or up-to-date information.\n                  - If a question can be answered based on your knowledge, respond directly **without using tools**.\n                  - If a tool is required:\n                      1. **Check if all necessary parameters are available.** If they are, use the tool directly.\n                      2. **If any parameters are missing, do not proceed.** Instead, ask the user for the required information, explaining why it is needed.\n                      3. **Wait for the user's response before using the tool.**\n                  - If the user asks multiple questions, **handle them one by one**.\n                  - If some questions require tools and others don't, **answer what you can immediately**, then use tools as needed.\n                  - After using a tool, continue answering any remaining questions.\n                  `,\n});\n```\n\nThis system prompt instructs the model to:\n\n- Not attempt to use tools with incomplete parameters\n- Clearly explain which parameters are missing and why they're needed\n- Ask the user for the missing information\n- Only use the tool once all required parameters are available\n\n#### 2. Implementing Parameter Validation in Tools\n\nImplement thorough parameter validation in your tool handlers to ensure they handle missing parameters gracefully:\n\n```typescript\nclient.registerTool(\n  \"calculator\",\n  async (name, input) =\u003e {\n    const { operation, a, b } = input;\n\n    // Validate required parameters\n    if (!operation) {\n      return {\n        content: [\n          { text: `Error: Operation parameter is required for calculator` },\n        ],\n        isError: true,\n      };\n    }\n\n    if (a === undefined || a === null) {\n      return {\n        content: [\n          { text: `Error: First operand (a) is required for calculator` },\n        ],\n        isError: true,\n      };\n    }\n\n    if (b === undefined || b === null) {\n      return {\n        content: [\n          { text: `Error: Second operand (b) is required for calculator` },\n        ],\n        isError: true,\n      };\n    }\n\n    // Tool implementation...\n    let result;\n    switch (operation) {\n      case \"add\":\n        result = a + b;\n        break;\n      case \"subtract\":\n        result = a - b;\n        break;\n      case \"multiply\":\n        result = a * b;\n        break;\n      case \"divide\":\n        if (b === 0) throw new Error(\"Division by zero\");\n        result = a / b;\n        break;\n      default:\n        throw new Error(`Unknown operation: ${operation}`);\n    }\n\n    return {\n      content: [{ text: `The result of ${a} ${operation} ${b} is ${result}` }],\n    };\n  },\n  \"Perform basic arithmetic operations\",\n  {\n    type: \"object\",\n    properties: {\n      operation: {\n        type: \"string\",\n        description:\n          \"The operation to perform (add, subtract, multiply, divide)\",\n        enum: [\"add\", \"subtract\", \"multiply\", \"divide\"],\n      },\n      a: { type: \"number\", description: \"The first operand\" },\n      b: { type: \"number\", description: \"The second operand\" },\n    },\n    required: [\"operation\", \"a\", \"b\"],\n  }\n);\n```\n\n#### 3. Interactive Conversation Flow\n\nImplement an interactive conversation flow that handles the back-and-forth between the user and the model:\n\n```typescript\nimport { BedrockMCPClient } from \"@juspay/bedrock-mcp-connector\";\nimport * as readline from \"readline\";\n\n// Create a readline interface for user input\nconst rl = readline.createInterface({\n  input: process.stdin,\n  output: process.stdout,\n});\n\n// Function to get user input\nconst getUserInput = (question) =\u003e\n  new Promise((resolve) =\u003e {\n    rl.question(question, (answer) =\u003e resolve(answer));\n  });\n\nasync function runInteractiveSession() {\n  const client = new BedrockMCPClient({\n    modelId: \"anthropic.claude-3-sonnet-20240229-v1:0\",\n    region: \"us-east-1\",\n    systemPrompt: `You are a helpful assistant with access to external tools.\n                  - Use available tools **only when necessary** to provide accurate or up-to-date information.\n                  - If a question can be answered based on your knowledge, respond directly **without using tools**.\n                  - If a tool is required:\n                      1. **Check if all necessary parameters are available.** If they are, use the tool directly.\n                      2. **If any parameters are missing, do not proceed.** Instead, ask the user for the required information, explaining why it is needed.\n                      3. **Wait for the user's response before using the tool.**\n                  - If the user asks multiple questions, **handle them one by one**.\n                  - If some questions require tools and others don't, **answer what you can immediately**, then use tools as needed.\n                  - After using a tool, continue answering any remaining questions.\n                  `,\n  });\n\n  // Register tools (calculator, weather forecast, etc.)\n  // ...\n\n  // Start the conversation\n  console.log(\"Ask me anything! (Type 'exit' to quit)\");\n\n  while (true) {\n    // Get user input\n    const userInput = await getUserInput(\"\u003e \");\n\n    if (userInput.toLowerCase() === \"exit\") break;\n\n    // Send to the model\n    const response = await client.sendPrompt(userInput);\n    console.log(\"\\nAssistant:\", response);\n  }\n\n  rl.close();\n}\n\nrunInteractiveSession().catch(console.error);\n```\n\n#### 4. Managing Tool Results Between Conversations\n\nWhen implementing multi-turn conversations, it's important to clear accumulated tool results between separate conversations to prevent results from previous conversations affecting new ones:\n\n```typescript\n// After completing a conversation or when starting a new one\nclient.clearConversationHistory();\nclient.getAgent().clearAccumulatedToolResults();\n```\n\nThis ensures that tool results from previous conversations don't appear in new conversations.\n\n#### Example: Complete Conversation Flow\n\nHere's an example of a complete conversation flow where the model asks for missing parameters:\n\n1. User asks a question with incomplete parameters:\n\n   ```\n   User: \"Can you calculate something for me? I want to multiply 42 by something.\"\n   ```\n\n2. Model responds, asking for the missing parameter:\n\n   ```\n   Assistant: \"I'd be happy to help you with that calculation. To use the calculator tool,\n   I need two operands (numbers) and the operation. You've provided one number (42) and\n   mentioned you want to multiply, but I'm missing the second operand.\n   Could you please tell me what number you want to multiply 42 by?\"\n   ```\n\n3. User provides the missing parameter:\n\n   ```\n   User: \"The second number is 7.\"\n   ```\n\n4. Model uses the tool with complete parameters:\n   ```\n   Assistant: \"I've calculated that 42 multiplied by 7 equals 294.\"\n   ```\n\nThis pattern allows for natural conversations where the model can request missing information and then use that information to complete the tool execution.\n\n### Creating a Custom Logger\n\nYou can create your own logger for other parts of your application:\n\n```typescript\nimport { createDefaultLogger, LogLevel } from \"@juspay/bedrock-mcp-connector\";\n\n// Create a logger with a custom prefix\nconst logger = createDefaultLogger(\"MyComponent\");\n\n// Set the log level\nlogger.setLevel(LogLevel.INFO);\n\n// Use the logger\nlogger.info(\"Application started\");\nlogger.debug(\"This won't be shown unless log level is DEBUG\");\nlogger.warn(\"Something might be wrong\");\nlogger.error(\"An error occurred\", errorObject);\n```\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuspay%2Fbedrock-mcp-connector","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjuspay%2Fbedrock-mcp-connector","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjuspay%2Fbedrock-mcp-connector/lists"}