This is page 570 of 575. Use http://codebase.md/awslabs/mcp?lines=true&page={x} to view the full context.
# Directory Structure
```
├── .devcontainer
│ └── devcontainer.json
├── .github
│ ├── actions
│ │ ├── build-and-push-container-image
│ │ │ └── action.yml
│ │ └── clear-space-ubuntu-latest-agressively
│ │ └── action.yml
│ ├── codecov.yml
│ ├── CODEOWNERS
│ ├── dependabot.yml
│ ├── ISSUE_TEMPLATE
│ │ ├── bug_report.yml
│ │ ├── documentation.yml
│ │ ├── feature_request.yml
│ │ ├── rfc.yml
│ │ └── support_awslabs_mcp_servers.yml
│ ├── pull_request_template.md
│ ├── SECURITY
│ ├── SUPPORT
│ └── workflows
│ ├── aws-api-mcp-upgrade-version.yml
│ ├── bandit-requirements.txt
│ ├── bandit.yml
│ ├── cfn_nag.yml
│ ├── check-gh-pages-builds.yml
│ ├── check-license-header-hash.txt
│ ├── check-license-header.json
│ ├── check-license-header.yml
│ ├── checkov.yml
│ ├── codeql.yml
│ ├── dependency-review-action.yml
│ ├── detect-secrets-requirements.txt
│ ├── gh-pages.yml
│ ├── merge-prevention.yml
│ ├── powershell.yml
│ ├── pre-commit-requirements.txt
│ ├── pre-commit.yml
│ ├── pull-request-lint.yml
│ ├── python.yml
│ ├── RELEASE_INSTRUCTIONS.md
│ ├── release-initiate-branch.yml
│ ├── release-merge-tag.yml
│ ├── release.py
│ ├── release.yml
│ ├── scanners.yml
│ ├── scorecard-analysis.yml
│ ├── semgrep-requirements.txt
│ ├── semgrep.yml
│ ├── stale.yml
│ ├── trivy.yml
│ └── typescript.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .python-version
├── .ruff.toml
├── .secrets.baseline
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── DESIGN_GUIDELINES.md
├── DEVELOPER_GUIDE.md
├── docs
│ └── images
│ └── root-readme
│ ├── cline-api-provider-filled.png
│ ├── cline-chat-interface.png
│ ├── cline-custom-instructions.png
│ ├── cline-select-aws-profile.png
│ ├── cline-select-bedrock.png
│ ├── configure-mcp-servers.png
│ ├── install-cline-extension.png
│ ├── mcp-servers-installed.png
│ └── select-mcp-servers.png
├── docusaurus
│ ├── .gitignore
│ ├── docs
│ │ ├── installation.md
│ │ ├── intro.md
│ │ ├── samples
│ │ │ ├── index.md
│ │ │ ├── mcp-integration-with-kb.md
│ │ │ ├── mcp-integration-with-nova-canvas.md
│ │ │ └── stepfunctions-tool-mcp-server.md
│ │ ├── servers
│ │ │ ├── amazon-bedrock-agentcore-mcp-server.md
│ │ │ ├── amazon-keyspaces-mcp-server.md
│ │ │ ├── amazon-mq-mcp-server.md
│ │ │ ├── amazon-neptune-mcp-server.md
│ │ │ ├── amazon-qbusiness-anonymous-mcp-server.md
│ │ │ ├── amazon-qindex-mcp-server.md
│ │ │ ├── amazon-sns-sqs-mcp-server.md
│ │ │ ├── aurora-dsql-mcp-server.md
│ │ │ ├── aws-api-mcp-server.md
│ │ │ ├── aws-appsync-mcp-server.md
│ │ │ ├── aws-bedrock-custom-model-import-mcp-server.md
│ │ │ ├── aws-bedrock-data-automation-mcp-server.md
│ │ │ ├── aws-dataprocessing-mcp-server.md
│ │ │ ├── aws-diagram-mcp-server.md
│ │ │ ├── aws-documentation-mcp-server.md
│ │ │ ├── aws-healthomics-mcp-server.md
│ │ │ ├── aws-iot-sitewise-mcp-server.md
│ │ │ ├── aws-knowledge-mcp-server.md
│ │ │ ├── aws-location-mcp-server.md
│ │ │ ├── aws-msk-mcp-server.md
│ │ │ ├── aws-pricing-mcp-server.md
│ │ │ ├── aws-serverless-mcp-server.md
│ │ │ ├── aws-support-mcp-server.md
│ │ │ ├── bedrock-kb-retrieval-mcp-server.md
│ │ │ ├── billing-cost-management-mcp-server.md
│ │ │ ├── ccapi-mcp-server.md
│ │ │ ├── cdk-mcp-server.md
│ │ │ ├── cfn-mcp-server.md
│ │ │ ├── cloudtrail-mcp-server.md
│ │ │ ├── cloudwatch-appsignals-mcp-server.md
│ │ │ ├── cloudwatch-mcp-server.md
│ │ │ ├── code-doc-gen-mcp-server.md
│ │ │ ├── core-mcp-server.md
│ │ │ ├── cost-explorer-mcp-server.md
│ │ │ ├── documentdb-mcp-server.md
│ │ │ ├── dynamodb-mcp-server.md
│ │ │ ├── ecs-mcp-server.md
│ │ │ ├── eks-mcp-server.md
│ │ │ ├── elasticache-mcp-server.md
│ │ │ ├── finch-mcp-server.md
│ │ │ ├── frontend-mcp-server.md
│ │ │ ├── git-repo-research-mcp-server.md
│ │ │ ├── healthlake-mcp-server.md
│ │ │ ├── iam-mcp-server.md
│ │ │ ├── kendra-index-mcp-server.md
│ │ │ ├── lambda-tool-mcp-server.md
│ │ │ ├── memcached-mcp-server.md
│ │ │ ├── mysql-mcp-server.md
│ │ │ ├── nova-canvas-mcp-server.md
│ │ │ ├── openapi-mcp-server.md
│ │ │ ├── postgres-mcp-server.md
│ │ │ ├── prometheus-mcp-server.md
│ │ │ ├── redshift-mcp-server.md
│ │ │ ├── s3-tables-mcp-server.md
│ │ │ ├── stepfunctions-tool-mcp-server.md
│ │ │ ├── syntheticdata-mcp-server.md
│ │ │ ├── terraform-mcp-server.md
│ │ │ ├── timestream-for-influxdb-mcp-server.md
│ │ │ ├── valkey-mcp-server.md
│ │ │ └── well-architected-security-mcp-server.mdx
│ │ └── vibe_coding.md
│ ├── docusaurus.config.ts
│ ├── package-lock.json
│ ├── package.json
│ ├── README.md
│ ├── sidebars.ts
│ ├── src
│ │ ├── components
│ │ │ ├── HomepageFeatures
│ │ │ │ └── styles.module.css
│ │ │ └── ServerCards
│ │ │ ├── index.tsx
│ │ │ └── styles.module.css
│ │ ├── css
│ │ │ ├── custom.css
│ │ │ └── doc-override.css
│ │ └── pages
│ │ ├── index.module.css
│ │ └── servers.tsx
│ ├── static
│ │ ├── .nojekyll
│ │ ├── assets
│ │ │ ├── icons
│ │ │ │ ├── activity.svg
│ │ │ │ ├── book-open.svg
│ │ │ │ ├── cpu.svg
│ │ │ │ ├── database.svg
│ │ │ │ ├── dollar-sign.svg
│ │ │ │ ├── help-circle.svg
│ │ │ │ ├── key.svg
│ │ │ │ ├── server.svg
│ │ │ │ ├── share-2.svg
│ │ │ │ ├── tool.svg
│ │ │ │ └── zap.svg
│ │ │ └── server-cards.json
│ │ └── img
│ │ ├── aws-logo.svg
│ │ └── logo.png
│ └── tsconfig.json
├── LICENSE
├── NOTICE
├── README.md
├── samples
│ ├── mcp-integration-with-kb
│ │ ├── .env.example
│ │ ├── .python-version
│ │ ├── assets
│ │ │ └── simplified-mcp-flow-diagram.png
│ │ ├── clients
│ │ │ └── client_server.py
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── user_interfaces
│ │ │ └── chat_bedrock_st.py
│ │ └── uv.lock
│ ├── mcp-integration-with-nova-canvas
│ │ ├── .env.example
│ │ ├── .python-version
│ │ ├── clients
│ │ │ └── client_server.py
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── user_interfaces
│ │ │ └── image_generator_st.py
│ │ └── uv.lock
│ ├── README.md
│ └── stepfunctions-tool-mcp-server
│ ├── README.md
│ └── sample_state_machines
│ ├── customer-create
│ │ └── app.py
│ ├── customer-id-from-email
│ │ └── app.py
│ ├── customer-info-from-id
│ │ └── app.py
│ └── template.yml
├── scripts
│ ├── README.md
│ └── verify_package_name.py
├── src
│ ├── amazon-bedrock-agentcore-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_bedrock_agentcore_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── config.py
│ │ │ ├── server.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── cache.py
│ │ │ ├── doc_fetcher.py
│ │ │ ├── indexer.py
│ │ │ ├── text_processor.py
│ │ │ └── url_validator.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── SECURITY.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_cache.py
│ │ │ ├── test_config.py
│ │ │ ├── test_doc_fetcher.py
│ │ │ ├── test_indexer.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_server.py
│ │ │ ├── test_text_processor.py
│ │ │ └── test_url_validator.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── amazon-kendra-index-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_kendra_index_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ └── util.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── amazon-keyspaces-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_keyspaces_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── config.py
│ │ │ ├── consts.py
│ │ │ ├── llm_context.py
│ │ │ ├── models.py
│ │ │ ├── server.py
│ │ │ └── services.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_tests.sh
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_client.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_query_analysis_service.py
│ │ │ ├── test_server.py
│ │ │ └── test_services.py
│ │ └── uv.lock
│ ├── amazon-mq-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_mq_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── aws_service_mcp_generator.py
│ │ │ ├── consts.py
│ │ │ ├── rabbitmq
│ │ │ │ ├── __init__.py
│ │ │ │ ├── admin.py
│ │ │ │ ├── connection.py
│ │ │ │ ├── doc
│ │ │ │ │ ├── rabbitmq_broker_sizing_guide.md
│ │ │ │ │ ├── rabbitmq_performance_optimization_best_practice.md
│ │ │ │ │ ├── rabbitmq_production_deployment_guidelines.md
│ │ │ │ │ ├── rabbitmq_quorum_queue_migration_guide.md
│ │ │ │ │ └── rabbitmq_setup_best_practice.md
│ │ │ │ ├── handlers.py
│ │ │ │ └── module.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── example
│ │ │ └── sample_mcp_q_cli.json
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── rabbitmq
│ │ │ │ ├── __init__.py
│ │ │ │ ├── conftest.py
│ │ │ │ ├── test_admin.py
│ │ │ │ ├── test_connection.py
│ │ │ │ ├── test_handlers.py
│ │ │ │ └── test_module.py
│ │ │ ├── test_aws_service_mcp_generator.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── amazon-neptune-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_neptune_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── exceptions.py
│ │ │ ├── graph_store
│ │ │ │ ├── __init__.py
│ │ │ │ ├── analytics.py
│ │ │ │ ├── base.py
│ │ │ │ └── database.py
│ │ │ ├── models.py
│ │ │ ├── neptune.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_analytics.py
│ │ │ ├── test_database.py
│ │ │ ├── test_exceptions.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_models.py
│ │ │ ├── test_neptune.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── amazon-qbusiness-anonymous-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_qbusiness_anonymous_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── clients.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── amazon-qindex-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_qindex_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── clients.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_clients.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ └── test_server.py
│ │ └── uv.lock
│ ├── amazon-sns-sqs-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── amazon_sns_sqs_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── common.py
│ │ │ ├── consts.py
│ │ │ ├── generator.py
│ │ │ ├── server.py
│ │ │ ├── sns.py
│ │ │ └── sqs.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── print_tools.py
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_tests.sh
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── test_common.py
│ │ │ ├── test_generator.py
│ │ │ ├── test_server.py
│ │ │ ├── test_sns.py
│ │ │ └── test_sqs.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aurora-dsql-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aurora_dsql_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── consts.py
│ │ │ ├── mutable_sql_detector.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_connection_reuse.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_profile_option.py
│ │ │ ├── test_readonly_enforcement.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-api-mcp-server
│ │ ├── .gitattributes
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_api_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── core
│ │ │ │ ├── __init__.py
│ │ │ │ ├── agent_scripts
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── manager.py
│ │ │ │ │ ├── models.py
│ │ │ │ │ └── registry
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── application-failure-troubleshooting.script.md
│ │ │ │ │ ├── cloudtral-mutli-region-setup.script.md
│ │ │ │ │ ├── create_amazon_aurora_db_cluster_with_instances.script.md
│ │ │ │ │ ├── lambda-timeout-debugging.script.md
│ │ │ │ │ ├── scripts_format.md
│ │ │ │ │ └── troubleshoot-permissions-with-cloudtrail-events.script.md
│ │ │ │ ├── aws
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── driver.py
│ │ │ │ │ ├── pagination.py
│ │ │ │ │ ├── regions.py
│ │ │ │ │ ├── service.py
│ │ │ │ │ └── services.py
│ │ │ │ ├── common
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── command_metadata.py
│ │ │ │ │ ├── command.py
│ │ │ │ │ ├── config.py
│ │ │ │ │ ├── errors.py
│ │ │ │ │ ├── file_operations.py
│ │ │ │ │ ├── file_system_controls.py
│ │ │ │ │ ├── helpers.py
│ │ │ │ │ ├── models.py
│ │ │ │ │ └── py.typed
│ │ │ │ ├── data
│ │ │ │ │ └── api_metadata.json
│ │ │ │ ├── metadata
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── read_only_operations_list.py
│ │ │ │ ├── parser
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── custom_validators
│ │ │ │ │ │ ├── __init__.py
│ │ │ │ │ │ ├── botocore_param_validator.py
│ │ │ │ │ │ ├── ec2_validator.py
│ │ │ │ │ │ └── ssm_validator.py
│ │ │ │ │ ├── interpretation.py
│ │ │ │ │ ├── lexer.py
│ │ │ │ │ └── parser.py
│ │ │ │ ├── py.typed
│ │ │ │ └── security
│ │ │ │ ├── __init__.py
│ │ │ │ ├── aws_api_customization.json
│ │ │ │ └── policy.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── CONTRIBUTING.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── agent_scripts
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_manager.py
│ │ │ │ └── test_registry
│ │ │ │ ├── another_valid_script.script.md
│ │ │ │ ├── test_script.script.md
│ │ │ │ └── valid_script.script.md
│ │ │ ├── aws
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_driver.py
│ │ │ │ ├── test_pagination.py
│ │ │ │ ├── test_service.py
│ │ │ │ └── test_services.py
│ │ │ ├── common
│ │ │ │ ├── test_command.py
│ │ │ │ ├── test_config.py
│ │ │ │ ├── test_file_operations.py
│ │ │ │ ├── test_file_system_controls.py
│ │ │ │ ├── test_file_validation.py
│ │ │ │ └── test_helpers.py
│ │ │ ├── fixtures.py
│ │ │ ├── history_handler.py
│ │ │ ├── metadata
│ │ │ │ ├── __init__.py
│ │ │ │ └── test_read_only_operations_list.py
│ │ │ ├── parser
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_file_path_detection.py
│ │ │ │ ├── test_lexer.py
│ │ │ │ ├── test_parser_customizations.py
│ │ │ │ └── test_parser.py
│ │ │ ├── test_security_policy.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-appsync-mcp-server
│ │ ├── .dockerignore
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_appsync_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── decorators.py
│ │ │ ├── helpers.py
│ │ │ ├── operations
│ │ │ │ ├── __init__.py
│ │ │ │ ├── create_api_cache.py
│ │ │ │ ├── create_api_key.py
│ │ │ │ ├── create_api.py
│ │ │ │ ├── create_channel_namespace.py
│ │ │ │ ├── create_datasource.py
│ │ │ │ ├── create_domain_name.py
│ │ │ │ ├── create_function.py
│ │ │ │ ├── create_graphql_api.py
│ │ │ │ ├── create_resolver.py
│ │ │ │ └── create_schema.py
│ │ │ ├── server.py
│ │ │ ├── tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── create_api_cache.py
│ │ │ │ ├── create_api_key.py
│ │ │ │ ├── create_api.py
│ │ │ │ ├── create_channel_namespace.py
│ │ │ │ ├── create_datasource.py
│ │ │ │ ├── create_domain_name.py
│ │ │ │ ├── create_function.py
│ │ │ │ ├── create_graphql_api.py
│ │ │ │ ├── create_resolver.py
│ │ │ │ └── create_schema.py
│ │ │ └── validators.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_all_create_tools_write_protection.py
│ │ │ ├── test_create_api_cache.py
│ │ │ ├── test_create_api_key.py
│ │ │ ├── test_create_api.py
│ │ │ ├── test_create_channel_namespace.py
│ │ │ ├── test_create_datasource_tool.py
│ │ │ ├── test_create_datasource.py
│ │ │ ├── test_create_domain_name.py
│ │ │ ├── test_create_function.py
│ │ │ ├── test_create_graphql_api.py
│ │ │ ├── test_create_resolver.py
│ │ │ ├── test_create_schema_tool.py
│ │ │ ├── test_create_schema.py
│ │ │ ├── test_helpers.py
│ │ │ ├── test_server.py
│ │ │ ├── test_validators.py
│ │ │ └── test_write_operation.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-bedrock-custom-model-import-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_bedrock_custom_model_import_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── llm_context.py
│ │ │ ├── models.py
│ │ │ ├── prompts.py
│ │ │ ├── server.py
│ │ │ ├── services
│ │ │ │ ├── __init__.py
│ │ │ │ ├── imported_model_service.py
│ │ │ │ └── model_import_service.py
│ │ │ ├── tools
│ │ │ │ ├── create_model_import_job.py
│ │ │ │ ├── delete_imported_model.py
│ │ │ │ ├── get_imported_model.py
│ │ │ │ ├── get_model_import_job.py
│ │ │ │ ├── list_imported_models.py
│ │ │ │ └── list_model_import_jobs.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── aws.py
│ │ │ ├── config.py
│ │ │ ├── consts.py
│ │ │ └── matching.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── services
│ │ │ │ ├── test_imported_model_service.py
│ │ │ │ └── test_model_import_service.py
│ │ │ ├── test_client.py
│ │ │ ├── test_init.py
│ │ │ ├── test_llm_context.py
│ │ │ ├── test_prompts.py
│ │ │ ├── test_server.py
│ │ │ ├── tools
│ │ │ │ ├── test_create_model_import_job.py
│ │ │ │ ├── test_delete_imported_model.py
│ │ │ │ ├── test_get_imported_model.py
│ │ │ │ ├── test_get_model_import_job.py
│ │ │ │ ├── test_list_imported_models.py
│ │ │ │ └── test_list_model_import_jobs.py
│ │ │ └── utils
│ │ │ ├── test_aws.py
│ │ │ ├── test_config.py
│ │ │ └── test_matching.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-bedrock-data-automation-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_bedrock_data_automation_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── helpers.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_helpers.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-dataprocessing-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_dataprocessing_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── core
│ │ │ │ ├── __init__.py
│ │ │ │ └── glue_data_catalog
│ │ │ │ ├── __init__.py
│ │ │ │ ├── data_catalog_database_manager.py
│ │ │ │ ├── data_catalog_handler.py
│ │ │ │ └── data_catalog_table_manager.py
│ │ │ ├── handlers
│ │ │ │ ├── __init__.py
│ │ │ │ ├── athena
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── athena_data_catalog_handler.py
│ │ │ │ │ ├── athena_query_handler.py
│ │ │ │ │ └── athena_workgroup_handler.py
│ │ │ │ ├── commons
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── common_resource_handler.py
│ │ │ │ ├── emr
│ │ │ │ │ ├── emr_ec2_cluster_handler.py
│ │ │ │ │ ├── emr_ec2_instance_handler.py
│ │ │ │ │ └── emr_ec2_steps_handler.py
│ │ │ │ └── glue
│ │ │ │ ├── __init__.py
│ │ │ │ ├── crawler_handler.py
│ │ │ │ ├── data_catalog_handler.py
│ │ │ │ ├── glue_commons_handler.py
│ │ │ │ ├── glue_etl_handler.py
│ │ │ │ ├── interactive_sessions_handler.py
│ │ │ │ └── worklows_handler.py
│ │ │ ├── models
│ │ │ │ ├── __init__.py
│ │ │ │ ├── athena_models.py
│ │ │ │ ├── common_resource_models.py
│ │ │ │ ├── data_catalog_models.py
│ │ │ │ ├── emr_models.py
│ │ │ │ └── glue_models.py
│ │ │ ├── server.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── aws_helper.py
│ │ │ ├── consts.py
│ │ │ ├── logging_helper.py
│ │ │ └── sql_analyzer.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── core
│ │ │ │ ├── __init__.py
│ │ │ │ └── glue_data_catalog
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_data_catalog_database_manager.py
│ │ │ │ ├── test_data_catalog_handler.py
│ │ │ │ └── test_data_catalog_table_manager.py
│ │ │ ├── handlers
│ │ │ │ ├── __init__.py
│ │ │ │ ├── athena
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── test_athena_data_catalog_handler.py
│ │ │ │ │ ├── test_athena_query_handler.py
│ │ │ │ │ ├── test_athena_workgroup_handler.py
│ │ │ │ │ └── test_custom_tags_athena.py
│ │ │ │ ├── commons
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ └── test_common_resource_handler.py
│ │ │ │ ├── emr
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── test_custom_tags_emr.py
│ │ │ │ │ ├── test_emr_ec2_cluster_handler.py
│ │ │ │ │ ├── test_emr_ec2_instance_handler.py
│ │ │ │ │ └── test_emr_ec2_steps_handler.py
│ │ │ │ └── glue
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_crawler_handler.py
│ │ │ │ ├── test_custom_tags_glue.py
│ │ │ │ ├── test_data_catalog_handler.py
│ │ │ │ ├── test_glue_commons_handler.py
│ │ │ │ ├── test_glue_etl_handler.py
│ │ │ │ ├── test_glue_interactive_sessions_handler.py
│ │ │ │ └── test_glue_workflows_handler.py
│ │ │ ├── models
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_athena_models.py
│ │ │ │ ├── test_common_resource_models.py
│ │ │ │ ├── test_data_catalog_models.py
│ │ │ │ ├── test_emr_models.py
│ │ │ │ ├── test_glue_models.py
│ │ │ │ ├── test_interactive_sessions_models.py
│ │ │ │ └── test_workflows_models.py
│ │ │ ├── test_init.py
│ │ │ ├── test_server.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── test_aws_helper.py
│ │ │ ├── test_custom_tags.py
│ │ │ ├── test_logging_helper.py
│ │ │ └── test_sql_analyzer.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-diagram-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_diagram_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── diagrams_tools.py
│ │ │ ├── models.py
│ │ │ ├── scanner.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── conftest.py
│ │ │ ├── README.md
│ │ │ ├── resources
│ │ │ │ ├── __init__.py
│ │ │ │ └── example_diagrams
│ │ │ │ ├── __init__.py
│ │ │ │ ├── aws_example.py
│ │ │ │ ├── flow_example.py
│ │ │ │ └── sequence_example.py
│ │ │ ├── test_diagrams.py
│ │ │ ├── test_models.py
│ │ │ ├── test_sarif_fix.py
│ │ │ ├── test_scanner.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-documentation-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_documentation_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ ├── server_aws_cn.py
│ │ │ ├── server_aws.py
│ │ │ ├── server_utils.py
│ │ │ ├── server.py
│ │ │ └── util.py
│ │ ├── basic-usage.gif
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── constants.py
│ │ │ ├── resources
│ │ │ │ └── lambda_sns_raw.html
│ │ │ ├── test_aws_cn_get_available_services_live.py
│ │ │ ├── test_aws_cn_read_documentation_live.py
│ │ │ ├── test_aws_read_documentation_live.py
│ │ │ ├── test_aws_recommend_live.py
│ │ │ ├── test_aws_search_live.py
│ │ │ ├── test_metadata_handling.py
│ │ │ ├── test_models.py
│ │ │ ├── test_server_aws_cn.py
│ │ │ ├── test_server_aws.py
│ │ │ ├── test_server_utils.py
│ │ │ ├── test_server.py
│ │ │ └── test_util.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-healthomics-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_healthomics_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── consts.py
│ │ │ ├── models.py
│ │ │ ├── server.py
│ │ │ ├── tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── helper_tools.py
│ │ │ │ ├── run_analysis.py
│ │ │ │ ├── troubleshooting.py
│ │ │ │ ├── workflow_analysis.py
│ │ │ │ ├── workflow_execution.py
│ │ │ │ ├── workflow_linting.py
│ │ │ │ └── workflow_management.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── aws_utils.py
│ │ │ ├── s3_utils.py
│ │ │ └── validation_utils.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── docs
│ │ │ └── workflow_linting.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.py
│ │ │ ├── test_aws_utils.py
│ │ │ ├── test_consts.py
│ │ │ ├── test_helper_tools.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_models.py
│ │ │ ├── test_run_analysis.py
│ │ │ ├── test_s3_utils.py
│ │ │ ├── test_server.py
│ │ │ ├── test_troubleshooting.py
│ │ │ ├── test_workflow_analysis.py
│ │ │ ├── test_workflow_execution.py
│ │ │ ├── test_workflow_linting.py
│ │ │ ├── test_workflow_management.py
│ │ │ └── test_workflow_tools.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-iot-sitewise-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_iot_sitewise_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── models
│ │ │ │ ├── computation_data_models.py
│ │ │ │ └── metadata_transfer_data_models.py
│ │ │ ├── prompts
│ │ │ │ ├── __init__.py
│ │ │ │ ├── anomaly_detection_workflow.py
│ │ │ │ ├── asset_hierarchy.py
│ │ │ │ ├── bulk_import_workflow.py
│ │ │ │ ├── data_exploration.py
│ │ │ │ └── data_ingestion.py
│ │ │ ├── server.py
│ │ │ ├── tool_metadata.py
│ │ │ ├── tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── sitewise_access.py
│ │ │ │ ├── sitewise_asset_models.py
│ │ │ │ ├── sitewise_assets.py
│ │ │ │ ├── sitewise_computation_models.py
│ │ │ │ ├── sitewise_data.py
│ │ │ │ ├── sitewise_executions.py
│ │ │ │ ├── sitewise_gateways.py
│ │ │ │ ├── sitewise_metadata_transfer.py
│ │ │ │ └── timestamp_tools.py
│ │ │ ├── validation_utils.py
│ │ │ └── validation.py
│ │ ├── CHANGELOG.md
│ │ ├── DEVELOPMENT.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── examples
│ │ │ └── wind_farm_example.py
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_server.py
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── models
│ │ │ │ ├── test_computation_data_models.py
│ │ │ │ └── test_metadata_transfer_data_models.py
│ │ │ ├── test_client.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_server.py
│ │ │ ├── test_validation_utils.py
│ │ │ ├── test_validation.py
│ │ │ └── tools
│ │ │ ├── test_sitewise_access.py
│ │ │ ├── test_sitewise_asset_models.py
│ │ │ ├── test_sitewise_assets.py
│ │ │ ├── test_sitewise_computation_models.py
│ │ │ ├── test_sitewise_data.py
│ │ │ ├── test_sitewise_executions.py
│ │ │ ├── test_sitewise_gateways.py
│ │ │ ├── test_sitewise_metadata_transfer.py
│ │ │ └── test_timestamp_tools.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-knowledge-mcp-server
│ │ └── README.md
│ ├── aws-location-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_location_server
│ │ │ ├── __init__.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_server_integration.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-msk-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_msk_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ └── tools
│ │ │ ├── __init__.py
│ │ │ ├── common_functions
│ │ │ │ ├── __init__.py
│ │ │ │ ├── client_manager.py
│ │ │ │ └── common_functions.py
│ │ │ ├── logs_and_telemetry
│ │ │ │ ├── __init__.py
│ │ │ │ ├── cluster_metrics_tools.py
│ │ │ │ ├── list_customer_iam_access.py
│ │ │ │ └── metric_config.py
│ │ │ ├── mutate_cluster
│ │ │ │ ├── __init__.py
│ │ │ │ ├── batch_associate_scram_secret.py
│ │ │ │ ├── batch_disassociate_scram_secret.py
│ │ │ │ ├── create_cluster_v2.py
│ │ │ │ ├── put_cluster_policy.py
│ │ │ │ ├── reboot_broker.py
│ │ │ │ ├── update_broker_count.py
│ │ │ │ ├── update_broker_storage.py
│ │ │ │ ├── update_broker_type.py
│ │ │ │ ├── update_cluster_configuration.py
│ │ │ │ ├── update_monitoring.py
│ │ │ │ └── update_security.py
│ │ │ ├── mutate_config
│ │ │ │ ├── __init__.py
│ │ │ │ ├── create_configuration.py
│ │ │ │ ├── tag_resource.py
│ │ │ │ ├── untag_resource.py
│ │ │ │ └── update_configuration.py
│ │ │ ├── mutate_vpc
│ │ │ │ ├── __init__.py
│ │ │ │ ├── create_vpc_connection.py
│ │ │ │ ├── delete_vpc_connection.py
│ │ │ │ └── reject_client_vpc_connection.py
│ │ │ ├── read_cluster
│ │ │ │ ├── __init__.py
│ │ │ │ ├── describe_cluster_operation.py
│ │ │ │ ├── describe_cluster.py
│ │ │ │ ├── get_bootstrap_brokers.py
│ │ │ │ ├── get_cluster_policy.py
│ │ │ │ ├── get_compatible_kafka_versions.py
│ │ │ │ ├── list_client_vpc_connections.py
│ │ │ │ ├── list_cluster_operations.py
│ │ │ │ ├── list_nodes.py
│ │ │ │ └── list_scram_secrets.py
│ │ │ ├── read_config
│ │ │ │ ├── __init__.py
│ │ │ │ ├── describe_configuration_revision.py
│ │ │ │ ├── describe_configuration.py
│ │ │ │ ├── list_configuration_revisions.py
│ │ │ │ └── list_tags_for_resource.py
│ │ │ ├── read_global
│ │ │ │ ├── __init__.py
│ │ │ │ ├── list_clusters.py
│ │ │ │ ├── list_configurations.py
│ │ │ │ ├── list_kafka_versions.py
│ │ │ │ └── list_vpc_connections.py
│ │ │ ├── read_vpc
│ │ │ │ ├── __init__.py
│ │ │ │ └── describe_vpc_connection.py
│ │ │ └── static_tools
│ │ │ ├── __init__.py
│ │ │ └── cluster_best_practices.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_client_manager.py
│ │ │ ├── test_cluster_metrics_tools.py
│ │ │ ├── test_common_functions.py
│ │ │ ├── test_create_cluster_v2.py
│ │ │ ├── test_create_configuration.py
│ │ │ ├── test_create_vpc_connection.py
│ │ │ ├── test_delete_vpc_connection.py
│ │ │ ├── test_describe_cluster_operation.py
│ │ │ ├── test_describe_cluster.py
│ │ │ ├── test_describe_configuration_revision.py
│ │ │ ├── test_describe_configuration.py
│ │ │ ├── test_describe_vpc_connection.py
│ │ │ ├── test_get_bootstrap_brokers.py
│ │ │ ├── test_get_cluster_policy.py
│ │ │ ├── test_get_compatible_kafka_versions.py
│ │ │ ├── test_init.py
│ │ │ ├── test_list_client_vpc_connections.py
│ │ │ ├── test_list_cluster_operations.py
│ │ │ ├── test_list_clusters.py
│ │ │ ├── test_list_configuration_revisions.py
│ │ │ ├── test_list_configurations.py
│ │ │ ├── test_list_customer_iam_access.py
│ │ │ ├── test_list_kafka_versions.py
│ │ │ ├── test_list_nodes.py
│ │ │ ├── test_list_scram_secrets.py
│ │ │ ├── test_list_tags_for_resource.py
│ │ │ ├── test_list_vpc_connections.py
│ │ │ ├── test_logs_and_telemetry.py
│ │ │ ├── test_main.py
│ │ │ ├── test_mutate_cluster_init.py
│ │ │ ├── test_mutate_cluster_success_cases.py
│ │ │ ├── test_mutate_cluster.py
│ │ │ ├── test_mutate_config_init.py
│ │ │ ├── test_mutate_vpc_init.py
│ │ │ ├── test_read_cluster_init_updated.py
│ │ │ ├── test_read_cluster_init.py
│ │ │ ├── test_read_config_init.py
│ │ │ ├── test_read_global_init.py
│ │ │ ├── test_read_vpc_init.py
│ │ │ ├── test_reject_client_vpc_connection.py
│ │ │ ├── test_server.py
│ │ │ ├── test_static_tools_init.py
│ │ │ ├── test_tag_resource.py
│ │ │ ├── test_tool_descriptions.py
│ │ │ ├── test_untag_resource.py
│ │ │ └── test_update_configuration.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-pricing-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_pricing_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── cdk_analyzer.py
│ │ │ ├── consts.py
│ │ │ ├── helpers.py
│ │ │ ├── models.py
│ │ │ ├── pricing_client.py
│ │ │ ├── pricing_transformer.py
│ │ │ ├── report_generator.py
│ │ │ ├── server.py
│ │ │ ├── static
│ │ │ │ ├── __init__.py
│ │ │ │ ├── COST_REPORT_TEMPLATE.md
│ │ │ │ └── patterns
│ │ │ │ ├── __init__.py
│ │ │ │ └── BEDROCK.md
│ │ │ └── terraform_analyzer.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_cdk_analyzer.py
│ │ │ ├── test_helpers.py
│ │ │ ├── test_pricing_client.py
│ │ │ ├── test_pricing_transformer.py
│ │ │ ├── test_report_generator.py
│ │ │ ├── test_server.py
│ │ │ └── test_terraform_analyzer.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── aws-serverless-mcp-server
│ │ ├── .pre-commit.config.yaml
│ │ ├── .python-version
│ │ ├── .secrets.baseline
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_serverless_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ ├── resources
│ │ │ │ ├── __init__.py
│ │ │ │ ├── deployment_details.py
│ │ │ │ ├── deployment_list.py
│ │ │ │ ├── template_details.py
│ │ │ │ └── template_list.py
│ │ │ ├── server.py
│ │ │ ├── template
│ │ │ │ ├── __init__.py
│ │ │ │ ├── registry.py
│ │ │ │ ├── renderer.py
│ │ │ │ └── templates
│ │ │ │ ├── backend.j2
│ │ │ │ ├── frontend.j2
│ │ │ │ ├── fullstack.j2
│ │ │ │ └── README.md
│ │ │ ├── templates
│ │ │ │ ├── __init__.py
│ │ │ │ └── iam_policies.py
│ │ │ ├── tools
│ │ │ │ ├── common
│ │ │ │ │ └── base_tool.py
│ │ │ │ ├── esm
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── esm_diagnosis.py
│ │ │ │ │ ├── esm_guidance.py
│ │ │ │ │ ├── esm_recommend.py
│ │ │ │ │ └── secure_esm_guidance.py
│ │ │ │ ├── guidance
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── deploy_serverless_app_help.py
│ │ │ │ │ ├── get_iac_guidance.py
│ │ │ │ │ ├── get_lambda_event_schemas.py
│ │ │ │ │ ├── get_lambda_guidance.py
│ │ │ │ │ └── get_serverless_templates.py
│ │ │ │ ├── poller
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── esm_diagnosis.py
│ │ │ │ │ ├── esm_guidance.py
│ │ │ │ │ └── esm_recommend.py
│ │ │ │ ├── sam
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── sam_build.py
│ │ │ │ │ ├── sam_deploy.py
│ │ │ │ │ ├── sam_init.py
│ │ │ │ │ ├── sam_local_invoke.py
│ │ │ │ │ └── sam_logs.py
│ │ │ │ ├── schemas
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── describe_schema.py
│ │ │ │ │ ├── list_registries.py
│ │ │ │ │ └── search_schema.py
│ │ │ │ └── webapps
│ │ │ │ ├── __init__.py
│ │ │ │ ├── configure_domain.py
│ │ │ │ ├── deploy_webapp.py
│ │ │ │ ├── get_metrics.py
│ │ │ │ ├── update_webapp_frontend.py
│ │ │ │ ├── utils
│ │ │ │ │ ├── deploy_service.py
│ │ │ │ │ ├── frontend_uploader.py
│ │ │ │ │ └── startup_script_generator.py
│ │ │ │ └── webapp_deployment_help.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── aws_client_helper.py
│ │ │ ├── cloudformation.py
│ │ │ ├── const.py
│ │ │ ├── data_scrubber.py
│ │ │ ├── deployment_manager.py
│ │ │ ├── github.py
│ │ │ └── process.py
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── README.md
│ │ │ ├── test_cloudformation.py
│ │ │ ├── test_configure_domain.py
│ │ │ ├── test_data_scrubber.py
│ │ │ ├── test_deploy_serverless_app_help.py
│ │ │ ├── test_deploy_service.py
│ │ │ ├── test_deploy_webapp.py
│ │ │ ├── test_deployment_details.py
│ │ │ ├── test_deployment_help.py
│ │ │ ├── test_deployment_list.py
│ │ │ ├── test_deployment_manager.py
│ │ │ ├── test_esm_diagnosis.py
│ │ │ ├── test_esm_guidance.py
│ │ │ ├── test_esm_recommend.py
│ │ │ ├── test_frontend_uploader.py
│ │ │ ├── test_get_iac_guidance.py
│ │ │ ├── test_get_lambda_event_schemas.py
│ │ │ ├── test_get_lambda_guidance.py
│ │ │ ├── test_get_metrics.py
│ │ │ ├── test_get_serverless_templates.py
│ │ │ ├── test_github.py
│ │ │ ├── test_iam_policies.py
│ │ │ ├── test_models.py
│ │ │ ├── test_process.py
│ │ │ ├── test_sam_build.py
│ │ │ ├── test_sam_deploy.py
│ │ │ ├── test_sam_init.py
│ │ │ ├── test_sam_local_invoke.py
│ │ │ ├── test_sam_logs.py
│ │ │ ├── test_schemas.py
│ │ │ ├── test_secure_esm_guidance.py
│ │ │ ├── test_server.py
│ │ │ ├── test_startup_script_generator.py
│ │ │ ├── test_template_details.py
│ │ │ ├── test_template_list.py
│ │ │ ├── test_template_registry.py
│ │ │ ├── test_template_renderer.py
│ │ │ └── test_update_webapp_frontend.py
│ │ └── uv.lock
│ ├── aws-support-mcp-server
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── aws_support_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── client.py
│ │ │ ├── consts.py
│ │ │ ├── debug_helper.py
│ │ │ ├── errors.py
│ │ │ ├── formatters.py
│ │ │ ├── models.py
│ │ │ └── server.py
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftests.py
│ │ │ ├── test_aws_support_mcp_server.py
│ │ │ └── test_models.py
│ │ └── uv.lock
│ ├── bedrock-kb-retrieval-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── bedrock_kb_retrieval_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── knowledgebases
│ │ │ │ ├── __init__.py
│ │ │ │ ├── clients.py
│ │ │ │ ├── discovery.py
│ │ │ │ └── retrieval.py
│ │ │ ├── models.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_tests.sh
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── conftest.py
│ │ │ ├── README.md
│ │ │ ├── test_clients.py
│ │ │ ├── test_discovery.py
│ │ │ ├── test_env_config.py
│ │ │ ├── test_models.py
│ │ │ ├── test_retrieval.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── billing-cost-management-mcp-server
│ │ ├── __init__.py
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── billing_cost_management_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── models.py
│ │ │ ├── prompts
│ │ │ │ ├── __init__.py
│ │ │ │ ├── decorator.py
│ │ │ │ ├── graviton_migration.py
│ │ │ │ ├── README.md
│ │ │ │ ├── savings_plans.py
│ │ │ │ └── types.py
│ │ │ ├── server.py
│ │ │ ├── templates
│ │ │ │ └── recommendation_templates
│ │ │ │ ├── ebs_volume.template
│ │ │ │ ├── ec2_asg.template
│ │ │ │ ├── ec2_instance.template
│ │ │ │ ├── ecs_service.template
│ │ │ │ ├── idle.template
│ │ │ │ ├── lambda_function.template
│ │ │ │ ├── rds_database.template
│ │ │ │ ├── reserved_instances.template
│ │ │ │ └── savings_plans.template
│ │ │ ├── tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── aws_pricing_operations.py
│ │ │ │ ├── aws_pricing_tools.py
│ │ │ │ ├── bcm_pricing_calculator_tools.py
│ │ │ │ ├── budget_tools.py
│ │ │ │ ├── compute_optimizer_tools.py
│ │ │ │ ├── cost_anomaly_tools.py
│ │ │ │ ├── cost_comparison_tools.py
│ │ │ │ ├── cost_explorer_operations.py
│ │ │ │ ├── cost_explorer_tools.py
│ │ │ │ ├── cost_optimization_hub_helpers.py
│ │ │ │ ├── cost_optimization_hub_tools.py
│ │ │ │ ├── free_tier_usage_tools.py
│ │ │ │ ├── recommendation_details_tools.py
│ │ │ │ ├── ri_performance_tools.py
│ │ │ │ ├── sp_performance_tools.py
│ │ │ │ ├── storage_lens_tools.py
│ │ │ │ └── unified_sql_tools.py
│ │ │ └── utilities
│ │ │ ├── __init__.py
│ │ │ ├── aws_service_base.py
│ │ │ ├── constants.py
│ │ │ ├── logging_utils.py
│ │ │ └── sql_utils.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── requirements.txt
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── prompts
│ │ │ │ ├── __init__.py
│ │ │ │ └── test_prompts.py
│ │ │ ├── README.md
│ │ │ ├── test_models.py
│ │ │ ├── test_server.py
│ │ │ ├── tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── fixtures.py
│ │ │ │ ├── test_aws_bcm_pricing_calculator_tools.py
│ │ │ │ ├── test_aws_pricing_tools.py
│ │ │ │ ├── test_budget_tools.py
│ │ │ │ ├── test_compute_optimizer_tools.py
│ │ │ │ ├── test_cost_anomaly_tools_enhanced.py
│ │ │ │ ├── test_cost_anomaly_tools.py
│ │ │ │ ├── test_cost_comparison_tools.py
│ │ │ │ ├── test_cost_explorer_operations.py
│ │ │ │ ├── test_cost_explorer_tools.py
│ │ │ │ ├── test_cost_optimization_hub_helpers.py
│ │ │ │ ├── test_cost_optimization_hub_tools.py
│ │ │ │ ├── test_free_tier_usage_tools_new.py
│ │ │ │ ├── test_recommendation_details_tools.py
│ │ │ │ ├── test_ri_performance_tools.py
│ │ │ │ ├── test_sp_performance_tools.py
│ │ │ │ ├── test_storage_lens_tools.py
│ │ │ │ └── test_unified_sql_tools.py
│ │ │ └── utilities
│ │ │ ├── test_aws_service_base.py
│ │ │ └── test_sql_utils.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── ccapi-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── ccapi_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── aws_client.py
│ │ │ ├── cloud_control_utils.py
│ │ │ ├── context.py
│ │ │ ├── errors.py
│ │ │ ├── iac_generator.py
│ │ │ ├── impl
│ │ │ │ ├── __init__.py
│ │ │ │ ├── tools
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── explanation.py
│ │ │ │ │ ├── infrastructure_generation.py
│ │ │ │ │ ├── resource_operations.py
│ │ │ │ │ ├── security_scanning.py
│ │ │ │ │ └── session_management.py
│ │ │ │ └── utils
│ │ │ │ ├── __init__.py
│ │ │ │ └── validation.py
│ │ │ ├── infrastructure_generator.py
│ │ │ ├── models
│ │ │ │ ├── __init__.py
│ │ │ │ └── models.py
│ │ │ ├── schema_manager.py
│ │ │ ├── server.py
│ │ │ └── static
│ │ │ └── __init__.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_tests.sh
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_aws_client.py
│ │ │ ├── test_checkov_install.py
│ │ │ ├── test_cloud_control_utils.py
│ │ │ ├── test_context.py
│ │ │ ├── test_errors.py
│ │ │ ├── test_explanation.py
│ │ │ ├── test_iac_generator.py
│ │ │ ├── test_infrastructure_generation.py
│ │ │ ├── test_infrastructure_generator.py
│ │ │ ├── test_models.py
│ │ │ ├── test_resource_operations.py
│ │ │ ├── test_schema_manager.py
│ │ │ ├── test_security_scanning.py
│ │ │ ├── test_server.py
│ │ │ ├── test_session_management.py
│ │ │ └── test_validation.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── cdk-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── cdk_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── core
│ │ │ │ ├── __init__.py
│ │ │ │ ├── resources.py
│ │ │ │ ├── search_utils.py
│ │ │ │ ├── server.py
│ │ │ │ └── tools.py
│ │ │ ├── data
│ │ │ │ ├── __init__.py
│ │ │ │ ├── cdk_nag_parser.py
│ │ │ │ ├── construct_descriptions.py
│ │ │ │ ├── genai_cdk_loader.py
│ │ │ │ ├── lambda_layer_parser.py
│ │ │ │ ├── lambda_powertools_loader.py
│ │ │ │ ├── schema_generator.py
│ │ │ │ └── solutions_constructs_parser.py
│ │ │ ├── server.py
│ │ │ └── static
│ │ │ ├── __init__.py
│ │ │ ├── CDK_GENERAL_GUIDANCE.md
│ │ │ ├── CDK_NAG_GUIDANCE.md
│ │ │ └── lambda_powertools
│ │ │ ├── bedrock.md
│ │ │ ├── cdk.md
│ │ │ ├── dependencies.md
│ │ │ ├── index.md
│ │ │ ├── insights.md
│ │ │ ├── logging.md
│ │ │ ├── metrics.md
│ │ │ └── tracing.md
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── core
│ │ │ │ ├── test_resources_enhanced.py
│ │ │ │ ├── test_resources.py
│ │ │ │ ├── test_search_utils.py
│ │ │ │ ├── test_server.py
│ │ │ │ └── test_tools.py
│ │ │ └── data
│ │ │ ├── test_cdk_nag_parser.py
│ │ │ ├── test_genai_cdk_loader.py
│ │ │ ├── test_lambda_powertools_loader.py
│ │ │ ├── test_schema_generator.py
│ │ │ └── test_solutions_constructs_parser.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── cfn-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── cfn_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── aws_client.py
│ │ │ ├── cloud_control_utils.py
│ │ │ ├── context.py
│ │ │ ├── errors.py
│ │ │ ├── iac_generator.py
│ │ │ ├── schema_manager.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_tests.sh
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_aws_client.py
│ │ │ ├── test_cloud_control_utils.py
│ │ │ ├── test_errors.py
│ │ │ ├── test_iac_generator.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_schema_manager.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── cloudtrail-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── cloudtrail_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── common.py
│ │ │ ├── models.py
│ │ │ ├── server.py
│ │ │ └── tools.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_models.py
│ │ │ ├── test_server.py
│ │ │ └── test_tools.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── cloudwatch-appsignals-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── cloudwatch_appsignals_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── audit_presentation_utils.py
│ │ │ ├── audit_utils.py
│ │ │ ├── aws_clients.py
│ │ │ ├── canary_utils.py
│ │ │ ├── enablement_guides
│ │ │ │ └── templates
│ │ │ │ └── ec2
│ │ │ │ └── ec2-python-enablement.md
│ │ │ ├── enablement_tools.py
│ │ │ ├── server.py
│ │ │ ├── service_audit_utils.py
│ │ │ ├── service_tools.py
│ │ │ ├── sli_report_client.py
│ │ │ ├── slo_tools.py
│ │ │ ├── trace_tools.py
│ │ │ └── utils.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.py
│ │ │ ├── test_audit_presentation_utils.py
│ │ │ ├── test_audit_utils.py
│ │ │ ├── test_aws_profile.py
│ │ │ ├── test_canary_utils.py
│ │ │ ├── test_enablement_tools.py
│ │ │ ├── test_initialization.py
│ │ │ ├── test_server_audit_functions.py
│ │ │ ├── test_server_audit_tools.py
│ │ │ ├── test_server.py
│ │ │ ├── test_service_audit_utils.py
│ │ │ ├── test_service_tools_operations.py
│ │ │ ├── test_sli_report_client.py
│ │ │ ├── test_slo_tools.py
│ │ │ └── test_utils.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── cloudwatch-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── cloudwatch_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── cloudwatch_alarms
│ │ │ │ ├── models.py
│ │ │ │ └── tools.py
│ │ │ ├── cloudwatch_logs
│ │ │ │ ├── models.py
│ │ │ │ └── tools.py
│ │ │ ├── cloudwatch_metrics
│ │ │ │ ├── cloudformation_template_generator.py
│ │ │ │ ├── constants.py
│ │ │ │ ├── data
│ │ │ │ │ └── metric_metadata.json
│ │ │ │ ├── metric_analyzer.py
│ │ │ │ ├── metric_data_decomposer.py
│ │ │ │ ├── models.py
│ │ │ │ └── tools.py
│ │ │ ├── common.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── cloudwatch_alarms
│ │ │ │ ├── test_active_alarms.py
│ │ │ │ ├── test_alarm_history_integration.py
│ │ │ │ ├── test_alarm_history.py
│ │ │ │ └── test_alarms_error_handling.py
│ │ │ ├── cloudwatch_logs
│ │ │ │ ├── test_logs_error_handling.py
│ │ │ │ ├── test_logs_models.py
│ │ │ │ └── test_logs_server.py
│ │ │ ├── cloudwatch_metrics
│ │ │ │ ├── test_analyze_metric.py
│ │ │ │ ├── test_cloudformation_template_generator.py
│ │ │ │ ├── test_decomposer_trend.py
│ │ │ │ ├── test_metric_analyzer.py
│ │ │ │ ├── test_metrics_error_handling.py
│ │ │ │ ├── test_metrics_models.py
│ │ │ │ ├── test_metrics_server.py
│ │ │ │ ├── test_seasonal_detector.py
│ │ │ │ ├── test_seasonality_enum.py
│ │ │ │ ├── test_utils.py
│ │ │ │ └── test_validation_error.py
│ │ │ ├── test_common_and_server.py
│ │ │ ├── test_init.py
│ │ │ └── test_main.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── code-doc-gen-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── code_doc_gen_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ └── utils
│ │ │ ├── doc_generator.py
│ │ │ ├── models.py
│ │ │ ├── repomix_manager.py
│ │ │ └── templates.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_doc_generator_edge_cases.py
│ │ │ ├── test_doc_generator.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_repomix_manager_scenarios.py
│ │ │ ├── test_repomix_manager.py
│ │ │ ├── test_repomix_statistics.py
│ │ │ ├── test_server_extended.py
│ │ │ ├── test_server.py
│ │ │ └── test_templates.py
│ │ └── uv.lock
│ ├── core-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── core_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ └── static
│ │ │ ├── __init__.py
│ │ │ └── PROMPT_UNDERSTANDING.md
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── README.md
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_response_types.py
│ │ │ ├── test_server.py
│ │ │ └── test_static.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── cost-explorer-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── cost_explorer_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── comparison_handler.py
│ │ │ ├── constants.py
│ │ │ ├── cost_usage_handler.py
│ │ │ ├── forecasting_handler.py
│ │ │ ├── helpers.py
│ │ │ ├── metadata_handler.py
│ │ │ ├── models.py
│ │ │ ├── server.py
│ │ │ └── utility_handler.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_comparison_handler.py
│ │ │ ├── test_cost_usage_handler.py
│ │ │ ├── test_forecasting_handler.py
│ │ │ ├── test_helpers.py
│ │ │ ├── test_metadata_handler.py
│ │ │ ├── test_models.py
│ │ │ ├── test_server.py
│ │ │ └── test_utility_handler.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── documentdb-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ └── documentdb_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── analytic_tools.py
│ │ │ ├── config.py
│ │ │ ├── connection_tools.py
│ │ │ ├── db_management_tools.py
│ │ │ ├── query_tools.py
│ │ │ ├── server.py
│ │ │ └── write_tools.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.py
│ │ │ ├── test_analytic_tools.py
│ │ │ ├── test_connection_tools.py
│ │ │ ├── test_db_management_tools.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_query_tools.py
│ │ │ └── test_write_tools.py
│ │ └── uv.lock
│ ├── dynamodb-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── dynamodb_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── common.py
│ │ │ ├── database_analysis_queries.py
│ │ │ ├── database_analyzers.py
│ │ │ ├── markdown_formatter.py
│ │ │ ├── prompts
│ │ │ │ └── dynamodb_architect.md
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── evals
│ │ │ │ ├── dynamic_evaluators.py
│ │ │ │ ├── evaluation_registry.py
│ │ │ │ ├── logging_config.py
│ │ │ │ ├── multiturn_evaluator.py
│ │ │ │ ├── README.md
│ │ │ │ ├── scenarios.py
│ │ │ │ └── test_dspy_evals.py
│ │ │ ├── test_dynamodb_server.py
│ │ │ ├── test_markdown_formatter.py
│ │ │ └── test_source_db_integration.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── ecs-mcp-server
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── ecs_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ ├── containerize.py
│ │ │ │ ├── delete.py
│ │ │ │ ├── ecs_troubleshooting.py
│ │ │ │ ├── infrastructure.py
│ │ │ │ ├── resource_management.py
│ │ │ │ ├── status.py
│ │ │ │ └── troubleshooting_tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── detect_image_pull_failures.py
│ │ │ │ ├── fetch_cloudformation_status.py
│ │ │ │ ├── fetch_network_configuration.py
│ │ │ │ ├── fetch_service_events.py
│ │ │ │ ├── fetch_task_failures.py
│ │ │ │ ├── fetch_task_logs.py
│ │ │ │ ├── get_ecs_troubleshooting_guidance.py
│ │ │ │ └── utils.py
│ │ │ ├── main.py
│ │ │ ├── modules
│ │ │ │ ├── __init__.py
│ │ │ │ ├── aws_knowledge_proxy.py
│ │ │ │ ├── containerize.py
│ │ │ │ ├── delete.py
│ │ │ │ ├── deployment_status.py
│ │ │ │ ├── infrastructure.py
│ │ │ │ ├── resource_management.py
│ │ │ │ └── troubleshooting.py
│ │ │ ├── templates
│ │ │ │ ├── ecr_infrastructure.json
│ │ │ │ └── ecs_infrastructure.json
│ │ │ └── utils
│ │ │ ├── arn_parser.py
│ │ │ ├── aws.py
│ │ │ ├── config.py
│ │ │ ├── docker.py
│ │ │ ├── security.py
│ │ │ ├── templates.py
│ │ │ └── time_utils.py
│ │ ├── DEVELOPMENT.md
│ │ ├── pyproject.toml
│ │ ├── pyrightconfig.json
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── integ
│ │ │ │ └── mcp-inspector
│ │ │ │ ├── .gitignore
│ │ │ │ ├── README.md
│ │ │ │ ├── run-tests.sh
│ │ │ │ └── scenarios
│ │ │ │ ├── 01_comprehensive_troubleshooting
│ │ │ │ │ ├── 01_create.sh
│ │ │ │ │ ├── 02_validate.sh
│ │ │ │ │ ├── 03_cleanup.sh
│ │ │ │ │ ├── description.txt
│ │ │ │ │ └── utils
│ │ │ │ │ ├── mcp_helpers.sh
│ │ │ │ │ └── validation_helpers.sh
│ │ │ │ └── 02_test_knowledge_proxy_tools
│ │ │ │ ├── 01_create.sh
│ │ │ │ ├── 02_validate.sh
│ │ │ │ ├── 03_cleanup.sh
│ │ │ │ ├── description.txt
│ │ │ │ └── utils
│ │ │ │ ├── knowledge_validation_helpers.sh
│ │ │ │ └── mcp_knowledge_helpers.sh
│ │ │ ├── llm_testing
│ │ │ │ ├── invalid_cfn_template.yaml
│ │ │ │ ├── README.md
│ │ │ │ ├── run_tests.sh
│ │ │ │ ├── scenarios
│ │ │ │ │ ├── 01_cloudformation_failure
│ │ │ │ │ │ ├── 01_create.sh
│ │ │ │ │ │ ├── 02_validate.sh
│ │ │ │ │ │ ├── 03_prompts.txt
│ │ │ │ │ │ ├── 04_evaluation.md
│ │ │ │ │ │ ├── 05_cleanup.sh
│ │ │ │ │ │ └── description.txt
│ │ │ │ │ ├── 02_service_failure
│ │ │ │ │ │ ├── 01_create.sh
│ │ │ │ │ │ ├── 02_validate.sh
│ │ │ │ │ │ ├── 03_prompts.txt
│ │ │ │ │ │ ├── 04_evaluation.md
│ │ │ │ │ │ ├── 05_cleanup.sh
│ │ │ │ │ │ └── description.txt
│ │ │ │ │ ├── 03_task_exit_failure
│ │ │ │ │ │ ├── 01_create.sh
│ │ │ │ │ │ ├── 02_validate.sh
│ │ │ │ │ │ ├── 03_prompts.txt
│ │ │ │ │ │ ├── 04_evaluation.md
│ │ │ │ │ │ ├── 05_cleanup.sh
│ │ │ │ │ │ └── description.txt
│ │ │ │ │ ├── 04_network_configuration_failure
│ │ │ │ │ │ ├── 01_create.sh
│ │ │ │ │ │ ├── 02_validate.sh
│ │ │ │ │ │ ├── 03_prompts.txt
│ │ │ │ │ │ ├── 05_cleanup.sh
│ │ │ │ │ │ └── description.txt
│ │ │ │ │ ├── 05_resource_constraint_failure
│ │ │ │ │ │ ├── 01_create.sh
│ │ │ │ │ │ ├── 02_validate.sh
│ │ │ │ │ │ ├── 03_prompts.txt
│ │ │ │ │ │ ├── 05_cleanup.sh
│ │ │ │ │ │ └── description.txt
│ │ │ │ │ └── 06_load_balancer_failure
│ │ │ │ │ ├── 01_create.sh
│ │ │ │ │ ├── 02_validate.sh
│ │ │ │ │ ├── 03_prompts.txt
│ │ │ │ │ ├── 05_cleanup.sh
│ │ │ │ │ └── description.txt
│ │ │ │ ├── SCRIPT_IMPROVEMENTS.md
│ │ │ │ └── utils
│ │ │ │ ├── aws_helpers.sh
│ │ │ │ └── evaluation_template.md
│ │ │ └── unit
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── conftest.py
│ │ │ │ ├── test_delete_api.py
│ │ │ │ ├── test_ecs_troubleshooting.py
│ │ │ │ ├── test_resource_management_api.py
│ │ │ │ └── troubleshooting_tools
│ │ │ │ └── test_fetch_network_configuration.py
│ │ │ ├── conftest.py
│ │ │ ├── modules
│ │ │ │ ├── test_aws_knowledge_proxy.py
│ │ │ │ └── test_resource_management_module.py
│ │ │ ├── test_aws_role_utils.py
│ │ │ ├── test_aws_utils.py
│ │ │ ├── test_containerize.py
│ │ │ ├── test_delete.py
│ │ │ ├── test_docker_utils.py
│ │ │ ├── test_docker_with_role.py
│ │ │ ├── test_image_pull_failure_extended.py
│ │ │ ├── test_image_pull_failure.py
│ │ │ ├── test_infrastructure_role.py
│ │ │ ├── test_infrastructure.py
│ │ │ ├── test_integration.py
│ │ │ ├── test_main.py
│ │ │ ├── test_resource_management_api_operation.py
│ │ │ ├── test_resource_management_tool.py
│ │ │ ├── test_resource_management.py
│ │ │ ├── test_security_integration.py
│ │ │ ├── test_status_pytest.py
│ │ │ ├── test_status.py
│ │ │ ├── troubleshooting_tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── conftest.py
│ │ │ │ ├── test_detect_image_pull_failures.py
│ │ │ │ ├── test_fetch_cloudformation_status.py
│ │ │ │ ├── test_fetch_service_events.py
│ │ │ │ ├── test_fetch_task_failures.py
│ │ │ │ ├── test_fetch_task_logs.py
│ │ │ │ ├── test_get_ecs_troubleshooting_guidance.py
│ │ │ │ ├── test_is_ecr_image_security.py
│ │ │ │ └── test_utils.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── async_test_utils.py
│ │ │ ├── test_arn_parser.py
│ │ │ ├── test_config.py
│ │ │ ├── test_docker.py
│ │ │ ├── test_response_sanitization.py
│ │ │ ├── test_security_extended.py
│ │ │ ├── test_security.py
│ │ │ ├── test_templates.py
│ │ │ └── test_time_utils.py
│ │ └── uv.lock
│ ├── eks-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── eks_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── aws_helper.py
│ │ │ ├── cloudwatch_handler.py
│ │ │ ├── cloudwatch_metrics_guidance_handler.py
│ │ │ ├── consts.py
│ │ │ ├── data
│ │ │ │ └── eks_cloudwatch_metrics_guidance.json
│ │ │ ├── eks_kb_handler.py
│ │ │ ├── eks_stack_handler.py
│ │ │ ├── iam_handler.py
│ │ │ ├── insights_handler.py
│ │ │ ├── k8s_apis.py
│ │ │ ├── k8s_client_cache.py
│ │ │ ├── k8s_handler.py
│ │ │ ├── logging_helper.py
│ │ │ ├── models.py
│ │ │ ├── scripts
│ │ │ │ └── update_eks_cloudwatch_metrics_guidance.py
│ │ │ ├── server.py
│ │ │ ├── templates
│ │ │ │ ├── eks-templates
│ │ │ │ │ └── eks-with-vpc.yaml
│ │ │ │ └── k8s-templates
│ │ │ │ ├── deployment.yaml
│ │ │ │ └── service.yaml
│ │ │ └── vpc_config_handler.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_aws_helper.py
│ │ │ ├── test_cloudwatch_handler.py
│ │ │ ├── test_cloudwatch_metrics_guidance_handler.py
│ │ │ ├── test_eks_kb_handler.py
│ │ │ ├── test_eks_stack_handler.py
│ │ │ ├── test_iam_handler.py
│ │ │ ├── test_init.py
│ │ │ ├── test_insights_handler.py
│ │ │ ├── test_k8s_apis.py
│ │ │ ├── test_k8s_client_cache.py
│ │ │ ├── test_k8s_handler.py
│ │ │ ├── test_logging_helper.py
│ │ │ ├── test_main.py
│ │ │ ├── test_models.py
│ │ │ ├── test_server.py
│ │ │ └── test_vpc_config_handler.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── elasticache-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── elasticache_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── common
│ │ │ │ ├── __init__.py
│ │ │ │ ├── connection.py
│ │ │ │ ├── decorators.py
│ │ │ │ └── server.py
│ │ │ ├── context.py
│ │ │ ├── main.py
│ │ │ └── tools
│ │ │ ├── __init__.py
│ │ │ ├── cc
│ │ │ │ ├── __init__.py
│ │ │ │ ├── connect.py
│ │ │ │ ├── create.py
│ │ │ │ ├── delete.py
│ │ │ │ ├── describe.py
│ │ │ │ ├── modify.py
│ │ │ │ ├── parsers.py
│ │ │ │ └── processors.py
│ │ │ ├── ce
│ │ │ │ ├── __init__.py
│ │ │ │ └── get_cost_and_usage.py
│ │ │ ├── cw
│ │ │ │ ├── __init__.py
│ │ │ │ └── get_metric_statistics.py
│ │ │ ├── cwlogs
│ │ │ │ ├── __init__.py
│ │ │ │ ├── create_log_group.py
│ │ │ │ ├── describe_log_groups.py
│ │ │ │ ├── describe_log_streams.py
│ │ │ │ ├── filter_log_events.py
│ │ │ │ └── get_log_events.py
│ │ │ ├── firehose
│ │ │ │ ├── __init__.py
│ │ │ │ └── list_delivery_streams.py
│ │ │ ├── misc
│ │ │ │ ├── __init__.py
│ │ │ │ ├── batch_apply_update_action.py
│ │ │ │ ├── batch_stop_update_action.py
│ │ │ │ ├── describe_cache_engine_versions.py
│ │ │ │ ├── describe_engine_default_parameters.py
│ │ │ │ ├── describe_events.py
│ │ │ │ └── describe_service_updates.py
│ │ │ ├── rg
│ │ │ │ ├── __init__.py
│ │ │ │ ├── complete_migration.py
│ │ │ │ ├── connect.py
│ │ │ │ ├── create.py
│ │ │ │ ├── delete.py
│ │ │ │ ├── describe.py
│ │ │ │ ├── modify.py
│ │ │ │ ├── parsers.py
│ │ │ │ ├── processors.py
│ │ │ │ ├── start_migration.py
│ │ │ │ └── test_migration.py
│ │ │ └── serverless
│ │ │ ├── __init__.py
│ │ │ ├── connect.py
│ │ │ ├── create.py
│ │ │ ├── delete.py
│ │ │ ├── describe.py
│ │ │ ├── models.py
│ │ │ └── modify.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_connection.py
│ │ │ ├── test_decorators.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ └── tools
│ │ │ ├── cc
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_connect_additional.py
│ │ │ │ ├── test_connect_coverage_additional.py
│ │ │ │ ├── test_connect_coverage.py
│ │ │ │ ├── test_connect.py
│ │ │ │ ├── test_create_additional.py
│ │ │ │ ├── test_create.py
│ │ │ │ ├── test_delete.py
│ │ │ │ ├── test_describe.py
│ │ │ │ ├── test_modify.py
│ │ │ │ ├── test_parsers.py
│ │ │ │ └── test_processors.py
│ │ │ ├── ce
│ │ │ │ ├── __init__.py
│ │ │ │ └── test_get_cost_and_usage.py
│ │ │ ├── cw
│ │ │ │ └── test_get_metric_statistics.py
│ │ │ ├── cwlogs
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_create_log_group.py
│ │ │ │ ├── test_describe_log_groups.py
│ │ │ │ ├── test_describe_log_streams.py
│ │ │ │ ├── test_filter_log_events.py
│ │ │ │ └── test_get_log_events.py
│ │ │ ├── firehose
│ │ │ │ └── test_list_delivery_streams.py
│ │ │ ├── misc
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_batch_apply_update_action.py
│ │ │ │ ├── test_batch_stop_update_action.py
│ │ │ │ ├── test_describe_cache_engine_versions.py
│ │ │ │ ├── test_describe_engine_default_parameters.py
│ │ │ │ ├── test_describe_events.py
│ │ │ │ └── test_describe_service_updates.py
│ │ │ ├── rg
│ │ │ │ ├── __init__.py
│ │ │ │ ├── test_complete_migration.py
│ │ │ │ ├── test_connect_additional.py
│ │ │ │ ├── test_connect_coverage_additional.py
│ │ │ │ ├── test_connect_optional_fields.py
│ │ │ │ ├── test_connect_partial_coverage.py
│ │ │ │ ├── test_connect.py
│ │ │ │ ├── test_create.py
│ │ │ │ ├── test_delete.py
│ │ │ │ ├── test_describe.py
│ │ │ │ ├── test_modify.py
│ │ │ │ ├── test_parsers.py
│ │ │ │ ├── test_processors.py
│ │ │ │ ├── test_start_migration.py
│ │ │ │ └── test_test_migration.py
│ │ │ └── serverless
│ │ │ ├── test_connect_additional.py
│ │ │ ├── test_connect_coverage_additional.py
│ │ │ ├── test_connect_optional_fields.py
│ │ │ ├── test_connect.py
│ │ │ ├── test_create.py
│ │ │ ├── test_delete.py
│ │ │ ├── test_describe.py
│ │ │ └── test_modify.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── finch-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── finch_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── consts.py
│ │ │ ├── models.py
│ │ │ ├── server.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── build.py
│ │ │ ├── common.py
│ │ │ ├── ecr.py
│ │ │ ├── push.py
│ │ │ └── vm.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── test_cli_flags.py
│ │ │ ├── test_logging_configuration.py
│ │ │ ├── test_server.py
│ │ │ ├── test_utils_build.py
│ │ │ ├── test_utils_common.py
│ │ │ ├── test_utils_ecr.py
│ │ │ ├── test_utils_push.py
│ │ │ └── test_utils_vm.py
│ │ └── uv.lock
│ ├── frontend-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── frontend_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── server.py
│ │ │ ├── static
│ │ │ │ └── react
│ │ │ │ ├── essential-knowledge.md
│ │ │ │ └── troubleshooting.md
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ └── file_utils.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_file_utils.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ └── test_server.py
│ │ └── uv.lock
│ ├── git-repo-research-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── git_repo_research_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── defaults.py
│ │ │ ├── embeddings.py
│ │ │ ├── github_search.py
│ │ │ ├── indexer.py
│ │ │ ├── models.py
│ │ │ ├── repository.py
│ │ │ ├── search.py
│ │ │ ├── server.py
│ │ │ └── utils.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_tests.sh
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_errors_repository.py
│ │ │ ├── test_github_search_edge_cases.py
│ │ │ ├── test_graphql_github_search.py
│ │ │ ├── test_local_repository.py
│ │ │ ├── test_repository_utils.py
│ │ │ ├── test_rest_github_search.py
│ │ │ ├── test_search.py
│ │ │ ├── test_server.py
│ │ │ └── test_url_repository.py
│ │ └── uv.lock
│ ├── healthlake-mcp-server
│ │ ├── .dockerignore
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── healthlake_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── fhir_operations.py
│ │ │ ├── main.py
│ │ │ ├── models.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── CONTRIBUTING.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── examples
│ │ │ ├── mcp_config.json
│ │ │ └── README.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.py
│ │ │ ├── test_fhir_client_comprehensive.py
│ │ │ ├── test_fhir_error_scenarios.py
│ │ │ ├── test_fhir_operations.py
│ │ │ ├── test_integration_mock_based.py
│ │ │ ├── test_main_edge_cases.py
│ │ │ ├── test_main.py
│ │ │ ├── test_mcp_integration_coverage.py
│ │ │ ├── test_models_edge_cases.py
│ │ │ ├── test_models.py
│ │ │ ├── test_readonly_mode.py
│ │ │ ├── test_server_core.py
│ │ │ ├── test_server_error_handling.py
│ │ │ ├── test_server_mcp_handlers.py
│ │ │ ├── test_server_toolhandler.py
│ │ │ └── test_server_validation.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── iam-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── iam_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── aws_client.py
│ │ │ ├── context.py
│ │ │ ├── errors.py
│ │ │ ├── models.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── DESIGN_COMPLIANCE.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── examples
│ │ │ ├── get_policy_document_example.py
│ │ │ └── inline_policy_demo.py
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── run_tests.sh
│ │ ├── tests
│ │ │ ├── test_context.py
│ │ │ ├── test_errors.py
│ │ │ ├── test_inline_policies.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── lambda-tool-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── lambda_tool_mcp_server
│ │ │ ├── __init__.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── examples
│ │ │ ├── README.md
│ │ │ └── sample_functions
│ │ │ ├── customer-create
│ │ │ │ └── app.py
│ │ │ ├── customer-id-from-email
│ │ │ │ └── app.py
│ │ │ ├── customer-info-from-id
│ │ │ │ └── app.py
│ │ │ └── template.yml
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── conftest.py
│ │ │ ├── README.md
│ │ │ ├── test_format_lambda_response.py
│ │ │ ├── test_integration_coverage.py
│ │ │ ├── test_integration.py
│ │ │ ├── test_register_lambda_functions.py
│ │ │ ├── test_schema_integration.py
│ │ │ ├── test_server_coverage_additional.py
│ │ │ ├── test_server_coverage.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── mcp-lambda-handler
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ └── mcp_lambda_handler
│ │ │ ├── __init__.py
│ │ │ ├── mcp_lambda_handler.py
│ │ │ ├── session.py
│ │ │ └── types.py
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ └── test_lambda_handler.py
│ │ └── uv.lock
│ ├── memcached-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── memcached_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── common
│ │ │ │ ├── config.py
│ │ │ │ ├── connection.py
│ │ │ │ └── server.py
│ │ │ ├── context.py
│ │ │ ├── main.py
│ │ │ └── tools
│ │ │ └── cache.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── ELASTICACHECONNECT.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_cache_readonly.py
│ │ │ ├── test_cache.py
│ │ │ ├── test_connection.py
│ │ │ ├── test_init.py
│ │ │ └── test_main.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── mysql-mcp-server
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── mysql_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── connection
│ │ │ │ ├── __init__.py
│ │ │ │ ├── abstract_db_connection.py
│ │ │ │ ├── asyncmy_pool_connection.py
│ │ │ │ ├── db_connection_singleton.py
│ │ │ │ └── rds_data_api_connection.py
│ │ │ ├── mutable_sql_detector.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.py
│ │ │ ├── test_abstract_db_connection.py
│ │ │ ├── test_asyncmy_pool_connection.py
│ │ │ ├── test_db_connection_singleton.py
│ │ │ ├── test_rds_data_api_connection.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── nova-canvas-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── nova_canvas_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── consts.py
│ │ │ ├── models.py
│ │ │ ├── novacanvas.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── conftest.py
│ │ │ ├── README.md
│ │ │ ├── test_models.py
│ │ │ ├── test_novacanvas.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── openapi-mcp-server
│ │ ├── .coveragerc
│ │ ├── .dockerignore
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── AUTHENTICATION.md
│ │ ├── AWS_BEST_PRACTICES.md
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── openapi_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── api
│ │ │ │ ├── __init__.py
│ │ │ │ └── config.py
│ │ │ ├── auth
│ │ │ │ ├── __init__.py
│ │ │ │ ├── api_key_auth.py
│ │ │ │ ├── auth_cache.py
│ │ │ │ ├── auth_errors.py
│ │ │ │ ├── auth_factory.py
│ │ │ │ ├── auth_protocol.py
│ │ │ │ ├── auth_provider.py
│ │ │ │ ├── base_auth.py
│ │ │ │ ├── basic_auth.py
│ │ │ │ ├── bearer_auth.py
│ │ │ │ ├── cognito_auth.py
│ │ │ │ └── register.py
│ │ │ ├── patch
│ │ │ │ └── __init__.py
│ │ │ ├── prompts
│ │ │ │ ├── __init__.py
│ │ │ │ ├── generators
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── operation_prompts.py
│ │ │ │ │ └── workflow_prompts.py
│ │ │ │ ├── models.py
│ │ │ │ └── prompt_manager.py
│ │ │ ├── server.py
│ │ │ └── utils
│ │ │ ├── __init__.py
│ │ │ ├── cache_provider.py
│ │ │ ├── config.py
│ │ │ ├── error_handler.py
│ │ │ ├── http_client.py
│ │ │ ├── metrics_provider.py
│ │ │ ├── openapi_validator.py
│ │ │ └── openapi.py
│ │ ├── CHANGELOG.md
│ │ ├── DEPLOYMENT.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── OBSERVABILITY.md
│ │ ├── pyproject.toml
│ │ ├── pyrightconfig.json
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── api
│ │ │ │ └── test_config.py
│ │ │ ├── auth
│ │ │ │ ├── test_api_key_auth.py
│ │ │ │ ├── test_auth_cache.py
│ │ │ │ ├── test_auth_errors.py
│ │ │ │ ├── test_auth_factory_caching.py
│ │ │ │ ├── test_auth_factory_coverage.py
│ │ │ │ ├── test_auth_factory.py
│ │ │ │ ├── test_auth_protocol_additional.py
│ │ │ │ ├── test_auth_protocol_boost.py
│ │ │ │ ├── test_auth_protocol_coverage.py
│ │ │ │ ├── test_auth_protocol_extended.py
│ │ │ │ ├── test_auth_protocol_improved.py
│ │ │ │ ├── test_auth_protocol.py
│ │ │ │ ├── test_auth_provider_additional.py
│ │ │ │ ├── test_base_auth_coverage.py
│ │ │ │ ├── test_base_auth.py
│ │ │ │ ├── test_basic_auth.py
│ │ │ │ ├── test_bearer_auth.py
│ │ │ │ ├── test_cognito_auth_additional_coverage.py
│ │ │ │ ├── test_cognito_auth_boost_coverage.py
│ │ │ │ ├── test_cognito_auth_client_credentials.py
│ │ │ │ ├── test_cognito_auth_coverage_boost.py
│ │ │ │ ├── test_cognito_auth_exceptions.py
│ │ │ │ ├── test_cognito_auth.py
│ │ │ │ ├── test_register_coverage.py
│ │ │ │ └── test_register.py
│ │ │ ├── prompts
│ │ │ │ ├── standalone
│ │ │ │ │ ├── test_operation_prompt.py
│ │ │ │ │ ├── test_prompt_arguments.py
│ │ │ │ │ └── test_secure_operation_prompt.py
│ │ │ │ ├── test_mcp_prompt_manager_integration.py
│ │ │ │ ├── test_mcp_prompt_manager.py
│ │ │ │ ├── test_models_dict_method.py
│ │ │ │ ├── test_operation_prompts_extended.py
│ │ │ │ ├── test_prompt_manager_additional.py
│ │ │ │ ├── test_prompt_manager_comprehensive.py
│ │ │ │ ├── test_prompt_manager_coverage.py
│ │ │ │ └── test_prompt_registration.py
│ │ │ ├── README.md
│ │ │ ├── test_api_name.py
│ │ │ ├── test_cache_coverage_89.py
│ │ │ ├── test_client.py
│ │ │ ├── test_coverage_boost.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main_extended.py
│ │ │ ├── test_main.py
│ │ │ ├── test_openapi_coverage_89.py
│ │ │ ├── test_server_auth_errors.py
│ │ │ ├── test_server_coverage_boost_2.py
│ │ │ ├── test_server_coverage_boost.py
│ │ │ ├── test_server_exception_handling.py
│ │ │ ├── test_server_extended.py
│ │ │ ├── test_server_httpx_version.py
│ │ │ ├── test_server_part1.py
│ │ │ ├── test_server_route_logging.py
│ │ │ ├── test_server_signal_handlers.py
│ │ │ ├── test_server.py
│ │ │ └── utils
│ │ │ ├── test_cache_provider.py
│ │ │ ├── test_error_handler_boost.py
│ │ │ ├── test_error_handler_extended.py
│ │ │ ├── test_error_handler_fix.py
│ │ │ ├── test_error_handler.py
│ │ │ ├── test_http_client_comprehensive.py
│ │ │ ├── test_http_client_extended.py
│ │ │ ├── test_http_client_extended2.py
│ │ │ ├── test_http_client_import_error.py
│ │ │ ├── test_http_client.py
│ │ │ ├── test_metrics_provider_decorators.py
│ │ │ ├── test_metrics_provider_extended2.py
│ │ │ ├── test_metrics_provider_prometheus.py
│ │ │ ├── test_metrics_provider.py
│ │ │ ├── test_openapi_validator.py
│ │ │ └── test_openapi.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── postgres-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── postgres_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── connection
│ │ │ │ ├── __init__.py
│ │ │ │ ├── abstract_db_connection.py
│ │ │ │ ├── db_connection_singleton.py
│ │ │ │ ├── psycopg_pool_connection.py
│ │ │ │ └── rds_api_connection.py
│ │ │ ├── mutable_sql_detector.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.py
│ │ │ ├── test_psycopg_connector.py
│ │ │ ├── test_server.py
│ │ │ └── test_singleton.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── prometheus-mcp-server
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── prometheus_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── consts.py
│ │ │ ├── models.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.py
│ │ │ ├── test_aws_credentials.py
│ │ │ ├── test_config_manager.py
│ │ │ ├── test_consts.py
│ │ │ ├── test_coverage_gaps.py
│ │ │ ├── test_coverage_improvement.py
│ │ │ ├── test_final_coverage.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_models.py
│ │ │ ├── test_prometheus_client.py
│ │ │ ├── test_prometheus_connection.py
│ │ │ ├── test_security_validator.py
│ │ │ ├── test_server_coverage.py
│ │ │ ├── test_tools.py
│ │ │ └── test_workspace_config.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── redshift-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── redshift_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── consts.py
│ │ │ ├── models.py
│ │ │ ├── redshift.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_redshift.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── s3-tables-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── s3_tables_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── constants.py
│ │ │ ├── database.py
│ │ │ ├── engines
│ │ │ │ ├── __init__.py
│ │ │ │ └── pyiceberg.py
│ │ │ ├── file_processor
│ │ │ │ ├── __init__.py
│ │ │ │ ├── csv.py
│ │ │ │ ├── parquet.py
│ │ │ │ └── utils.py
│ │ │ ├── models.py
│ │ │ ├── namespaces.py
│ │ │ ├── resources.py
│ │ │ ├── s3_operations.py
│ │ │ ├── server.py
│ │ │ ├── table_buckets.py
│ │ │ ├── tables.py
│ │ │ └── utils.py
│ │ ├── CHANGELOG.md
│ │ ├── CONTEXT.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_csv.py
│ │ │ ├── test_database.py
│ │ │ ├── test_file_processor_utils.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_namespaces.py
│ │ │ ├── test_parquet.py
│ │ │ ├── test_pyiceberg.py
│ │ │ ├── test_resources.py
│ │ │ ├── test_s3_operations.py
│ │ │ ├── test_server.py
│ │ │ ├── test_table_buckets.py
│ │ │ ├── test_tables.py
│ │ │ └── test_utils.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── stepfunctions-tool-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── stepfunctions_tool_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── aws_helper.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── README.md
│ │ │ ├── test_aws_helper.py
│ │ │ ├── test_create_state_machine_tool.py
│ │ │ ├── test_filter_state_machines_by_tag.py
│ │ │ ├── test_format_state_machine_response.py
│ │ │ ├── test_get_schema_arn_from_state_machine_arn.py
│ │ │ ├── test_get_schema_from_registry.py
│ │ │ ├── test_invoke_express_state_machine_impl.py
│ │ │ ├── test_invoke_standard_state_machine_impl.py
│ │ │ ├── test_main.py
│ │ │ ├── test_register_state_machines.py
│ │ │ ├── test_sanitize_tool_name.py
│ │ │ ├── test_server.py
│ │ │ └── test_validate_state_machine_name.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── syntheticdata-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── syntheticdata_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── pandas_interpreter.py
│ │ │ ├── server.py
│ │ │ └── storage
│ │ │ ├── __init__.py
│ │ │ ├── base.py
│ │ │ ├── loader.py
│ │ │ └── s3.py
│ │ ├── CHANGELOG.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── conftest.py
│ │ │ ├── test_constants.py
│ │ │ ├── test_pandas_interpreter.py
│ │ │ ├── test_server.py
│ │ │ └── test_storage
│ │ │ ├── __init__.py
│ │ │ ├── test_loader.py
│ │ │ └── test_s3.py
│ │ └── uv.lock
│ ├── terraform-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── terraform_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── impl
│ │ │ │ ├── resources
│ │ │ │ │ ├── __init__.py
│ │ │ │ │ ├── terraform_aws_provider_resources_listing.py
│ │ │ │ │ └── terraform_awscc_provider_resources_listing.py
│ │ │ │ └── tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── execute_terraform_command.py
│ │ │ │ ├── execute_terragrunt_command.py
│ │ │ │ ├── run_checkov_scan.py
│ │ │ │ ├── search_aws_provider_docs.py
│ │ │ │ ├── search_awscc_provider_docs.py
│ │ │ │ ├── search_specific_aws_ia_modules.py
│ │ │ │ ├── search_user_provided_module.py
│ │ │ │ └── utils.py
│ │ │ ├── models
│ │ │ │ ├── __init__.py
│ │ │ │ └── models.py
│ │ │ ├── scripts
│ │ │ │ ├── generate_aws_provider_resources.py
│ │ │ │ ├── generate_awscc_provider_resources.py
│ │ │ │ └── scrape_aws_terraform_best_practices.py
│ │ │ ├── server.py
│ │ │ └── static
│ │ │ ├── __init__.py
│ │ │ ├── AWS_PROVIDER_RESOURCES.md
│ │ │ ├── AWS_TERRAFORM_BEST_PRACTICES.md
│ │ │ ├── AWSCC_PROVIDER_RESOURCES.md
│ │ │ ├── MCP_INSTRUCTIONS.md
│ │ │ └── TERRAFORM_WORKFLOW_GUIDE.md
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── __init__.py
│ │ │ ├── .gitignore
│ │ │ ├── conftest.py
│ │ │ ├── README.md
│ │ │ ├── test_command_impl.py
│ │ │ ├── test_execute_terraform_command.py
│ │ │ ├── test_execute_terragrunt_command.py
│ │ │ ├── test_models.py
│ │ │ ├── test_parameter_annotations.py
│ │ │ ├── test_resources.py
│ │ │ ├── test_run_checkov_scan.py
│ │ │ ├── test_search_user_provided_module.py
│ │ │ ├── test_server.py
│ │ │ ├── test_tool_implementations.py
│ │ │ ├── test_utils_additional.py
│ │ │ └── test_utils.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── timestream-for-influxdb-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── timestream_for_influxdb_mcp_server
│ │ │ ├── __init__.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ └── test_server.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ ├── valkey-mcp-server
│ │ ├── .gitignore
│ │ ├── .python-version
│ │ ├── awslabs
│ │ │ ├── __init__.py
│ │ │ └── valkey_mcp_server
│ │ │ ├── __init__.py
│ │ │ ├── common
│ │ │ │ ├── __init__.py
│ │ │ │ ├── config.py
│ │ │ │ ├── connection.py
│ │ │ │ └── server.py
│ │ │ ├── context.py
│ │ │ ├── main.py
│ │ │ ├── tools
│ │ │ │ ├── __init__.py
│ │ │ │ ├── bitmap.py
│ │ │ │ ├── hash.py
│ │ │ │ ├── hyperloglog.py
│ │ │ │ ├── json.py
│ │ │ │ ├── list.py
│ │ │ │ ├── misc.py
│ │ │ │ ├── server_management.py
│ │ │ │ ├── set.py
│ │ │ │ ├── sorted_set.py
│ │ │ │ ├── stream.py
│ │ │ │ └── string.py
│ │ │ └── version.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── ELASTICACHECONNECT.md
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── test_bitmap.py
│ │ │ ├── test_config.py
│ │ │ ├── test_connection.py
│ │ │ ├── test_hash.py
│ │ │ ├── test_hyperloglog.py
│ │ │ ├── test_init.py
│ │ │ ├── test_json_additional.py
│ │ │ ├── test_json_readonly.py
│ │ │ ├── test_json.py
│ │ │ ├── test_list_additional.py
│ │ │ ├── test_list_readonly.py
│ │ │ ├── test_list.py
│ │ │ ├── test_main.py
│ │ │ ├── test_misc.py
│ │ │ ├── test_server_management.py
│ │ │ ├── test_set_readonly.py
│ │ │ ├── test_set.py
│ │ │ ├── test_sorted_set_additional.py
│ │ │ ├── test_sorted_set_readonly.py
│ │ │ ├── test_sorted_set.py
│ │ │ ├── test_stream_additional.py
│ │ │ ├── test_stream_readonly.py
│ │ │ ├── test_stream.py
│ │ │ └── test_string.py
│ │ ├── uv-requirements.txt
│ │ └── uv.lock
│ └── well-architected-security-mcp-server
│ ├── .python-version
│ ├── awslabs
│ │ └── well_architected_security_mcp_server
│ │ ├── __init__.py
│ │ ├── consts.py
│ │ ├── server.py
│ │ └── util
│ │ ├── __init__.py
│ │ ├── network_security.py
│ │ ├── prompt_utils.py
│ │ ├── resource_utils.py
│ │ ├── security_services.py
│ │ └── storage_security.py
│ ├── PROMPT_TEMPLATE.md
│ ├── pyproject.toml
│ ├── README.md
│ ├── tests
│ │ ├── __init__.py
│ │ ├── conftest.py
│ │ ├── README.md
│ │ ├── test_access_analyzer_fix.py
│ │ ├── test_network_security_additional.py
│ │ ├── test_network_security.py
│ │ ├── test_prompt_utils_coverage.py
│ │ ├── test_prompt_utils.py
│ │ ├── test_resource_utils_fix.py
│ │ ├── test_resource_utils.py
│ │ ├── test_security_services_additional.py
│ │ ├── test_security_services_coverage.py
│ │ ├── test_security_services.py
│ │ ├── test_server_additional.py
│ │ ├── test_server_coverage.py
│ │ ├── test_server_prompts.py
│ │ ├── test_server_security_findings.py
│ │ ├── test_server.py
│ │ ├── test_storage_security_additional.py
│ │ ├── test_storage_security_comprehensive.py
│ │ ├── test_storage_security_edge_cases.py
│ │ ├── test_storage_security_recommendations.py
│ │ ├── test_storage_security.py
│ │ └── test_user_agent_config.py
│ └── uv.lock
└── VIBE_CODING_TIPS_TRICKS.md
```
# Files
--------------------------------------------------------------------------------
/src/aws-dataprocessing-mcp-server/tests/core/glue_data_catalog/test_data_catalog_handler.py:
--------------------------------------------------------------------------------
```python
1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | """Tests for the DataCatalogManager class."""
16 |
17 | import pytest
18 | from awslabs.aws_dataprocessing_mcp_server.core.glue_data_catalog.data_catalog_handler import (
19 | DataCatalogManager,
20 | )
21 | from awslabs.aws_dataprocessing_mcp_server.models.data_catalog_models import (
22 | CreateCatalogResponse,
23 | CreateConnectionResponse,
24 | CreatePartitionResponse,
25 | DeleteCatalogResponse,
26 | DeleteConnectionResponse,
27 | DeletePartitionResponse,
28 | GetCatalogResponse,
29 | GetConnectionResponse,
30 | GetPartitionResponse,
31 | ImportCatalogResponse,
32 | ListCatalogsResponse,
33 | ListConnectionsResponse,
34 | ListPartitionsResponse,
35 | UpdateConnectionResponse,
36 | UpdatePartitionResponse,
37 | )
38 | from botocore.exceptions import ClientError
39 | from datetime import datetime
40 | from unittest.mock import MagicMock, patch
41 |
42 |
43 | class TestDataCatalogManager:
44 | """Tests for the DataCatalogManager class."""
45 |
46 | @pytest.fixture
47 | def mock_ctx(self):
48 | """Create a mock Context."""
49 | mock = MagicMock()
50 | mock.request_id = 'test-request-id'
51 | return mock
52 |
53 | @pytest.fixture
54 | def mock_glue_client(self):
55 | """Create a mock Glue client."""
56 | mock = MagicMock()
57 | return mock
58 |
59 | @pytest.fixture
60 | def manager(self, mock_glue_client):
61 | """Create a DataCatalogManager instance with a mocked Glue client."""
62 | with patch(
63 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client',
64 | return_value=mock_glue_client,
65 | ):
66 | manager = DataCatalogManager(allow_write=True)
67 | return manager
68 |
69 | @pytest.mark.asyncio
70 | async def test_create_connection_success(self, manager, mock_ctx, mock_glue_client):
71 | """Test that create_connection returns a successful response when the Glue API call succeeds."""
72 | # Setup
73 | connection_name = 'test-connection'
74 | connection_input = {
75 | 'ConnectionType': 'JDBC',
76 | 'ConnectionProperties': {
77 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test',
78 | 'USERNAME': 'test-user',
79 | 'PASSWORD': 'test-password', # pragma: allowlist secret
80 | },
81 | }
82 | catalog_id = '123456789012'
83 | tags = {'tag1': 'value1', 'tag2': 'value2'}
84 |
85 | # Mock the AWS helper prepare_resource_tags method
86 | with patch(
87 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
88 | return_value={'mcp:managed': 'true'},
89 | ):
90 | # Call the method
91 | result = await manager.create_connection(
92 | mock_ctx,
93 | connection_name=connection_name,
94 | connection_input=connection_input,
95 | catalog_id=catalog_id,
96 | tags=tags,
97 | )
98 |
99 | # Verify that the Glue client was called with the correct parameters
100 | mock_glue_client.create_connection.assert_called_once()
101 | call_args = mock_glue_client.create_connection.call_args[1]
102 |
103 | assert call_args['ConnectionInput']['Name'] == connection_name
104 | assert call_args['ConnectionInput']['ConnectionType'] == 'JDBC'
105 | assert (
106 | call_args['ConnectionInput']['ConnectionProperties']['JDBC_CONNECTION_URL']
107 | == 'jdbc:mysql://localhost:3306/test'
108 | )
109 | assert call_args['ConnectionInput']['ConnectionProperties']['USERNAME'] == 'test-user'
110 | assert (
111 | call_args['ConnectionInput']['ConnectionProperties']['PASSWORD']
112 | == 'test-password' # pragma: allowlist secret
113 | )
114 | assert call_args['CatalogId'] == catalog_id
115 |
116 | # Verify that the tags were merged correctly
117 | expected_tags = {'tag1': 'value1', 'tag2': 'value2', 'mcp:managed': 'true'}
118 | assert call_args['Tags'] == expected_tags
119 |
120 | # Verify the response
121 | assert isinstance(result, CreateConnectionResponse)
122 | assert result.isError is False
123 | assert result.connection_name == connection_name
124 | assert result.catalog_id == catalog_id
125 | assert result.operation == 'create-connection'
126 | assert len(result.content) == 1
127 | assert result.content[0].text == f'Successfully created connection: {connection_name}'
128 |
129 | @pytest.mark.asyncio
130 | async def test_create_connection_error(self, manager, mock_ctx, mock_glue_client):
131 | """Test that create_connection returns an error response when the Glue API call fails."""
132 | # Setup
133 | connection_name = 'test-connection'
134 | connection_input = {
135 | 'ConnectionType': 'JDBC',
136 | 'ConnectionProperties': {
137 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test',
138 | 'USERNAME': 'test-user',
139 | 'PASSWORD': 'test-password', # pragma: allowlist secret
140 | },
141 | }
142 |
143 | # Mock the AWS helper prepare_resource_tags method
144 | with patch(
145 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
146 | return_value={'mcp:managed': 'true'},
147 | ):
148 | # Mock the Glue client to raise an exception
149 | error_response = {
150 | 'Error': {'Code': 'AlreadyExistsException', 'Message': 'Connection already exists'}
151 | }
152 | mock_glue_client.create_connection.side_effect = ClientError(
153 | error_response, 'CreateConnection'
154 | )
155 |
156 | # Call the method
157 | result = await manager.create_connection(
158 | mock_ctx, connection_name=connection_name, connection_input=connection_input
159 | )
160 |
161 | # Verify the response
162 | assert isinstance(result, CreateConnectionResponse)
163 | assert result.isError is True
164 | assert result.connection_name == connection_name
165 | assert result.operation == 'create-connection'
166 | assert len(result.content) == 1
167 | assert 'Failed to create connection' in result.content[0].text
168 | assert 'AlreadyExistsException' in result.content[0].text
169 |
170 | @pytest.mark.asyncio
171 | async def test_delete_connection_success(self, manager, mock_ctx, mock_glue_client):
172 | """Test that delete_connection returns a successful response when the Glue API call succeeds."""
173 | # Setup
174 | connection_name = 'test-connection'
175 | catalog_id = '123456789012'
176 |
177 | # Mock the get_connection response to indicate the connection is MCP managed
178 | mock_glue_client.get_connection.return_value = {
179 | 'Connection': {'Name': connection_name, 'Parameters': {'mcp:managed': 'true'}}
180 | }
181 |
182 | # Mock the AWS helper is_resource_mcp_managed method
183 | with (
184 | patch(
185 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
186 | return_value=True,
187 | ),
188 | patch(
189 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
190 | return_value='us-east-1',
191 | ),
192 | patch(
193 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
194 | return_value='123456789012',
195 | ),
196 | ):
197 | # Call the method
198 | result = await manager.delete_connection(
199 | mock_ctx, connection_name=connection_name, catalog_id=catalog_id
200 | )
201 |
202 | # Verify that the Glue client was called with the correct parameters
203 | mock_glue_client.delete_connection.assert_called_once_with(
204 | ConnectionName=connection_name, CatalogId=catalog_id
205 | )
206 |
207 | # Verify the response
208 | assert isinstance(result, DeleteConnectionResponse)
209 | assert result.isError is False
210 | assert result.connection_name == connection_name
211 | assert result.catalog_id == catalog_id
212 | assert result.operation == 'delete-connection'
213 | assert len(result.content) == 1
214 | assert result.content[0].text == f'Successfully deleted connection: {connection_name}'
215 |
216 | @pytest.mark.asyncio
217 | async def test_delete_connection_not_mcp_managed(self, manager, mock_ctx, mock_glue_client):
218 | """Test that delete_connection returns an error when the connection is not MCP managed."""
219 | # Setup
220 | connection_name = 'test-connection'
221 |
222 | # Mock the get_connection response to indicate the connection is not MCP managed
223 | mock_glue_client.get_connection.return_value = {
224 | 'Connection': {'Name': connection_name, 'Parameters': {}}
225 | }
226 |
227 | # Mock the AWS helper is_resource_mcp_managed method
228 | with (
229 | patch(
230 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
231 | return_value=False,
232 | ),
233 | patch(
234 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
235 | return_value='us-east-1',
236 | ),
237 | patch(
238 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
239 | return_value='123456789012',
240 | ),
241 | ):
242 | # Call the method
243 | result = await manager.delete_connection(mock_ctx, connection_name=connection_name)
244 |
245 | # Verify that the Glue client was not called to delete the connection
246 | mock_glue_client.delete_connection.assert_not_called()
247 |
248 | # Verify the response
249 | assert isinstance(result, DeleteConnectionResponse)
250 | assert result.isError is True
251 | assert result.connection_name == connection_name
252 | assert result.operation == 'delete-connection'
253 | assert len(result.content) == 1
254 | assert 'not managed by the MCP server' in result.content[0].text
255 |
256 | @pytest.mark.asyncio
257 | async def test_get_connection_success(self, manager, mock_ctx, mock_glue_client):
258 | """Test that get_connection returns a successful response when the Glue API call succeeds."""
259 | # Setup
260 | connection_name = 'test-connection'
261 | catalog_id = '123456789012'
262 | connection_type = 'JDBC'
263 | connection_properties = {
264 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test',
265 | 'USERNAME': 'test-user',
266 | }
267 | creation_time = datetime(2023, 1, 1, 0, 0, 0)
268 | last_updated_time = datetime(2023, 1, 2, 0, 0, 0)
269 |
270 | # Mock the get_connection response
271 | mock_glue_client.get_connection.return_value = {
272 | 'Connection': {
273 | 'Name': connection_name,
274 | 'ConnectionType': connection_type,
275 | 'ConnectionProperties': connection_properties,
276 | 'CreationTime': creation_time,
277 | 'LastUpdatedTime': last_updated_time,
278 | 'LastUpdatedBy': 'test-user',
279 | 'Status': 'ACTIVE',
280 | 'StatusReason': 'Connection is active',
281 | }
282 | }
283 |
284 | # Call the method
285 | result = await manager.get_connection(
286 | mock_ctx, connection_name=connection_name, catalog_id=catalog_id, hide_password=True
287 | )
288 |
289 | # Verify that the Glue client was called with the correct parameters
290 | mock_glue_client.get_connection.assert_called_once_with(
291 | Name=connection_name, CatalogId=catalog_id, HidePassword=True
292 | )
293 |
294 | # Verify the response
295 | assert isinstance(result, GetConnectionResponse)
296 | assert result.isError is False
297 | assert result.connection_name == connection_name
298 | assert result.connection_type == connection_type
299 | assert result.connection_properties == connection_properties
300 | assert result.creation_time == creation_time.isoformat()
301 | assert result.last_updated_time == last_updated_time.isoformat()
302 | assert result.last_updated_by == 'test-user'
303 | assert result.status == 'ACTIVE'
304 | assert result.status_reason == 'Connection is active'
305 | assert result.catalog_id == catalog_id
306 | assert result.operation == 'get-connection'
307 | assert len(result.content) == 1
308 | assert result.content[0].text == f'Successfully retrieved connection: {connection_name}'
309 |
310 | @pytest.mark.asyncio
311 | async def test_list_connections_success(self, manager, mock_ctx, mock_glue_client):
312 | """Test that list_connections returns a successful response when the Glue API call succeeds."""
313 | # Setup
314 | catalog_id = '123456789012'
315 | filter_dict = {'ConnectionType': 'JDBC'}
316 | hide_password = True
317 | next_token = 'next-token'
318 | max_results = 10
319 |
320 | # Mock the get_connections response
321 | creation_time = datetime(2023, 1, 1, 0, 0, 0)
322 | last_updated_time = datetime(2023, 1, 2, 0, 0, 0)
323 | mock_glue_client.get_connections.return_value = {
324 | 'ConnectionList': [
325 | {
326 | 'Name': 'conn1',
327 | 'ConnectionType': 'JDBC',
328 | 'ConnectionProperties': {
329 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/db1'
330 | },
331 | 'CreationTime': creation_time,
332 | 'LastUpdatedTime': last_updated_time,
333 | },
334 | {
335 | 'Name': 'conn2',
336 | 'ConnectionType': 'JDBC',
337 | 'ConnectionProperties': {
338 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/db2'
339 | },
340 | 'CreationTime': creation_time,
341 | 'LastUpdatedTime': last_updated_time,
342 | },
343 | ],
344 | 'NextToken': 'next-token-response',
345 | }
346 |
347 | # Call the method
348 | result = await manager.list_connections(
349 | mock_ctx,
350 | catalog_id=catalog_id,
351 | filter_dict=filter_dict,
352 | hide_password=hide_password,
353 | next_token=next_token,
354 | max_results=max_results,
355 | )
356 |
357 | # Verify that the Glue client was called with the correct parameters
358 | mock_glue_client.get_connections.assert_called_once_with(
359 | CatalogId=catalog_id,
360 | Filter=filter_dict,
361 | HidePassword=hide_password,
362 | NextToken=next_token,
363 | MaxResults=max_results,
364 | )
365 |
366 | # Verify the response
367 | assert isinstance(result, ListConnectionsResponse)
368 | assert result.isError is False
369 | assert len(result.connections) == 2
370 | assert result.count == 2
371 | assert result.catalog_id == catalog_id
372 | assert result.next_token == 'next-token-response'
373 | assert result.operation == 'list-connections'
374 | assert len(result.content) == 1
375 | assert result.content[0].text == 'Successfully listed 2 connections'
376 |
377 | # Verify the connection summaries
378 | assert result.connections[0].name == 'conn1'
379 | assert result.connections[0].connection_type == 'JDBC'
380 | assert result.connections[0].connection_properties == {
381 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/db1'
382 | }
383 | assert result.connections[0].creation_time == creation_time.isoformat()
384 | assert result.connections[0].last_updated_time == last_updated_time.isoformat()
385 |
386 | assert result.connections[1].name == 'conn2'
387 | assert result.connections[1].connection_type == 'JDBC'
388 | assert result.connections[1].connection_properties == {
389 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/db2'
390 | }
391 | assert result.connections[1].creation_time == creation_time.isoformat()
392 | assert result.connections[1].last_updated_time == last_updated_time.isoformat()
393 |
394 | @pytest.mark.asyncio
395 | async def test_create_partition_success(self, manager, mock_ctx, mock_glue_client):
396 | """Test that create_partition returns a successful response when the Glue API call succeeds."""
397 | # Setup
398 | database_name = 'test-db'
399 | table_name = 'test-table'
400 | partition_values = ['2023', '01', '01']
401 | partition_input = {
402 | 'StorageDescriptor': {
403 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
404 | }
405 | }
406 | catalog_id = '123456789012'
407 |
408 | # Mock the AWS helper prepare_resource_tags method
409 | with patch(
410 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
411 | return_value={'mcp:managed': 'true'},
412 | ):
413 | # Call the method
414 | result = await manager.create_partition(
415 | mock_ctx,
416 | database_name=database_name,
417 | table_name=table_name,
418 | partition_values=partition_values,
419 | partition_input=partition_input,
420 | catalog_id=catalog_id,
421 | )
422 |
423 | # Verify that the Glue client was called with the correct parameters
424 | mock_glue_client.create_partition.assert_called_once()
425 | call_args = mock_glue_client.create_partition.call_args[1]
426 |
427 | assert call_args['DatabaseName'] == database_name
428 | assert call_args['TableName'] == table_name
429 | assert call_args['PartitionInput']['Values'] == partition_values
430 | assert (
431 | call_args['PartitionInput']['StorageDescriptor']['Location']
432 | == 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
433 | )
434 | assert call_args['CatalogId'] == catalog_id
435 |
436 | # Verify that the MCP tags were added to Parameters
437 | assert call_args['PartitionInput']['Parameters']['mcp:managed'] == 'true'
438 |
439 | # Verify the response
440 | assert isinstance(result, CreatePartitionResponse)
441 | assert result.isError is False
442 | assert result.database_name == database_name
443 | assert result.table_name == table_name
444 | assert result.partition_values == partition_values
445 | assert result.operation == 'create-partition'
446 | assert len(result.content) == 1
447 | assert (
448 | result.content[0].text
449 | == f'Successfully created partition in table: {database_name}.{table_name}'
450 | )
451 |
452 | @pytest.mark.asyncio
453 | async def test_get_partition_success(self, manager, mock_ctx, mock_glue_client):
454 | """Test that get_partition returns a successful response when the Glue API call succeeds."""
455 | # Setup
456 | database_name = 'test-db'
457 | table_name = 'test-table'
458 | partition_values = ['2023', '01', '01']
459 | catalog_id = '123456789012'
460 | creation_time = datetime(2023, 1, 1, 0, 0, 0)
461 | last_access_time = datetime(2023, 1, 2, 0, 0, 0)
462 |
463 | # Mock the get_partition response
464 | mock_glue_client.get_partition.return_value = {
465 | 'Partition': {
466 | 'Values': partition_values,
467 | 'DatabaseName': database_name,
468 | 'TableName': table_name,
469 | 'CreationTime': creation_time,
470 | 'LastAccessTime': last_access_time,
471 | 'StorageDescriptor': {
472 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
473 | },
474 | 'Parameters': {'key1': 'value1'},
475 | }
476 | }
477 |
478 | # Call the method
479 | result = await manager.get_partition(
480 | mock_ctx,
481 | database_name=database_name,
482 | table_name=table_name,
483 | partition_values=partition_values,
484 | catalog_id=catalog_id,
485 | )
486 |
487 | # Verify that the Glue client was called with the correct parameters
488 | mock_glue_client.get_partition.assert_called_once_with(
489 | DatabaseName=database_name,
490 | TableName=table_name,
491 | PartitionValues=partition_values,
492 | CatalogId=catalog_id,
493 | )
494 |
495 | # Verify the response
496 | assert isinstance(result, GetPartitionResponse)
497 | assert result.isError is False
498 | assert result.database_name == database_name
499 | assert result.table_name == table_name
500 | assert result.partition_values == partition_values
501 | assert result.creation_time == creation_time.isoformat()
502 | assert result.last_access_time == last_access_time.isoformat()
503 | assert (
504 | result.storage_descriptor['Location']
505 | == 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
506 | )
507 | assert result.parameters == {'key1': 'value1'}
508 | assert result.operation == 'get-partition'
509 | assert len(result.content) == 1
510 | assert (
511 | result.content[0].text
512 | == f'Successfully retrieved partition from table: {database_name}.{table_name}'
513 | )
514 |
515 | @pytest.mark.asyncio
516 | async def test_list_partitions_success(self, manager, mock_ctx, mock_glue_client):
517 | """Test that list_partitions returns a successful response when the Glue API call succeeds."""
518 | # Setup
519 | database_name = 'test-db'
520 | table_name = 'test-table'
521 | max_results = 10
522 | expression = "year='2023'"
523 | catalog_id = '123456789012'
524 |
525 | # Mock the get_partitions response
526 | creation_time = datetime(2023, 1, 1, 0, 0, 0)
527 | last_access_time = datetime(2023, 1, 2, 0, 0, 0)
528 | mock_glue_client.get_partitions.return_value = {
529 | 'Partitions': [
530 | {
531 | 'Values': ['2023', '01', '01'],
532 | 'DatabaseName': database_name,
533 | 'TableName': table_name,
534 | 'CreationTime': creation_time,
535 | 'LastAccessTime': last_access_time,
536 | 'StorageDescriptor': {
537 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
538 | },
539 | 'Parameters': {'key1': 'value1'},
540 | },
541 | {
542 | 'Values': ['2023', '01', '02'],
543 | 'DatabaseName': database_name,
544 | 'TableName': table_name,
545 | 'CreationTime': creation_time,
546 | 'LastAccessTime': last_access_time,
547 | 'StorageDescriptor': {
548 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=02/'
549 | },
550 | 'Parameters': {'key2': 'value2'},
551 | },
552 | ],
553 | 'NextToken': 'next-token-response',
554 | }
555 |
556 | # Call the method
557 | result = await manager.list_partitions(
558 | mock_ctx,
559 | database_name=database_name,
560 | table_name=table_name,
561 | max_results=max_results,
562 | expression=expression,
563 | catalog_id=catalog_id,
564 | )
565 |
566 | # Verify that the Glue client was called with the correct parameters
567 | mock_glue_client.get_partitions.assert_called_once_with(
568 | DatabaseName=database_name,
569 | TableName=table_name,
570 | MaxResults=max_results,
571 | Expression=expression,
572 | CatalogId=catalog_id,
573 | )
574 |
575 | # Verify the response
576 | assert isinstance(result, ListPartitionsResponse)
577 | assert result.isError is False
578 | assert len(result.partitions) == 2
579 | assert result.count == 2
580 | assert result.database_name == database_name
581 | assert result.table_name == table_name
582 | assert result.next_token == 'next-token-response'
583 | assert result.expression == expression
584 | assert result.operation == 'list-partitions'
585 | assert len(result.content) == 1
586 | assert (
587 | result.content[0].text
588 | == f'Successfully listed 2 partitions in table {database_name}.{table_name}'
589 | )
590 |
591 | # Verify the partition summaries
592 | assert result.partitions[0].values == ['2023', '01', '01']
593 | assert result.partitions[0].database_name == database_name
594 | assert result.partitions[0].table_name == table_name
595 | assert result.partitions[0].creation_time == creation_time.isoformat()
596 | assert result.partitions[0].last_access_time == last_access_time.isoformat()
597 | assert (
598 | result.partitions[0].storage_descriptor['Location']
599 | == 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
600 | )
601 | assert result.partitions[0].parameters == {'key1': 'value1'}
602 |
603 | assert result.partitions[1].values == ['2023', '01', '02']
604 | assert result.partitions[1].database_name == database_name
605 | assert result.partitions[1].table_name == table_name
606 | assert result.partitions[1].creation_time == creation_time.isoformat()
607 | assert result.partitions[1].last_access_time == last_access_time.isoformat()
608 | assert (
609 | result.partitions[1].storage_descriptor['Location']
610 | == 's3://test-bucket/test-db/test-table/year=2023/month=01/day=02/'
611 | )
612 | assert result.partitions[1].parameters == {'key2': 'value2'}
613 |
614 | @pytest.mark.asyncio
615 | async def test_create_catalog_success(self, manager, mock_ctx, mock_glue_client):
616 | """Test that create_catalog returns a successful response when the Glue API call succeeds."""
617 | # Setup
618 | catalog_name = 'test-catalog'
619 | catalog_input = {'Description': 'Test catalog', 'Type': 'GLUE'}
620 | tags = {'tag1': 'value1', 'tag2': 'value2'}
621 |
622 | # Mock the AWS helper prepare_resource_tags method
623 | with patch(
624 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
625 | return_value={'mcp:managed': 'true'},
626 | ):
627 | # Call the method
628 | result = await manager.create_catalog(
629 | mock_ctx, catalog_name=catalog_name, catalog_input=catalog_input, tags=tags
630 | )
631 |
632 | # Verify that the Glue client was called with the correct parameters
633 | mock_glue_client.create_catalog.assert_called_once()
634 | call_args = mock_glue_client.create_catalog.call_args[1]
635 |
636 | assert call_args['Name'] == catalog_name
637 | assert call_args['CatalogInput']['Description'] == 'Test catalog'
638 | assert call_args['CatalogInput']['Type'] == 'GLUE'
639 |
640 | # Verify that the tags were merged correctly
641 | expected_tags = {'tag1': 'value1', 'tag2': 'value2', 'mcp:managed': 'true'}
642 | assert call_args['Tags'] == expected_tags
643 |
644 | # Verify that the MCP tags were added to Parameters
645 | assert call_args['CatalogInput']['Parameters']['mcp:managed'] == 'true'
646 |
647 | # Verify the response
648 | assert isinstance(result, CreateCatalogResponse)
649 | assert result.isError is False
650 | assert result.catalog_id == catalog_name
651 | assert result.operation == 'create-catalog'
652 | assert len(result.content) == 1
653 | assert result.content[0].text == f'Successfully created catalog: {catalog_name}'
654 |
655 | @pytest.mark.asyncio
656 | async def test_get_catalog_success(self, manager, mock_ctx, mock_glue_client):
657 | """Test that get_catalog returns a successful response when the Glue API call succeeds."""
658 | # Setup
659 | catalog_id = 'test-catalog'
660 | name = 'Test Catalog'
661 | description = 'Test catalog description'
662 | create_time = datetime(2023, 1, 1, 0, 0, 0)
663 | update_time = datetime(2023, 1, 2, 0, 0, 0)
664 |
665 | # Mock the get_catalog response
666 | mock_glue_client.get_catalog.return_value = {
667 | 'Catalog': {
668 | 'Name': name,
669 | 'Description': description,
670 | 'Parameters': {'key1': 'value1'},
671 | 'CreateTime': create_time,
672 | 'UpdateTime': update_time,
673 | }
674 | }
675 |
676 | # Call the method
677 | result = await manager.get_catalog(mock_ctx, catalog_id=catalog_id)
678 |
679 | # Verify that the Glue client was called with the correct parameters
680 | mock_glue_client.get_catalog.assert_called_once_with(CatalogId=catalog_id)
681 |
682 | # Verify the response
683 | assert isinstance(result, GetCatalogResponse)
684 | assert result.isError is False
685 | assert result.catalog_id == catalog_id
686 | assert result.name == name
687 | assert result.description == description
688 | assert result.parameters == {'key1': 'value1'}
689 | assert result.create_time == create_time.isoformat()
690 | assert result.update_time == update_time.isoformat()
691 | assert result.operation == 'get-catalog'
692 | assert len(result.content) == 1
693 | assert result.content[0].text == f'Successfully retrieved catalog: {catalog_id}'
694 |
695 | @pytest.mark.asyncio
696 | async def test_list_catalogs_success(self, manager, mock_ctx, mock_glue_client):
697 | """Test that list_connections returns a successful response when the Glue API call succeeds."""
698 | next_token = 'next-token'
699 | max_results = 10
700 |
701 | creation_time = datetime(2023, 1, 1, 0, 0, 0)
702 | last_updated_time = datetime(2023, 1, 2, 0, 0, 0)
703 | mock_glue_client.get_catalogs.return_value = {
704 | 'CatalogList': [
705 | {
706 | 'CatalogId': '123',
707 | 'Name': 'catalog1',
708 | 'CreateTime': creation_time,
709 | 'UpdateTime': last_updated_time,
710 | },
711 | {
712 | 'CatalogId': '456',
713 | 'Name': 'catalog2',
714 | 'CreateTime': creation_time,
715 | 'UpdateTime': last_updated_time,
716 | },
717 | ],
718 | 'NextToken': 'next-token-response',
719 | }
720 |
721 | result = await manager.list_catalogs(
722 | mock_ctx,
723 | next_token=next_token,
724 | max_results=max_results,
725 | parent_catalog_id='parent-catalog-id',
726 | )
727 |
728 | mock_glue_client.get_catalogs.assert_called_once_with(
729 | NextToken=next_token, MaxResults=max_results, ParentCatalogId='parent-catalog-id'
730 | )
731 |
732 | assert isinstance(result, ListCatalogsResponse)
733 | assert result.isError is False
734 | assert len(result.catalogs) == 2
735 | assert result.count == 2
736 | assert result.next_token == 'next-token-response'
737 | assert result.operation == 'list-catalogs'
738 | assert len(result.content) == 1
739 | assert result.content[0].text == 'Successfully listed 2 catalogs'
740 |
741 | assert result.catalogs[0].name == 'catalog1'
742 | assert result.catalogs[0].create_time == creation_time.isoformat()
743 | assert result.catalogs[0].update_time == last_updated_time.isoformat()
744 |
745 | assert result.catalogs[1].name == 'catalog2'
746 | assert result.catalogs[1].create_time == creation_time.isoformat()
747 | assert result.catalogs[1].update_time == last_updated_time.isoformat()
748 |
749 | @pytest.mark.asyncio
750 | async def test_list_catalogs_error(self, manager, mock_ctx, mock_glue_client):
751 | """Test that list_connections returns an error response when the Glue API call fails."""
752 | error_response = {
753 | 'Error': {'Code': 'InternalServiceException', 'Message': 'Internal service error'}
754 | }
755 | mock_glue_client.get_catalogs.side_effect = ClientError(error_response, 'GetCatalogs')
756 |
757 | result = await manager.list_catalogs(mock_ctx)
758 |
759 | assert isinstance(result, ListCatalogsResponse)
760 | assert result.isError is True
761 | assert result.operation == 'list-catalogs'
762 | assert len(result.content) == 1
763 | assert 'Failed to list catalogs' in result.content[0].text
764 | assert 'InternalServiceException' in result.content[0].text
765 |
766 | @pytest.mark.asyncio
767 | async def test_list_catalogs_empty_result(self, manager, mock_ctx, mock_glue_client):
768 | """Test that list_connections handles empty results correctly."""
769 | mock_glue_client.get_catalogs.return_value = {'CatalogList': []}
770 |
771 | result = await manager.list_catalogs(mock_ctx)
772 |
773 | assert isinstance(result, ListCatalogsResponse)
774 | assert result.isError is False
775 | assert result.catalogs == []
776 | assert result.count == 0
777 | assert result.operation == 'list-catalogs'
778 | assert len(result.content) == 1
779 | assert 'Successfully listed 0 catalogs' in result.content[0].text
780 |
781 | @pytest.mark.asyncio
782 | async def test_update_connection_success(self, manager, mock_ctx, mock_glue_client):
783 | """Test that update_connection returns a successful response when the Glue API call succeeds."""
784 | # Setup
785 | connection_name = 'test-connection'
786 | connection_input = {
787 | 'ConnectionType': 'JDBC',
788 | 'ConnectionProperties': {
789 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test-updated',
790 | 'USERNAME': 'test-user-updated',
791 | 'PASSWORD': 'test-password-updated', # pragma: allowlist secret
792 | },
793 | }
794 | catalog_id = '123456789012'
795 |
796 | # Mock the get_connection response to indicate the connection is MCP managed
797 | mock_glue_client.get_connection.return_value = {
798 | 'Connection': {
799 | 'Name': connection_name,
800 | }
801 | }
802 |
803 | # Mock the AWS helper is_resource_mcp_managed method
804 | with (
805 | patch(
806 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
807 | return_value=True,
808 | ),
809 | patch(
810 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
811 | return_value='us-east-1',
812 | ),
813 | patch(
814 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
815 | return_value='123456789012',
816 | ),
817 | ):
818 | # Call the method
819 | result = await manager.update_connection(
820 | mock_ctx,
821 | connection_name=connection_name,
822 | connection_input=connection_input,
823 | catalog_id=catalog_id,
824 | )
825 |
826 | # Verify that the Glue client was called with the correct parameters
827 | mock_glue_client.update_connection.assert_called_once()
828 | call_args = mock_glue_client.update_connection.call_args[1]
829 |
830 | assert call_args['Name'] == connection_name
831 | assert call_args['ConnectionInput']['Name'] == connection_name
832 | assert call_args['ConnectionInput']['ConnectionType'] == 'JDBC'
833 | assert (
834 | call_args['ConnectionInput']['ConnectionProperties']['JDBC_CONNECTION_URL']
835 | == 'jdbc:mysql://localhost:3306/test-updated'
836 | )
837 | assert (
838 | call_args['ConnectionInput']['ConnectionProperties']['USERNAME']
839 | == 'test-user-updated'
840 | )
841 | assert (
842 | call_args['ConnectionInput']['ConnectionProperties']['PASSWORD']
843 | == 'test-password-updated' # pragma: allowlist secret
844 | )
845 | assert call_args['CatalogId'] == catalog_id
846 |
847 | # Verify the response
848 | assert isinstance(result, UpdateConnectionResponse)
849 | assert result.isError is False
850 | assert result.connection_name == connection_name
851 | assert result.catalog_id == catalog_id
852 | assert result.operation == 'update-connection'
853 | assert len(result.content) == 1
854 | assert result.content[0].text == f'Successfully updated connection: {connection_name}'
855 |
856 | @pytest.mark.asyncio
857 | async def test_update_connection_not_mcp_managed(self, manager, mock_ctx, mock_glue_client):
858 | """Test that update_connection returns an error when the connection is not MCP managed."""
859 | # Setup
860 | connection_name = 'test-connection'
861 | connection_input = {
862 | 'ConnectionType': 'JDBC',
863 | 'ConnectionProperties': {
864 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test-updated',
865 | 'USERNAME': 'test-user-updated',
866 | 'PASSWORD': 'test-password-updated', # pragma: allowlist secret
867 | },
868 | }
869 |
870 | # Mock the get_connection response to indicate the connection is not MCP managed
871 | mock_glue_client.get_connection.return_value = {
872 | 'Connection': {'Name': connection_name, 'Parameters': {}}
873 | }
874 |
875 | # Mock the AWS helper is_resource_mcp_managed method
876 | with (
877 | patch(
878 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
879 | return_value=False,
880 | ),
881 | patch(
882 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
883 | return_value='us-east-1',
884 | ),
885 | patch(
886 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
887 | return_value='123456789012',
888 | ),
889 | ):
890 | # Call the method
891 | result = await manager.update_connection(
892 | mock_ctx, connection_name=connection_name, connection_input=connection_input
893 | )
894 |
895 | # Verify that the Glue client was not called to update the connection
896 | mock_glue_client.update_connection.assert_not_called()
897 |
898 | # Verify the response
899 | assert isinstance(result, UpdateConnectionResponse)
900 | assert result.isError is True
901 | assert result.connection_name == connection_name
902 | assert result.operation == 'update-connection'
903 | assert len(result.content) == 1
904 | assert 'not managed by the MCP server' in result.content[0].text
905 |
906 | @pytest.mark.asyncio
907 | async def test_delete_partition_success(self, manager, mock_ctx, mock_glue_client):
908 | """Test that delete_partition returns a successful response when the Glue API call succeeds."""
909 | # Setup
910 | database_name = 'test-db'
911 | table_name = 'test-table'
912 | partition_values = ['2023', '01', '01']
913 | catalog_id = '123456789012'
914 |
915 | # Mock the get_partition response to indicate the partition is MCP managed
916 | mock_glue_client.get_partition.return_value = {
917 | 'Partition': {
918 | 'Values': partition_values,
919 | 'DatabaseName': database_name,
920 | 'TableName': table_name,
921 | 'Parameters': {'mcp:managed': 'true', 'mcp:ResourceType': 'GluePartition'},
922 | }
923 | }
924 |
925 | # Mock the AWS helper is_resource_mcp_managed method
926 | with (
927 | patch(
928 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
929 | return_value=True,
930 | ),
931 | patch(
932 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
933 | return_value='us-east-1',
934 | ),
935 | patch(
936 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
937 | return_value='123456789012',
938 | ),
939 | ):
940 | # Call the method
941 | result = await manager.delete_partition(
942 | mock_ctx,
943 | database_name=database_name,
944 | table_name=table_name,
945 | partition_values=partition_values,
946 | catalog_id=catalog_id,
947 | )
948 |
949 | # Verify that the Glue client was called with the correct parameters
950 | mock_glue_client.delete_partition.assert_called_once_with(
951 | DatabaseName=database_name,
952 | TableName=table_name,
953 | PartitionValues=partition_values,
954 | CatalogId=catalog_id,
955 | )
956 |
957 | # Verify the response
958 | assert isinstance(result, DeletePartitionResponse)
959 | assert result.isError is False
960 | assert result.database_name == database_name
961 | assert result.table_name == table_name
962 | assert result.partition_values == partition_values
963 | assert result.operation == 'delete-partition'
964 | assert len(result.content) == 1
965 | assert (
966 | result.content[0].text
967 | == f'Successfully deleted partition from table: {database_name}.{table_name}'
968 | )
969 |
970 | @pytest.mark.asyncio
971 | async def test_update_partition_success(self, manager, mock_ctx, mock_glue_client):
972 | """Test that update_partition returns a successful response when the Glue API call succeeds."""
973 | # Setup
974 | database_name = 'test-db'
975 | table_name = 'test-table'
976 | partition_values = ['2023', '01', '01']
977 | partition_input = {
978 | 'StorageDescriptor': {
979 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
980 | }
981 | }
982 | catalog_id = '123456789012'
983 |
984 | # Mock the get_partition response to indicate the partition is MCP managed
985 | mock_glue_client.get_partition.return_value = {
986 | 'Partition': {
987 | 'Values': partition_values,
988 | 'DatabaseName': database_name,
989 | 'TableName': table_name,
990 | 'Parameters': {'mcp:managed': 'true', 'mcp:ResourceType': 'GluePartition'},
991 | }
992 | }
993 |
994 | # Mock the AWS helper is_resource_mcp_managed method
995 | with (
996 | patch(
997 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
998 | return_value=True,
999 | ),
1000 | patch(
1001 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1002 | return_value='us-east-1',
1003 | ),
1004 | patch(
1005 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1006 | return_value='123456789012',
1007 | ),
1008 | ):
1009 | # Call the method
1010 | result = await manager.update_partition(
1011 | mock_ctx,
1012 | database_name=database_name,
1013 | table_name=table_name,
1014 | partition_values=partition_values,
1015 | partition_input=partition_input,
1016 | catalog_id=catalog_id,
1017 | )
1018 |
1019 | # Verify that the Glue client was called with the correct parameters
1020 | mock_glue_client.update_partition.assert_called_once()
1021 | call_args = mock_glue_client.update_partition.call_args[1]
1022 |
1023 | assert call_args['DatabaseName'] == database_name
1024 | assert call_args['TableName'] == table_name
1025 | assert call_args['PartitionValueList'] == partition_values
1026 | assert (
1027 | call_args['PartitionInput']['StorageDescriptor']['Location']
1028 | == 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
1029 | )
1030 | assert call_args['CatalogId'] == catalog_id
1031 |
1032 | # Verify that the MCP tags were preserved
1033 | assert call_args['PartitionInput']['Parameters']['mcp:managed'] == 'true'
1034 | assert call_args['PartitionInput']['Parameters']['mcp:ResourceType'] == 'GluePartition'
1035 |
1036 | # Verify the response
1037 | assert isinstance(result, UpdatePartitionResponse)
1038 | assert result.isError is False
1039 | assert result.database_name == database_name
1040 | assert result.table_name == table_name
1041 | assert result.partition_values == partition_values
1042 | assert result.operation == 'update-partition'
1043 | assert len(result.content) == 1
1044 | assert (
1045 | result.content[0].text
1046 | == f'Successfully updated partition in table: {database_name}.{table_name}'
1047 | )
1048 |
1049 | @pytest.mark.asyncio
1050 | async def test_delete_catalog_success(self, manager, mock_ctx, mock_glue_client):
1051 | """Test that delete_catalog returns a successful response when the Glue API call succeeds."""
1052 | # Setup
1053 | catalog_id = 'test-catalog'
1054 |
1055 | # Mock the get_catalog response to indicate the catalog is MCP managed
1056 | mock_glue_client.get_catalog.return_value = {
1057 | 'Catalog': {
1058 | 'Name': 'Test Catalog',
1059 | 'Parameters': {'mcp:managed': 'true', 'mcp:ResourceType': 'GlueCatalog'},
1060 | }
1061 | }
1062 |
1063 | # Mock the AWS helper is_resource_mcp_managed method
1064 | with (
1065 | patch(
1066 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
1067 | return_value=True,
1068 | ),
1069 | patch(
1070 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1071 | return_value='us-east-1',
1072 | ),
1073 | patch(
1074 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1075 | return_value='123456789012',
1076 | ),
1077 | ):
1078 | # Call the method
1079 | result = await manager.delete_catalog(mock_ctx, catalog_id=catalog_id)
1080 |
1081 | # Verify that the Glue client was called with the correct parameters
1082 | mock_glue_client.delete_catalog.assert_called_once_with(CatalogId=catalog_id)
1083 |
1084 | # Verify the response
1085 | assert isinstance(result, DeleteCatalogResponse)
1086 | assert result.isError is False
1087 | assert result.catalog_id == catalog_id
1088 | assert result.operation == 'delete-catalog'
1089 | assert len(result.content) == 1
1090 | assert result.content[0].text == f'Successfully deleted catalog: {catalog_id}'
1091 |
1092 | @pytest.mark.asyncio
1093 | async def test_delete_catalog_not_mcp_managed(self, manager, mock_ctx, mock_glue_client):
1094 | """Test that delete_catalog returns an error when the catalog is not MCP managed."""
1095 | # Setup
1096 | catalog_id = 'test-catalog'
1097 |
1098 | # Mock the get_catalog response to indicate the catalog is not MCP managed
1099 | mock_glue_client.get_catalog.return_value = {
1100 | 'Catalog': {'Name': 'Test Catalog', 'Parameters': {}}
1101 | }
1102 |
1103 | # Mock the AWS helper is_resource_mcp_managed method
1104 | with (
1105 | patch(
1106 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
1107 | return_value=False,
1108 | ),
1109 | patch(
1110 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1111 | return_value='us-east-1',
1112 | ),
1113 | patch(
1114 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1115 | return_value='123456789012',
1116 | ),
1117 | ):
1118 | # Call the method
1119 | result = await manager.delete_catalog(mock_ctx, catalog_id=catalog_id)
1120 |
1121 | # Verify that the Glue client was not called to delete the catalog
1122 | mock_glue_client.delete_catalog.assert_not_called()
1123 |
1124 | # Verify the response
1125 | assert isinstance(result, DeleteCatalogResponse)
1126 | assert result.isError is True
1127 | assert result.catalog_id == catalog_id
1128 | assert result.operation == 'delete-catalog'
1129 | assert len(result.content) == 1
1130 | assert 'not managed by the MCP server' in result.content[0].text
1131 |
1132 | @pytest.mark.asyncio
1133 | async def test_delete_catalog_not_found(self, manager, mock_ctx, mock_glue_client):
1134 | """Test that delete_catalog returns an error when the catalog is not found."""
1135 | # Setup
1136 | catalog_id = 'test-catalog'
1137 |
1138 | # Mock the get_catalog to raise EntityNotFoundException
1139 | error_response = {
1140 | 'Error': {'Code': 'EntityNotFoundException', 'Message': 'Catalog not found'}
1141 | }
1142 | mock_glue_client.get_catalog.side_effect = ClientError(error_response, 'GetCatalog')
1143 |
1144 | # Call the method
1145 | result = await manager.delete_catalog(mock_ctx, catalog_id=catalog_id)
1146 |
1147 | # Verify that the Glue client was not called to delete the catalog
1148 | mock_glue_client.delete_catalog.assert_not_called()
1149 |
1150 | # Verify the response
1151 | assert isinstance(result, DeleteCatalogResponse)
1152 | assert result.isError is True
1153 | assert result.catalog_id == catalog_id
1154 | assert result.operation == 'delete-catalog'
1155 | assert len(result.content) == 1
1156 | assert 'Catalog test-catalog not found' in result.content[0].text
1157 |
1158 | @pytest.mark.asyncio
1159 | async def test_delete_catalog_error(self, manager, mock_ctx, mock_glue_client):
1160 | """Test that delete_catalog returns an error response when the Glue API call fails."""
1161 | # Setup
1162 | catalog_id = 'test-catalog'
1163 |
1164 | # Mock the get_catalog response to indicate the catalog is MCP managed
1165 | mock_glue_client.get_catalog.return_value = {
1166 | 'Catalog': {
1167 | 'Name': 'Test Catalog',
1168 | 'Parameters': {'mcp:managed': 'true', 'mcp:ResourceType': 'GlueCatalog'},
1169 | }
1170 | }
1171 |
1172 | # Mock the AWS helper is_resource_mcp_managed method
1173 | with (
1174 | patch(
1175 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
1176 | return_value=True,
1177 | ),
1178 | patch(
1179 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1180 | return_value='us-east-1',
1181 | ),
1182 | patch(
1183 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1184 | return_value='123456789012',
1185 | ),
1186 | ):
1187 | # Mock the Glue client to raise an exception
1188 | error_response = {
1189 | 'Error': {'Code': 'ValidationException', 'Message': 'Invalid catalog ID'}
1190 | }
1191 | mock_glue_client.delete_catalog.side_effect = ClientError(
1192 | error_response, 'DeleteCatalog'
1193 | )
1194 |
1195 | # Call the method
1196 | result = await manager.delete_catalog(mock_ctx, catalog_id=catalog_id)
1197 |
1198 | # Verify the response
1199 | assert isinstance(result, DeleteCatalogResponse)
1200 | assert result.isError is True
1201 | assert result.catalog_id == catalog_id
1202 | assert result.operation == 'delete-catalog'
1203 | assert len(result.content) == 1
1204 | assert 'Failed to delete catalog' in result.content[0].text
1205 | assert 'ValidationException' in result.content[0].text
1206 |
1207 | @pytest.mark.asyncio
1208 | async def test_import_catalog_to_glue_success(self, manager, mock_ctx, mock_glue_client):
1209 | """Test that import_catalog_to_glue returns a successful response when the Glue API call succeeds."""
1210 | # Setup
1211 | catalog_id = 'test-catalog'
1212 |
1213 | # Mock the AWS helper prepare_resource_tags method
1214 | with patch(
1215 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
1216 | return_value={'mcp:managed': 'true', 'mcp:ResourceType': 'GlueCatalogImport'},
1217 | ):
1218 | # Call the method
1219 | result = await manager.import_catalog_to_glue(
1220 | mock_ctx,
1221 | catalog_id=catalog_id,
1222 | )
1223 |
1224 | # Verify that the Glue client was called with the correct parameters
1225 | mock_glue_client.import_catalog_to_glue.assert_called_once_with(
1226 | CatalogId=catalog_id,
1227 | )
1228 |
1229 | # Verify the response
1230 | assert isinstance(result, ImportCatalogResponse)
1231 | assert result.isError is False
1232 | assert result.catalog_id == catalog_id
1233 | assert result.operation == 'import-catalog-to-glue'
1234 | assert len(result.content) == 1
1235 | assert 'Successfully initiated catalog import' in result.content[0].text
1236 |
1237 | @pytest.mark.asyncio
1238 | async def test_import_catalog_to_glue_error(self, manager, mock_ctx, mock_glue_client):
1239 | """Test that import_catalog_to_glue returns an error response when the Glue API call fails."""
1240 | # Setup
1241 | catalog_id = 'test-catalog'
1242 |
1243 | # Mock the AWS helper prepare_resource_tags method
1244 | with patch(
1245 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
1246 | return_value={'mcp:managed': 'true', 'mcp:ResourceType': 'GlueCatalogImport'},
1247 | ):
1248 | # Mock the Glue client to raise an exception
1249 | error_response = {
1250 | 'Error': {'Code': 'ValidationException', 'Message': 'Invalid catalog ID'}
1251 | }
1252 | mock_glue_client.import_catalog_to_glue.side_effect = ClientError(
1253 | error_response, 'ImportCatalogToGlue'
1254 | )
1255 |
1256 | # Call the method
1257 | result = await manager.import_catalog_to_glue(
1258 | mock_ctx,
1259 | catalog_id=catalog_id,
1260 | )
1261 |
1262 | # Verify the response
1263 | assert isinstance(result, ImportCatalogResponse)
1264 | assert result.isError is True
1265 | assert result.catalog_id == catalog_id
1266 | assert result.operation == 'import-catalog-to-glue'
1267 | assert len(result.content) == 1
1268 | assert 'Failed to import' in result.content[0].text
1269 | assert 'ValidationException' in result.content[0].text
1270 |
1271 | @pytest.mark.asyncio
1272 | async def test_update_partition_not_mcp_managed(self, manager, mock_ctx, mock_glue_client):
1273 | """Test that update_partition returns an error when the partition is not MCP managed."""
1274 | # Setup
1275 | database_name = 'test-db'
1276 | table_name = 'test-table'
1277 | partition_values = ['2023', '01', '01']
1278 | partition_input = {
1279 | 'StorageDescriptor': {
1280 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
1281 | }
1282 | }
1283 |
1284 | # Mock the get_partition response to indicate the partition is not MCP managed
1285 | mock_glue_client.get_partition.return_value = {
1286 | 'Partition': {
1287 | 'Values': partition_values,
1288 | 'DatabaseName': database_name,
1289 | 'TableName': table_name,
1290 | 'Parameters': {},
1291 | }
1292 | }
1293 |
1294 | # Mock the AWS helper is_resource_mcp_managed method
1295 | with (
1296 | patch(
1297 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
1298 | return_value=False,
1299 | ),
1300 | patch(
1301 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1302 | return_value='us-east-1',
1303 | ),
1304 | patch(
1305 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1306 | return_value='123456789012',
1307 | ),
1308 | ):
1309 | # Call the method
1310 | result = await manager.update_partition(
1311 | mock_ctx,
1312 | database_name=database_name,
1313 | table_name=table_name,
1314 | partition_values=partition_values,
1315 | partition_input=partition_input,
1316 | )
1317 |
1318 | # Verify that the Glue client was not called to update the partition
1319 | mock_glue_client.update_partition.assert_not_called()
1320 |
1321 | # Verify the response
1322 | assert isinstance(result, UpdatePartitionResponse)
1323 | assert result.isError is True
1324 | assert result.database_name == database_name
1325 | assert result.table_name == table_name
1326 | assert result.partition_values == partition_values
1327 | assert result.operation == 'update-partition'
1328 | assert len(result.content) == 1
1329 | assert 'not managed by the MCP server' in result.content[0].text
1330 |
1331 | @pytest.mark.asyncio
1332 | async def test_update_partition_not_found(self, manager, mock_ctx, mock_glue_client):
1333 | """Test that update_partition returns an error when the partition is not found."""
1334 | # Setup
1335 | database_name = 'test-db'
1336 | table_name = 'test-table'
1337 | partition_values = ['2023', '01', '01']
1338 | partition_input = {
1339 | 'StorageDescriptor': {
1340 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
1341 | }
1342 | }
1343 |
1344 | # Mock the get_partition to raise EntityNotFoundException
1345 | error_response = {
1346 | 'Error': {'Code': 'EntityNotFoundException', 'Message': 'Partition not found'}
1347 | }
1348 | mock_glue_client.get_partition.side_effect = ClientError(error_response, 'GetPartition')
1349 |
1350 | # Call the method
1351 | result = await manager.update_partition(
1352 | mock_ctx,
1353 | database_name=database_name,
1354 | table_name=table_name,
1355 | partition_values=partition_values,
1356 | partition_input=partition_input,
1357 | )
1358 |
1359 | # Verify that the Glue client was not called to update the partition
1360 | mock_glue_client.update_partition.assert_not_called()
1361 |
1362 | # Verify the response
1363 | assert isinstance(result, UpdatePartitionResponse)
1364 | assert result.isError is True
1365 | assert result.database_name == database_name
1366 | assert result.table_name == table_name
1367 | assert result.partition_values == partition_values
1368 | assert result.operation == 'update-partition'
1369 | assert len(result.content) == 1
1370 | assert (
1371 | f'Partition in table {database_name}.{table_name} not found' in result.content[0].text
1372 | )
1373 |
1374 | @pytest.mark.asyncio
1375 | async def test_update_partition_error(self, manager, mock_ctx, mock_glue_client):
1376 | """Test that update_partition returns an error response when the Glue API call fails."""
1377 | # Setup
1378 | database_name = 'test-db'
1379 | table_name = 'test-table'
1380 | partition_values = ['2023', '01', '01']
1381 | partition_input = {
1382 | 'StorageDescriptor': {
1383 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
1384 | }
1385 | }
1386 | catalog_id = '123456789012'
1387 |
1388 | # Mock the get_partition response to indicate the partition is MCP managed
1389 | mock_glue_client.get_partition.return_value = {
1390 | 'Partition': {
1391 | 'Values': partition_values,
1392 | 'DatabaseName': database_name,
1393 | 'TableName': table_name,
1394 | 'Parameters': {'mcp:managed': 'true', 'mcp:ResourceType': 'GluePartition'},
1395 | }
1396 | }
1397 |
1398 | # Mock the AWS helper is_resource_mcp_managed method
1399 | with (
1400 | patch(
1401 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
1402 | return_value=True,
1403 | ),
1404 | patch(
1405 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1406 | return_value='us-east-1',
1407 | ),
1408 | patch(
1409 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1410 | return_value='123456789012',
1411 | ),
1412 | ):
1413 | # Mock the Glue client to raise an exception
1414 | error_response = {
1415 | 'Error': {'Code': 'ValidationException', 'Message': 'Invalid partition input'}
1416 | }
1417 | mock_glue_client.update_partition.side_effect = ClientError(
1418 | error_response, 'UpdatePartition'
1419 | )
1420 |
1421 | # Call the method
1422 | result = await manager.update_partition(
1423 | mock_ctx,
1424 | database_name=database_name,
1425 | table_name=table_name,
1426 | partition_values=partition_values,
1427 | partition_input=partition_input,
1428 | catalog_id=catalog_id,
1429 | )
1430 |
1431 | # Verify the response
1432 | assert isinstance(result, UpdatePartitionResponse)
1433 | assert result.isError is True
1434 | assert result.database_name == database_name
1435 | assert result.table_name == table_name
1436 | assert result.partition_values == partition_values
1437 | assert result.operation == 'update-partition'
1438 | assert len(result.content) == 1
1439 | assert 'Failed to update partition' in result.content[0].text
1440 | assert 'ValidationException' in result.content[0].text
1441 |
1442 | @pytest.mark.asyncio
1443 | async def test_delete_partition_not_mcp_managed(self, manager, mock_ctx, mock_glue_client):
1444 | """Test that delete_partition returns an error when the partition is not MCP managed."""
1445 | # Setup
1446 | database_name = 'test-db'
1447 | table_name = 'test-table'
1448 | partition_values = ['2023', '01', '01']
1449 |
1450 | # Mock the get_partition response to indicate the partition is not MCP managed
1451 | mock_glue_client.get_partition.return_value = {
1452 | 'Partition': {
1453 | 'Values': partition_values,
1454 | 'DatabaseName': database_name,
1455 | 'TableName': table_name,
1456 | 'Parameters': {},
1457 | }
1458 | }
1459 |
1460 | # Mock the AWS helper is_resource_mcp_managed method
1461 | with (
1462 | patch(
1463 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
1464 | return_value=False,
1465 | ),
1466 | patch(
1467 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1468 | return_value='us-east-1',
1469 | ),
1470 | patch(
1471 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1472 | return_value='123456789012',
1473 | ),
1474 | ):
1475 | # Call the method
1476 | result = await manager.delete_partition(
1477 | mock_ctx,
1478 | database_name=database_name,
1479 | table_name=table_name,
1480 | partition_values=partition_values,
1481 | )
1482 |
1483 | # Verify that the Glue client was not called to delete the partition
1484 | mock_glue_client.delete_partition.assert_not_called()
1485 |
1486 | # Verify the response
1487 | assert isinstance(result, DeletePartitionResponse)
1488 | assert result.isError is True
1489 | assert result.database_name == database_name
1490 | assert result.table_name == table_name
1491 | assert result.partition_values == partition_values
1492 | assert result.operation == 'delete-partition'
1493 | assert len(result.content) == 1
1494 | assert 'not managed by the MCP server' in result.content[0].text
1495 |
1496 | @pytest.mark.asyncio
1497 | async def test_delete_partition_not_found(self, manager, mock_ctx, mock_glue_client):
1498 | """Test that delete_partition returns an error when the partition is not found."""
1499 | # Setup
1500 | database_name = 'test-db'
1501 | table_name = 'test-table'
1502 | partition_values = ['2023', '01', '01']
1503 |
1504 | # Mock the get_partition to raise EntityNotFoundException
1505 | error_response = {
1506 | 'Error': {'Code': 'EntityNotFoundException', 'Message': 'Partition not found'}
1507 | }
1508 | mock_glue_client.get_partition.side_effect = ClientError(error_response, 'GetPartition')
1509 |
1510 | # Call the method
1511 | result = await manager.delete_partition(
1512 | mock_ctx,
1513 | database_name=database_name,
1514 | table_name=table_name,
1515 | partition_values=partition_values,
1516 | )
1517 |
1518 | # Verify that the Glue client was not called to delete the partition
1519 | mock_glue_client.delete_partition.assert_not_called()
1520 |
1521 | # Verify the response
1522 | assert isinstance(result, DeletePartitionResponse)
1523 | assert result.isError is True
1524 | assert result.database_name == database_name
1525 | assert result.table_name == table_name
1526 | assert result.partition_values == partition_values
1527 | assert result.operation == 'delete-partition'
1528 | assert len(result.content) == 1
1529 | assert (
1530 | f'Partition in table {database_name}.{table_name} not found' in result.content[0].text
1531 | )
1532 |
1533 | @pytest.mark.asyncio
1534 | async def test_delete_partition_error(self, manager, mock_ctx, mock_glue_client):
1535 | """Test that delete_partition returns an error response when the Glue API call fails."""
1536 | # Setup
1537 | database_name = 'test-db'
1538 | table_name = 'test-table'
1539 | partition_values = ['2023', '01', '01']
1540 | catalog_id = '123456789012'
1541 |
1542 | # Mock the get_partition response to indicate the partition is MCP managed
1543 | mock_glue_client.get_partition.return_value = {
1544 | 'Partition': {
1545 | 'Values': partition_values,
1546 | 'DatabaseName': database_name,
1547 | 'TableName': table_name,
1548 | 'Parameters': {'mcp:managed': 'true', 'mcp:ResourceType': 'GluePartition'},
1549 | }
1550 | }
1551 |
1552 | # Mock the AWS helper is_resource_mcp_managed method
1553 | with (
1554 | patch(
1555 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
1556 | return_value=True,
1557 | ),
1558 | patch(
1559 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
1560 | return_value='us-east-1',
1561 | ),
1562 | patch(
1563 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
1564 | return_value='123456789012',
1565 | ),
1566 | ):
1567 | # Mock the Glue client to raise an exception
1568 | error_response = {
1569 | 'Error': {'Code': 'ValidationException', 'Message': 'Invalid partition values'}
1570 | }
1571 | mock_glue_client.delete_partition.side_effect = ClientError(
1572 | error_response, 'DeletePartition'
1573 | )
1574 |
1575 | # Call the method
1576 | result = await manager.delete_partition(
1577 | mock_ctx,
1578 | database_name=database_name,
1579 | table_name=table_name,
1580 | partition_values=partition_values,
1581 | catalog_id=catalog_id,
1582 | )
1583 |
1584 | # Verify the response
1585 | assert isinstance(result, DeletePartitionResponse)
1586 | assert result.isError is True
1587 | assert result.database_name == database_name
1588 | assert result.table_name == table_name
1589 | assert result.partition_values == partition_values
1590 | assert result.operation == 'delete-partition'
1591 | assert len(result.content) == 1
1592 | assert 'Failed to delete partition' in result.content[0].text
1593 | assert 'ValidationException' in result.content[0].text
1594 |
1595 | @pytest.mark.asyncio
1596 | async def test_get_connection_error(self, manager, mock_ctx, mock_glue_client):
1597 | """Test that get_connection returns an error response when the Glue API call fails."""
1598 | # Setup
1599 | connection_name = 'test-connection'
1600 | catalog_id = '123456789012'
1601 |
1602 | # Mock the Glue client to raise an exception
1603 | error_response = {
1604 | 'Error': {'Code': 'EntityNotFoundException', 'Message': 'Connection not found'}
1605 | }
1606 | mock_glue_client.get_connection.side_effect = ClientError(error_response, 'GetConnection')
1607 |
1608 | # Call the method
1609 | result = await manager.get_connection(
1610 | mock_ctx, connection_name=connection_name, catalog_id=catalog_id
1611 | )
1612 |
1613 | # Verify the response
1614 | assert isinstance(result, GetConnectionResponse)
1615 | assert result.isError is True
1616 | assert result.connection_name == connection_name
1617 | assert result.catalog_id == catalog_id
1618 | assert result.operation == 'get-connection'
1619 | assert len(result.content) == 1
1620 | assert 'Failed to get connection' in result.content[0].text
1621 | assert 'EntityNotFoundException' in result.content[0].text
1622 |
1623 | @pytest.mark.asyncio
1624 | async def test_get_connection_with_all_parameters(self, manager, mock_ctx, mock_glue_client):
1625 | """Test that get_connection handles all optional parameters correctly."""
1626 | # Setup
1627 | connection_name = 'test-connection'
1628 | catalog_id = '123456789012'
1629 | hide_password = True
1630 | apply_override_for_compute_environment = 'test-env'
1631 |
1632 | # Mock the get_connection response
1633 | mock_glue_client.get_connection.return_value = {
1634 | 'Connection': {
1635 | 'Name': connection_name,
1636 | 'ConnectionType': 'JDBC',
1637 | 'ConnectionProperties': {
1638 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test'
1639 | },
1640 | }
1641 | }
1642 |
1643 | # Call the method
1644 | result = await manager.get_connection(
1645 | mock_ctx,
1646 | connection_name=connection_name,
1647 | catalog_id=catalog_id,
1648 | hide_password=hide_password,
1649 | apply_override_for_compute_environment=apply_override_for_compute_environment,
1650 | )
1651 |
1652 | # Verify that the Glue client was called with the correct parameters
1653 | mock_glue_client.get_connection.assert_called_once_with(
1654 | Name=connection_name,
1655 | CatalogId=catalog_id,
1656 | HidePassword=True,
1657 | ApplyOverrideForComputeEnvironment=apply_override_for_compute_environment,
1658 | )
1659 |
1660 | # Verify the response
1661 | assert isinstance(result, GetConnectionResponse)
1662 | assert result.isError is False
1663 | assert result.connection_name == connection_name
1664 | assert result.catalog_id == catalog_id
1665 | assert result.operation == 'get-connection'
1666 |
1667 | @pytest.mark.asyncio
1668 | async def test_list_connections_error(self, manager, mock_ctx, mock_glue_client):
1669 | """Test that list_connections returns an error response when the Glue API call fails."""
1670 | # Setup
1671 | catalog_id = '123456789012'
1672 |
1673 | # Mock the Glue client to raise an exception
1674 | error_response = {
1675 | 'Error': {'Code': 'InternalServiceException', 'Message': 'Internal service error'}
1676 | }
1677 | mock_glue_client.get_connections.side_effect = ClientError(
1678 | error_response, 'GetConnections'
1679 | )
1680 |
1681 | # Call the method
1682 | result = await manager.list_connections(mock_ctx, catalog_id=catalog_id)
1683 |
1684 | # Verify the response
1685 | assert isinstance(result, ListConnectionsResponse)
1686 | assert result.isError is True
1687 | assert result.catalog_id == catalog_id
1688 | assert result.operation == 'list-connections'
1689 | assert len(result.content) == 1
1690 | assert 'Failed to list connections' in result.content[0].text
1691 | assert 'InternalServiceException' in result.content[0].text
1692 |
1693 | @pytest.mark.asyncio
1694 | async def test_list_connections_empty_result(self, manager, mock_ctx, mock_glue_client):
1695 | """Test that list_connections handles empty results correctly."""
1696 | # Setup
1697 | catalog_id = '123456789012'
1698 |
1699 | # Mock the get_connections response with empty list
1700 | mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1701 |
1702 | # Call the method
1703 | result = await manager.list_connections(mock_ctx, catalog_id=catalog_id)
1704 |
1705 | # Verify the response
1706 | assert isinstance(result, ListConnectionsResponse)
1707 | assert result.isError is False
1708 | assert result.catalog_id == catalog_id
1709 | assert result.connections == []
1710 | assert result.count == 0
1711 | assert result.operation == 'list-connections'
1712 | assert len(result.content) == 1
1713 | assert 'Successfully listed 0 connections' in result.content[0].text
1714 |
1715 | @pytest.mark.asyncio
1716 | async def test_create_partition_error(self, manager, mock_ctx, mock_glue_client):
1717 | """Test that create_partition returns an error response when the Glue API call fails."""
1718 | # Setup
1719 | database_name = 'test-db'
1720 | table_name = 'test-table'
1721 | partition_values = ['2023', '01', '01']
1722 | partition_input = {
1723 | 'StorageDescriptor': {
1724 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
1725 | }
1726 | }
1727 |
1728 | # Mock the AWS helper prepare_resource_tags method
1729 | with patch(
1730 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
1731 | return_value={'mcp:managed': 'true'},
1732 | ):
1733 | # Mock the Glue client to raise an exception
1734 | error_response = {
1735 | 'Error': {'Code': 'AlreadyExistsException', 'Message': 'Partition already exists'}
1736 | }
1737 | mock_glue_client.create_partition.side_effect = ClientError(
1738 | error_response, 'CreatePartition'
1739 | )
1740 |
1741 | # Call the method
1742 | result = await manager.create_partition(
1743 | mock_ctx,
1744 | database_name=database_name,
1745 | table_name=table_name,
1746 | partition_values=partition_values,
1747 | partition_input=partition_input,
1748 | )
1749 |
1750 | # Verify the response
1751 | assert isinstance(result, CreatePartitionResponse)
1752 | assert result.isError is True
1753 | assert result.database_name == database_name
1754 | assert result.table_name == table_name
1755 | assert result.partition_values == partition_values
1756 | assert result.operation == 'create-partition'
1757 | assert len(result.content) == 1
1758 | assert 'Failed to create partition' in result.content[0].text
1759 | assert 'AlreadyExistsException' in result.content[0].text
1760 |
1761 | @pytest.mark.asyncio
1762 | async def test_get_partition_error(self, manager, mock_ctx, mock_glue_client):
1763 | """Test that get_partition returns an error response when the Glue API call fails."""
1764 | # Setup
1765 | database_name = 'test-db'
1766 | table_name = 'test-table'
1767 | partition_values = ['2023', '01', '01']
1768 | catalog_id = '123456789012'
1769 |
1770 | # Mock the Glue client to raise an exception
1771 | error_response = {
1772 | 'Error': {'Code': 'EntityNotFoundException', 'Message': 'Partition not found'}
1773 | }
1774 | mock_glue_client.get_partition.side_effect = ClientError(error_response, 'GetPartition')
1775 |
1776 | # Call the method
1777 | result = await manager.get_partition(
1778 | mock_ctx,
1779 | database_name=database_name,
1780 | table_name=table_name,
1781 | partition_values=partition_values,
1782 | catalog_id=catalog_id,
1783 | )
1784 |
1785 | # Verify the response
1786 | assert isinstance(result, GetPartitionResponse)
1787 | assert result.isError is True
1788 | assert result.database_name == database_name
1789 | assert result.table_name == table_name
1790 | assert result.partition_values == partition_values
1791 | assert result.operation == 'get-partitionet' # Note: There's a typo in the original code
1792 | assert len(result.content) == 1
1793 | assert 'Failed to get partition' in result.content[0].text
1794 | assert 'EntityNotFoundException' in result.content[0].text
1795 |
1796 | @pytest.mark.asyncio
1797 | async def test_list_partitions_error(self, manager, mock_ctx, mock_glue_client):
1798 | """Test that list_partitions returns an error response when the Glue API call fails."""
1799 | # Setup
1800 | database_name = 'test-db'
1801 | table_name = 'test-table'
1802 |
1803 | # Mock the Glue client to raise an exception
1804 | error_response = {
1805 | 'Error': {'Code': 'InternalServiceException', 'Message': 'Internal service error'}
1806 | }
1807 | mock_glue_client.get_partitions.side_effect = ClientError(error_response, 'GetPartitions')
1808 |
1809 | # Call the method
1810 | result = await manager.list_partitions(
1811 | mock_ctx, database_name=database_name, table_name=table_name
1812 | )
1813 |
1814 | # Verify the response
1815 | assert isinstance(result, ListPartitionsResponse)
1816 | assert result.isError is True
1817 | assert result.database_name == database_name
1818 | assert result.table_name == table_name
1819 | assert result.operation == 'list-partitions'
1820 | assert len(result.content) == 1
1821 | assert 'Failed to list partitions' in result.content[0].text
1822 | assert 'InternalServiceException' in result.content[0].text
1823 |
1824 | @pytest.mark.asyncio
1825 | async def test_list_partitions_empty_result(self, manager, mock_ctx, mock_glue_client):
1826 | """Test that list_partitions handles empty results correctly."""
1827 | # Setup
1828 | database_name = 'test-db'
1829 | table_name = 'test-table'
1830 |
1831 | # Mock the get_partitions response with empty list
1832 | mock_glue_client.get_partitions.return_value = {'Partitions': []}
1833 |
1834 | # Call the method
1835 | result = await manager.list_partitions(
1836 | mock_ctx, database_name=database_name, table_name=table_name
1837 | )
1838 |
1839 | # Verify the response
1840 | assert isinstance(result, ListPartitionsResponse)
1841 | assert result.isError is False
1842 | assert result.database_name == database_name
1843 | assert result.table_name == table_name
1844 | assert result.partitions == []
1845 | assert result.count == 0
1846 | assert result.operation == 'list-partitions'
1847 | assert len(result.content) == 1
1848 | assert (
1849 | f'Successfully listed 0 partitions in table {database_name}.{table_name}'
1850 | in result.content[0].text
1851 | )
1852 |
1853 | @pytest.mark.asyncio
1854 | async def test_list_partitions_with_all_parameters(self, manager, mock_ctx, mock_glue_client):
1855 | """Test that list_partitions handles all optional parameters correctly."""
1856 | # Setup
1857 | database_name = 'test-db'
1858 | table_name = 'test-table'
1859 | max_results = 10
1860 | expression = "year='2023'"
1861 | catalog_id = '123456789012'
1862 | segment = {'SegmentNumber': 0, 'TotalSegments': 1}
1863 | exclude_column_schema = True
1864 | transaction_id = 'test-transaction-id'
1865 | query_as_of_time = '2023-01-01T00:00:00Z'
1866 |
1867 | # Mock the get_partitions response
1868 | mock_glue_client.get_partitions.return_value = {'Partitions': []}
1869 |
1870 | # Call the method
1871 | result = await manager.list_partitions(
1872 | mock_ctx,
1873 | database_name=database_name,
1874 | table_name=table_name,
1875 | max_results=max_results,
1876 | expression=expression,
1877 | catalog_id=catalog_id,
1878 | segment=segment,
1879 | exclude_column_schema=exclude_column_schema,
1880 | transaction_id=transaction_id,
1881 | query_as_of_time=query_as_of_time,
1882 | )
1883 |
1884 | # Verify that the Glue client was called with the correct parameters
1885 | mock_glue_client.get_partitions.assert_called_once_with(
1886 | DatabaseName=database_name,
1887 | TableName=table_name,
1888 | MaxResults=max_results,
1889 | Expression=expression,
1890 | CatalogId=catalog_id,
1891 | Segment=segment,
1892 | ExcludeColumnSchema='true',
1893 | TransactionId=transaction_id,
1894 | QueryAsOfTime=query_as_of_time,
1895 | )
1896 |
1897 | # Verify the response
1898 | assert isinstance(result, ListPartitionsResponse)
1899 | assert result.isError is False
1900 | assert result.database_name == database_name
1901 | assert result.table_name == table_name
1902 | assert result.operation == 'list-partitions'
1903 |
1904 | @pytest.mark.asyncio
1905 | async def test_create_catalog_error(self, manager, mock_ctx, mock_glue_client):
1906 | """Test that create_catalog returns an error response when the Glue API call fails."""
1907 | # Setup
1908 | catalog_name = 'test-catalog'
1909 | catalog_input = {'Description': 'Test catalog', 'Type': 'GLUE'}
1910 |
1911 | # Mock the AWS helper prepare_resource_tags method
1912 | with patch(
1913 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
1914 | return_value={'mcp:managed': 'true'},
1915 | ):
1916 | # Mock the Glue client to raise an exception
1917 | error_response = {
1918 | 'Error': {'Code': 'AlreadyExistsException', 'Message': 'Catalog already exists'}
1919 | }
1920 | mock_glue_client.create_catalog.side_effect = ClientError(
1921 | error_response, 'CreateCatalog'
1922 | )
1923 |
1924 | # Call the method
1925 | result = await manager.create_catalog(
1926 | mock_ctx, catalog_name=catalog_name, catalog_input=catalog_input
1927 | )
1928 |
1929 | # Verify the response
1930 | assert isinstance(result, CreateCatalogResponse)
1931 | assert result.isError is True
1932 | assert result.catalog_id == catalog_name
1933 | assert result.operation == 'create-catalog'
1934 | assert len(result.content) == 1
1935 | assert 'Failed to create catalog' in result.content[0].text
1936 | assert 'AlreadyExistsException' in result.content[0].text
1937 |
1938 | @pytest.mark.asyncio
1939 | async def test_get_catalog_error(self, manager, mock_ctx, mock_glue_client):
1940 | """Test that get_catalog returns an error response when the Glue API call fails."""
1941 | # Setup
1942 | catalog_id = 'test-catalog'
1943 |
1944 | # Mock the Glue client to raise an exception
1945 | error_response = {
1946 | 'Error': {'Code': 'EntityNotFoundException', 'Message': 'Catalog not found'}
1947 | }
1948 | mock_glue_client.get_catalog.side_effect = ClientError(error_response, 'GetCatalog')
1949 |
1950 | # Call the method
1951 | result = await manager.get_catalog(mock_ctx, catalog_id=catalog_id)
1952 |
1953 | # Verify the response
1954 | assert isinstance(result, GetCatalogResponse)
1955 | assert result.isError is True
1956 | assert result.catalog_id == catalog_id
1957 | assert result.operation == 'get-catalog'
1958 | assert len(result.content) == 1
1959 | assert 'Failed to get catalog' in result.content[0].text
1960 | assert 'EntityNotFoundException' in result.content[0].text
1961 |
1962 | @pytest.mark.asyncio
1963 | async def test_create_connection_with_empty_parameters(
1964 | self, manager, mock_ctx, mock_glue_client
1965 | ):
1966 | """Test that create_connection handles empty parameters correctly."""
1967 | # Setup
1968 | connection_name = 'test-connection'
1969 | connection_input = {
1970 | 'ConnectionType': 'JDBC',
1971 | 'ConnectionProperties': {
1972 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test',
1973 | },
1974 | }
1975 |
1976 | # Mock the AWS helper prepare_resource_tags method
1977 | with patch(
1978 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags',
1979 | return_value={'mcp:managed': 'true'},
1980 | ):
1981 | # Call the method
1982 | result = await manager.create_connection(
1983 | mock_ctx, connection_name=connection_name, connection_input=connection_input
1984 | )
1985 |
1986 | # Verify that the Glue client was called with the correct parameters
1987 | mock_glue_client.create_connection.assert_called_once()
1988 | call_args = mock_glue_client.create_connection.call_args[1]
1989 |
1990 | assert call_args['ConnectionInput']['Name'] == connection_name
1991 | assert call_args['ConnectionInput']['ConnectionType'] == 'JDBC'
1992 | assert (
1993 | call_args['ConnectionInput']['ConnectionProperties']['JDBC_CONNECTION_URL']
1994 | == 'jdbc:mysql://localhost:3306/test'
1995 | )
1996 |
1997 | # Verify the response
1998 | assert isinstance(result, CreateConnectionResponse)
1999 | assert result.isError is False
2000 | assert result.connection_name == connection_name
2001 | assert result.operation == 'create-connection'
2002 |
2003 | @pytest.mark.asyncio
2004 | async def test_update_connection_with_empty_parameters(
2005 | self, manager, mock_ctx, mock_glue_client
2006 | ):
2007 | """Test that update_connection handles empty parameters correctly."""
2008 | # Setup
2009 | connection_name = 'test-connection'
2010 | connection_input = {
2011 | 'ConnectionType': 'JDBC',
2012 | 'ConnectionProperties': {
2013 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test-updated',
2014 | },
2015 | }
2016 |
2017 | # Mock the get_connection response to indicate the connection is MCP managed
2018 | mock_glue_client.get_connection.return_value = {
2019 | 'Connection': {
2020 | 'Name': connection_name,
2021 | }
2022 | }
2023 |
2024 | # Mock the AWS helper is_resource_mcp_managed method
2025 | with (
2026 | patch(
2027 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
2028 | return_value=True,
2029 | ),
2030 | patch(
2031 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
2032 | return_value='us-east-1',
2033 | ),
2034 | patch(
2035 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
2036 | return_value='123456789012',
2037 | ),
2038 | ):
2039 | # Call the method
2040 | result = await manager.update_connection(
2041 | mock_ctx, connection_name=connection_name, connection_input=connection_input
2042 | )
2043 |
2044 | # Verify that the Glue client was called with the correct parameters
2045 | mock_glue_client.update_connection.assert_called_once()
2046 | call_args = mock_glue_client.update_connection.call_args[1]
2047 |
2048 | assert call_args['Name'] == connection_name
2049 | assert call_args['ConnectionInput']['Name'] == connection_name
2050 | assert call_args['ConnectionInput']['ConnectionType'] == 'JDBC'
2051 | assert (
2052 | call_args['ConnectionInput']['ConnectionProperties']['JDBC_CONNECTION_URL']
2053 | == 'jdbc:mysql://localhost:3306/test-updated'
2054 | )
2055 |
2056 | # Verify the response
2057 | assert isinstance(result, UpdateConnectionResponse)
2058 | assert result.isError is False
2059 | assert result.connection_name == connection_name
2060 | assert result.operation == 'update-connection'
2061 |
2062 | @pytest.mark.asyncio
2063 | async def test_update_connection_with_new_parameters(
2064 | self, manager, mock_ctx, mock_glue_client
2065 | ):
2066 | """Test that update_connection handles new parameters correctly."""
2067 | # Setup
2068 | connection_name = 'test-connection'
2069 | connection_input = {
2070 | 'ConnectionType': 'JDBC',
2071 | 'ConnectionProperties': {
2072 | 'JDBC_CONNECTION_URL': 'jdbc:mysql://localhost:3306/test-updated',
2073 | },
2074 | }
2075 |
2076 | # Mock the get_connection response to indicate the connection is MCP managed
2077 | mock_glue_client.get_connection.return_value = {
2078 | 'Connection': {
2079 | 'Name': connection_name,
2080 | }
2081 | }
2082 |
2083 | # Mock the AWS helper is_resource_mcp_managed method
2084 | with (
2085 | patch(
2086 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
2087 | return_value=True,
2088 | ),
2089 | patch(
2090 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
2091 | return_value='us-east-1',
2092 | ),
2093 | patch(
2094 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
2095 | return_value='123456789012',
2096 | ),
2097 | ):
2098 | # Call the method
2099 | result = await manager.update_connection(
2100 | mock_ctx, connection_name=connection_name, connection_input=connection_input
2101 | )
2102 |
2103 | # Verify that the Glue client was called with the correct parameters
2104 | mock_glue_client.update_connection.assert_called_once()
2105 | call_args = mock_glue_client.update_connection.call_args[1]
2106 |
2107 | assert call_args['Name'] == connection_name
2108 | assert call_args['ConnectionInput']['Name'] == connection_name
2109 | assert call_args['ConnectionInput']['ConnectionType'] == 'JDBC'
2110 | assert (
2111 | call_args['ConnectionInput']['ConnectionProperties']['JDBC_CONNECTION_URL']
2112 | == 'jdbc:mysql://localhost:3306/test-updated'
2113 | )
2114 |
2115 | # Verify the response
2116 | assert isinstance(result, UpdateConnectionResponse)
2117 | assert result.isError is False
2118 | assert result.connection_name == connection_name
2119 | assert result.operation == 'update-connection'
2120 |
2121 | @pytest.mark.asyncio
2122 | async def test_update_partition_with_new_parameters(self, manager, mock_ctx, mock_glue_client):
2123 | """Test that update_partition handles new parameters correctly."""
2124 | # Setup
2125 | database_name = 'test-db'
2126 | table_name = 'test-table'
2127 | partition_values = ['2023', '01', '01']
2128 | partition_input = {
2129 | 'StorageDescriptor': {
2130 | 'Location': 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
2131 | },
2132 | 'Parameters': {'new-param': 'new-value'},
2133 | }
2134 |
2135 | # Mock the get_partition response to indicate the partition is MCP managed
2136 | mock_glue_client.get_partition.return_value = {
2137 | 'Partition': {
2138 | 'Values': partition_values,
2139 | 'DatabaseName': database_name,
2140 | 'TableName': table_name,
2141 | 'Parameters': {'mcp:managed': 'true', 'mcp:ResourceType': 'GluePartition'},
2142 | }
2143 | }
2144 |
2145 | # Mock the AWS helper is_resource_mcp_managed method
2146 | with (
2147 | patch(
2148 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed',
2149 | return_value=True,
2150 | ),
2151 | patch(
2152 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region',
2153 | return_value='us-east-1',
2154 | ),
2155 | patch(
2156 | 'awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id',
2157 | return_value='123456789012',
2158 | ),
2159 | ):
2160 | # Call the method
2161 | result = await manager.update_partition(
2162 | mock_ctx,
2163 | database_name=database_name,
2164 | table_name=table_name,
2165 | partition_values=partition_values,
2166 | partition_input=partition_input,
2167 | )
2168 |
2169 | # Verify that the Glue client was called with the correct parameters
2170 | mock_glue_client.update_partition.assert_called_once()
2171 | call_args = mock_glue_client.update_partition.call_args[1]
2172 |
2173 | assert call_args['DatabaseName'] == database_name
2174 | assert call_args['TableName'] == table_name
2175 | assert call_args['PartitionValueList'] == partition_values
2176 | assert (
2177 | call_args['PartitionInput']['StorageDescriptor']['Location']
2178 | == 's3://test-bucket/test-db/test-table/year=2023/month=01/day=01/'
2179 | )
2180 |
2181 | # Verify that the MCP tags were preserved and new parameters were added
2182 | assert call_args['PartitionInput']['Parameters']['mcp:managed'] == 'true'
2183 | assert call_args['PartitionInput']['Parameters']['mcp:ResourceType'] == 'GluePartition'
2184 | assert call_args['PartitionInput']['Parameters']['new-param'] == 'new-value'
2185 |
2186 | # Verify the response
2187 | assert isinstance(result, UpdatePartitionResponse)
2188 | assert result.isError is False
2189 | assert result.database_name == database_name
2190 | assert result.table_name == table_name
2191 | assert result.partition_values == partition_values
2192 | assert result.operation == 'update-partition'
2193 |
```