generate_image
Create custom images from text descriptions using Amazon Nova Canvas AI. Save generated visuals directly to your workspace for design projects and visual content creation.
Instructions
Generate an image using Amazon Nova Canvas with text prompt.
This tool uses Amazon Nova Canvas to generate images based on a text prompt.
The generated image will be saved to a file and the path will be returned.
IMPORTANT FOR ASSISTANT: Always send the current workspace directory when calling this tool!
The workspace_dir parameter should be set to the directory where the user is currently working
so that images are saved to a location accessible to the user.
## Prompt Best Practices
An effective prompt often includes short descriptions of:
1. The subject
2. The environment
3. (optional) The position or pose of the subject
4. (optional) Lighting description
5. (optional) Camera position/framing
6. (optional) The visual style or medium ("photo", "illustration", "painting", etc.)
Do not use negation words like "no", "not", "without" in your prompt. Instead, use the
negative_prompt parameter to specify what you don't want in the image.
You should always include "people, anatomy, hands, low quality, low resolution, low detail" in your negative_prompt
## Example Prompts
- "realistic editorial photo of female teacher standing at a blackboard with a warm smile"
- "whimsical and ethereal soft-shaded story illustration: A woman in a large hat stands at the ship's railing looking out across the ocean"
- "drone view of a dark river winding through a stark Iceland landscape, cinematic quality"
Returns:
McpImageGenerationResponse: A response containing the generated image paths.Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| prompt | Yes | The text description of the image to generate (1-1024 characters) | |
| negative_prompt | No | Text to define what not to include in the image (1-1024 characters) | |
| filename | No | The name of the file to save the image to (without extension) | |
| width | No | The width of the generated image (320-4096, divisible by 16) | |
| height | No | The height of the generated image (320-4096, divisible by 16) | |
| quality | No | The quality of the generated image ("standard" or "premium") | standard |
| cfg_scale | No | How strongly the image adheres to the prompt (1.1-10.0) | |
| seed | No | Seed for generation (0-858,993,459) | |
| number_of_images | No | The number of images to generate (1-5) | |
| workspace_dir | No | The current workspace directory where the image should be saved. CRITICAL: Assistant must always provide the current IDE workspace directory parameter to save images to the user's current project. |
Implementation Reference
- The MCP tool handler for 'generate_image', including registration via @mcp.tool decorator, input schema via pydantic Fields, logic to invoke generate_image_with_text helper, and return McpImageGenerationResponse.
@mcp.tool(name='generate_image') async def mcp_generate_image( ctx: Context, prompt: str = Field( description='The text description of the image to generate (1-1024 characters)' ), negative_prompt: Optional[str] = Field( default=None, description='Text to define what not to include in the image (1-1024 characters)', ), filename: Optional[str] = Field( default=None, description='The name of the file to save the image to (without extension)', ), width: int = Field( default=DEFAULT_WIDTH, description='The width of the generated image (320-4096, divisible by 16)', ), height: int = Field( default=DEFAULT_HEIGHT, description='The height of the generated image (320-4096, divisible by 16)', ), quality: str = Field( default=DEFAULT_QUALITY, description='The quality of the generated image ("standard" or "premium")', ), cfg_scale: float = Field( default=DEFAULT_CFG_SCALE, description='How strongly the image adheres to the prompt (1.1-10.0)', ), seed: Optional[int] = Field(default=None, description='Seed for generation (0-858,993,459)'), number_of_images: int = Field( default=DEFAULT_NUMBER_OF_IMAGES, description='The number of images to generate (1-5)', ), workspace_dir: Optional[str] = Field( default=None, description="""The current workspace directory where the image should be saved. CRITICAL: Assistant must always provide the current IDE workspace directory parameter to save images to the user's current project.""", ), ) -> McpImageGenerationResponse: """Generate an image using Amazon Nova Canvas with text prompt. This tool uses Amazon Nova Canvas to generate images based on a text prompt. The generated image will be saved to a file and the path will be returned. IMPORTANT FOR ASSISTANT: Always send the current workspace directory when calling this tool! The workspace_dir parameter should be set to the directory where the user is currently working so that images are saved to a location accessible to the user. ## Prompt Best Practices An effective prompt often includes short descriptions of: 1. The subject 2. The environment 3. (optional) The position or pose of the subject 4. (optional) Lighting description 5. (optional) Camera position/framing 6. (optional) The visual style or medium ("photo", "illustration", "painting", etc.) Do not use negation words like "no", "not", "without" in your prompt. Instead, use the negative_prompt parameter to specify what you don't want in the image. You should always include "people, anatomy, hands, low quality, low resolution, low detail" in your negative_prompt ## Example Prompts - "realistic editorial photo of female teacher standing at a blackboard with a warm smile" - "whimsical and ethereal soft-shaded story illustration: A woman in a large hat stands at the ship's railing looking out across the ocean" - "drone view of a dark river winding through a stark Iceland landscape, cinematic quality" Returns: McpImageGenerationResponse: A response containing the generated image paths. """ logger.debug( f"MCP tool generate_image called with prompt: '{prompt[:30]}...', dims: {width}x{height}" ) try: logger.info( f'Generating image with text prompt, quality: {quality}, cfg_scale: {cfg_scale}' ) response = await generate_image_with_text( prompt=prompt, bedrock_runtime_client=bedrock_runtime_client, negative_prompt=negative_prompt, filename=filename, width=width, height=height, quality=quality, cfg_scale=cfg_scale, seed=seed, number_of_images=number_of_images, workspace_dir=workspace_dir, ) if response.status == 'success': # return response.paths return McpImageGenerationResponse( status='success', paths=[f'file://{path}' for path in response.paths], ) else: logger.error(f'Image generation returned error status: {response.message}') await ctx.error(f'Failed to generate image: {response.message}') # type: ignore # Return empty image or raise exception based on requirements raise Exception(f'Failed to generate image: {response.message}') except Exception as e: logger.error(f'Error in mcp_generate_image: {str(e)}') await ctx.error(f'Error generating image: {str(e)}') # type: ignore raise - Core helper function that performs the actual image generation using Amazon Nova Canvas on Bedrock Runtime, handles API request/response, and saves images to files.
async def generate_image_with_text( prompt: str, bedrock_runtime_client: BedrockRuntimeClient, negative_prompt: Optional[str] = None, filename: Optional[str] = None, width: int = DEFAULT_WIDTH, height: int = DEFAULT_HEIGHT, quality: str = DEFAULT_QUALITY, cfg_scale: float = DEFAULT_CFG_SCALE, seed: Optional[int] = None, number_of_images: int = DEFAULT_NUMBER_OF_IMAGES, workspace_dir: Optional[str] = None, ) -> ImageGenerationResponse: """Generate an image using Amazon Nova Canvas with text prompt. This function uses Amazon Nova Canvas to generate images based on a text prompt. The generated image will be saved to a file and the path will be returned. Args: prompt: The text description of the image to generate (1-1024 characters). bedrock_runtime_client: BedrockRuntimeClient object. negative_prompt: Text to define what not to include in the image (1-1024 characters). filename: The name of the file to save the image to (without extension). If not provided, a random name will be generated. width: The width of the generated image (320-4096, divisible by 16). height: The height of the generated image (320-4096, divisible by 16). quality: The quality of the generated image ("standard" or "premium"). cfg_scale: How strongly the image adheres to the prompt (1.1-10.0). seed: Seed for generation (0-858,993,459). Random if not provided. number_of_images: The number of images to generate (1-5). workspace_dir: Directory where the images should be saved. If None, uses current directory. Returns: ImageGenerationResponse: An object containing the paths to the generated images, PIL Image objects, and status information. """ logger.debug(f"Generating text-to-image with prompt: '{prompt[:30]}...' ({width}x{height})") try: # Validate input parameters using Pydantic try: logger.debug('Validating parameters and creating request model') # Create image generation config config = ImageGenerationConfig( width=width, height=height, quality=Quality.STANDARD if quality == DEFAULT_QUALITY else Quality.PREMIUM, cfgScale=cfg_scale, seed=seed if seed is not None else random.randint(0, 858993459), numberOfImages=number_of_images, ) # Create text-to-image params # The Nova Canvas API doesn't accept null for negativeText if negative_prompt is not None: text_params = TextToImageParams(text=prompt, negativeText=negative_prompt) else: text_params = TextToImageParams(text=prompt) # Create the full request request_model = TextImageRequest( textToImageParams=text_params, imageGenerationConfig=config ) # Convert model to dictionary request_model_dict = request_model.to_api_dict() logger.info('Request validation successful') except Exception as e: logger.error(f'Parameter validation failed: {str(e)}') return ImageGenerationResponse( status='error', message=f'Validation error: {str(e)}', paths=[], prompt=prompt, negative_prompt=negative_prompt, ) try: # Invoke the Nova Canvas API logger.debug('Sending request to Nova Canvas API') model_response = await invoke_nova_canvas(request_model_dict, bedrock_runtime_client) # Extract the image data base64_images = model_response['images'] logger.info(f'Received {len(base64_images)} images from Nova Canvas API') # Save the generated images result = save_generated_images( base64_images, filename, number_of_images, prefix='nova_canvas', workspace_dir=workspace_dir, ) logger.info(f'Successfully generated {len(result["paths"])} image(s)') return ImageGenerationResponse( status='success', message=f'Generated {len(result["paths"])} image(s)', paths=result['paths'], prompt=prompt, negative_prompt=negative_prompt, ) except Exception as e: logger.error(f'Image generation failed: {str(e)}') return ImageGenerationResponse( status='error', message=str(e), paths=[], prompt=prompt, negative_prompt=negative_prompt, ) except Exception as e: logger.error(f'Unexpected error in generate_image_with_text: {str(e)}') return ImageGenerationResponse( status='error', message=str(e), paths=[], prompt=prompt, negative_prompt=negative_prompt, ) - Pydantic model defining the output schema for the generate_image tool response, containing status and list of image file paths.
class McpImageGenerationResponse(BaseModel): """Response from image generation API. This model represents the response from the Amazon Nova Canvas API for both text-to-image and color-guided image generation. """ status: str paths: List[str] - Pydantic models for the internal Nova Canvas API request (TextImageRequest, TextToImageParams, ImageGenerationConfig), used by the helper to validate and serialize the request to Bedrock.
class TextImageRequest(BaseModel): """Request model for text-to-image generation. This model combines the task type, text parameters, and generation configuration for a complete text-to-image request. Attributes: taskType: The type of task (TEXT_IMAGE). textToImageParams: Parameters for text-to-image generation. imageGenerationConfig: Configuration for image generation. """ taskType: Literal[TaskType.TEXT_IMAGE] = TaskType.TEXT_IMAGE textToImageParams: TextToImageParams imageGenerationConfig: Optional[ImageGenerationConfig] = Field( default_factory=ImageGenerationConfig ) # instead of overriding model_dump, we add a post-model_dump extension method def to_api_dict(self) -> Dict[str, Any]: """Convert model to dictionary suitable for API requests. Returns: A dictionary representation of the model suitable for API requests. """ text_to_image_params = self.textToImageParams.model_dump() # Remove negativeText if it's None if text_to_image_params.get('negativeText') is None: text_to_image_params.pop('negativeText', None) return { 'taskType': self.taskType, 'textToImageParams': text_to_image_params, 'imageGenerationConfig': self.imageGenerationConfig.model_dump() if self.imageGenerationConfig else ImageGenerationConfig().model_dump(), # Return default config instead of None }