awslabs.ccapi-mcp-server 1.0.4__tar.gz → 1.0.13__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_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/Dockerfile +33 -23
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/PKG-INFO +7 -7
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/README.md +5 -5
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/__init__.py +1 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/__init__.py +1 -1
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/cloud_control_utils.py +28 -4
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/tools/explanation.py +26 -2
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/tools/infrastructure_generation.py +8 -3
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/tools/resource_operations.py +25 -8
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/tools/session_management.py +2 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/infrastructure_generator.py +7 -13
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/server.py +1 -1
- awslabs_ccapi_mcp_server-1.0.13/docker-healthcheck.sh +25 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/pyproject.toml +2 -2
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_cloud_control_utils.py +58 -30
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_explanation.py +48 -0
- awslabs_ccapi_mcp_server-1.0.13/tests/test_infrastructure_generation.py +242 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_infrastructure_generator.py +76 -3
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_resource_operations.py +163 -7
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_security_scanning.py +60 -0
- awslabs_ccapi_mcp_server-1.0.13/uv-requirements.txt +27 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/uv.lock +290 -148
- awslabs_ccapi_mcp_server-1.0.4/docker-healthcheck.sh +0 -26
- awslabs_ccapi_mcp_server-1.0.4/tests/test_infrastructure_generation.py +0 -110
- awslabs_ccapi_mcp_server-1.0.4/uv-requirements.txt +0 -24
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/.gitignore +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/.python-version +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/CHANGELOG.md +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/LICENSE +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/NOTICE +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/aws_client.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/context.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/errors.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/iac_generator.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/__init__.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/tools/__init__.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/tools/security_scanning.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/utils/__init__.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/impl/utils/validation.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/models/__init__.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/models/models.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/schema_manager.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/awslabs/ccapi_mcp_server/static/__init__.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/run_tests.sh +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/__init__.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_aws_client.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_checkov_install.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_context.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_errors.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_iac_generator.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_models.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_schema_manager.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_server.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_session_management.py +0 -0
- {awslabs_ccapi_mcp_server-1.0.4 → awslabs_ccapi_mcp_server-1.0.13}/tests/test_validation.py +0 -0
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
#
|
|
16
|
-
FROM public.ecr.aws/
|
|
15
|
+
# dependabot should continue to update this to the latest hash.
|
|
16
|
+
FROM public.ecr.aws/docker/library/python:3.13-alpine@sha256:e7e041128ffc3e3600509f508e44d34ab08ff432bdb62ec508d01dfc5ca459f7 AS uv
|
|
17
17
|
|
|
18
18
|
# Install the project into `/app`
|
|
19
19
|
WORKDIR /app
|
|
@@ -31,40 +31,50 @@ ENV UV_PYTHON_PREFERENCE=only-system
|
|
|
31
31
|
ENV UV_FROZEN=true
|
|
32
32
|
|
|
33
33
|
# Copy the required files first
|
|
34
|
-
COPY pyproject.toml uv.lock ./
|
|
34
|
+
COPY pyproject.toml uv.lock uv-requirements.txt ./
|
|
35
|
+
|
|
36
|
+
# Python optimization and uv configuration
|
|
37
|
+
ENV PIP_NO_CACHE_DIR=1 \
|
|
38
|
+
PIP_DISABLE_PIP_VERSION_CHECK=1
|
|
39
|
+
|
|
40
|
+
# Install system dependencies and Python package manager
|
|
41
|
+
RUN apk update && \
|
|
42
|
+
apk add --no-cache --virtual .build-deps \
|
|
43
|
+
build-base \
|
|
44
|
+
gcc \
|
|
45
|
+
musl-dev \
|
|
46
|
+
libffi-dev \
|
|
47
|
+
openssl-dev \
|
|
48
|
+
cargo
|
|
35
49
|
|
|
36
50
|
# Install the project's dependencies using the lockfile and settings
|
|
37
51
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
38
|
-
pip install uv
|
|
39
|
-
uv sync --frozen --no-install-project --no-dev --no-editable
|
|
52
|
+
pip install --require-hashes --requirement uv-requirements.txt --no-cache-dir && \
|
|
53
|
+
uv sync --python 3.13 --frozen --no-install-project --no-dev --no-editable
|
|
40
54
|
|
|
41
55
|
# Then, add the rest of the project source code and install it
|
|
42
56
|
# Installing separately from its dependencies allows optimal layer caching
|
|
43
57
|
COPY . /app
|
|
44
58
|
RUN --mount=type=cache,target=/root/.cache/uv \
|
|
45
|
-
uv sync --frozen --no-dev --no-editable
|
|
59
|
+
uv sync --python 3.13 --frozen --no-dev --no-editable
|
|
46
60
|
|
|
47
61
|
# Make the directory just in case it doesn't exist
|
|
48
62
|
RUN mkdir -p /root/.local
|
|
49
63
|
|
|
50
|
-
FROM public.ecr.aws/
|
|
64
|
+
FROM public.ecr.aws/docker/library/python:3.13-alpine@sha256:e7e041128ffc3e3600509f508e44d34ab08ff432bdb62ec508d01dfc5ca459f7
|
|
51
65
|
|
|
52
66
|
# Place executables in the environment at the front of the path and include other binaries
|
|
53
|
-
ENV PATH="/app/.venv/bin:$PATH
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
# Install
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
chmod o+x /root
|
|
65
|
-
|
|
66
|
-
# Get the project from the uv layer
|
|
67
|
-
COPY --from=uv --chown=app:app /root/.local /root/.local
|
|
67
|
+
ENV PATH="/app/.venv/bin:$PATH" \
|
|
68
|
+
PYTHONUNBUFFERED=1
|
|
69
|
+
|
|
70
|
+
# Install runtime dependencies and create application user
|
|
71
|
+
RUN apk update && \
|
|
72
|
+
apk add --no-cache ca-certificates && \
|
|
73
|
+
update-ca-certificates && \
|
|
74
|
+
addgroup -S app && \
|
|
75
|
+
adduser -S app -G app -h /app
|
|
76
|
+
|
|
77
|
+
# Copy application artifacts from build stage
|
|
68
78
|
COPY --from=uv --chown=app:app /app/.venv /app/.venv
|
|
69
79
|
|
|
70
80
|
# Get healthcheck script
|
|
@@ -74,5 +84,5 @@ COPY ./docker-healthcheck.sh /usr/local/bin/docker-healthcheck.sh
|
|
|
74
84
|
USER app
|
|
75
85
|
|
|
76
86
|
# When running the container, add --db-path and a bind mount to the host's db file
|
|
77
|
-
HEALTHCHECK --interval=
|
|
87
|
+
HEALTHCHECK --interval=60s --timeout=10s --start-period=10s --retries=3 CMD ["docker-healthcheck.sh"]
|
|
78
88
|
ENTRYPOINT ["awslabs.ccapi-mcp-server"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: awslabs.ccapi-mcp-server
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.13
|
|
4
4
|
Summary: An AWS Labs Model Context Protocol (MCP) server for managing AWS resources via Cloud Control API
|
|
5
5
|
Project-URL: homepage, https://awslabs.github.io/mcp/
|
|
6
6
|
Project-URL: docs, https://awslabs.github.io/mcp/servers/ccapi-mcp-server/
|
|
@@ -25,7 +25,7 @@ Requires-Dist: boto3>=1.34.0
|
|
|
25
25
|
Requires-Dist: botocore>=1.34.0
|
|
26
26
|
Requires-Dist: checkov>=3.0.0
|
|
27
27
|
Requires-Dist: loguru>=0.7.0
|
|
28
|
-
Requires-Dist: mcp[cli]>=1.
|
|
28
|
+
Requires-Dist: mcp[cli]>=1.23.0
|
|
29
29
|
Requires-Dist: pydantic>=2.10.6
|
|
30
30
|
Description-Content-Type: text/markdown
|
|
31
31
|
|
|
@@ -194,9 +194,9 @@ This ensures you always know which AWS account and region will be affected by op
|
|
|
194
194
|
|
|
195
195
|
## Installation
|
|
196
196
|
|
|
197
|
-
| Cursor | VS Code |
|
|
198
|
-
|
|
199
|
-
| [](https://cursor.com/en/install-mcp?name=awslabs.ccapi-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMuY2NhcGktbWNwLXNlcnZlckBsYXRlc3QiLCJlbnYiOnsiQVdTX1BST0ZJTEUiOiJ5b3VyLWF3cy1wcm9maWxlIiwiQVdTX1JFR0lPTiI6InVzLWVhc3QtMSIsIkZBU1RNQ1BfTE9HX0xFVkVMIjoiRVJST1IifSwiZGlzYWJsZWQiOmZhbHNlLCJhdXRvQXBwcm92ZSI6W119) | [](https://insiders.vscode.dev/redirect/mcp/install?name=AWS%20Cloud%20Control%20API%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.ccapi-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22AWS_PROFILE%22%3A%22your-aws-profile%22%2C%22AWS_REGION%22%3A%22us-east-1%22%2C%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D) |
|
|
197
|
+
| Kiro | Cursor | VS Code |
|
|
198
|
+
|:----:|:------:|:-------:|
|
|
199
|
+
| [](https://kiro.dev/launch/mcp/add?name=awslabs.ccapi-mcp-server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.ccapi-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22AWS_PROFILE%22%3A%22your-aws-profile%22%2C%22AWS_REGION%22%3A%22us-east-1%22%2C%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%7D) | [](https://cursor.com/en/install-mcp?name=awslabs.ccapi-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMuY2NhcGktbWNwLXNlcnZlckBsYXRlc3QiLCJlbnYiOnsiQVdTX1BST0ZJTEUiOiJ5b3VyLWF3cy1wcm9maWxlIiwiQVdTX1JFR0lPTiI6InVzLWVhc3QtMSIsIkZBU1RNQ1BfTE9HX0xFVkVMIjoiRVJST1IifSwiZGlzYWJsZWQiOmZhbHNlLCJhdXRvQXBwcm92ZSI6W119) | [](https://insiders.vscode.dev/redirect/mcp/install?name=AWS%20Cloud%20Control%20API%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.ccapi-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22AWS_PROFILE%22%3A%22your-aws-profile%22%2C%22AWS_REGION%22%3A%22us-east-1%22%2C%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D) |
|
|
200
200
|
|
|
201
201
|
**Before installation, configure AWS credentials using one of these methods:**
|
|
202
202
|
|
|
@@ -209,7 +209,7 @@ Ensure your IAM role or user has the necessary permissions (see [Security Consid
|
|
|
209
209
|
|
|
210
210
|
### Configuration
|
|
211
211
|
|
|
212
|
-
Configure the MCP server in your MCP client configuration (e.g., for
|
|
212
|
+
Configure the MCP server in your MCP client configuration (e.g., for Kiro, edit `~/.kiro/settings/mcp.json`):
|
|
213
213
|
|
|
214
214
|
```json
|
|
215
215
|
{
|
|
@@ -555,7 +555,7 @@ Creates CloudFormation templates from existing AWS resources using AWS CloudForm
|
|
|
555
555
|
|
|
556
556
|
- **Multiple Infrastructure MCP Servers**: Using CCAPI MCP server alongside other MCP servers that perform similar functions (such as Terraform MCP, CDK MCP, CFN MCP) may cause LLMs to randomly choose between them
|
|
557
557
|
- **Built-in Tools**: LLMs may choose built-in tools instead of this MCP server's tools:
|
|
558
|
-
-
|
|
558
|
+
- Kiro CLI: `aws`, `shell`, `read`, `write`
|
|
559
559
|
- Other tools may have similar built-in AWS or system capabilities
|
|
560
560
|
|
|
561
561
|
## Basic Usage
|
|
@@ -163,9 +163,9 @@ This ensures you always know which AWS account and region will be affected by op
|
|
|
163
163
|
|
|
164
164
|
## Installation
|
|
165
165
|
|
|
166
|
-
| Cursor | VS Code |
|
|
167
|
-
|
|
168
|
-
| [](https://cursor.com/en/install-mcp?name=awslabs.ccapi-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMuY2NhcGktbWNwLXNlcnZlckBsYXRlc3QiLCJlbnYiOnsiQVdTX1BST0ZJTEUiOiJ5b3VyLWF3cy1wcm9maWxlIiwiQVdTX1JFR0lPTiI6InVzLWVhc3QtMSIsIkZBU1RNQ1BfTE9HX0xFVkVMIjoiRVJST1IifSwiZGlzYWJsZWQiOmZhbHNlLCJhdXRvQXBwcm92ZSI6W119) | [](https://insiders.vscode.dev/redirect/mcp/install?name=AWS%20Cloud%20Control%20API%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.ccapi-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22AWS_PROFILE%22%3A%22your-aws-profile%22%2C%22AWS_REGION%22%3A%22us-east-1%22%2C%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D) |
|
|
166
|
+
| Kiro | Cursor | VS Code |
|
|
167
|
+
|:----:|:------:|:-------:|
|
|
168
|
+
| [](https://kiro.dev/launch/mcp/add?name=awslabs.ccapi-mcp-server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.ccapi-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22AWS_PROFILE%22%3A%22your-aws-profile%22%2C%22AWS_REGION%22%3A%22us-east-1%22%2C%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%7D) | [](https://cursor.com/en/install-mcp?name=awslabs.ccapi-mcp-server&config=eyJjb21tYW5kIjoidXZ4IGF3c2xhYnMuY2NhcGktbWNwLXNlcnZlckBsYXRlc3QiLCJlbnYiOnsiQVdTX1BST0ZJTEUiOiJ5b3VyLWF3cy1wcm9maWxlIiwiQVdTX1JFR0lPTiI6InVzLWVhc3QtMSIsIkZBU1RNQ1BfTE9HX0xFVkVMIjoiRVJST1IifSwiZGlzYWJsZWQiOmZhbHNlLCJhdXRvQXBwcm92ZSI6W119) | [](https://insiders.vscode.dev/redirect/mcp/install?name=AWS%20Cloud%20Control%20API%20MCP%20Server&config=%7B%22command%22%3A%22uvx%22%2C%22args%22%3A%5B%22awslabs.ccapi-mcp-server%40latest%22%5D%2C%22env%22%3A%7B%22AWS_PROFILE%22%3A%22your-aws-profile%22%2C%22AWS_REGION%22%3A%22us-east-1%22%2C%22FASTMCP_LOG_LEVEL%22%3A%22ERROR%22%7D%2C%22disabled%22%3Afalse%2C%22autoApprove%22%3A%5B%5D%7D) |
|
|
169
169
|
|
|
170
170
|
**Before installation, configure AWS credentials using one of these methods:**
|
|
171
171
|
|
|
@@ -178,7 +178,7 @@ Ensure your IAM role or user has the necessary permissions (see [Security Consid
|
|
|
178
178
|
|
|
179
179
|
### Configuration
|
|
180
180
|
|
|
181
|
-
Configure the MCP server in your MCP client configuration (e.g., for
|
|
181
|
+
Configure the MCP server in your MCP client configuration (e.g., for Kiro, edit `~/.kiro/settings/mcp.json`):
|
|
182
182
|
|
|
183
183
|
```json
|
|
184
184
|
{
|
|
@@ -524,7 +524,7 @@ Creates CloudFormation templates from existing AWS resources using AWS CloudForm
|
|
|
524
524
|
|
|
525
525
|
- **Multiple Infrastructure MCP Servers**: Using CCAPI MCP server alongside other MCP servers that perform similar functions (such as Terraform MCP, CDK MCP, CFN MCP) may cause LLMs to randomly choose between them
|
|
526
526
|
- **Built-in Tools**: LLMs may choose built-in tools instead of this MCP server's tools:
|
|
527
|
-
-
|
|
527
|
+
- Kiro CLI: `aws`, `shell`, `read`, `write`
|
|
528
528
|
- Other tools may have similar built-in AWS or system capabilities
|
|
529
529
|
|
|
530
530
|
## Basic Usage
|
|
@@ -13,19 +13,43 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
from awslabs.ccapi_mcp_server.errors import ClientError
|
|
16
|
+
from os import environ
|
|
16
17
|
from typing import Any, Dict
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
def
|
|
20
|
-
"""
|
|
20
|
+
def supports_tagging(resource_type: str, schema: Dict) -> bool:
|
|
21
|
+
"""Check if a resource type supports tagging based on schema."""
|
|
22
|
+
# Trust the schema - if it has Tags property, resource supports tagging
|
|
23
|
+
# If schema doesn't show Tags, assume resource doesn't support tagging
|
|
24
|
+
return 'Tags' in schema.get('properties', {})
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def add_default_tags(
|
|
28
|
+
properties: Dict,
|
|
29
|
+
schema: Dict,
|
|
30
|
+
resource_type: str = '',
|
|
31
|
+
environment_variables: Dict | None = None,
|
|
32
|
+
) -> Dict:
|
|
33
|
+
"""Add default tags to resource properties if DEFAULT_TAGS is enabled and resource supports tagging."""
|
|
21
34
|
# Return empty dict when properties is None or empty dict {}
|
|
22
|
-
# This prevents processing invalid/missing resource properties
|
|
23
35
|
if not properties:
|
|
24
36
|
return {}
|
|
25
37
|
|
|
38
|
+
# FIRST: Check DEFAULT_TAGS setting - if disabled, return immediately without any tagging logic
|
|
39
|
+
if environment_variables:
|
|
40
|
+
default_tags_setting = environment_variables.get('DEFAULT_TAGS', 'enabled').lower()
|
|
41
|
+
else:
|
|
42
|
+
default_tags_setting = environ.get('DEFAULT_TAGS', 'enabled').lower()
|
|
43
|
+
|
|
44
|
+
if default_tags_setting == 'disabled':
|
|
45
|
+
return properties.copy()
|
|
46
|
+
|
|
47
|
+
# SECOND: Only if DEFAULT_TAGS is enabled, check if resource supports tagging
|
|
48
|
+
if resource_type and not supports_tagging(resource_type, schema):
|
|
49
|
+
return properties.copy()
|
|
50
|
+
|
|
26
51
|
properties_with_tags = properties.copy()
|
|
27
52
|
|
|
28
|
-
# Always try to add tags - don't check schema since it can be unreliable
|
|
29
53
|
# Ensure Tags array exists
|
|
30
54
|
if 'Tags' not in properties_with_tags:
|
|
31
55
|
properties_with_tags['Tags'] = []
|
|
@@ -19,6 +19,7 @@ import uuid
|
|
|
19
19
|
from awslabs.ccapi_mcp_server.errors import ClientError
|
|
20
20
|
from awslabs.ccapi_mcp_server.impl.utils.validation import ensure_string
|
|
21
21
|
from awslabs.ccapi_mcp_server.models.models import ExplainRequest
|
|
22
|
+
from os import environ
|
|
22
23
|
from typing import Any
|
|
23
24
|
|
|
24
25
|
|
|
@@ -37,7 +38,12 @@ def _format_value(value: Any) -> str:
|
|
|
37
38
|
|
|
38
39
|
|
|
39
40
|
def _generate_explanation(
|
|
40
|
-
content: Any,
|
|
41
|
+
content: Any,
|
|
42
|
+
context: str,
|
|
43
|
+
operation: str,
|
|
44
|
+
format: str,
|
|
45
|
+
user_intent: str,
|
|
46
|
+
environment_variables: dict | None = None,
|
|
41
47
|
) -> str:
|
|
42
48
|
"""Generate comprehensive explanation for any type of content."""
|
|
43
49
|
content_type = type(content).__name__
|
|
@@ -77,7 +83,18 @@ def _generate_explanation(
|
|
|
77
83
|
if operation in ['create', 'update', 'delete']:
|
|
78
84
|
explanation += '\n\n**Infrastructure Operation Notes:**'
|
|
79
85
|
explanation += '\n• This operation will modify AWS resources'
|
|
80
|
-
|
|
86
|
+
|
|
87
|
+
# Check DEFAULT_TAGS setting
|
|
88
|
+
if environment_variables:
|
|
89
|
+
default_tags_setting = environment_variables.get('DEFAULT_TAGS', 'enabled').lower()
|
|
90
|
+
else:
|
|
91
|
+
default_tags_setting = environ.get('DEFAULT_TAGS', 'enabled').lower()
|
|
92
|
+
|
|
93
|
+
if default_tags_setting == 'disabled':
|
|
94
|
+
explanation += '\n• Default management tags are disabled and will not be applied'
|
|
95
|
+
else:
|
|
96
|
+
explanation += '\n• Default management tags will be applied for tracking'
|
|
97
|
+
|
|
81
98
|
explanation += '\n• Changes will be applied to the specified AWS region'
|
|
82
99
|
|
|
83
100
|
return explanation
|
|
@@ -253,6 +270,7 @@ async def explain_impl(request: ExplainRequest, workflow_store: dict) -> dict:
|
|
|
253
270
|
raise ClientError("Either 'content' or 'generated_code_token' must be provided")
|
|
254
271
|
|
|
255
272
|
# Handle infrastructure operations with token workflow
|
|
273
|
+
workflow_data = None
|
|
256
274
|
if has_generated_code_token:
|
|
257
275
|
# Infrastructure operation - consume generated_code_token
|
|
258
276
|
if request.generated_code_token not in workflow_store:
|
|
@@ -296,6 +314,11 @@ async def explain_impl(request: ExplainRequest, workflow_store: dict) -> dict:
|
|
|
296
314
|
'operation': ensure_string(request.operation),
|
|
297
315
|
}
|
|
298
316
|
|
|
317
|
+
# Get environment variables from workflow store if available
|
|
318
|
+
environment_variables = None
|
|
319
|
+
if workflow_data:
|
|
320
|
+
environment_variables = workflow_data.get('data', {}).get('environment_variables')
|
|
321
|
+
|
|
299
322
|
# Generate comprehensive explanation based on content type and format
|
|
300
323
|
explanation = _generate_explanation(
|
|
301
324
|
explanation_content,
|
|
@@ -303,6 +326,7 @@ async def explain_impl(request: ExplainRequest, workflow_store: dict) -> dict:
|
|
|
303
326
|
ensure_string(request.operation, 'analyze'),
|
|
304
327
|
ensure_string(request.format, 'detailed'),
|
|
305
328
|
ensure_string(request.user_intent),
|
|
329
|
+
environment_variables or {},
|
|
306
330
|
)
|
|
307
331
|
|
|
308
332
|
# Force the LLM to see the response by making it very explicit
|
|
@@ -34,8 +34,12 @@ async def generate_infrastructure_code_impl_wrapper(
|
|
|
34
34
|
if not aws_session_data.get('credentials_valid'):
|
|
35
35
|
raise ClientError('Invalid AWS credentials')
|
|
36
36
|
|
|
37
|
-
#
|
|
38
|
-
|
|
37
|
+
# Get environment variables from the parent environment token
|
|
38
|
+
env_token = cred_data.get('parent_token')
|
|
39
|
+
environment_variables = None
|
|
40
|
+
if env_token and env_token in workflow_store:
|
|
41
|
+
env_data = workflow_store[env_token]['data']
|
|
42
|
+
environment_variables = env_data.get('environment_variables', {})
|
|
39
43
|
|
|
40
44
|
# Generate infrastructure code using the existing implementation
|
|
41
45
|
result = await generate_infrastructure_code_impl(
|
|
@@ -43,7 +47,8 @@ async def generate_infrastructure_code_impl_wrapper(
|
|
|
43
47
|
properties=request.properties,
|
|
44
48
|
identifier=request.identifier,
|
|
45
49
|
patch_document=request.patch_document,
|
|
46
|
-
region=request.region or aws_session_data.get('region')
|
|
50
|
+
region=request.region or aws_session_data.get('region'),
|
|
51
|
+
environment_variables=environment_variables or {},
|
|
47
52
|
)
|
|
48
53
|
|
|
49
54
|
# Generate a generated code token that enforces using the exact properties and template
|
|
@@ -21,7 +21,6 @@ from awslabs.ccapi_mcp_server.context import Context
|
|
|
21
21
|
from awslabs.ccapi_mcp_server.errors import ClientError, handle_aws_api_error
|
|
22
22
|
from awslabs.ccapi_mcp_server.impl.utils.validation import (
|
|
23
23
|
cleanup_workflow_tokens,
|
|
24
|
-
ensure_region_string,
|
|
25
24
|
validate_identifier,
|
|
26
25
|
validate_resource_type,
|
|
27
26
|
validate_workflow_token,
|
|
@@ -115,8 +114,11 @@ async def create_resource_impl(request: CreateResourceRequest, workflow_store: d
|
|
|
115
114
|
# Use ONLY the properties that were explained - no manual override possible
|
|
116
115
|
properties = workflow_data['data']['properties']
|
|
117
116
|
|
|
118
|
-
#
|
|
119
|
-
|
|
117
|
+
# Use MCP env region or session region, no hardcoded fallback
|
|
118
|
+
env_vars = aws_session_data.get('environment_variables', {})
|
|
119
|
+
region_str = env_vars.get('AWS_REGION') or aws_session_data.get('region')
|
|
120
|
+
if not region_str:
|
|
121
|
+
raise ClientError('No region configured in MCP environment or AWS session')
|
|
120
122
|
cloudcontrol_client = get_aws_client('cloudcontrol', region_str)
|
|
121
123
|
try:
|
|
122
124
|
response = cloudcontrol_client.create_resource(
|
|
@@ -176,8 +178,11 @@ async def update_resource_impl(request: UpdateResourceRequest, workflow_store: d
|
|
|
176
178
|
pass
|
|
177
179
|
|
|
178
180
|
validate_patch(request.patch_document)
|
|
179
|
-
#
|
|
180
|
-
|
|
181
|
+
# Use MCP env region or session region, no hardcoded fallback
|
|
182
|
+
env_vars = aws_session_data.get('environment_variables', {})
|
|
183
|
+
region_str = env_vars.get('AWS_REGION') or aws_session_data.get('region')
|
|
184
|
+
if not region_str:
|
|
185
|
+
raise ClientError('No region configured in MCP environment or AWS session')
|
|
181
186
|
cloudcontrol_client = get_aws_client('cloudcontrol', region_str)
|
|
182
187
|
|
|
183
188
|
# Convert patch document to JSON string for the API
|
|
@@ -239,7 +244,11 @@ async def delete_resource_impl(request: DeleteResourceRequest, workflow_store: d
|
|
|
239
244
|
'You have configured this tool in readonly mode. To make this change you will have to update your configuration.'
|
|
240
245
|
)
|
|
241
246
|
|
|
242
|
-
|
|
247
|
+
env_vars = aws_session_data.get('environment_variables', {})
|
|
248
|
+
region_str = env_vars.get('AWS_REGION') or aws_session_data.get('region')
|
|
249
|
+
if not region_str:
|
|
250
|
+
raise ClientError('No region configured in MCP environment or AWS session')
|
|
251
|
+
cloudcontrol_client = get_aws_client('cloudcontrol', region_str)
|
|
243
252
|
try:
|
|
244
253
|
response = cloudcontrol_client.delete_resource(
|
|
245
254
|
TypeName=request.resource_type, Identifier=request.identifier
|
|
@@ -260,7 +269,11 @@ async def get_resource_impl(
|
|
|
260
269
|
validate_resource_type(request.resource_type)
|
|
261
270
|
validate_identifier(request.identifier)
|
|
262
271
|
|
|
263
|
-
|
|
272
|
+
# Use environment variables for get operations (no session data available)
|
|
273
|
+
region_str = request.region or environ.get('AWS_REGION') or environ.get('AWS_DEFAULT_REGION')
|
|
274
|
+
if not region_str:
|
|
275
|
+
raise ClientError('No region specified and no default region configured')
|
|
276
|
+
cloudcontrol = get_aws_client('cloudcontrol', region_str)
|
|
264
277
|
try:
|
|
265
278
|
result = cloudcontrol.get_resource(
|
|
266
279
|
TypeName=request.resource_type, Identifier=request.identifier
|
|
@@ -356,7 +369,11 @@ async def get_resource_request_status_impl(request_token: str, region: str | Non
|
|
|
356
369
|
if not request_token:
|
|
357
370
|
raise ClientError('Please provide a request token to track the request')
|
|
358
371
|
|
|
359
|
-
|
|
372
|
+
# Use environment variables for status operations (no session data available)
|
|
373
|
+
region_str = region or environ.get('AWS_REGION') or environ.get('AWS_DEFAULT_REGION')
|
|
374
|
+
if not region_str:
|
|
375
|
+
raise ClientError('No region specified and no default region configured')
|
|
376
|
+
cloudcontrol_client = get_aws_client('cloudcontrol', region_str)
|
|
360
377
|
try:
|
|
361
378
|
response = cloudcontrol_client.get_resource_request_status(
|
|
362
379
|
RequestToken=request_token,
|
|
@@ -46,6 +46,7 @@ def check_aws_credentials() -> dict:
|
|
|
46
46
|
'AWS_PROFILE': environ.get('AWS_PROFILE', ''),
|
|
47
47
|
'AWS_REGION': environ.get('AWS_REGION', ''),
|
|
48
48
|
'SECURITY_SCANNING': environ.get('SECURITY_SCANNING', 'enabled'),
|
|
49
|
+
'DEFAULT_TAGS': environ.get('DEFAULT_TAGS', 'enabled'),
|
|
49
50
|
},
|
|
50
51
|
}
|
|
51
52
|
except Exception as e:
|
|
@@ -59,6 +60,7 @@ def check_aws_credentials() -> dict:
|
|
|
59
60
|
'AWS_PROFILE': environ.get('AWS_PROFILE', ''),
|
|
60
61
|
'AWS_REGION': environ.get('AWS_REGION', ''),
|
|
61
62
|
'SECURITY_SCANNING': environ.get('SECURITY_SCANNING', 'enabled'),
|
|
63
|
+
'DEFAULT_TAGS': environ.get('DEFAULT_TAGS', 'enabled'),
|
|
62
64
|
},
|
|
63
65
|
}
|
|
64
66
|
|
|
@@ -28,6 +28,7 @@ async def generate_infrastructure_code(
|
|
|
28
28
|
identifier: str = '',
|
|
29
29
|
patch_document: List = [],
|
|
30
30
|
region: str = '',
|
|
31
|
+
environment_variables: Dict | None = None,
|
|
31
32
|
) -> Dict:
|
|
32
33
|
"""Generate infrastructure code for security scanning before resource creation or update."""
|
|
33
34
|
if not resource_type:
|
|
@@ -43,17 +44,6 @@ async def generate_infrastructure_code(
|
|
|
43
44
|
# Check if resource supports tagging
|
|
44
45
|
supports_tagging = 'Tags' in schema.get('properties', {})
|
|
45
46
|
|
|
46
|
-
# Fallback: Known AWS resources that support tagging even if schema doesn't show it
|
|
47
|
-
if not supports_tagging and resource_type in [
|
|
48
|
-
'AWS::S3::Bucket',
|
|
49
|
-
'AWS::EC2::Instance',
|
|
50
|
-
'AWS::RDS::DBInstance',
|
|
51
|
-
]:
|
|
52
|
-
supports_tagging = True
|
|
53
|
-
print(
|
|
54
|
-
f"Schema for {resource_type} doesn't show Tags property, but we know it supports tagging"
|
|
55
|
-
)
|
|
56
|
-
|
|
57
47
|
if is_update:
|
|
58
48
|
# This is an update operation
|
|
59
49
|
if not identifier:
|
|
@@ -119,7 +109,9 @@ async def generate_infrastructure_code(
|
|
|
119
109
|
update_properties = current_properties
|
|
120
110
|
|
|
121
111
|
# V1: Always add required MCP server identification tags for updates too
|
|
122
|
-
properties_with_tags = add_default_tags(
|
|
112
|
+
properties_with_tags = add_default_tags(
|
|
113
|
+
update_properties, schema, resource_type, environment_variables
|
|
114
|
+
)
|
|
123
115
|
|
|
124
116
|
operation = 'update'
|
|
125
117
|
else:
|
|
@@ -128,7 +120,9 @@ async def generate_infrastructure_code(
|
|
|
128
120
|
raise ClientError('Please provide the properties for the desired resource')
|
|
129
121
|
|
|
130
122
|
# V1: Always add required MCP server identification tags
|
|
131
|
-
properties_with_tags = add_default_tags(
|
|
123
|
+
properties_with_tags = add_default_tags(
|
|
124
|
+
properties, schema, resource_type, environment_variables
|
|
125
|
+
)
|
|
132
126
|
|
|
133
127
|
operation = 'create'
|
|
134
128
|
|
|
@@ -718,7 +718,7 @@ def main():
|
|
|
718
718
|
|
|
719
719
|
# Display read-only mode status
|
|
720
720
|
if args.readonly:
|
|
721
|
-
print('\n
|
|
721
|
+
print('\n[WARNING] READ-ONLY MODE ACTIVE [WARNING]')
|
|
722
722
|
print('The server will not perform any create, update, or delete operations.')
|
|
723
723
|
|
|
724
724
|
mcp.run()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
3
|
+
#
|
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
# you may not use this file except in compliance with the License.
|
|
6
|
+
# You may obtain a copy of the License at
|
|
7
|
+
#
|
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
#
|
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
# See the License for the specific language governing permissions and
|
|
14
|
+
# limitations under the License.
|
|
15
|
+
|
|
16
|
+
SERVER="ccapi-mcp-server"
|
|
17
|
+
|
|
18
|
+
# Check if the server process is running
|
|
19
|
+
if pgrep -P 0 -a -l -x -f "/app/.venv/bin/python3 /app/.venv/bin/awslabs.$SERVER" > /dev/null; then
|
|
20
|
+
echo -n "$SERVER is running";
|
|
21
|
+
exit 0;
|
|
22
|
+
fi;
|
|
23
|
+
|
|
24
|
+
# Unhealthy
|
|
25
|
+
exit 1;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "awslabs.ccapi-mcp-server"
|
|
3
|
-
version = "1.0.
|
|
3
|
+
version = "1.0.13"
|
|
4
4
|
description = "An AWS Labs Model Context Protocol (MCP) server for managing AWS resources via Cloud Control API"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
7
7
|
dependencies = [
|
|
8
8
|
"loguru>=0.7.0",
|
|
9
9
|
"pydantic>=2.10.6",
|
|
10
|
-
"mcp[cli]>=1.
|
|
10
|
+
"mcp[cli]>=1.23.0",
|
|
11
11
|
"boto3>=1.34.0",
|
|
12
12
|
"botocore>=1.34.0",
|
|
13
13
|
"checkov>=3.0.0",
|