#
tokens: 7143/50000 10/10 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .github
│   └── workflows
│       └── npm-publish.yml
├── .gitignore
├── example-client
│   ├── package-lock.json
│   ├── package.json
│   ├── README.md
│   ├── src
│   │   └── index.ts
│   └── tsconfig.json
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
1 | node_modules/
2 | build/
3 | *.log
4 | .env*
5 | .vscode/
6 | 
```

--------------------------------------------------------------------------------
/example-client/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | ## Example client to call the `generate_image` tool
 2 | 
 3 | This example demonstrates how to call the `generate_image` tool from terminal.
 4 | 
 5 | ### Prerequisites
 6 | 
 7 | - build the MCP server
 8 | ```bash
 9 | cd mcp-server-amazon-bedrock
10 | npm install
11 | npm run build
12 | ```
13 | 
14 | ### Usage
15 | 
16 | ```bash
17 | cd example-client
18 | npm install
19 | npm run build
20 | node build/index.js
21 | ```
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/zxkane-mcp-server-amazon-bedrock-badge.png)](https://mseep.ai/app/zxkane-mcp-server-amazon-bedrock)
  2 | 
  3 | # Amazon Bedrock MCP Server
  4 | 
  5 | A Model Control Protocol (MCP) server that integrates with Amazon Bedrock's Nova Canvas model for AI image generation.
  6 | 
  7 | <a href="https://glama.ai/mcp/servers/9qw7dwpvj9"><img width="380" height="200" src="https://glama.ai/mcp/servers/9qw7dwpvj9/badge" alt="Amazon Bedrock Server MCP server" /></a>
  8 | 
  9 | ## Features
 10 | 
 11 | - High-quality image generation from text descriptions using Amazon's Nova Canvas model
 12 | - Advanced control through negative prompts to refine image composition
 13 | - Flexible configuration options for image dimensions and quality
 14 | - Deterministic image generation with seed control
 15 | - Robust input validation and error handling
 16 | 
 17 | ## Prerequisites
 18 | 
 19 | 1. Active AWS account with Amazon Bedrock and Nova Canvas model access
 20 | 2. Properly configured AWS credentials with required permissions
 21 | 3. Node.js version 18 or later
 22 | 
 23 | ## Installation
 24 | 
 25 | ### AWS Credentials Configuration
 26 | 
 27 | The server requires AWS credentials with appropriate Amazon Bedrock permissions. Configure these using one of the following methods:
 28 | 
 29 | 1. Environment variables:
 30 |    ```bash
 31 |    export AWS_ACCESS_KEY_ID=your_access_key
 32 |    export AWS_SECRET_ACCESS_KEY=your_secret_key
 33 |    export AWS_REGION=us-east-1  # or your preferred region
 34 |    ```
 35 | 
 36 | 2. AWS credentials file (`~/.aws/credentials`):
 37 |    ```ini
 38 |    [the_profile_name]
 39 |    aws_access_key_id = your_access_key
 40 |    aws_secret_access_key = your_secret_key
 41 |    ```
 42 |    Environment variable for active profile:
 43 |    ```bash
 44 |    export AWS_PROFILE=the_profile_name
 45 |    ```
 46 | 
 47 | 3. IAM role (when deployed on AWS infrastructure)
 48 | 
 49 | ### Claude Desktop Integration
 50 | 
 51 | To integrate with Claude Desktop, add the following configuration to your settings file:
 52 | 
 53 | MacOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
 54 | Windows: `%APPDATA%/Claude/claude_desktop_config.json`
 55 | 
 56 | ```json
 57 | {
 58 |   "mcpServers": {
 59 |     "amazon-bedrock": {
 60 |       "command": "npx",
 61 |       "args": [
 62 |         "-y",
 63 |         "@zxkane/mcp-server-amazon-bedrock"
 64 |       ],
 65 |       "env": {
 66 |         "AWS_PROFILE": "your_profile_name",         // Optional, only if you want to use a specific profile
 67 |         "AWS_ACCESS_KEY_ID": "your_access_key",     // Optional if using AWS credentials file or IAM role
 68 |         "AWS_SECRET_ACCESS_KEY": "your_secret_key", // Optional if using AWS credentials file or IAM role
 69 |         "AWS_REGION": "us-east-1"                   // Optional, defaults to 'us-east-1'
 70 |       }
 71 |     }
 72 |   }
 73 | }
 74 | ```
 75 | 
 76 | ## Available Tools
 77 | 
 78 | ### generate_image
 79 | 
 80 | Creates images from text descriptions using Amazon Bedrock's Nova Canvas model.
 81 | 
 82 | #### Parameters
 83 | 
 84 | - `prompt` (required): Descriptive text for the desired image (1-1024 characters)
 85 | - `negativePrompt` (optional): Elements to exclude from the image (1-1024 characters)
 86 | - `width` (optional): Image width in pixels (default: 1024)
 87 | - `height` (optional): Image height in pixels (default: 1024)
 88 | - `quality` (optional): Image quality level - "standard" or "premium" (default: "standard")
 89 | - `cfg_scale` (optional): Prompt adherence strength (1.1-10, default: 6.5)
 90 | - `seed` (optional): Generation seed for reproducibility (0-858993459, default: 12)
 91 | - `numberOfImages` (optional): Batch size for generation (1-5, default: 1)
 92 | 
 93 | #### Example Implementation
 94 | 
 95 | ```typescript
 96 | const result = await callTool('generate_image', {
 97 |   prompt: "A serene mountain landscape at sunset",
 98 |   negativePrompt: "people, buildings, vehicles",
 99 |   quality: "premium",
100 |   cfg_scale: 8,
101 |   numberOfImages: 2
102 | });
103 | ```
104 | 
105 | #### Prompt Guidelines
106 | 
107 | For optimal results, avoid negative phrasing ("no", "not", "without") in the main prompt. Instead, move these elements to the `negativePrompt` parameter. For example, rather than using "a landscape without buildings" in the prompt, use "buildings" in the `negativePrompt`.
108 | 
109 | For detailed usage guidelines, refer to the [Nova Canvas documentation][nova-canvas-doc].
110 | 
111 | ## Development
112 | 
113 | To set up and run the server in a local environment:
114 | 
115 | ```bash
116 | git clone https://github.com/zxkane/mcp-server-amazon-bedrock.git
117 | cd mcp-server-amazon-bedrock
118 | npm install
119 | npm run build
120 | ```
121 | 
122 | ### Performance Considerations
123 | 
124 | Generation time is influenced by resolution (`width` and `height`), `numberOfImages`, and `quality` settings. When using higher values, be mindful of potential timeout implications in your implementation.
125 | 
126 | ## License
127 | 
128 | This project is licensed under the MIT License - see the LICENSE file for details.
129 | 
130 | [nova-canvas-doc]: https://docs.aws.amazon.com/nova/latest/userguide/image-gen-access.html
131 | 
```

