awslabs.nova-canvas-mcp-server 0.1.10233__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- awslabs_nova_canvas_mcp_server-0.1.10233/.gitignore +59 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/.pre-commit-config.yaml +14 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/.python-version +1 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/CHANGELOG.md +58 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/PKG-INFO +74 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/README.md +63 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/awslabs/__init__.py +2 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/awslabs/nova_canvas_mcp_server/__init__.py +3 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/awslabs/nova_canvas_mcp_server/consts.py +61 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/awslabs/nova_canvas_mcp_server/models.py +287 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/awslabs/nova_canvas_mcp_server/novacanvas.py +396 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/awslabs/nova_canvas_mcp_server/server.py +324 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/pyproject.toml +82 -0
- awslabs_nova_canvas_mcp_server-0.1.10233/uv.lock +830 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
share/python-wheels/
|
|
20
|
+
*.egg-info/
|
|
21
|
+
.installed.cfg
|
|
22
|
+
*.egg
|
|
23
|
+
MANIFEST
|
|
24
|
+
|
|
25
|
+
# Virtual environments
|
|
26
|
+
.venv
|
|
27
|
+
env/
|
|
28
|
+
venv/
|
|
29
|
+
ENV/
|
|
30
|
+
|
|
31
|
+
# IDE
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
*.swp
|
|
35
|
+
*.swo
|
|
36
|
+
|
|
37
|
+
# Testing
|
|
38
|
+
.tox/
|
|
39
|
+
.coverage
|
|
40
|
+
.coverage.*
|
|
41
|
+
htmlcov/
|
|
42
|
+
.pytest_cache/
|
|
43
|
+
|
|
44
|
+
# Ruff
|
|
45
|
+
.ruff_cache/
|
|
46
|
+
|
|
47
|
+
# Build
|
|
48
|
+
*.manifest
|
|
49
|
+
*.spec
|
|
50
|
+
.pybuilder/
|
|
51
|
+
target/
|
|
52
|
+
|
|
53
|
+
# Environments
|
|
54
|
+
.env
|
|
55
|
+
.env.local
|
|
56
|
+
.env.*.local
|
|
57
|
+
|
|
58
|
+
# PyPI
|
|
59
|
+
.pypirc
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
repos:
|
|
2
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
+
rev: v0.9.6
|
|
4
|
+
hooks:
|
|
5
|
+
- id: ruff
|
|
6
|
+
args: [--fix]
|
|
7
|
+
- id: ruff-format
|
|
8
|
+
|
|
9
|
+
- repo: https://github.com/commitizen-tools/commitizen
|
|
10
|
+
rev: v3.13.0
|
|
11
|
+
hooks:
|
|
12
|
+
- id: commitizen
|
|
13
|
+
- id: commitizen-branch
|
|
14
|
+
stages: [push]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.13
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## v0.1.6 (2025-03-30)
|
|
9
|
+
|
|
10
|
+
### Fix
|
|
11
|
+
|
|
12
|
+
- update __version__ format to remove v prefix
|
|
13
|
+
|
|
14
|
+
## v0.1.5 (2025-03-30)
|
|
15
|
+
|
|
16
|
+
### Fix
|
|
17
|
+
|
|
18
|
+
- __version__
|
|
19
|
+
|
|
20
|
+
## v0.1.4 (2025-03-30)
|
|
21
|
+
|
|
22
|
+
### Fix
|
|
23
|
+
|
|
24
|
+
- __version__
|
|
25
|
+
|
|
26
|
+
## v0.1.3 (2025-03-30)
|
|
27
|
+
|
|
28
|
+
### Fix
|
|
29
|
+
|
|
30
|
+
- pyproject.toml
|
|
31
|
+
|
|
32
|
+
## v0.1.2 (2025-03-30)
|
|
33
|
+
|
|
34
|
+
### Fix
|
|
35
|
+
|
|
36
|
+
- uv package
|
|
37
|
+
- release
|
|
38
|
+
|
|
39
|
+
## v0.1.1 (2025-03-30)
|
|
40
|
+
|
|
41
|
+
### Fix
|
|
42
|
+
|
|
43
|
+
- release
|
|
44
|
+
|
|
45
|
+
## v0.1.0 (2025-03-30)
|
|
46
|
+
|
|
47
|
+
### Feat
|
|
48
|
+
|
|
49
|
+
- MCP server for generating images with Amazon Nova Canvas
|
|
50
|
+
- **doc**: material mkdocs (#5)
|
|
51
|
+
- **doc**: initial documentation (#4)
|
|
52
|
+
- **security**: add CODEOWNERS (#2)
|
|
53
|
+
- **cicd**: add github workflows (#1)
|
|
54
|
+
|
|
55
|
+
### Fix
|
|
56
|
+
|
|
57
|
+
- pyright errors on overrides
|
|
58
|
+
- optional fields
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: awslabs.nova-canvas-mcp-server
|
|
3
|
+
Version: 0.1.10233
|
|
4
|
+
Summary: An AWS Labs Model Context Protocol (MCP) server for Amazon Nova Canvas
|
|
5
|
+
Requires-Python: >=3.13
|
|
6
|
+
Requires-Dist: boto3>=1.37.24
|
|
7
|
+
Requires-Dist: loguru>=0.7.3
|
|
8
|
+
Requires-Dist: mcp[cli]>=1.6.0
|
|
9
|
+
Requires-Dist: pydantic>=2.11.1
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
|
|
12
|
+
# awslabs MCP Nova Canvas Server
|
|
13
|
+
|
|
14
|
+
MCP server for generating images using Amazon Nova Canvas
|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **Text-based image generation** - Create images from text prompts with `generate_image`
|
|
19
|
+
- Customizable dimensions (320-4096px), quality options, and negative prompting
|
|
20
|
+
- Supports multiple image generation (1-5) in single request
|
|
21
|
+
- Adjustable parameters like cfg_scale (1.1-10.0) and seeded generation
|
|
22
|
+
|
|
23
|
+
- **Color-guided image generation** - Generate images with specific color palettes using `generate_image_with_colors`
|
|
24
|
+
- Define up to 10 hex color values to influence the image style and mood
|
|
25
|
+
- Same customization options as text-based generation
|
|
26
|
+
|
|
27
|
+
- **Workspace integration** - Images saved to user-specified workspace directories with automatic folder creation
|
|
28
|
+
|
|
29
|
+
- **AWS authentication** - Uses AWS profiles for secure access to Amazon Nova Canvas services
|
|
30
|
+
|
|
31
|
+
## Prerequisites
|
|
32
|
+
|
|
33
|
+
1. Install `uv` from [Astral](https://docs.astral.sh/uv/getting-started/installation/) or the [GitHub README](https://github.com/astral-sh/uv#installation)
|
|
34
|
+
2. Install Python using `uv python install 3.13`
|
|
35
|
+
3. Set up AWS credentials with access to Amazon Bedrock and Nova Canvas
|
|
36
|
+
- You need an AWS account with Amazon Bedrock and Amazon Nova Canvas enabled
|
|
37
|
+
- Configure AWS credentials with `aws configure` or environment variables
|
|
38
|
+
- Ensure your IAM role/user has permissions to use Amazon Bedrock and Nova Canvas
|
|
39
|
+
|
|
40
|
+
## Installation
|
|
41
|
+
|
|
42
|
+
Install the MCP server:
|
|
43
|
+
|
|
44
|
+
Add the server to your MCP client config (e.g. for Amazon Q CLI MCP, `~/.aws/amazonq/mcp.json`):
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"mcpServers": {
|
|
49
|
+
"awslabs.nova-canvas-mcp-server": {
|
|
50
|
+
"command": "uvx",
|
|
51
|
+
"args": ["awslabs.nova-canvas-mcp-server@latest"],
|
|
52
|
+
"env": {
|
|
53
|
+
"AWS_PROFILE": "your-aws-profile", // Optional: specify AWS profile
|
|
54
|
+
"AWS_REGION": "us-east-1" // Required: region where Bedrock is available
|
|
55
|
+
},
|
|
56
|
+
"disabled": false,
|
|
57
|
+
"autoApprove": []
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### AWS Authentication
|
|
64
|
+
|
|
65
|
+
The MCP server uses the AWS profile specified in the `AWS_PROFILE` environment variable. If not provided, it defaults to the "default" profile in your AWS configuration file.
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
"env": {
|
|
69
|
+
"AWS_PROFILE": "your-aws-profile", // Specify which AWS profile to use
|
|
70
|
+
"AWS_REGION": "us-east-1" // Region where Bedrock is available
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Make sure the AWS profile has permissions to access Amazon Bedrock and Amazon Nova Canvas. The MCP server creates a boto3 session using the specified profile to authenticate with AWS services. Your AWS IAM credentials remain on your local machine and are strictly used for using the Amazon Bedrock model APIs.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# awslabs MCP Nova Canvas Server
|
|
2
|
+
|
|
3
|
+
MCP server for generating images using Amazon Nova Canvas
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Text-based image generation** - Create images from text prompts with `generate_image`
|
|
8
|
+
- Customizable dimensions (320-4096px), quality options, and negative prompting
|
|
9
|
+
- Supports multiple image generation (1-5) in single request
|
|
10
|
+
- Adjustable parameters like cfg_scale (1.1-10.0) and seeded generation
|
|
11
|
+
|
|
12
|
+
- **Color-guided image generation** - Generate images with specific color palettes using `generate_image_with_colors`
|
|
13
|
+
- Define up to 10 hex color values to influence the image style and mood
|
|
14
|
+
- Same customization options as text-based generation
|
|
15
|
+
|
|
16
|
+
- **Workspace integration** - Images saved to user-specified workspace directories with automatic folder creation
|
|
17
|
+
|
|
18
|
+
- **AWS authentication** - Uses AWS profiles for secure access to Amazon Nova Canvas services
|
|
19
|
+
|
|
20
|
+
## Prerequisites
|
|
21
|
+
|
|
22
|
+
1. Install `uv` from [Astral](https://docs.astral.sh/uv/getting-started/installation/) or the [GitHub README](https://github.com/astral-sh/uv#installation)
|
|
23
|
+
2. Install Python using `uv python install 3.13`
|
|
24
|
+
3. Set up AWS credentials with access to Amazon Bedrock and Nova Canvas
|
|
25
|
+
- You need an AWS account with Amazon Bedrock and Amazon Nova Canvas enabled
|
|
26
|
+
- Configure AWS credentials with `aws configure` or environment variables
|
|
27
|
+
- Ensure your IAM role/user has permissions to use Amazon Bedrock and Nova Canvas
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
Install the MCP server:
|
|
32
|
+
|
|
33
|
+
Add the server to your MCP client config (e.g. for Amazon Q CLI MCP, `~/.aws/amazonq/mcp.json`):
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"awslabs.nova-canvas-mcp-server": {
|
|
39
|
+
"command": "uvx",
|
|
40
|
+
"args": ["awslabs.nova-canvas-mcp-server@latest"],
|
|
41
|
+
"env": {
|
|
42
|
+
"AWS_PROFILE": "your-aws-profile", // Optional: specify AWS profile
|
|
43
|
+
"AWS_REGION": "us-east-1" // Required: region where Bedrock is available
|
|
44
|
+
},
|
|
45
|
+
"disabled": false,
|
|
46
|
+
"autoApprove": []
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### AWS Authentication
|
|
53
|
+
|
|
54
|
+
The MCP server uses the AWS profile specified in the `AWS_PROFILE` environment variable. If not provided, it defaults to the "default" profile in your AWS configuration file.
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
"env": {
|
|
58
|
+
"AWS_PROFILE": "your-aws-profile", // Specify which AWS profile to use
|
|
59
|
+
"AWS_REGION": "us-east-1" // Region where Bedrock is available
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Make sure the AWS profile has permissions to access Amazon Bedrock and Amazon Nova Canvas. The MCP server creates a boto3 session using the specified profile to authenticate with AWS services. Your AWS IAM credentials remain on your local machine and are strictly used for using the Amazon Bedrock model APIs.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Constants
|
|
2
|
+
NOVA_CANVAS_MODEL_ID = 'amazon.nova-canvas-v1:0'
|
|
3
|
+
DEFAULT_WIDTH = 1024
|
|
4
|
+
DEFAULT_HEIGHT = 1024
|
|
5
|
+
DEFAULT_QUALITY = 'standard'
|
|
6
|
+
DEFAULT_CFG_SCALE = 6.5
|
|
7
|
+
DEFAULT_NUMBER_OF_IMAGES = 1
|
|
8
|
+
DEFAULT_OUTPUT_DIR = 'output' # Default directory inside workspace_dir
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Nova Canvas Prompt Best Practices
|
|
12
|
+
PROMPT_INSTRUCTIONS = """
|
|
13
|
+
# Amazon Nova Canvas Prompting Best Practices
|
|
14
|
+
|
|
15
|
+
## General Guidelines
|
|
16
|
+
|
|
17
|
+
- Prompts must be no longer than 1024 characters. For very long prompts, place the least important details near the end.
|
|
18
|
+
- Do not use negation words like "no", "not", "without" in your prompt. The model doesn't understand negation and will result in the opposite of what you intend.
|
|
19
|
+
- Use negative prompts (via the `negative_prompt` parameter) to specify objects or characteristics to exclude from the image.
|
|
20
|
+
- Omit negation words from your negative prompts as well.
|
|
21
|
+
|
|
22
|
+
## Effective Prompt Structure
|
|
23
|
+
|
|
24
|
+
An effective prompt often includes short descriptions of:
|
|
25
|
+
|
|
26
|
+
1. The subject
|
|
27
|
+
2. The environment
|
|
28
|
+
3. (optional) The position or pose of the subject
|
|
29
|
+
4. (optional) Lighting description
|
|
30
|
+
5. (optional) Camera position/framing
|
|
31
|
+
6. (optional) The visual style or medium ("photo", "illustration", "painting", etc.)
|
|
32
|
+
|
|
33
|
+
## Refining Results
|
|
34
|
+
|
|
35
|
+
When the output is close to what you want but not perfect:
|
|
36
|
+
|
|
37
|
+
1. Use a consistent `seed` value and make small changes to your prompt or negative prompt.
|
|
38
|
+
2. Once the prompt is refined, generate more variations using the same prompt but different `seed` values.
|
|
39
|
+
|
|
40
|
+
## Examples
|
|
41
|
+
|
|
42
|
+
### Example 1: Stock Photo
|
|
43
|
+
**Prompt:** "realistic editorial photo of female teacher standing at a blackboard with a warm smile"
|
|
44
|
+
**Negative Prompt:** "crossed arms"
|
|
45
|
+
|
|
46
|
+
### Example 2: Story Illustration
|
|
47
|
+
**Prompt:** "whimsical and ethereal soft-shaded story illustration: A woman in a large hat stands at the ship's railing looking out across the ocean"
|
|
48
|
+
**Negative Prompt:** "clouds, waves"
|
|
49
|
+
|
|
50
|
+
### Example 3: Pre-visualization for TV/Film
|
|
51
|
+
**Prompt:** "drone view of a dark river winding through a stark Iceland landscape, cinematic quality"
|
|
52
|
+
|
|
53
|
+
### Example 4: Fashion/Editorial Content
|
|
54
|
+
**Prompt:** "A cool looking stylish man in an orange jacket, dark skin, wearing reflective glasses. Shot from slightly low angle, face and chest in view, aqua blue sleek building shapes in background."
|
|
55
|
+
|
|
56
|
+
## Using Negative Prompts
|
|
57
|
+
|
|
58
|
+
Negative prompts can be surprisingly useful. Use them to exclude objects or style characteristics that might otherwise naturally occur as a result of your main prompt.
|
|
59
|
+
|
|
60
|
+
For example, adding "waves, clouds" as a negative prompt to a ship scene will result in a cleaner, more minimal composition.
|
|
61
|
+
"""
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"""Pydantic models for Amazon Nova Canvas image generation."""
|
|
2
|
+
|
|
3
|
+
import random
|
|
4
|
+
import re
|
|
5
|
+
from enum import Enum
|
|
6
|
+
from pydantic import BaseModel, Field, field_validator, model_validator
|
|
7
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Quality(str, Enum):
|
|
11
|
+
"""Quality options for image generation.
|
|
12
|
+
|
|
13
|
+
Attributes:
|
|
14
|
+
STANDARD: Standard quality image generation.
|
|
15
|
+
PREMIUM: Premium quality image generation with enhanced details.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
STANDARD = 'standard'
|
|
19
|
+
PREMIUM = 'premium'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TaskType(str, Enum):
|
|
23
|
+
"""Task types for image generation.
|
|
24
|
+
|
|
25
|
+
Attributes:
|
|
26
|
+
TEXT_IMAGE: Generate an image from text description.
|
|
27
|
+
COLOR_GUIDED_GENERATION: Generate an image guided by both text and color palette.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
TEXT_IMAGE = 'TEXT_IMAGE'
|
|
31
|
+
COLOR_GUIDED_GENERATION = 'COLOR_GUIDED_GENERATION'
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ImageGenerationConfig(BaseModel):
|
|
35
|
+
"""Configuration for image generation.
|
|
36
|
+
|
|
37
|
+
This model defines the parameters that control the image generation process,
|
|
38
|
+
including dimensions, quality, and generation settings.
|
|
39
|
+
|
|
40
|
+
Attributes:
|
|
41
|
+
width: Width of the generated image (320-4096, must be divisible by 16).
|
|
42
|
+
height: Height of the generated image (320-4096, must be divisible by 16).
|
|
43
|
+
quality: Quality level of the generated image (standard or premium).
|
|
44
|
+
cfgScale: How strongly the image adheres to the prompt (1.1-10.0).
|
|
45
|
+
seed: Seed for reproducible generation (0-858993459).
|
|
46
|
+
numberOfImages: Number of images to generate (1-5).
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
width: int = Field(default=1024, ge=320, le=4096)
|
|
50
|
+
height: int = Field(default=1024, ge=320, le=4096)
|
|
51
|
+
quality: Quality = Quality.STANDARD
|
|
52
|
+
cfgScale: float = Field(default=6.5, ge=1.1, le=10.0)
|
|
53
|
+
seed: int = Field(default_factory=lambda: random.randint(0, 858993459), ge=0, le=858993459)
|
|
54
|
+
numberOfImages: int = Field(default=1, ge=1, le=5)
|
|
55
|
+
|
|
56
|
+
@field_validator('width', 'height')
|
|
57
|
+
@classmethod
|
|
58
|
+
def must_be_divisible_by_16(cls, v: int) -> int:
|
|
59
|
+
"""Validate that width and height are divisible by 16.
|
|
60
|
+
|
|
61
|
+
Args:
|
|
62
|
+
v: The width or height value to validate.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
The validated value if it passes.
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
ValueError: If the value is not divisible by 16.
|
|
69
|
+
"""
|
|
70
|
+
if v % 16 != 0:
|
|
71
|
+
raise ValueError('Value must be divisible by 16')
|
|
72
|
+
return v
|
|
73
|
+
|
|
74
|
+
@model_validator(mode='after')
|
|
75
|
+
def validate_aspect_ratio_and_total_pixels(self):
|
|
76
|
+
"""Validate aspect ratio and total pixel count.
|
|
77
|
+
|
|
78
|
+
Ensures that:
|
|
79
|
+
1. The aspect ratio is between 1:4 and 4:1
|
|
80
|
+
2. The total pixel count is less than 4,194,304
|
|
81
|
+
|
|
82
|
+
Returns:
|
|
83
|
+
The validated model if it passes.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
ValueError: If the aspect ratio or total pixel count is invalid.
|
|
87
|
+
"""
|
|
88
|
+
width = self.width
|
|
89
|
+
height = self.height
|
|
90
|
+
|
|
91
|
+
# Check aspect ratio between 1:4 and 4:1
|
|
92
|
+
aspect_ratio = width / height
|
|
93
|
+
if aspect_ratio < 0.25 or aspect_ratio > 4.0:
|
|
94
|
+
raise ValueError('Aspect ratio must be between 1:4 and 4:1')
|
|
95
|
+
|
|
96
|
+
# Check total pixel count
|
|
97
|
+
total_pixels = width * height
|
|
98
|
+
if total_pixels >= 4194304:
|
|
99
|
+
raise ValueError('Total pixel count must be less than 4,194,304')
|
|
100
|
+
|
|
101
|
+
return self
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class TextToImageParams(BaseModel):
|
|
105
|
+
"""Parameters for text-to-image generation.
|
|
106
|
+
|
|
107
|
+
This model defines the text prompts used to generate images.
|
|
108
|
+
|
|
109
|
+
Attributes:
|
|
110
|
+
text: The text description of the image to generate (1-1024 characters).
|
|
111
|
+
negativeText: Optional text to define what not to include in the image (1-1024 characters).
|
|
112
|
+
"""
|
|
113
|
+
|
|
114
|
+
text: str = Field(..., min_length=1, max_length=1024)
|
|
115
|
+
negativeText: Optional[str] = Field(default=None, min_length=1, max_length=1024)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class ColorGuidedGenerationParams(BaseModel):
|
|
119
|
+
"""Parameters for color-guided generation.
|
|
120
|
+
|
|
121
|
+
This model defines the text prompts and color palette used to generate images.
|
|
122
|
+
|
|
123
|
+
Attributes:
|
|
124
|
+
colors: List of hexadecimal color values (e.g., "#FF9800") to guide the image generation.
|
|
125
|
+
text: The text description of the image to generate (1-1024 characters).
|
|
126
|
+
negativeText: Optional text to define what not to include in the image (1-1024 characters).
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
colors: List[str] = Field(..., max_length=10)
|
|
130
|
+
text: str = Field(..., min_length=1, max_length=1024)
|
|
131
|
+
negativeText: Optional[str] = Field(default=None, min_length=1, max_length=1024)
|
|
132
|
+
|
|
133
|
+
@field_validator('colors')
|
|
134
|
+
@classmethod
|
|
135
|
+
def validate_hex_colors(cls, v: List[str]) -> List[str]:
|
|
136
|
+
"""Validate that colors are in the correct hexadecimal format.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
v: List of color strings to validate.
|
|
140
|
+
|
|
141
|
+
Returns:
|
|
142
|
+
The validated list if all colors pass.
|
|
143
|
+
|
|
144
|
+
Raises:
|
|
145
|
+
ValueError: If any color is not a valid hexadecimal color in the format '#RRGGBB'.
|
|
146
|
+
"""
|
|
147
|
+
hex_pattern = re.compile(r'^#[0-9A-Fa-f]{6}$')
|
|
148
|
+
for color in v:
|
|
149
|
+
if not hex_pattern.match(color):
|
|
150
|
+
raise ValueError(
|
|
151
|
+
f"Color '{color}' is not a valid hexadecimal color in the format '#RRGGBB'"
|
|
152
|
+
)
|
|
153
|
+
return v
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class TextImageRequest(BaseModel):
|
|
157
|
+
"""Request model for text-to-image generation.
|
|
158
|
+
|
|
159
|
+
This model combines the task type, text parameters, and generation configuration
|
|
160
|
+
for a complete text-to-image request.
|
|
161
|
+
|
|
162
|
+
Attributes:
|
|
163
|
+
taskType: The type of task (TEXT_IMAGE).
|
|
164
|
+
textToImageParams: Parameters for text-to-image generation.
|
|
165
|
+
imageGenerationConfig: Configuration for image generation.
|
|
166
|
+
"""
|
|
167
|
+
|
|
168
|
+
taskType: Literal[TaskType.TEXT_IMAGE] = TaskType.TEXT_IMAGE
|
|
169
|
+
textToImageParams: TextToImageParams
|
|
170
|
+
imageGenerationConfig: Optional[ImageGenerationConfig] = Field(
|
|
171
|
+
default_factory=ImageGenerationConfig
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
# instead of overriding model_dump, we add a post-model_dump extension method
|
|
175
|
+
def to_api_dict(self) -> Dict[str, Any]:
|
|
176
|
+
"""Convert model to dictionary suitable for API requests.
|
|
177
|
+
|
|
178
|
+
Returns:
|
|
179
|
+
A dictionary representation of the model suitable for API requests.
|
|
180
|
+
"""
|
|
181
|
+
text_to_image_params = self.textToImageParams.model_dump()
|
|
182
|
+
# Remove negativeText if it's None
|
|
183
|
+
if text_to_image_params.get('negativeText') is None:
|
|
184
|
+
text_to_image_params.pop('negativeText', None)
|
|
185
|
+
|
|
186
|
+
return {
|
|
187
|
+
'taskType': self.taskType,
|
|
188
|
+
'textToImageParams': text_to_image_params,
|
|
189
|
+
'imageGenerationConfig': self.imageGenerationConfig.model_dump()
|
|
190
|
+
if self.imageGenerationConfig
|
|
191
|
+
else None,
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class ColorGuidedRequest(BaseModel):
|
|
196
|
+
"""Request model for color-guided generation.
|
|
197
|
+
|
|
198
|
+
This model combines the task type, color-guided parameters, and generation configuration
|
|
199
|
+
for a complete color-guided generation request.
|
|
200
|
+
|
|
201
|
+
Attributes:
|
|
202
|
+
taskType: The type of task (COLOR_GUIDED_GENERATION).
|
|
203
|
+
colorGuidedGenerationParams: Parameters for color-guided generation.
|
|
204
|
+
imageGenerationConfig: Configuration for image generation.
|
|
205
|
+
"""
|
|
206
|
+
|
|
207
|
+
taskType: Literal[TaskType.COLOR_GUIDED_GENERATION] = TaskType.COLOR_GUIDED_GENERATION
|
|
208
|
+
colorGuidedGenerationParams: ColorGuidedGenerationParams
|
|
209
|
+
imageGenerationConfig: Optional[ImageGenerationConfig] = Field(
|
|
210
|
+
default_factory=ImageGenerationConfig
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
# instead of overriding model_dump, we add a post-model_dump extension method
|
|
214
|
+
def to_api_dict(self) -> Dict[str, Any]:
|
|
215
|
+
"""Convert model to dictionary suitable for API requests.
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
A dictionary representation of the model suitable for API requests.
|
|
219
|
+
"""
|
|
220
|
+
color_guided_params = self.colorGuidedGenerationParams.model_dump()
|
|
221
|
+
# Remove negativeText if it's None
|
|
222
|
+
if color_guided_params.get('negativeText') is None:
|
|
223
|
+
color_guided_params.pop('negativeText', None)
|
|
224
|
+
|
|
225
|
+
return {
|
|
226
|
+
'taskType': self.taskType,
|
|
227
|
+
'colorGuidedGenerationParams': color_guided_params,
|
|
228
|
+
'imageGenerationConfig': self.imageGenerationConfig.model_dump()
|
|
229
|
+
if self.imageGenerationConfig
|
|
230
|
+
else None,
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
class McpImageGenerationResponse(BaseModel):
|
|
235
|
+
"""Response from image generation API.
|
|
236
|
+
|
|
237
|
+
This model represents the response from the Amazon Nova Canvas API
|
|
238
|
+
for both text-to-image and color-guided image generation.
|
|
239
|
+
"""
|
|
240
|
+
|
|
241
|
+
status: str
|
|
242
|
+
paths: List[str]
|
|
243
|
+
|
|
244
|
+
|
|
245
|
+
class ImageGenerationResponse(BaseModel):
|
|
246
|
+
"""Response from image generation API.
|
|
247
|
+
|
|
248
|
+
This model represents the response from the Amazon Nova Canvas API
|
|
249
|
+
for both text-to-image and color-guided image generation.
|
|
250
|
+
|
|
251
|
+
Attributes:
|
|
252
|
+
status: Status of the image generation request ('success' or 'error').
|
|
253
|
+
message: Message describing the result or error.
|
|
254
|
+
paths: List of paths to the generated image files.
|
|
255
|
+
images: List of PIL Image objects.
|
|
256
|
+
prompt: The text prompt used to generate the images.
|
|
257
|
+
negative_prompt: The negative prompt used to generate the images, if any.
|
|
258
|
+
colors: The colors used to guide the image generation, if any.
|
|
259
|
+
"""
|
|
260
|
+
|
|
261
|
+
status: str
|
|
262
|
+
message: str
|
|
263
|
+
paths: List[str]
|
|
264
|
+
prompt: str
|
|
265
|
+
negative_prompt: Optional[str] = None
|
|
266
|
+
colors: Optional[List[str]] = None
|
|
267
|
+
|
|
268
|
+
class Config:
|
|
269
|
+
"""Pydantic configuration."""
|
|
270
|
+
|
|
271
|
+
arbitrary_types_allowed = True # Allow PIL.Image.Image type
|
|
272
|
+
|
|
273
|
+
def __getitem__(self, key: str) -> Any:
|
|
274
|
+
"""Support dictionary-style access for backward compatibility.
|
|
275
|
+
|
|
276
|
+
Args:
|
|
277
|
+
key: The attribute name to access.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
The value of the attribute.
|
|
281
|
+
|
|
282
|
+
Raises:
|
|
283
|
+
KeyError: If the attribute does not exist.
|
|
284
|
+
"""
|
|
285
|
+
if hasattr(self, key):
|
|
286
|
+
return getattr(self, key)
|
|
287
|
+
raise KeyError(f"'{key}' not found in ImageGenerationResponse")
|