awslabs.cdk-mcp-server 0.1.0__tar.gz → 0.1.1__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_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/.gitignore +3 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/PKG-INFO +1 -1
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/schema_generator.py +2 -1
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/pyproject.toml +26 -1
- awslabs_cdk_mcp_server-0.1.1/tests/__init__.py +10 -0
- awslabs_cdk_mcp_server-0.1.1/tests/core/test_resources.py +190 -0
- awslabs_cdk_mcp_server-0.1.1/tests/core/test_search_utils.py +77 -0
- awslabs_cdk_mcp_server-0.1.1/tests/core/test_server.py +55 -0
- awslabs_cdk_mcp_server-0.1.1/tests/core/test_tools.py +153 -0
- awslabs_cdk_mcp_server-0.1.1/tests/data/test_cdk_nag_parser.py +280 -0
- awslabs_cdk_mcp_server-0.1.1/tests/data/test_genai_cdk_loader.py +345 -0
- awslabs_cdk_mcp_server-0.1.1/tests/data/test_lambda_powertools_loader.py +97 -0
- awslabs_cdk_mcp_server-0.1.1/tests/data/test_schema_generator.py +448 -0
- awslabs_cdk_mcp_server-0.1.1/tests/data/test_solutions_constructs_parser.py +200 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/uv.lock +185 -1
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/.pre-commit-config.yaml +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/.python-version +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/CHANGELOG.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/LICENSE +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/NOTICE +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/README.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/__init__.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/__init__.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/core/__init__.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/core/resources.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/core/search_utils.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/core/server.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/core/tools.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/__init__.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/cdk_nag_parser.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/construct_descriptions.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/genai_cdk_loader.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/lambda_layer_parser.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/lambda_powertools_loader.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/data/solutions_constructs_parser.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/server.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/CDK_GENERAL_GUIDANCE.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/CDK_NAG_GUIDANCE.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/__init__.py +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/actiongroups.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/alias.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/collaboration.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/creation.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/custom_orchestration.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/overview.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/agent/prompt_override.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/bedrockguardrails.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/chunking.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/datasources.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/kendra.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/overview.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/parsing.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/transformation.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/aurora.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/creation.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/opensearch.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/knowledgebases/vector/pinecone.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/bedrock/profiles.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/opensearch-vectorindex/overview.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/genai_cdk/opensearchserverless/overview.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/bedrock.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/cdk.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/dependencies.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/index.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/insights.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/logging.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/metrics.md +0 -0
- {awslabs_cdk_mcp_server-0.1.0 → awslabs_cdk_mcp_server-0.1.1}/awslabs/cdk_mcp_server/static/lambda_powertools/tracing.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: awslabs.cdk-mcp-server
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: An AWS CDK MCP server that provides guidance on AWS Cloud Development Kit best practices, infrastructure as code patterns, and security compliance with CDK Nag. This server offers tools to validate infrastructure designs, explain CDK Nag rules, analyze suppressions, generate Bedrock Agent schemas, and discover Solutions Constructs patterns.
|
|
5
5
|
Project-URL: Homepage, https://awslabs.github.io/mcp/
|
|
6
6
|
Project-URL: Documentation, https://awslabs.github.io/mcp/servers/cdk-mcp-server/
|
|
@@ -20,7 +20,8 @@ from typing import Any, Dict, List, Optional, Tuple
|
|
|
20
20
|
|
|
21
21
|
def generate_fallback_script(lambda_code_path: str, output_path: str) -> str:
|
|
22
22
|
"""Generate a standalone script for schema generation."""
|
|
23
|
-
return f'''
|
|
23
|
+
return f'''# pyright: ignore
|
|
24
|
+
#!/usr/bin/env python3
|
|
24
25
|
"""
|
|
25
26
|
Schema Generator for Bedrock Agent Action Groups
|
|
26
27
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "awslabs.cdk-mcp-server"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.1"
|
|
4
4
|
description = "An AWS CDK MCP server that provides guidance on AWS Cloud Development Kit best practices, infrastructure as code patterns, and security compliance with CDK Nag. This server offers tools to validate infrastructure designs, explain CDK Nag rules, analyze suppressions, generate Bedrock Agent schemas, and discover Solutions Constructs patterns."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -45,6 +45,10 @@ dev = [
|
|
|
45
45
|
"pre-commit>=4.1.0",
|
|
46
46
|
"ruff>=0.9.7",
|
|
47
47
|
"pyright>=1.1.398",
|
|
48
|
+
"pytest>=8.0.0",
|
|
49
|
+
"pytest-cov>=4.1.0",
|
|
50
|
+
"pytest-mock>=3.12.0",
|
|
51
|
+
"pytest-asyncio>=0.23.5",
|
|
48
52
|
]
|
|
49
53
|
|
|
50
54
|
[build-system]
|
|
@@ -107,3 +111,24 @@ packages = ["awslabs"]
|
|
|
107
111
|
|
|
108
112
|
[tool.bandit]
|
|
109
113
|
exclude_dirs = ["venv","tests"]
|
|
114
|
+
|
|
115
|
+
[tool.pytest.ini_options]
|
|
116
|
+
minversion = "8.0"
|
|
117
|
+
addopts = "-ra -q --cov=awslabs.cdk_mcp_server --cov-report=term-missing"
|
|
118
|
+
testpaths = [
|
|
119
|
+
"tests",
|
|
120
|
+
]
|
|
121
|
+
python_files = ["test_*.py"]
|
|
122
|
+
python_classes = ["Test*"]
|
|
123
|
+
python_functions = ["test_*"]
|
|
124
|
+
filterwarnings = [
|
|
125
|
+
"ignore::DeprecationWarning",
|
|
126
|
+
"ignore::UserWarning",
|
|
127
|
+
]
|
|
128
|
+
asyncio_mode = "auto"
|
|
129
|
+
|
|
130
|
+
[tool.pyright]
|
|
131
|
+
ignore = ["scripts/generate_schema_*.py"]
|
|
132
|
+
|
|
133
|
+
[tool.coverage.run]
|
|
134
|
+
source = ["awslabs"]
|
|
@@ -0,0 +1,10 @@
|
|
|
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.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from awslabs.cdk_mcp_server.core.resources import (
|
|
3
|
+
RulePack,
|
|
4
|
+
get_all_cdk_nag_rules,
|
|
5
|
+
get_available_sections_resource,
|
|
6
|
+
get_cdk_nag_errors,
|
|
7
|
+
get_cdk_nag_warnings,
|
|
8
|
+
get_genai_cdk_construct_nested_section_resource,
|
|
9
|
+
get_genai_cdk_construct_resource,
|
|
10
|
+
get_genai_cdk_construct_section_resource,
|
|
11
|
+
get_genai_cdk_overview_resource,
|
|
12
|
+
get_lambda_powertools_guidance,
|
|
13
|
+
get_lambda_powertools_index,
|
|
14
|
+
get_solutions_construct_pattern_resource,
|
|
15
|
+
)
|
|
16
|
+
from unittest.mock import patch
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@pytest.mark.asyncio
|
|
20
|
+
async def test_get_all_cdk_nag_rules():
|
|
21
|
+
"""Test getting all CDK Nag rules for a rule pack."""
|
|
22
|
+
with patch('awslabs.cdk_mcp_server.core.resources.get_rule_pack') as mock_get_rule_pack:
|
|
23
|
+
mock_get_rule_pack.return_value = 'Test rule pack content'
|
|
24
|
+
|
|
25
|
+
# Test with valid rule pack
|
|
26
|
+
result = await get_all_cdk_nag_rules(RulePack.AWS_SOLUTIONS.value)
|
|
27
|
+
assert result == 'Test rule pack content'
|
|
28
|
+
mock_get_rule_pack.assert_called_once_with(RulePack.AWS_SOLUTIONS)
|
|
29
|
+
|
|
30
|
+
# Test with invalid rule pack
|
|
31
|
+
result = await get_all_cdk_nag_rules('Invalid Pack')
|
|
32
|
+
assert 'Invalid rule pack' in result
|
|
33
|
+
assert RulePack.AWS_SOLUTIONS.value in result
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@pytest.mark.asyncio
|
|
37
|
+
async def test_get_cdk_nag_warnings():
|
|
38
|
+
"""Test getting CDK Nag warnings for a rule pack."""
|
|
39
|
+
with patch('awslabs.cdk_mcp_server.core.resources.get_warnings') as mock_get_warnings:
|
|
40
|
+
mock_get_warnings.return_value = 'Test warnings content'
|
|
41
|
+
|
|
42
|
+
# Test with valid rule pack
|
|
43
|
+
result = await get_cdk_nag_warnings(RulePack.AWS_SOLUTIONS.value)
|
|
44
|
+
assert result == 'Test warnings content'
|
|
45
|
+
mock_get_warnings.assert_called_once_with(RulePack.AWS_SOLUTIONS)
|
|
46
|
+
|
|
47
|
+
# Test with invalid rule pack
|
|
48
|
+
result = await get_cdk_nag_warnings('Invalid Pack')
|
|
49
|
+
assert 'Invalid rule pack' in result
|
|
50
|
+
assert RulePack.AWS_SOLUTIONS.value in result
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@pytest.mark.asyncio
|
|
54
|
+
async def test_get_cdk_nag_errors():
|
|
55
|
+
"""Test getting CDK Nag errors for a rule pack."""
|
|
56
|
+
with patch('awslabs.cdk_mcp_server.core.resources.get_errors') as mock_get_errors:
|
|
57
|
+
mock_get_errors.return_value = 'Test errors content'
|
|
58
|
+
|
|
59
|
+
# Test with valid rule pack
|
|
60
|
+
result = await get_cdk_nag_errors(RulePack.AWS_SOLUTIONS.value)
|
|
61
|
+
assert result == 'Test errors content'
|
|
62
|
+
mock_get_errors.assert_called_once_with(RulePack.AWS_SOLUTIONS)
|
|
63
|
+
|
|
64
|
+
# Test with invalid rule pack
|
|
65
|
+
result = await get_cdk_nag_errors('Invalid Pack')
|
|
66
|
+
assert 'Invalid rule pack' in result
|
|
67
|
+
assert RulePack.AWS_SOLUTIONS.value in result
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@pytest.mark.asyncio
|
|
71
|
+
async def test_get_lambda_powertools_guidance():
|
|
72
|
+
"""Test getting Lambda Powertools guidance."""
|
|
73
|
+
with patch(
|
|
74
|
+
'awslabs.cdk_mcp_server.core.resources.get_lambda_powertools_section'
|
|
75
|
+
) as mock_get_section:
|
|
76
|
+
mock_get_section.return_value = 'Test guidance content'
|
|
77
|
+
|
|
78
|
+
# Test with specific topic
|
|
79
|
+
result = await get_lambda_powertools_guidance('logging')
|
|
80
|
+
assert result == 'Test guidance content'
|
|
81
|
+
mock_get_section.assert_called_once_with('logging')
|
|
82
|
+
|
|
83
|
+
# Test with empty topic
|
|
84
|
+
result = await get_lambda_powertools_guidance()
|
|
85
|
+
assert result == 'Test guidance content'
|
|
86
|
+
mock_get_section.assert_called_with('')
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
@pytest.mark.asyncio
|
|
90
|
+
async def test_get_lambda_powertools_index():
|
|
91
|
+
"""Test getting Lambda Powertools index."""
|
|
92
|
+
with patch(
|
|
93
|
+
'awslabs.cdk_mcp_server.core.resources.get_lambda_powertools_section'
|
|
94
|
+
) as mock_get_section:
|
|
95
|
+
mock_get_section.return_value = 'Test index content'
|
|
96
|
+
|
|
97
|
+
result = await get_lambda_powertools_index()
|
|
98
|
+
assert result == 'Test index content'
|
|
99
|
+
mock_get_section.assert_called_once_with('index')
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@pytest.mark.asyncio
|
|
103
|
+
async def test_get_solutions_construct_pattern_resource():
|
|
104
|
+
"""Test getting Solutions Construct pattern resource."""
|
|
105
|
+
with patch('awslabs.cdk_mcp_server.core.resources.get_pattern_raw') as mock_get_pattern:
|
|
106
|
+
# Test with valid pattern
|
|
107
|
+
mock_get_pattern.return_value = {'content': 'Test pattern content'}
|
|
108
|
+
result = await get_solutions_construct_pattern_resource('aws-lambda-dynamodb')
|
|
109
|
+
assert result == 'Test pattern content'
|
|
110
|
+
mock_get_pattern.assert_called_once_with('aws-lambda-dynamodb')
|
|
111
|
+
|
|
112
|
+
# Test with invalid pattern
|
|
113
|
+
mock_get_pattern.return_value = {'error': 'Pattern not found'}
|
|
114
|
+
with patch('awslabs.cdk_mcp_server.data.solutions_constructs_parser') as mock_fetch_list:
|
|
115
|
+
mock_fetch_list.return_value = ['pattern1', 'pattern2']
|
|
116
|
+
result = await get_solutions_construct_pattern_resource('invalid-pattern')
|
|
117
|
+
assert "Pattern 'invalid-pattern' not found" in result
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@pytest.mark.asyncio
|
|
121
|
+
async def test_get_genai_cdk_construct_section_resource():
|
|
122
|
+
"""Test getting GenAI CDK construct section resource."""
|
|
123
|
+
with patch(
|
|
124
|
+
'awslabs.cdk_mcp_server.core.resources.get_genai_cdk_construct_section'
|
|
125
|
+
) as mock_get_section:
|
|
126
|
+
mock_get_section.return_value = 'Test section content'
|
|
127
|
+
|
|
128
|
+
result = await get_genai_cdk_construct_section_resource('bedrock', 'agent', 'actiongroups')
|
|
129
|
+
assert result == 'Test section content'
|
|
130
|
+
mock_get_section.assert_called_once_with('bedrock', 'agent', 'actiongroups')
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
@pytest.mark.asyncio
|
|
134
|
+
async def test_get_genai_cdk_construct_nested_section_resource():
|
|
135
|
+
"""Test getting GenAI CDK construct nested section resource."""
|
|
136
|
+
with patch(
|
|
137
|
+
'awslabs.cdk_mcp_server.core.resources.get_genai_cdk_construct_section'
|
|
138
|
+
) as mock_get_section:
|
|
139
|
+
mock_get_section.return_value = 'Test nested section content'
|
|
140
|
+
|
|
141
|
+
result = await get_genai_cdk_construct_nested_section_resource(
|
|
142
|
+
'bedrock', 'knowledgebases', 'vector', 'opensearch'
|
|
143
|
+
)
|
|
144
|
+
assert result == 'Test nested section content'
|
|
145
|
+
mock_get_section.assert_called_once_with('bedrock', 'knowledgebases', 'vector/opensearch')
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
@pytest.mark.asyncio
|
|
149
|
+
async def test_get_available_sections_resource():
|
|
150
|
+
"""Test getting available sections resource."""
|
|
151
|
+
with patch(
|
|
152
|
+
'awslabs.cdk_mcp_server.core.resources.list_available_sections'
|
|
153
|
+
) as mock_list_sections:
|
|
154
|
+
# Test with sections available
|
|
155
|
+
mock_list_sections.return_value = ['section1', 'section2']
|
|
156
|
+
result = await get_available_sections_resource('bedrock', 'agent')
|
|
157
|
+
assert 'Available Sections for Agent in Bedrock' in result
|
|
158
|
+
assert 'section1' in result
|
|
159
|
+
assert 'section2' in result
|
|
160
|
+
|
|
161
|
+
# Test with no sections
|
|
162
|
+
mock_list_sections.return_value = []
|
|
163
|
+
result = await get_available_sections_resource('bedrock', 'agent')
|
|
164
|
+
assert 'No sections found' in result
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
@pytest.mark.asyncio
|
|
168
|
+
async def test_get_genai_cdk_construct_resource():
|
|
169
|
+
"""Test getting GenAI CDK construct resource."""
|
|
170
|
+
with patch(
|
|
171
|
+
'awslabs.cdk_mcp_server.core.resources.get_genai_cdk_construct'
|
|
172
|
+
) as mock_get_construct:
|
|
173
|
+
mock_get_construct.return_value = 'Test construct content'
|
|
174
|
+
|
|
175
|
+
result = await get_genai_cdk_construct_resource('bedrock', 'Agent')
|
|
176
|
+
assert result == 'Test construct content'
|
|
177
|
+
mock_get_construct.assert_called_once_with('bedrock', 'Agent')
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
@pytest.mark.asyncio
|
|
181
|
+
async def test_get_genai_cdk_overview_resource():
|
|
182
|
+
"""Test getting GenAI CDK overview resource."""
|
|
183
|
+
with patch(
|
|
184
|
+
'awslabs.cdk_mcp_server.core.resources.get_genai_cdk_overview'
|
|
185
|
+
) as mock_get_overview:
|
|
186
|
+
mock_get_overview.return_value = 'Test overview content'
|
|
187
|
+
|
|
188
|
+
result = await get_genai_cdk_overview_resource('bedrock')
|
|
189
|
+
assert result == 'Test overview content'
|
|
190
|
+
mock_get_overview.assert_called_once_with('bedrock')
|
|
@@ -0,0 +1,77 @@
|
|
|
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
|
+
from awslabs.cdk_mcp_server.core import search_utils
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def test_normalize_term():
|
|
15
|
+
"""Test term normalization."""
|
|
16
|
+
assert search_utils.normalize_term('Test-Term') == 'test term'
|
|
17
|
+
assert search_utils.normalize_term('Test_Term') == 'test term'
|
|
18
|
+
assert search_utils.normalize_term('Test Term') == 'test term'
|
|
19
|
+
assert search_utils.normalize_term('Test%20Term') == 'test term'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_get_term_variations():
|
|
23
|
+
"""Test getting term variations."""
|
|
24
|
+
variations = search_utils.get_term_variations('knowledgebase')
|
|
25
|
+
assert 'knowledgebases' in variations
|
|
26
|
+
assert 'knowledge-base' in variations
|
|
27
|
+
assert 'knowledge-bases' in variations
|
|
28
|
+
|
|
29
|
+
variations = search_utils.get_term_variations('agent')
|
|
30
|
+
assert 'agents' in variations
|
|
31
|
+
|
|
32
|
+
variations = search_utils.get_term_variations('actiongroup')
|
|
33
|
+
assert 'actiongroups' in variations
|
|
34
|
+
assert 'action-group' in variations
|
|
35
|
+
assert 'action-groups' in variations
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def test_expand_search_terms():
|
|
39
|
+
"""Test expanding search terms."""
|
|
40
|
+
terms = ['knowledgebase', 'agent']
|
|
41
|
+
expanded = search_utils.expand_search_terms(terms)
|
|
42
|
+
assert 'knowledgebase' in expanded
|
|
43
|
+
assert 'knowledgebases' in expanded
|
|
44
|
+
assert 'agent' in expanded
|
|
45
|
+
assert 'agents' in expanded
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_calculate_match_score():
|
|
49
|
+
"""Test calculating match score."""
|
|
50
|
+
item_text = 'This is a test item with some content'
|
|
51
|
+
search_terms = ['test', 'content']
|
|
52
|
+
name_parts = ['TestItem']
|
|
53
|
+
|
|
54
|
+
result = search_utils.calculate_match_score(item_text, search_terms, name_parts)
|
|
55
|
+
assert result['score'] > 0
|
|
56
|
+
assert len(result['matched_terms']) > 0
|
|
57
|
+
assert result['has_match'] is True
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def test_search_items_with_terms():
|
|
61
|
+
"""Test searching items with terms."""
|
|
62
|
+
items = [
|
|
63
|
+
{'name': 'TestItem1', 'description': 'This is a test item'},
|
|
64
|
+
{'name': 'TestItem2', 'description': 'This is another test item'},
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
def get_text_fn(item):
|
|
68
|
+
return item['description']
|
|
69
|
+
|
|
70
|
+
def get_name_parts_fn(item):
|
|
71
|
+
return [item['name']]
|
|
72
|
+
|
|
73
|
+
results = search_utils.search_items_with_terms(items, ['test'], get_text_fn, get_name_parts_fn)
|
|
74
|
+
|
|
75
|
+
assert len(results) == 2
|
|
76
|
+
assert results[0]['score'] >= results[1]['score']
|
|
77
|
+
assert 'test' in results[0]['matched_terms']
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from awslabs.cdk_mcp_server.core.server import main, mcp
|
|
3
|
+
from unittest.mock import patch
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_mcp_server_initialization():
|
|
7
|
+
"""Test MCP server initialization."""
|
|
8
|
+
# Check server name
|
|
9
|
+
assert mcp.name == 'AWS CDK MCP Server'
|
|
10
|
+
|
|
11
|
+
# Check dependencies
|
|
12
|
+
assert 'pydantic' in mcp.dependencies
|
|
13
|
+
assert 'aws-lambda-powertools' in mcp.dependencies
|
|
14
|
+
assert 'httpx' in mcp.dependencies
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@pytest.mark.asyncio
|
|
18
|
+
async def test_mcp_server_tool_registration():
|
|
19
|
+
"""Test MCP server tool registration."""
|
|
20
|
+
# Get all registered tools
|
|
21
|
+
tools = await mcp.list_tools()
|
|
22
|
+
|
|
23
|
+
# Check CDK tools
|
|
24
|
+
assert any(t.name == 'CDKGeneralGuidance' for t in tools)
|
|
25
|
+
assert any(t.name == 'ExplainCDKNagRule' for t in tools)
|
|
26
|
+
assert any(t.name == 'CheckCDKNagSuppressions' for t in tools)
|
|
27
|
+
|
|
28
|
+
# Check Bedrock tools
|
|
29
|
+
assert any(t.name == 'GenerateBedrockAgentSchema' for t in tools)
|
|
30
|
+
|
|
31
|
+
# Check Solutions Constructs tools
|
|
32
|
+
assert any(t.name == 'GetAwsSolutionsConstructPattern' for t in tools)
|
|
33
|
+
|
|
34
|
+
# Check GenAI CDK Constructs tools
|
|
35
|
+
assert any(t.name == 'SearchGenAICDKConstructs' for t in tools)
|
|
36
|
+
|
|
37
|
+
# Check Lambda tools
|
|
38
|
+
assert any(t.name == 'LambdaLayerDocumentationProvider' for t in tools)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@patch('awslabs.cdk_mcp_server.core.server.mcp.run')
|
|
42
|
+
def test_main_with_default_args(mock_run):
|
|
43
|
+
"""Test main function with default arguments."""
|
|
44
|
+
with patch('sys.argv', ['server.py']):
|
|
45
|
+
main()
|
|
46
|
+
mock_run.assert_called_once_with()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
@patch('awslabs.cdk_mcp_server.core.server.mcp.run')
|
|
50
|
+
def test_main_with_sse_args(mock_run):
|
|
51
|
+
"""Test main function with SSE transport arguments."""
|
|
52
|
+
with patch('sys.argv', ['server.py', '--sse', '--port', '9999']):
|
|
53
|
+
main()
|
|
54
|
+
assert mcp.settings.port == 9999
|
|
55
|
+
mock_run.assert_called_once_with(transport='sse')
|
|
@@ -0,0 +1,153 @@
|
|
|
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
|
+
import pytest
|
|
12
|
+
from awslabs.cdk_mcp_server.core.tools import (
|
|
13
|
+
bedrock_schema_generator_from_file,
|
|
14
|
+
cdk_guidance,
|
|
15
|
+
check_cdk_nag_suppressions_tool,
|
|
16
|
+
explain_cdk_nag_rule,
|
|
17
|
+
get_aws_solutions_construct_pattern,
|
|
18
|
+
lambda_layer_documentation_provider,
|
|
19
|
+
search_genai_cdk_constructs,
|
|
20
|
+
)
|
|
21
|
+
from unittest.mock import MagicMock
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.fixture
|
|
25
|
+
def mock_context():
|
|
26
|
+
"""Fixture that provides a mocked MCP context."""
|
|
27
|
+
context = MagicMock()
|
|
28
|
+
context.settings = MagicMock()
|
|
29
|
+
return context
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@pytest.mark.asyncio
|
|
33
|
+
async def test_cdk_guidance(mock_context):
|
|
34
|
+
"""Test CDK guidance tool."""
|
|
35
|
+
result = await cdk_guidance(mock_context)
|
|
36
|
+
assert isinstance(result, str)
|
|
37
|
+
assert len(result) > 0
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@pytest.mark.asyncio
|
|
41
|
+
async def test_explain_cdk_nag_rule(mock_context):
|
|
42
|
+
"""Test CDK Nag rule explanation tool."""
|
|
43
|
+
result = await explain_cdk_nag_rule(mock_context, rule_id='AwsSolutions-APIG3')
|
|
44
|
+
assert isinstance(result, dict)
|
|
45
|
+
assert 'rule_id' in result
|
|
46
|
+
assert 'content' in result
|
|
47
|
+
assert 'source' in result
|
|
48
|
+
assert 'status' in result
|
|
49
|
+
assert result['rule_id'] == 'AwsSolutions-APIG3'
|
|
50
|
+
assert result['source'] == 'https://github.com/cdklabs/cdk-nag/blob/main/RULES.md'
|
|
51
|
+
assert result['status'] == 'success'
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@pytest.mark.asyncio
|
|
55
|
+
async def test_check_cdk_nag_suppressions_tool(mock_context):
|
|
56
|
+
"""Test CDK Nag suppressions check tool."""
|
|
57
|
+
result = await check_cdk_nag_suppressions_tool(mock_context, code='test code')
|
|
58
|
+
assert isinstance(result, dict)
|
|
59
|
+
assert 'has_suppressions' in result
|
|
60
|
+
assert 'message' in result
|
|
61
|
+
assert 'status' in result
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@pytest.mark.asyncio
|
|
65
|
+
async def test_bedrock_schema_generator_from_file_throws_error(mock_context):
|
|
66
|
+
"""Test Bedrock schema generator tool."""
|
|
67
|
+
with pytest.raises(Exception):
|
|
68
|
+
await bedrock_schema_generator_from_file(
|
|
69
|
+
mock_context,
|
|
70
|
+
lambda_code_path='test.py', # non existing path
|
|
71
|
+
output_path='test.json', # non existing path
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@pytest.mark.asyncio
|
|
76
|
+
async def test_get_aws_solutions_construct_pattern(mock_context):
|
|
77
|
+
"""Test AWS Solutions Construct pattern tool."""
|
|
78
|
+
result = await get_aws_solutions_construct_pattern(mock_context, pattern_name='aws-alb-lambda')
|
|
79
|
+
assert isinstance(result, dict)
|
|
80
|
+
assert 'description' in result
|
|
81
|
+
assert 'use_cases' in result
|
|
82
|
+
assert 'services' in result
|
|
83
|
+
assert 'documentation_uri' in result
|
|
84
|
+
assert result['pattern_name'] == 'aws-alb-lambda'
|
|
85
|
+
assert result['services'] == ['Application Load Balancer', 'Lambda']
|
|
86
|
+
assert (
|
|
87
|
+
result['description']
|
|
88
|
+
== 'This AWS Solutions Construct implements an an Application Load Balancer to an AWS Lambda function'
|
|
89
|
+
)
|
|
90
|
+
assert result['documentation_uri'] == 'aws-solutions-constructs://aws-alb-lambda'
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@pytest.mark.asyncio
|
|
94
|
+
async def test_search_genai_cdk_constructs(mock_context):
|
|
95
|
+
"""Test GenAI CDK constructs search tool."""
|
|
96
|
+
result = await search_genai_cdk_constructs(mock_context, query='knowledge base')
|
|
97
|
+
assert isinstance(result, dict)
|
|
98
|
+
assert 'count' in result
|
|
99
|
+
assert 'results' in result
|
|
100
|
+
assert 'status' in result
|
|
101
|
+
assert 'installation_required' in result
|
|
102
|
+
assert result['status'] == 'success'
|
|
103
|
+
assert (
|
|
104
|
+
result['installation_required']['package_name'] == '@cdklabs/generative-ai-cdk-constructs'
|
|
105
|
+
)
|
|
106
|
+
assert (
|
|
107
|
+
result['installation_required']['message']
|
|
108
|
+
== 'This construct requires the @cdklabs/generative-ai-cdk-constructs package to be installed'
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@pytest.mark.asyncio
|
|
113
|
+
async def test_lambda_layer_documentation_provider_generic(mock_context):
|
|
114
|
+
"""Test Lambda layer documentation provider tool."""
|
|
115
|
+
result = await lambda_layer_documentation_provider(mock_context, layer_type='generic')
|
|
116
|
+
assert isinstance(result, dict)
|
|
117
|
+
assert 'code_examples' in result
|
|
118
|
+
assert 'directory_structure' in result
|
|
119
|
+
assert 'source_url' in result
|
|
120
|
+
assert 'layer_type' in result
|
|
121
|
+
assert result['layer_type'] == 'generic'
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@pytest.mark.asyncio
|
|
125
|
+
async def test_lambda_layer_documentation_provider_python(mock_context):
|
|
126
|
+
"""Test Lambda layer documentation provider tool."""
|
|
127
|
+
result = await lambda_layer_documentation_provider(mock_context, layer_type='python')
|
|
128
|
+
assert isinstance(result, dict)
|
|
129
|
+
assert 'layer_type' in result
|
|
130
|
+
assert 'documentation_source' in result
|
|
131
|
+
assert 'documentation_usage_guide' in result
|
|
132
|
+
assert 'code_generation_guidance' in result
|
|
133
|
+
assert result['layer_type'] == 'python'
|
|
134
|
+
assert result['documentation_source']['server'] == 'awslabs.aws-documentation-mcp-server'
|
|
135
|
+
assert result['documentation_source']['tool'] == 'read_documentation'
|
|
136
|
+
assert result['documentation_source']['parameters']['max_length'] == 10000
|
|
137
|
+
assert (
|
|
138
|
+
result['documentation_usage_guide']['when_to_fetch_full_docs']
|
|
139
|
+
== 'Fetch full documentation to view detailed property definitions, learn about optional parameters, and find additional code examples'
|
|
140
|
+
)
|
|
141
|
+
assert result['documentation_usage_guide']['contains_sample_code'] == True # noqa: E712
|
|
142
|
+
assert result['documentation_usage_guide']['contains_props_documentation'] == True # noqa: E712
|
|
143
|
+
assert result['code_generation_guidance']['imports'] == [
|
|
144
|
+
"import { PythonLayerVersion } from '@aws-cdk/aws-lambda-python-alpha'"
|
|
145
|
+
]
|
|
146
|
+
assert result['code_generation_guidance']['construct_types'] == {
|
|
147
|
+
'python': 'PythonLayerVersion'
|
|
148
|
+
}
|
|
149
|
+
assert result['code_generation_guidance']['required_properties'] == {'python': ['entry']}
|
|
150
|
+
assert (
|
|
151
|
+
result['code_generation_guidance']['sample_code']
|
|
152
|
+
== "new python.PythonLayerVersion(this, 'MyLayer', {\n entry: '/path/to/my/layer', // point this to your library's directory\n})"
|
|
153
|
+
)
|