--------------------------------------------------------------------------------
/example-client/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "example-client",
 3 |   "version": "1.0.0",
 4 |   "type": "module",
 5 |   "scripts": {
 6 |     "build": "tsc",
 7 |     "start": "node build/index.js"
 8 |   },
 9 |   "dependencies": {
10 |     "@modelcontextprotocol/sdk": "^1.0.0",
11 |     "terminal-image": "^3.0.0",
12 |     "typescript": "^5.0.0"
13 |   }
14 | }
15 | 
```

--------------------------------------------------------------------------------
/example-client/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2020",
 4 |     "module": "ES2020",
 5 |     "moduleResolution": "node",
 6 |     "esModuleInterop": true,
 7 |     "strict": true,
 8 |     "outDir": "build",
 9 |     "skipLibCheck": true,
10 |     "forceConsistentCasingInFileNames": true
11 |   },
12 |   "include": ["src/**/*"],
13 |   "exclude": ["node_modules"]
14 | }
15 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "Node16",
 5 |     "moduleResolution": "Node16",
 6 |     "outDir": "./build",
 7 |     "rootDir": "./src",
 8 |     "strict": true,
 9 |     "esModuleInterop": true,
10 |     "skipLibCheck": true,
11 |     "forceConsistentCasingInFileNames": true
12 |   },
13 |   "include": ["src/**/*"],
14 |   "exclude": ["node_modules"]
15 | }
16 | 
```

