awslabs.nova-canvas-mcp-server 0.2.1__tar.gz → 0.2.6__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.
Files changed (24) hide show
  1. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/PKG-INFO +5 -1
  2. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/awslabs/nova_canvas_mcp_server/models.py +2 -2
  3. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/pyproject.toml +14 -1
  4. awslabs_nova_canvas_mcp_server-0.2.6/run_tests.sh +156 -0
  5. awslabs_nova_canvas_mcp_server-0.2.6/tests/.gitignore +25 -0
  6. awslabs_nova_canvas_mcp_server-0.2.6/tests/README.md +51 -0
  7. awslabs_nova_canvas_mcp_server-0.2.6/tests/__init__.py +11 -0
  8. awslabs_nova_canvas_mcp_server-0.2.6/tests/conftest.py +97 -0
  9. awslabs_nova_canvas_mcp_server-0.2.6/tests/test_models.py +504 -0
  10. awslabs_nova_canvas_mcp_server-0.2.6/tests/test_novacanvas.py +536 -0
  11. awslabs_nova_canvas_mcp_server-0.2.6/tests/test_server.py +298 -0
  12. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/uv.lock +197 -7
  13. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/.gitignore +0 -0
  14. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/.pre-commit-config.yaml +0 -0
  15. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/.python-version +0 -0
  16. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/CHANGELOG.md +0 -0
  17. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/LICENSE +0 -0
  18. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/NOTICE +0 -0
  19. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/README.md +0 -0
  20. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/awslabs/__init__.py +0 -0
  21. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/awslabs/nova_canvas_mcp_server/__init__.py +0 -0
  22. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/awslabs/nova_canvas_mcp_server/consts.py +0 -0
  23. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/awslabs/nova_canvas_mcp_server/novacanvas.py +0 -0
  24. {awslabs_nova_canvas_mcp_server-0.2.1 → awslabs_nova_canvas_mcp_server-0.2.6}/awslabs/nova_canvas_mcp_server/server.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: awslabs.nova-canvas-mcp-server
3
- Version: 0.2.1
3
+ Version: 0.2.6
4
4
  Summary: An AWS Labs Model Context Protocol (MCP) server for Amazon Nova Canvas
5
5
  Project-URL: Homepage, https://awslabs.github.io/mcp/
6
6
  Project-URL: Documentation, https://awslabs.github.io/mcp/servers/nova-mcp-server/
@@ -25,6 +25,10 @@ Requires-Dist: boto3>=1.37.24
25
25
  Requires-Dist: loguru>=0.7.3
26
26
  Requires-Dist: mcp[cli]>=1.6.0
27
27
  Requires-Dist: pydantic>=2.11.1
28
+ Requires-Dist: pytest-asyncio>=0.26.0
29
+ Requires-Dist: pytest-cov>=4.1.0
30
+ Requires-Dist: pytest-mock>=3.12.0
31
+ Requires-Dist: pytest>=8.0.0
28
32
  Description-Content-Type: text/markdown
29
33
 
30
34
  # Amazon Nova Canvas MCP Server
@@ -198,7 +198,7 @@ class TextImageRequest(BaseModel):
198
198
  'textToImageParams': text_to_image_params,
199
199
  'imageGenerationConfig': self.imageGenerationConfig.model_dump()
200
200
  if self.imageGenerationConfig
201
- else None,
201
+ else ImageGenerationConfig().model_dump(), # Return default config instead of None
202
202
  }
203
203
 
204
204
 
@@ -237,7 +237,7 @@ class ColorGuidedRequest(BaseModel):
237
237
  'colorGuidedGenerationParams': color_guided_params,
238
238
  'imageGenerationConfig': self.imageGenerationConfig.model_dump()
239
239
  if self.imageGenerationConfig
240
- else None,
240
+ else ImageGenerationConfig().model_dump(), # Return default config instead of None
241
241
  }
242
242
 
243
243
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "awslabs.nova-canvas-mcp-server"
3
- version = "0.2.1"
3
+ version = "0.2.6"
4
4
  description = "An AWS Labs Model Context Protocol (MCP) server for Amazon Nova Canvas"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -9,6 +9,10 @@ dependencies = [
9
9
  "loguru>=0.7.3",
10
10
  "mcp[cli]>=1.6.0",
11
11
  "pydantic>=2.11.1",
12
+ "pytest>=8.0.0",
13
+ "pytest-asyncio>=0.26.0",
14
+ "pytest-cov>=4.1.0",
15
+ "pytest-mock>=3.12.0",
12
16
  ]
13
17
  license = {text = "Apache-2.0"}
14
18
  license-files = ["LICENSE", "NOTICE" ]