--------------------------------------------------------------------------------
/.github/workflows/npm-publish.yml:
--------------------------------------------------------------------------------

```yaml
 1 | name: Publish to NPM
 2 | 
 3 | on:
 4 |   release:
 5 |     types: [created]
 6 | 
 7 | jobs:
 8 |   publish:
 9 |     runs-on: ubuntu-latest
10 |     steps:
11 |       - uses: actions/checkout@v4
12 |       
13 |       - name: Setup Node.js
14 |         uses: actions/setup-node@v4
15 |         with:
16 |           node-version: '20'
17 |           registry-url: 'https://registry.npmjs.org'
18 |       
19 |       - name: Install dependencies
20 |         run: npm ci
21 |       
22 |       - name: Build
23 |         run: npm run build
24 |       
25 |       - name: Publish to NPM
26 |         run: npm publish
27 |         env:
28 |           NODE_AUTH_TOKEN: ${{ secrets.npm_token }} 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "name": "@zxkane/mcp-server-amazon-bedrock",
 3 |   "version": "0.1.1",
 4 |   "description": "Use Amazon Bedrock Nova models to generate image.",
 5 |   "author": "Kane Zhu",
 6 |   "type": "module",
 7 |   "bin": {
 8 |     "mcp-server-amazon-bedrock": "./build/index.js"
 9 |   },
10 |   "files": [
11 |     "build"
12 |   ],
13 |   "publishConfig": {
14 |     "access": "public"
15 |   },
16 |   "scripts": {
17 |     "build": "tsc && node -e \"require('fs').chmodSync('build/index.js', '755')\"",
18 |     "prepare": "npm run build",
19 |     "watch": "tsc --watch",
20 |     "inspector": "npx @modelcontextprotocol/inspector build/index.js"
21 |   },
22 |   "dependencies": {
23 |     "@aws-sdk/client-bedrock-runtime": "^3.716.0",
24 |     "@aws-sdk/credential-providers": "^3.716.0",
25 |     "@modelcontextprotocol/sdk": "0.6.0",
26 |     "zod": "^3.24.1"
27 |   },
28 |   "devDependencies": {
29 |     "@types/node": "^20.11.24",
30 |     "typescript": "^5.3.3"
31 |   },
32 |   "keywords": [
33 |     "mcp",
34 |     "amazon",
35 |     "bedrock",
36 |     "ai",
37 |     "image-generation"
38 |   ],
39 |   "license": "MIT"
40 | }
41 | 
```

--------------------------------------------------------------------------------
/example-client/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | import path from 'path';
  2 | import { fileURLToPath } from 'url';
  3 | import { Client } from "@modelcontextprotocol/sdk/client/index.js";
  4 | import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
  5 | import {
  6 |   ListToolsResultSchema,
  7 |   CallToolResultSchema
  8 | } from "@modelcontextprotocol/sdk/types.js";
  9 | import terminalImage from "terminal-image";
 10 | 
 11 | async function main() {
 12 |   // Get the current file's directory
 13 |   const __filename = fileURLToPath(import.meta.url);
 14 |   const __dirname = path.dirname(__filename);
 15 | 
 16 |   // Initialize the client
 17 |   const client = new Client(
 18 |     {
 19 |       name: "example-bedrock-client",
 20 |       version: "1.0.0",
 21 |     },
 22 |     {
 23 |       capabilities: {},
 24 |     }
 25 |   );
 26 | 
 27 |   try {
 28 |     // Use path.resolve to get the correct path to the server script
 29 |     const transport = new StdioClientTransport({
 30 |       command: path.resolve(__dirname, "../../build/index.js"),
 31 |       env: {
 32 |         ...process.env, // Pass all environment variables
 33 |         NODE_ENV: process.env.NODE_ENV || 'development',
 34 |       }
 35 |     });
 36 |     await client.connect(transport);
 37 |     console.log("Connected to Amazon Bedrock MCP server");
 38 | 
 39 |     // List available tools
 40 |     const tools = await client.request(
 41 |       { method: "tools/list" },
 42 |       ListToolsResultSchema
 43 |     );
 44 |     console.log("Available tools:", tools);
 45 | 
 46 |     // Log start time
 47 |     const startTime = new Date();
 48 |     console.log(`Image Generation Request started at: ${startTime.toISOString()}`);
 49 | 
 50 |     // Example: Generate an image using the generate_image tool
 51 |     const imageResult = await client.request(
 52 |       {
 53 |         method: "tools/call",
 54 |         params: {
 55 |           name: "generate_image",
 56 |           arguments: {
 57 |             prompt: "A serene landscape with mountains and a lake at sunset",
 58 |             width: 1024,
 59 |             height: 1024,
 60 |             quality: "standard", 
 61 |             cfg_scale: 7,
 62 |             seed: 42,
 63 |             numberOfImages: 2,
 64 |           },
 65 |         },
 66 |       },
 67 |       CallToolResultSchema
 68 |     );
 69 |     // Log end time and duration
 70 |     const endTime = new Date();
 71 |     const duration = endTime.getTime() - startTime.getTime();
 72 | 
 73 |     if (imageResult.content && imageResult.content.length > 0) {
 74 |       for (const content of imageResult.content) {
 75 |         if (content.type === "image") {
 76 |           console.log("Image generated successfully!");
 77 |           try {
 78 |             const buffer = Buffer.from(content.data, 'base64');
 79 |             console.log(await terminalImage.buffer(buffer));
 80 |           } catch (err) {
 81 |             console.error('Error displaying image:', err);
 82 |           }
 83 |         } else if (content.type === "text") {
 84 |           console.log("Text generated:", content.text);
 85 |         }
 86 |       }
 87 |     }
 88 | 
 89 |     console.log(`Request completed at: ${endTime.toISOString()}`);
 90 |     console.log(`Total duration: ${duration}ms`);
 91 | 
 92 |     // Clean up
 93 |     await client.close();
 94 |   } catch (error) {
 95 |     console.error("Error:", error);
 96 |     process.exit(1);
 97 |   }
 98 | }
 99 | 