@@ -45,6 +49,7 @@ dev = [
45
49
  "pre-commit>=4.2.0",
46
50
  "pyright>=1.1.398",
47
51
  "pytest>=8.0.0",
52
+ "pytest-asyncio>=0.26.0",
48
53
  "pytest-cov>=4.1.0",
49
54
  "ruff>=0.11.2",
50
55
  ]
@@ -112,3 +117,11 @@ exclude_dirs = ["venv","tests"]
112
117
 
113
118
  [tool.coverage.run]
114
119
  source = ["awslabs"]
120
+
121
+ [tool.pytest.ini_options]
122
+ testpaths = "tests"
123
+ asyncio_mode = "auto"
124
+ asyncio_default_fixture_loop_scope = "function"
125
+ markers = [
126
+ "asyncio: mark a test as an asyncio coroutine",
127
+ ]
@@ -0,0 +1,156 @@
1
+ #!/bin/bash
2
+ # Script to run the nova-canvas-mcp-server tests
3
+
4
+ # Set the Python path to include the current directory and the parent directory
5
+ export PYTHONPATH=$PYTHONPATH:$(pwd):$(pwd)/..
6
+
7
+ # Check if we're in a virtual environment
8
+ if [ -z "$VIRTUAL_ENV" ]; then
9
+ echo "Warning: You are not running in a virtual environment."
10
+ echo "It's recommended to create and activate a virtual environment before running tests."
11
+ echo "You can create one with: python -m venv venv"
12
+ echo "And activate it with: source venv/bin/activate (Linux/Mac) or venv\\Scripts\\activate (Windows)"
13
+ echo "Continuing without a virtual environment..."
14
+ echo ""
15
+ fi
16
+
17
+ # Always use python -m pytest to ensure we use the correct pytest
18
+ PYTEST_CMD="python -m pytest"
19
+
20
+ # Check if pytest and other dependencies are installed
21
+ echo "Checking for required packages..."
22
+ MISSING_PACKAGES=()
23
+
24
+ # Check for pytest
25
+ python -c "import pytest" 2>/dev/null
26
+ if [ $? -ne 0 ]; then
27
+ MISSING_PACKAGES+=("pytest pytest-asyncio pytest-cov")
28
+ fi
29
+
30
+ # Check for boto3 package
31
+ python -c "import boto3" 2>/dev/null
32
+ if [ $? -ne 0 ]; then
33
+ MISSING_PACKAGES+=("boto3")
34
+ fi
35
+
36
+ # Check for loguru package
37
+ python -c "import loguru" 2>/dev/null
38
+ if [ $? -ne 0 ]; then
39
+ MISSING_PACKAGES+=("loguru")
40
+ fi
41
+
42
+ # Check for pydantic package
43
+ python -c "import pydantic" 2>/dev/null
44
+ if [ $? -ne 0 ]; then
45
+ MISSING_PACKAGES+=("pydantic")
46
+ fi
47
+
48
+ # Install missing packages
49
+ if [ ${#MISSING_PACKAGES[@]} -gt 0 ]; then
50
+ echo "Installing missing packages: ${MISSING_PACKAGES[*]}"
51
+
52
+ # Try pip first (more reliable)
53
+ if command -v pip &> /dev/null; then
54
+ echo "Using pip to install packages..."
55
+ pip install ${MISSING_PACKAGES[*]} -v
56
+ # Try pip3 if pip is not available
57
+ elif command -v pip3 &> /dev/null; then
58
+ echo "Using pip3 to install packages..."
59
+ pip3 install ${MISSING_PACKAGES[*]} -v
60
+ # Try uv as a last resort
61
+ elif command -v uv &> /dev/null; then
62
+ echo "Using uv to install packages..."
63
+ uv pip install ${MISSING_PACKAGES[*]} -v
64
+ else
65
+ echo "Error: No package manager (pip, pip3, or uv) is available. Please install the missing packages manually."
66
+ exit 1
67
+ fi
68
+
69
+ # Verify installation with more verbose output
70
+ echo "Verifying package installations..."
71
+ for pkg in "pytest" "boto3" "loguru" "pydantic"; do
72
+ echo "Checking for $pkg..."
73
+ python -c "import $pkg; print(f'$pkg version: {$pkg.__version__}')" 2>/dev/null
74
+ if [ $? -ne 0 ]; then
75
+ echo "Failed to install $pkg. Trying to install it individually..."
76
+ pip install $pkg -v || pip3 install $pkg -v || echo "Failed to install $pkg. Please install it manually."
77
+
78
+ # Check again
79
+ python -c "import $pkg" 2>/dev/null
80
+ if [ $? -ne 0 ]; then
81
+ echo "Still failed to install $pkg. Please install it manually."
82
+ echo "You can try: pip install $pkg"
83
+ exit 1
84
+ fi
85
+ fi
86
+ done
87
+ fi
88
+
89
+ # Print debug information
90
+ echo "Debug information:"
91
+ echo "Python version: $(python --version)"
92
+ echo "Python path: $PYTHONPATH"
93
+ echo "Current directory: $(pwd)"
94
+ echo "Python executable: $(which python)"
95
+ echo "Pytest module location: $(python -c "import pytest; print(pytest.__file__)" 2>/dev/null || echo "Not found")"
96
+
97
+ # Check if nova_canvas_mcp_server module can be imported
98
+ echo "Checking if nova_canvas_mcp_server module can be imported..."
99
+ python -c "import awslabs.nova_canvas_mcp_server; print(f'nova_canvas_mcp_server module found at: {awslabs.nova_canvas_mcp_server.__file__}')" 2>/dev/null
100
+ if [ $? -ne 0 ]; then
101
+ echo "Warning: nova_canvas_mcp_server module cannot be imported. This may cause test failures."
102
+ echo "Installing the package in development mode..."
103
+
104
+ # Check if uv is available
105
+ if command -v uv &> /dev/null; then
106
+ uv pip install -e .
107
+ # Check if pip is available
108
+ elif command -v pip &> /dev/null; then
109
+ pip install -e .
110
+ else
111
+ echo "Neither uv nor pip is available. Creating a symbolic link instead..."
112
+ # Create a symbolic link to the module in the current directory
113
+ ln -sf $(pwd)/awslabs/nova_canvas_mcp_server $(pwd)/nova_canvas_mcp_server 2>/dev/null
114
+ fi
115
+
116
+ echo "Trying again..."
117
+ python -c "import awslabs.nova_canvas_mcp_server; print(f'nova_canvas_mcp_server module found at: {awslabs.nova_canvas_mcp_server.__file__}')" 2>/dev/null
118
+ if [ $? -ne 0 ]; then
119
+ echo "Still cannot import nova_canvas_mcp_server module. Tests may fail."
120
+ echo "Directory structure:"
121
+ ls -la
122
+ echo "awslabs directory:"
123
+ ls -la awslabs 2>/dev/null || echo "awslabs directory not found"
124
+ fi
125
+ fi
126
+
127
+ # Check if tests directory exists
128
+ if [ -d "tests" ]; then
129
+ # List test files
130
+ echo "Test files found:"
131
+ find tests -name "test_*.py" | sort
132
+
133
+ # Run the tests
134
+ echo "Running tests..."
135
+ $PYTEST_CMD -xvs tests/
136
+
137
+ # If pytest fails, try using unittest as a fallback
138
+ if [ $? -ne 0 ]; then
139
+ echo "Pytest failed. Trying to run tests with unittest as a fallback..."
140
+ python -m unittest discover -s tests
141
+ fi
142
+
143
+ # Run tests with coverage
144
+ echo "Running tests with coverage..."
145
+ $PYTEST_CMD --cov --cov-branch --cov-report=term-missing tests/
146
+
147
+ # For GitHub Actions, provide an alternative command that uses python -m pytest
148
+ if [ -n "$GITHUB_ACTIONS" ]; then
149
+ echo "Running tests with python -m pytest for GitHub Actions..."
150
+ python -m pytest --cov --cov-branch --cov-report=term-missing --cov-report=xml:nova-canvas-mcp-server-coverage.xml tests/
151
+ fi
152
+ else
153
+ echo "No tests directory found, skipping tests"
154
+ fi
155
+
156
+ echo "Test run completed."
@@ -0,0 +1,25 @@
1
+ # Pytest cache
2
+ __pycache__/
3
+ .pytest_cache/
4
+
5
+ # Coverage reports
6
+ .coverage
7
+ htmlcov/
8
+ coverage.xml
9
+
10
+ # Test output
11
+ output/
12
+
13
+ # Temporary files
14
+ *.tmp
15
+ *.log
16
+
17
+ # Virtual environment
18
+ venv/
19
+ .venv/
20
+
21
+ # IDE files
22
+ .idea/
23
+ .vscode/
24
+ *.swp
25
+ *.swo
@@ -0,0 +1,51 @@
1
+ # Nova Canvas MCP Server Tests
2
+
3
+ This directory contains tests for the Nova Canvas MCP Server, which provides tools for generating images using Amazon Nova Canvas through Amazon Bedrock.
4
+
5
+ ## Test Structure
6
+
7
+ The test suite is organized as follows:
8
+
9
+ - `conftest.py`: Contains pytest fixtures used across the test suite
10
+ - `test_models.py`: Tests for the Pydantic models used for request/response handling
11
+ - `test_novacanvas.py`: Tests for the Nova Canvas API interaction functions
12
+ - `test_server.py`: Tests for the MCP server functionality
13
+
14
+ ## Running Tests
15
+
16
+ You can run the tests using the provided `run_tests.sh` script in the parent directory:
17
+
18
+ ```bash
19
+ cd src/nova-canvas-mcp-server
20
+ ./run_tests.sh
21
+ ```
22
+
23
+ This script will:
24
+ 1. Set up the Python environment
25
+ 2. Install any missing dependencies
26
+ 3. Run the tests with pytest
27
+ 4. Generate a coverage report
28
+ 5. Run code quality checks (ruff format, ruff lint, pyright)
29
+
30
+ ## Test Coverage
31
+
32
+ The test suite aims to provide comprehensive coverage of the Nova Canvas MCP Server functionality, including:
33
+
34
+ - Validation of input parameters
35
+ - Error handling
36
+ - API interaction
37
+ - Image generation with text prompts
38
+ - Image generation with color guidance
39
+ - File saving functionality
40
+ - MCP server integration
41
+
42
+ ## Adding New Tests
43
+
44
+ When adding new tests, please follow these guidelines:
45
+
46
+ 1. Use the appropriate test file based on what you're testing
47
+ 2. Follow the existing test patterns
48
+ 3. Use descriptive test names that clearly indicate what is being tested
49
+ 4. Use fixtures from `conftest.py` where appropriate
50
+ 5. Mock external dependencies (e.g., Bedrock runtime client)
51
+ 6. Test both success and error cases
@@ -0,0 +1,11 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
4
+ # with the License. A copy of the License is located at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
9
+ # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
10
+ # and limitations under the License.
11
+ """Tests for the nova-canvas-mcp-server."""
@@ -0,0 +1,97 @@
1
+ # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance
4
+ # with the License. A copy of the License is located at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
9
+ # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
10
+ # and limitations under the License.
11
+ """Test fixtures for the nova-canvas-mcp-server tests."""
12
+
13
+ import base64
14
+ import json
15
+ import pytest
16
+ import tempfile
17
+ from typing import Dict, Generator, List
18
+ from unittest.mock import AsyncMock, MagicMock
19
+
20
+
21
+ @pytest.fixture
22
+ def temp_workspace_dir() -> Generator[str, None, None]:
23
+ """Create a temporary directory for image output."""
24
+ with tempfile.TemporaryDirectory() as temp_dir:
25
+ yield temp_dir
26
+
27
+
28
+ @pytest.fixture
29
+ def mock_bedrock_runtime_client() -> MagicMock:
30
+ """Create a mock Bedrock runtime client for testing."""
31
+ mock_client = MagicMock()
32
+
33
+ # Mock the invoke_model method
34
+ mock_response = {'body': MagicMock()}
35
+ mock_response['body'].read.return_value = json.dumps(
36
+ {
37
+ 'images': [
38
+ base64.b64encode(b'mock_image_data_1').decode('utf-8'),
39
+ base64.b64encode(b'mock_image_data_2').decode('utf-8'),
40
+ ]
41
+ }
42
+ ).encode('utf-8')
43
+
44
+ mock_client.invoke_model.return_value = mock_response
45
+ return mock_client
46
+
47
+
48
+ @pytest.fixture
49
+ def sample_text_prompt() -> str:
50
+ """Return a sample text prompt for testing."""
51
+ return 'A beautiful mountain landscape with a lake and trees'
52
+
53
+
54
+ @pytest.fixture
55
+ def sample_negative_prompt() -> str:
56
+ """Return a sample negative prompt for testing."""
57
+ return 'people, anatomy, hands, low quality, low resolution, low detail'
58
+
59
+
60
+ @pytest.fixture
61
+ def sample_colors() -> List[str]:
62
+ """Return a sample list of colors for testing."""
63
+ return ['#FF5733', '#33FF57', '#3357FF']
64
+
65
+
66
+ @pytest.fixture
67
+ def sample_base64_images() -> List[str]:
68
+ """Return a list of sample base64-encoded images for testing."""
69
+ return [
70
+ base64.b64encode(b'mock_image_data_1').decode('utf-8'),
71
+ base64.b64encode(b'mock_image_data_2').decode('utf-8'),
72
+ ]
73
+
74
+
75
+ @pytest.fixture
76
+ def mock_successful_response() -> Dict:
77
+ """Return a mock successful response from the Nova Canvas API."""
78
+ return {
79
+ 'images': [
80
+ base64.b64encode(b'mock_image_data_1').decode('utf-8'),
81
+ base64.b64encode(b'mock_image_data_2').decode('utf-8'),
82
+ ]
83
+ }
84
+
85
+
86
+ @pytest.fixture
87
+ def mock_error_response() -> Dict:
88
+ """Return a mock error response from the Nova Canvas API."""
89
+ return {'error': 'An error occurred during image generation'}
90
+
91
+
92
+ @pytest.fixture
93
+ def mock_context() -> AsyncMock:
94
+ """Create a mock MCP context for testing."""
95
+ context = AsyncMock()
96
+ context.error = AsyncMock()
97
+ return context