100 | // Handle interrupts
101 | process.on("SIGINT", () => {
102 |   console.log("Interrupted, exiting...");
103 |   process.exit(0);
104 | });
105 | 
106 | main().catch(console.error);
107 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | #!/usr/bin/env node
  2 | 
  3 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
  4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  5 | import {
  6 |   CallToolRequestSchema,
  7 |   ErrorCode,
  8 |   ListToolsRequestSchema,
  9 |   McpError,
 10 | } from "@modelcontextprotocol/sdk/types.js";
 11 | import { BedrockRuntimeClient, InvokeModelCommand } from "@aws-sdk/client-bedrock-runtime";
 12 | import { NodeHttpHandler } from "@smithy/node-http-handler";
 13 | import { fromNodeProviderChain, fromIni } from "@aws-sdk/credential-providers";
 14 | import { z } from "zod";
 15 | 
 16 | const AWS_REGION = process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION || 'us-east-1';
 17 | const AWS_PROFILE = process.env.AWS_PROFILE || 'default';
 18 | 
 19 | // Log AWS configuration for debugging
 20 | console.error('AWS Configuration:', {
 21 |   region: AWS_REGION,
 22 |   profile: AWS_PROFILE,
 23 |   hasAccessKeyId: !!process.env.AWS_ACCESS_KEY_ID,
 24 |   hasSecretKey: !!process.env.AWS_SECRET_ACCESS_KEY,
 25 |   hasSessionToken: !!process.env.AWS_SESSION_TOKEN
 26 | });
 27 | 
 28 | // Initialize Bedrock client with comprehensive configuration including credentials and timeouts
 29 | const bedrock = new BedrockRuntimeClient({
 30 |   region: AWS_REGION,
 31 |   maxAttempts: 3,
 32 |   // Try explicit profile credentials first, then fall back to provider chain
 33 |   credentials: async () => {
 34 |     try {
 35 |       // First try loading from profile
 36 |       const profileCreds = await fromIni({ profile: AWS_PROFILE })();
 37 |       console.error('Successfully loaded credentials from profile');
 38 |       return profileCreds;
 39 |     } catch (error) {
 40 |       console.error('Failed to load profile credentials, falling back to provider chain:', error);
 41 |       try {
 42 |         // Fall back to provider chain
 43 |         const chainCreds = await fromNodeProviderChain()();
 44 |         console.error('Successfully loaded credentials from provider chain');
 45 |         return chainCreds;
 46 |       } catch (error) {
 47 |         console.error('Failed to load credentials from provider chain:', error);
 48 |         throw error;
 49 |       }
 50 |     }
 51 |   },
 52 |   requestHandler: new NodeHttpHandler({
 53 |     connectionTimeout: 10000, // 10 seconds connection timeout
 54 |     requestTimeout: 300000, // 5 minutes request timeout
 55 |   })
 56 | });
 57 | 
 58 | // Log Bedrock client initialization
 59 | console.error('Bedrock client initialized');
 60 | 
 61 | // Constants
 62 | const NOVA_MODEL_ID = 'amazon.nova-canvas-v1:0';
 63 | 
 64 | // Input validation schemas based on AWS Nova documentation
 65 | const GenerateImageSchema = z.object({
 66 |   prompt: z.string().min(1).max(1024, "Prompt must be 1-1024 characters"),
 67 |   negativePrompt: z.string().min(1).max(1024, "Negative prompt must be 1-1024 characters").optional(),
 68 |   width: z.number().int()
 69 |     .min(320, "Width must be at least 320 pixels")
 70 |     .max(4096, "Width must be at most 4096 pixels")
 71 |     .refine(val => val % 16 === 0, "Width must be divisible by 16")
 72 |     .default(1024),
 73 |   height: z.number().int()
 74 |     .min(320, "Height must be at least 320 pixels")
 75 |     .max(4096, "Height must be at most 4096 pixels")
 76 |     .refine(val => val % 16 === 0, "Height must be divisible by 16")
 77 |     .default(1024),
 78 |   quality: z.enum(["standard", "premium"]).default("standard"),
 79 |   cfg_scale: z.number().min(1.1).max(10).default(6.5),
 80 |   seed: z.number().int().min(0).max(858993459).default(12),
 81 |   numberOfImages: z.number().int().min(1).max(5).default(1)
 82 | }).refine(
 83 |   (data) => {
 84 |     // Check aspect ratio between 1:4 and 4:1
 85 |     const ratio = data.width / data.height;
 86 |     return ratio >= 0.25 && ratio <= 4;
 87 |   },
 88 |   "Aspect ratio must be between 1:4 and 4:1"
 89 | ).refine(
 90 |   (data) => {
 91 |     // Check total pixel count
 92 |     return data.width * data.height < 4194304;
 93 |   },
 94 |   "Total pixel count must be less than 4,194,304"
 95 | );
 96 | 
 97 | type GenerateImageInput = z.infer<typeof GenerateImageSchema>;
 98 | 
 99 | // Constants for image generation
100 | const GENERATION_TYPES = {
101 |   TEXT_TO_IMAGE: "TEXT_IMAGE",
102 | };
103 | 
104 | /**
105 |  * Create an MCP server for Amazon Bedrock image generation
106 |  */
107 | const server = new Server(
108 |   {
109 |     name: "mcp-server-amazon-bedrock",
110 |     version: "0.1.0",
111 |   },
112 |   {
113 |     capabilities: {
114 |       tools: {},
115 |       logging: {},
116 |     },
117 |   }
118 | );
119 | 
120 | /**
121 |  * Handler that lists available tools.
122 |  * Exposes a single "generate_image" tool that generates images using Amazon Bedrock.
123 |  */
124 | server.setRequestHandler(ListToolsRequestSchema, async () => {
125 |   return {
126 |     tools: [
127 |       {
128 |         name: "generate_image",
129 |         description: "Generate image(s) using Amazon Nova Canvas model. The returned data is Base64-encoded string that represent each image that was generated.",
130 |         inputSchema: {
131 |           type: "object",
132 |           properties: {
133 |             prompt: {
134 |               type: "string",
135 |               description: "Text description of the image to generate (1-1024 characters)",
136 |             },
137 |             negativePrompt: {
138 |               type: "string",
139 |               description: "Optional text description of what to avoid in the image (1-1024 characters)",
140 |             },
141 |             width: {
142 |               type: "number",
143 |               description: "Width of the generated image (default: 1024)",
144 |             },
145 |             height: {
146 |               type: "number",
147 |               description: "Height of the generated image (default: 1024)",
148 |             },
149 |             quality: {
150 |               type: "string",
151 |               enum: ["standard", "premium"],
152 |               description: "Quality of the generated image (default: standard)",
153 |             },
154 |             cfg_scale: {
155 |               type: "number",
156 |               description: "How closely to follow the prompt (1.1-10, default: 6.5)",
157 |             },
158 |             seed: {
159 |               type: "number",
160 |               description: "Seed for reproducible generation (0-858993459, default: 12)",
161 |             },
162 |             numberOfImages: {
163 |               type: "number",
164 |               description: "Number of images to generate (1-5, default: 1)",
165 |             },
166 |           },
167 |           required: ["prompt"],
168 |         },
169 |       },
170 |     ],
171 |   };
172 | });
173 | 
174 | interface BedrockResponse {
175 |   images: string[];
176 |   error?: string;
177 | }
178 | /**
179 |  * Handler for the generate_image tool.
180 |  * Uses Amazon Bedrock to generate an image based on the provided parameters.
181 |  */
182 | server.setRequestHandler(CallToolRequestSchema, async (request) => {
183 |   if (request.params.name !== "generate_image") {
184 |     throw new McpError(
185 |       ErrorCode.MethodNotFound,
186 |       `Unknown tool: ${request.params.name}`
187 |     );
188 |   }
189 | 
190 |   try {
191 |     // Validate and parse input
192 |     const args = GenerateImageSchema.parse(request.params.arguments);
193 |     
194 |     server.sendLoggingMessage({
195 |       level: "info",
196 |       data: `Configuration: ${JSON.stringify({
197 |         width: args.width,
198 |         height: args.height,
199 |         quality: args.quality,
200 |         numberOfImages: args.numberOfImages,
201 |         cfgScale: args.cfg_scale,
202 |         seed: args.seed
203 |       })}`,
204 |     });
205 | 
206 |     const progressToken = request.params._meta?.progressToken;
207 | 
208 |     server.sendLoggingMessage({
209 |       level: "info",
210 |       data: "Sending request to Bedrock API...",
211 |     });
212 | 
213 |     const response = await bedrock.send(new InvokeModelCommand({
214 |       modelId: NOVA_MODEL_ID,
215 |       contentType: "application/json",
216 |       accept: "application/json",
217 |       body: JSON.stringify({
218 |         taskType: GENERATION_TYPES.TEXT_TO_IMAGE,
219 |         textToImageParams: {
220 |           text: args.prompt,
221 |           negativeText: args.negativePrompt || undefined,
222 |         },
223 |         imageGenerationConfig: {
224 |           numberOfImages: args.numberOfImages,
225 |           height: args.height,
226 |           width: args.width,
227 |           quality: args.quality,
228 |           cfgScale: args.cfg_scale,
229 |           seed: args.seed
230 |         },
231 |       }),
232 |     }));
233 | 
234 |     server.sendLoggingMessage({
235 |       level: "info",
236 |       data: "Received response from Bedrock API",
237 |     });
238 | 
239 |     if (!response.body) {
240 |       server.sendLoggingMessage({
241 |         level: "error",
242 |         data: "No response body received from Bedrock",
243 |       });
244 |       throw new McpError(
245 |         ErrorCode.InternalError,
246 |         "No response body received from Bedrock"
247 |       );
248 |     }
249 | 
250 |     const responseBody = JSON.parse(new TextDecoder().decode(response.body)) as BedrockResponse;
251 | 
252 |     if (!responseBody.images || responseBody.images.length === 0) {
253 |       server.sendLoggingMessage({
254 |         level: "error",
255 |         data: "No image data in response",
256 |       });
257 |       throw new McpError(
258 |         ErrorCode.InternalError,
259 |         `No image data in response due to ${responseBody.error}.`
260 |       );
261 |     }
262 | 
263 |     server.sendLoggingMessage({
264 |       level: "info",
265 |       data: "Successfully generated image",
266 |     });
267 | 
268 |     // Return the response in the correct MCP format
269 |     return {
270 |       content: [
271 |         {
272 |           type: "text",
273 |           text: `This is the image generated for your request '${args.prompt}'.`,
274 |         },
275 |         ...responseBody.images.map(image => ({
276 |           type: "image",
277 |           data: image as string,
278 |           mimeType: "image/png",
279 |         })),
280 |         {
281 |           type: "text",
282 |           text: "This is the end of the image generation.",
283 |         }
284 |       ],
285 |     };
286 |   } catch (error) {
287 |     console.error('Error:', error);
288 | 
289 |     // Handle Zod validation errors
290 |     if (error instanceof z.ZodError) {
291 |       throw new McpError(
292 |         ErrorCode.InvalidParams,
293 |         `Invalid parameters: ${error.errors.map(e => e.message).join(", ")}`
294 |       );
295 |     }
296 | 
297 |     // Handle AWS Bedrock errors
298 |     if (error instanceof Error) {
299 |       throw new McpError(
300 |         ErrorCode.InternalError,
301 |         `Failed to generate image: ${error.message}`
302 |       );
303 |     }
304 | 
305 |     // Handle unknown errors
306 |     throw new McpError(
307 |       ErrorCode.InternalError,
308 |       "An unexpected error occurred"
309 |     );
310 |   }
311 | });
312 | 
313 | /**
314 |  * Start the server using stdio transport.
315 |  */
316 | async function main() {
317 |   try {
318 |     const transport = new StdioServerTransport();
319 |     await server.connect(transport);
320 |     console.error('Amazon Bedrock MCP server running on stdio');
321 |   } catch (error) {
322 |     console.error('Failed to start MCP server:', error);
323 |     throw error;
324 |   }
325 | }
326 | 
327 | // Error handling
328 | server.onerror = (error) => console.error('[MCP Error]', error);
329 | process.on('SIGINT', async () => {
330 |   await server.close();
331 |   process.exit(0);
332 | });
333 | 
334 | main().catch((error) => {
335 |   console.error("Server error:", error);
336 |   process.exit(1);
337 | });
338 | 
```