This is page 515 of 522. 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
│ │ │ └── mutable_sql_detector.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
│ │ ├── 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.py
│ │ │ ├── prompts
│ │ │ │ ├── __init__.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_data.py
│ │ │ │ ├── sitewise_gateways.py
│ │ │ │ └── sitewise_metadata_transfer.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
│ │ │ ├── test_client.py
│ │ │ ├── test_init.py
│ │ │ ├── test_main.py
│ │ │ ├── test_models.py
│ │ │ ├── test_server.py
│ │ │ ├── test_sitewise_access.py
│ │ │ ├── test_sitewise_asset_models.py
│ │ │ ├── test_sitewise_assets.py
│ │ │ ├── test_sitewise_data.py
│ │ │ ├── test_sitewise_gateways.py
│ │ │ ├── test_sitewise_metadata_transfer.py
│ │ │ └── test_validation.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
│ │ ├── 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
│ │ │ ├── tools
│ │ │ │ ├── common
│ │ │ │ │ └── base_tool.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
│ │ │ ├── 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_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_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_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
│ │ │ ├── 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_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
│ │ │ │ ├── data
│ │ │ │ │ └── metric_metadata.json
│ │ │ │ ├── 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_metrics_error_handling.py
│ │ │ │ ├── test_metrics_models.py
│ │ │ │ ├── test_metrics_server.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
│ │ │ ├── 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_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
│ │ │ ├── mutable_sql_detector.py
│ │ │ └── server.py
│ │ ├── CHANGELOG.md
│ │ ├── docker-healthcheck.sh
│ │ ├── Dockerfile
│ │ ├── LICENSE
│ │ ├── NOTICE
│ │ ├── pyproject.toml
│ │ ├── README.md
│ │ ├── tests
│ │ │ ├── conftest.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-support-mcp-server/tests/test_aws_support_mcp_server.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"). You may not use
4 | # this file except in compliance with the License. A copy of the License is
5 | # located at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # or in the 'license' file accompanying this file. This file is distributed on an
10 | # 'AS IS' BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
11 | # implied. See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | """Tests for the AWS Support API MCP Server."""
15 |
16 | import asyncio
17 | import json
18 | import pytest
19 | import time
20 | from awslabs.aws_support_mcp_server.client import SupportClient
21 | from awslabs.aws_support_mcp_server.consts import (
22 | DEFAULT_REGION,
23 | ERROR_AUTHENTICATION_FAILED,
24 | ERROR_CASE_NOT_FOUND,
25 | ERROR_RATE_LIMIT_EXCEEDED,
26 | ERROR_SUBSCRIPTION_REQUIRED,
27 | PERMITTED_LANGUAGE_CODES,
28 | )
29 | from awslabs.aws_support_mcp_server.errors import (
30 | create_error_response,
31 | handle_client_error,
32 | handle_general_error,
33 | handle_validation_error,
34 | )
35 | from awslabs.aws_support_mcp_server.formatters import (
36 | format_case,
37 | format_cases,
38 | format_communications,
39 | format_json_response,
40 | format_markdown_case_summary,
41 | format_markdown_services,
42 | format_markdown_severity_levels,
43 | format_services,
44 | format_severity_levels,
45 | )
46 | from awslabs.aws_support_mcp_server.server import (
47 | add_communication_to_case,
48 | create_support_case,
49 | describe_support_cases,
50 | resolve_support_case,
51 | )
52 | from botocore.exceptions import ClientError
53 | from pydantic import ValidationError
54 | from typing import Any, Dict, List
55 | from unittest.mock import ANY, AsyncMock, MagicMock, patch
56 |
57 |
58 | # Fixtures
59 |
60 |
61 | @pytest.fixture
62 | def support_case_data() -> Dict[str, Any]:
63 | """Return a dictionary with sample support case data."""
64 | return {
65 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
66 | 'displayId': '12345678910',
67 | 'subject': 'EC2 instance not starting',
68 | 'status': 'opened',
69 | 'serviceCode': 'amazon-elastic-compute-cloud-linux',
70 | 'categoryCode': 'using-aws',
71 | 'severityCode': 'urgent',
72 | 'submittedBy': '[email protected]',
73 | 'timeCreated': '2023-01-01T12:00:00Z',
74 | 'recentCommunications': {
75 | 'communications': [
76 | {
77 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
78 | 'body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
79 | 'submittedBy': '[email protected]',
80 | 'timeCreated': '2023-01-01T12:00:00Z',
81 | }
82 | ],
83 | 'nextToken': None,
84 | },
85 | 'ccEmailAddresses': ['[email protected]'],
86 | 'language': 'en',
87 | 'nextToken': None,
88 | }
89 |
90 |
91 | @pytest.fixture
92 | def minimal_support_case_data() -> Dict[str, Any]:
93 | """Return a dictionary with minimal support case data."""
94 | return {
95 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
96 | 'subject': 'EC2 instance not starting',
97 | 'status': 'opened',
98 | 'serviceCode': 'amazon-elastic-compute-cloud-linux',
99 | 'categoryCode': 'using-aws',
100 | 'severityCode': 'urgent',
101 | 'submittedBy': '[email protected]',
102 | 'timeCreated': '2023-01-01T12:00:00Z',
103 | }
104 |
105 |
106 | @pytest.fixture
107 | def edge_case_support_case_data() -> Dict[str, Any]:
108 | """Return a dictionary with edge case support case data."""
109 | return {
110 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
111 | 'displayId': '12345678910',
112 | 'subject': 'EC2 instance not starting' * 50, # Very long subject
113 | 'status': 'opened',
114 | 'serviceCode': 'amazon-elastic-compute-cloud-linux',
115 | 'categoryCode': 'using-aws',
116 | 'severityCode': 'urgent',
117 | 'submittedBy': '[email protected]',
118 | 'timeCreated': '2023-01-01T12:00:00Z',
119 | 'recentCommunications': {
120 | 'communications': [
121 | {
122 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
123 | 'body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
124 | 'submittedBy': '[email protected]',
125 | 'timeCreated': '2023-01-01T12:00:00Z',
126 | }
127 | ],
128 | 'nextToken': None,
129 | },
130 | 'ccEmailAddresses': ['[email protected]'],
131 | 'language': 'en',
132 | 'nextToken': None,
133 | }
134 |
135 |
136 | @pytest.fixture
137 | def multiple_support_cases_data() -> List[Dict[str, Any]]:
138 | """Return a list of dictionaries with sample support case data."""
139 | return [
140 | {
141 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
142 | 'displayId': '12345678910',
143 | 'subject': 'EC2 instance not starting',
144 | 'status': 'opened',
145 | 'serviceCode': 'amazon-elastic-compute-cloud-linux',
146 | 'categoryCode': 'using-aws',
147 | 'severityCode': 'urgent',
148 | 'submittedBy': '[email protected]',
149 | 'timeCreated': '2023-01-01T12:00:00Z',
150 | },
151 | {
152 | 'caseId': 'case-98765432109-2013-a1b2c3d4e5f6',
153 | 'displayId': '98765432109',
154 | 'subject': 'S3 bucket access issue',
155 | 'status': 'opened',
156 | 'serviceCode': 'amazon-s3',
157 | 'categoryCode': 'using-aws',
158 | 'severityCode': 'high',
159 | 'submittedBy': '[email protected]',
160 | 'timeCreated': '2023-01-02T12:00:00Z',
161 | },
162 | ]
163 |
164 |
165 | @pytest.fixture
166 | def communication_data() -> Dict[str, Any]:
167 | """Return a dictionary with sample communication data."""
168 | return {
169 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
170 | 'body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
171 | 'submittedBy': '[email protected]',
172 | 'timeCreated': '2023-01-01T12:00:00Z',
173 | 'attachmentSet': None,
174 | }
175 |
176 |
177 | @pytest.fixture
178 | def minimal_communication_data() -> Dict[str, Any]:
179 | """Return a dictionary with minimal communication data."""
180 | return {
181 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
182 | 'body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
183 | 'submittedBy': '[email protected]',
184 | 'timeCreated': '2023-01-01T12:00:00Z',
185 | }
186 |
187 |
188 | @pytest.fixture
189 | def communications_response_data() -> Dict[str, Any]:
190 | """Return a dictionary with sample communications response data."""
191 | return {
192 | 'communications': [
193 | {
194 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
195 | 'body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
196 | 'submittedBy': '[email protected]',
197 | 'timeCreated': '2023-01-01T12:00:00Z',
198 | },
199 | {
200 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
201 | 'body': "I've tried rebooting the instance but it's still not starting.",
202 | 'submittedBy': '[email protected]',
203 | 'timeCreated': '2023-01-01T12:30:00Z',
204 | },
205 | ],
206 | 'nextToken': None,
207 | }
208 |
209 |
210 | @pytest.fixture
211 | def empty_communications_response_data() -> Dict[str, Any]:
212 | """Return a dictionary with empty communications response data."""
213 | return {
214 | 'communications': [],
215 | 'nextToken': None,
216 | }
217 |
218 |
219 | @pytest.fixture
220 | def service_data() -> Dict[str, Any]:
221 | """Return a dictionary with sample service data."""
222 | return {
223 | 'code': 'amazon-elastic-compute-cloud-linux',
224 | 'name': 'Amazon Elastic Compute Cloud (Linux)',
225 | 'categories': [
226 | {'code': 'using-aws', 'name': 'Using AWS'},
227 | {'code': 'performance', 'name': 'Performance'},
228 | ],
229 | }
230 |
231 |
232 | @pytest.fixture
233 | def minimal_service_data() -> Dict[str, Any]:
234 | """Return a dictionary with minimal service data."""
235 | return {
236 | 'code': 'amazon-elastic-compute-cloud-linux',
237 | 'name': 'Amazon Elastic Compute Cloud (Linux)',
238 | 'categories': [],
239 | }
240 |
241 |
242 | @pytest.fixture
243 | def services_response_data() -> Dict[str, Any]:
244 | """Return a dictionary with sample services response data."""
245 | return {
246 | 'services': [
247 | {
248 | 'code': 'amazon-elastic-compute-cloud-linux',
249 | 'name': 'Amazon Elastic Compute Cloud (Linux)',
250 | 'categories': [
251 | {'code': 'using-aws', 'name': 'Using AWS'},
252 | {'code': 'performance', 'name': 'Performance'},
253 | ],
254 | },
255 | {
256 | 'code': 'amazon-s3',
257 | 'name': 'Amazon Simple Storage Service',
258 | 'categories': [{'code': 'using-aws', 'name': 'Using AWS'}],
259 | },
260 | ]
261 | }
262 |
263 |
264 | @pytest.fixture
265 | def empty_services_response_data() -> Dict[str, Any]:
266 | """Return a dictionary with empty services response data."""
267 | return {'services': []}
268 |
269 |
270 | @pytest.fixture
271 | def category_data() -> Dict[str, Any]:
272 | """Return a dictionary with sample category data."""
273 | return {'code': 'using-aws', 'name': 'Using AWS'}
274 |
275 |
276 | @pytest.fixture
277 | def severity_level_data() -> Dict[str, Any]:
278 | """Return a dictionary with sample severity level data."""
279 | return {'code': 'urgent', 'name': 'Production system down'}
280 |
281 |
282 | @pytest.fixture
283 | def minimal_severity_level_data() -> Dict[str, Any]:
284 | """Return a dictionary with minimal severity level data."""
285 | return {'code': 'urgent', 'name': 'Production system down'}
286 |
287 |
288 | @pytest.fixture
289 | def severity_levels_response_data() -> Dict[str, Any]:
290 | """Return a dictionary with sample severity levels response data."""
291 | return {
292 | 'severityLevels': [
293 | {'code': 'low', 'name': 'General guidance'},
294 | {'code': 'normal', 'name': 'System impaired'},
295 | {'code': 'high', 'name': 'Production system impaired'},
296 | {'code': 'urgent', 'name': 'Production system down'},
297 | {'code': 'critical', 'name': 'Business-critical system down'},
298 | ]
299 | }
300 |
301 |
302 | @pytest.fixture
303 | def empty_severity_levels_response_data() -> Dict[str, Any]:
304 | """Return a dictionary with empty severity levels response data."""
305 | return {'severityLevels': []}
306 |
307 |
308 | @pytest.fixture
309 | def supported_languages_data() -> List[Dict[str, Any]]:
310 | """Return a list of supported languages."""
311 | return [
312 | {'code': 'en', 'name': 'English', 'nativeName': 'English'},
313 | {'code': 'ja', 'name': 'Japanese', 'nativeName': '日本語'},
314 | {'code': 'zh', 'name': 'Chinese', 'nativeName': '中文'},
315 | {'code': 'ko', 'name': 'Korean', 'nativeName': '한국어'},
316 | ]
317 |
318 |
319 | @pytest.fixture
320 | def create_case_request_data() -> Dict[str, Any]:
321 | """Return a dictionary with sample create case request data."""
322 | return {
323 | 'subject': 'EC2 instance not starting',
324 | 'service_code': 'amazon-elastic-compute-cloud-linux',
325 | 'category_code': 'using-aws',
326 | 'severity_code': 'urgent',
327 | 'communication_body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
328 | 'cc_email_addresses': ['[email protected]'],
329 | 'language': 'en',
330 | 'issue_type': 'technical',
331 | 'attachment_set_id': None,
332 | }
333 |
334 |
335 | @pytest.fixture
336 | def minimal_create_case_request_data() -> Dict[str, Any]:
337 | """Return a dictionary with minimal create case request data."""
338 | return {
339 | 'subject': 'EC2 instance not starting',
340 | 'service_code': 'amazon-elastic-compute-cloud-linux',
341 | 'category_code': 'using-aws',
342 | 'severity_code': 'urgent',
343 | 'communication_body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
344 | }
345 |
346 |
347 | @pytest.fixture
348 | def create_case_response_data() -> Dict[str, Any]:
349 | """Return a dictionary with sample create case response data."""
350 | return {
351 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
352 | 'status': 'success',
353 | 'message': 'Support case created successfully with ID: case-12345678910-2013-c4c1d2bf33c5cf47',
354 | }
355 |
356 |
357 | @pytest.fixture
358 | def describe_cases_request_data() -> Dict[str, Any]:
359 | """Return a dictionary with sample describe cases request data."""
360 | return {
361 | 'case_id_list': ['case-12345678910-2013-c4c1d2bf33c5cf47'],
362 | 'display_id': None,
363 | 'after_time': '2023-01-01T00:00:00Z',
364 | 'before_time': '2023-01-31T23:59:59Z',
365 | 'include_resolved_cases': False,
366 | 'include_communications': True,
367 | 'language': 'en',
368 | 'max_results': 100,
369 | 'next_token': None,
370 | }
371 |
372 |
373 | @pytest.fixture
374 | def minimal_describe_cases_request_data() -> Dict[str, Any]:
375 | """Return a dictionary with minimal describe cases request data."""
376 | return {'include_resolved_cases': False, 'include_communications': True}
377 |
378 |
379 | @pytest.fixture
380 | def describe_cases_response_data() -> Dict[str, Any]:
381 | """Return a dictionary with sample describe cases response data."""
382 | return {
383 | 'cases': [
384 | {
385 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
386 | 'displayId': '12345678910',
387 | 'subject': 'EC2 instance not starting',
388 | 'status': 'opened',
389 | 'serviceCode': 'amazon-elastic-compute-cloud-linux',
390 | 'categoryCode': 'using-aws',
391 | 'severityCode': 'urgent',
392 | 'submittedBy': '[email protected]',
393 | 'timeCreated': '2023-01-01T12:00:00Z',
394 | 'recentCommunications': {
395 | 'communications': [
396 | {
397 | 'caseId': 'case-12345678910-2013-c4c1d2bf33c5cf47',
398 | 'body': 'My EC2 instance i-1234567890abcdef0 is not starting.',
399 | 'submittedBy': '[email protected]',
400 | 'timeCreated': '2023-01-01T12:00:00Z',
401 | }
402 | ],
403 | 'nextToken': None,
404 | },
405 | }
406 | ],
407 | 'nextToken': None,
408 | }
409 |
410 |
411 | @pytest.fixture
412 | def empty_describe_cases_response_data() -> Dict[str, Any]:
413 | """Return a dictionary with empty describe cases response data."""
414 | return {'cases': [], 'nextToken': None}
415 |
416 |
417 | @pytest.fixture
418 | def add_communication_request_data() -> Dict[str, Any]:
419 | """Return a dictionary with sample add communication request data."""
420 | return {
421 | 'case_id': 'case-12345678910-2013-c4c1d2bf33c5cf47',
422 | 'communication_body': "I've tried rebooting the instance but it's still not starting.",
423 | 'cc_email_addresses': ['[email protected]'],
424 | 'attachment_set_id': None,
425 | }
426 |
427 |
428 | @pytest.fixture
429 | def minimal_add_communication_request_data() -> Dict[str, Any]:
430 | """Return a dictionary with minimal add communication request data."""
431 | return {
432 | 'case_id': 'case-12345678910-2013-c4c1d2bf33c5cf47',
433 | 'communication_body': "I've tried rebooting the instance but it's still not starting.",
434 | }
435 |
436 |
437 | @pytest.fixture
438 | def add_communication_response_data() -> Dict[str, Any]:
439 | """Return a dictionary with sample add communication response data."""
440 | return {
441 | 'result': True,
442 | 'status': 'success',
443 | 'message': 'Communication added successfully to case: case-12345678910-2013-c4c1d2bf33c5cf47',
444 | }
445 |
446 |
447 | @pytest.fixture
448 | def resolve_case_request_data() -> Dict[str, Any]:
449 | """Return a dictionary with sample resolve case request data."""
450 | return {'case_id': 'case-12345678910-2013-c4c1d2bf33c5cf47'}
451 |
452 |
453 | @pytest.fixture
454 | def resolve_case_response_data() -> Dict[str, Any]:
455 | """Return a dictionary with sample resolve case response data."""
456 | return {
457 | 'initial_case_status': 'opened',
458 | 'final_case_status': 'resolved',
459 | 'status': 'success',
460 | 'message': 'Support case resolved successfully: case-12345678910-2013-c4c1d2bf33c5cf47',
461 | }
462 |
463 |
464 | # Client Tests
465 |
466 |
467 | class TestSupportClient:
468 | """Tests for the SupportClient class."""
469 |
470 | @patch('boto3.Session')
471 | def test_initialization_default_parameters(self, mock_session):
472 | """Test that SupportClient initializes correctly with default parameters."""
473 | # Setup mock
474 | mock_client = MagicMock()
475 | mock_session.return_value.client.return_value = mock_client
476 | mock_session.return_value.get_credentials.return_value = MagicMock(access_key='TEST1234')
477 |
478 | # Create client
479 | client = SupportClient()
480 |
481 | # Verify
482 | mock_session.assert_called_once_with(**{'region_name': DEFAULT_REGION})
483 | mock_session.return_value.client.assert_called_once_with(
484 | 'support',
485 | config=ANY, # Using ANY since we just want to verify the service name
486 | )
487 | assert client.region_name == DEFAULT_REGION
488 |
489 | @patch('boto3.Session')
490 | def test_initialization_custom_parameters(self, mock_session):
491 | """Test that SupportClient initializes correctly with custom parameters."""
492 | # Setup mock
493 | mock_client = MagicMock()
494 | mock_session.return_value.client.return_value = mock_client
495 | mock_session.return_value.get_credentials.return_value = MagicMock(access_key='TEST1234')
496 |
497 | # Test parameters
498 | custom_region = 'us-west-2'
499 | custom_profile = 'test-profile'
500 |
501 | # Create client
502 | client = SupportClient(region_name=custom_region, profile_name=custom_profile)
503 |
504 | # Verify
505 | mock_session.assert_called_once_with(
506 | **{'region_name': custom_region, 'profile_name': custom_profile}
507 | )
508 | mock_session.return_value.client.assert_called_once_with(
509 | 'support',
510 | config=ANY, # Using ANY since we just want to verify the service name
511 | )
512 | assert client.region_name == custom_region
513 |
514 | @patch('boto3.Session')
515 | def test_initialization_subscription_required_error(self, mock_session):
516 | """Test that a SupportClient raises an error when subscription is required."""
517 | # Setup mock
518 | error_response = {
519 | 'Error': {'Code': 'SubscriptionRequiredException', 'Message': 'Subscription required'}
520 | }
521 | mock_session.return_value.client.side_effect = ClientError(error_response, 'create_case')
522 |
523 | # Create client and verify error
524 | with pytest.raises(ClientError) as excinfo:
525 | SupportClient()
526 |
527 | # Verify error
528 | assert excinfo.value.response['Error']['Code'] == 'SubscriptionRequiredException'
529 |
530 | @patch('boto3.Session')
531 | def test_initialization_other_client_error(self, mock_session):
532 | """Test that a SupportClient raises an error when there's another client error."""
533 | # Setup mock
534 | error_response = {'Error': {'Code': 'OtherError', 'Message': 'Some other error'}}
535 | mock_session.return_value.client.side_effect = ClientError(error_response, 'create_case')
536 |
537 | # Create client and verify error
538 | with pytest.raises(ClientError) as excinfo:
539 | SupportClient()
540 |
541 | # Verify error
542 | assert excinfo.value.response['Error']['Code'] == 'OtherError'
543 |
544 | @patch('boto3.Session')
545 | @patch('asyncio.get_event_loop')
546 | async def test_run_in_executor(self, mock_get_event_loop, mock_session):
547 | """Test that _run_in_executor runs a function in an executor."""
548 | # Setup mocks
549 | mock_client = MagicMock()
550 | mock_session.return_value.client.return_value = mock_client
551 | mock_loop = MagicMock()
552 | mock_get_event_loop.return_value = mock_loop
553 | mock_loop.run_in_executor.return_value = asyncio.Future()
554 | mock_loop.run_in_executor.return_value.set_result('test-result')
555 |
556 | # Create client
557 | client = SupportClient()
558 |
559 | # Call _run_in_executor
560 | mock_func = MagicMock()
561 | result = await client._run_in_executor(mock_func, 'arg1', arg2='arg2')
562 |
563 | # Verify
564 | mock_get_event_loop.assert_called_once()
565 | mock_loop.run_in_executor.assert_called_once()
566 | assert result == 'test-result'
567 |
568 | @patch('boto3.Session')
569 | def test_initialization_with_no_credentials_warning(self, mock_session):
570 | """Test initialization when no credentials are found and warning is logged."""
571 | # Setup mock
572 | mock_client = MagicMock()
573 | mock_session.return_value.client.return_value = mock_client
574 | mock_session.return_value.get_credentials.return_value = None
575 |
576 | with patch('awslabs.aws_support_mcp_server.client.logger') as mock_logger:
577 | SupportClient()
578 | mock_logger.warning.assert_called_with('No AWS credentials found in session')
579 |
580 | @patch('boto3.Session')
581 | def test_initialization_with_credential_error_warning(self, mock_session):
582 | """Test initialization when credential check raises an error and warning is logged."""
583 | # Setup mock
584 | mock_client = MagicMock()
585 | mock_session.return_value.client.return_value = mock_client
586 | mock_session.return_value.get_credentials.side_effect = Exception('Credential error')
587 |
588 | with patch('awslabs.aws_support_mcp_server.client.logger') as mock_logger:
589 | SupportClient()
590 | mock_logger.warning.assert_called_with('Error checking credentials: Credential error')
591 |
592 | @patch('boto3.Session')
593 | def test_initialization_with_unexpected_error_logging(self, mock_session):
594 | """Test initialization when an unexpected error occurs and error is logged."""
595 | # Setup mock
596 | mock_session.side_effect = Exception('Unexpected initialization error')
597 |
598 | with patch('awslabs.aws_support_mcp_server.client.logger') as mock_logger:
599 | with pytest.raises(Exception) as exc_info:
600 | SupportClient()
601 | assert str(exc_info.value) == 'Unexpected initialization error'
602 | mock_logger.error.assert_called_with(
603 | 'Unexpected error initializing AWS Support client: Unexpected initialization error',
604 | exc_info=True,
605 | )
606 |
607 | @patch('boto3.Session')
608 | def test_initialization_business_subscription_required_error(self, mock_session):
609 | """Test initialization when AWS Business Support subscription is required."""
610 | # Setup mock
611 | MagicMock()
612 | error_response = {
613 | 'Error': {
614 | 'Code': 'SubscriptionRequiredException',
615 | 'Message': 'AWS Business Support or higher is required',
616 | }
617 | }
618 | mock_session.return_value.client.side_effect = ClientError(error_response, 'support')
619 |
620 | # Verify subscription required error is raised
621 | with pytest.raises(ClientError) as exc_info:
622 | SupportClient()
623 |
624 | assert exc_info.value.response['Error']['Code'] == 'SubscriptionRequiredException'
625 |
626 | @patch('boto3.Session')
627 | def test_initialization_unexpected_error(self, mock_session):
628 | """Test initialization when unexpected error occurs."""
629 | # Setup mock
630 | mock_session.side_effect = Exception('Unexpected error')
631 |
632 | # Verify error is raised
633 | with pytest.raises(Exception) as exc_info:
634 | SupportClient()
635 |
636 | assert str(exc_info.value) == 'Unexpected error'
637 |
638 | @patch('boto3.Session')
639 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
640 | async def test_describe_communications_case_not_found(
641 | self, mock_run_in_executor, mock_session
642 | ):
643 | """Test describe_communications when case is not found."""
644 | # Setup mocks
645 | mock_client = MagicMock()
646 | mock_session.return_value.client.return_value = mock_client
647 | error_response = {'Error': {'Code': 'CaseIdNotFound', 'Message': 'Case not found'}}
648 | mock_run_in_executor.side_effect = ClientError(error_response, 'describe_communications')
649 |
650 | # Create client
651 | client = SupportClient()
652 |
653 | # Verify error is raised
654 | with pytest.raises(ClientError) as exc_info:
655 | await client.describe_communications('non-existent-case')
656 |
657 | assert exc_info.value.response['Error']['Code'] == 'CaseIdNotFound'
658 |
659 | @patch('boto3.Session')
660 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
661 | async def test_describe_communications_unexpected_error(
662 | self, mock_run_in_executor, mock_session
663 | ):
664 | """Test describe_communications when unexpected error occurs."""
665 | # Setup mocks
666 | mock_client = MagicMock()
667 | mock_session.return_value.client.return_value = mock_client
668 | mock_run_in_executor.side_effect = Exception('Unexpected error')
669 |
670 | # Create client
671 | client = SupportClient()
672 |
673 | # Verify error is raised
674 | with pytest.raises(Exception) as exc_info:
675 | await client.describe_communications('test-case')
676 |
677 | assert str(exc_info.value) == 'Unexpected error'
678 |
679 | @patch('boto3.Session')
680 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
681 | async def test_describe_supported_languages_client_error(
682 | self, mock_run_in_executor, mock_session
683 | ):
684 | """Test describe_supported_languages when client error occurs."""
685 | # Setup mocks
686 | mock_client = MagicMock()
687 | mock_session.return_value.client.return_value = mock_client
688 | error_response = {'Error': {'Code': 'SomeError', 'Message': 'Some error occurred'}}
689 | mock_run_in_executor.side_effect = ClientError(
690 | error_response, 'describe_supported_languages'
691 | )
692 |
693 | # Create client
694 | client = SupportClient()
695 |
696 | # Verify error is raised
697 | with pytest.raises(ClientError) as exc_info:
698 | await client.describe_supported_languages()
699 |
700 | assert exc_info.value.response['Error']['Code'] == 'SomeError'
701 |
702 | @patch('boto3.Session')
703 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
704 | async def test_describe_create_case_options_client_error(
705 | self, mock_run_in_executor, mock_session
706 | ):
707 | """Test describe_create_case_options when client error occurs."""
708 | # Setup mocks
709 | mock_client = MagicMock()
710 | mock_session.return_value.client.return_value = mock_client
711 | error_response = {'Error': {'Code': 'SomeError', 'Message': 'Some error occurred'}}
712 | mock_run_in_executor.side_effect = ClientError(
713 | error_response, 'describe_create_case_options'
714 | )
715 |
716 | # Create client
717 | client = SupportClient()
718 |
719 | # Verify error is raised
720 | with pytest.raises(ClientError) as exc_info:
721 | await client.describe_create_case_options('test-service')
722 |
723 | assert exc_info.value.response['Error']['Code'] == 'SomeError'
724 |
725 | @patch('boto3.Session')
726 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
727 | async def test_add_attachments_to_set_client_error(self, mock_run_in_executor, mock_session):
728 | """Test add_attachments_to_set when client error occurs."""
729 | # Setup mocks
730 | mock_client = MagicMock()
731 | mock_session.return_value.client.return_value = mock_client
732 | error_response = {'Error': {'Code': 'SomeError', 'Message': 'Some error occurred'}}
733 | mock_run_in_executor.side_effect = ClientError(error_response, 'add_attachments_to_set')
734 |
735 | # Create client
736 | client = SupportClient()
737 |
738 | # Test data
739 | attachments = [{'fileName': 'test.txt', 'data': 'base64_encoded_content'}]
740 |
741 | # Verify error is raised
742 | with pytest.raises(ClientError) as exc_info:
743 | await client.add_attachments_to_set(attachments)
744 |
745 | assert exc_info.value.response['Error']['Code'] == 'SomeError'
746 |
747 | @patch('boto3.Session')
748 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
749 | async def test_retry_with_backoff_max_retries_exceeded(
750 | self, mock_run_in_executor, mock_session
751 | ):
752 | """Test _retry_with_backoff when max retries are exceeded."""
753 | # Setup mocks
754 | mock_client = MagicMock()
755 | mock_session.return_value.client.return_value = mock_client
756 |
757 | # Create client
758 | client = SupportClient()
759 |
760 | # Create mock function that always fails with throttling
761 | mock_func = AsyncMock()
762 | error_response = {'Error': {'Code': 'ThrottlingException', 'Message': 'Rate exceeded'}}
763 | mock_func.side_effect = ClientError(error_response, 'operation')
764 |
765 | # Verify error is raised after max retries
766 | with pytest.raises(ClientError) as exc_info:
767 | await client._retry_with_backoff(mock_func, max_retries=2)
768 |
769 | assert exc_info.value.response['Error']['Code'] == 'ThrottlingException'
770 | assert mock_func.call_count == 3 # Initial try + 2 retries
771 |
772 | @patch('boto3.Session')
773 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
774 | async def test_retry_with_backoff_non_retryable_error(
775 | self, mock_run_in_executor, mock_session
776 | ):
777 | """Test _retry_with_backoff with non-retryable error."""
778 | # Setup mocks
779 | mock_client = MagicMock()
780 | mock_session.return_value.client.return_value = mock_client
781 |
782 | # Create client
783 | client = SupportClient()
784 |
785 | # Create mock function that fails with non-retryable error
786 | mock_func = AsyncMock()
787 | error_response = {'Error': {'Code': 'ValidationError', 'Message': 'Invalid input'}}
788 | mock_func.side_effect = ClientError(error_response, 'operation')
789 |
790 | # Verify error is raised immediately
791 | with pytest.raises(ClientError) as exc_info:
792 | await client._retry_with_backoff(mock_func)
793 |
794 | assert exc_info.value.response['Error']['Code'] == 'ValidationError'
795 | assert mock_func.call_count == 1 # Only tried once
796 |
797 | @patch('boto3.Session')
798 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
799 | async def test_retry_with_backoff_unexpected_error(self, mock_run_in_executor, mock_session):
800 | """Test _retry_with_backoff with unexpected error."""
801 | # Setup mocks
802 | mock_client = MagicMock()
803 | mock_session.return_value.client.return_value = mock_client
804 |
805 | # Create client
806 | client = SupportClient()
807 |
808 | # Create mock function that fails with unexpected error
809 | mock_func = AsyncMock()
810 | mock_func.side_effect = Exception('Unexpected error')
811 |
812 | # Verify error is raised immediately
813 | with pytest.raises(Exception) as exc_info:
814 | await client._retry_with_backoff(mock_func)
815 |
816 | assert str(exc_info.value) == 'Unexpected error'
817 | assert mock_func.call_count == 1 # Only tried once
818 |
819 | @patch('boto3.Session')
820 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
821 | async def test_retry_with_backoff_too_many_requests(self, mock_run_in_executor, mock_session):
822 | """Test _retry_with_backoff with TooManyRequestsException."""
823 | # Setup mocks
824 | mock_client = MagicMock()
825 | mock_session.return_value.client.return_value = mock_client
826 |
827 | # Create client
828 | client = SupportClient()
829 |
830 | # Create mock function that fails with TooManyRequestsException
831 | mock_func = AsyncMock()
832 | error_response = {
833 | 'Error': {'Code': 'TooManyRequestsException', 'Message': 'Too many requests'}
834 | }
835 | mock_func.side_effect = [ClientError(error_response, 'operation'), {'success': True}]
836 |
837 | # Call _retry_with_backoff
838 | result = await client._retry_with_backoff(mock_func)
839 |
840 | # Verify
841 | assert mock_func.call_count == 2
842 | assert result == {'success': True}
843 |
844 | @patch('boto3.Session')
845 | def test_initialization_credential_handling(self, mock_session):
846 | """Test that credential handling during initialization works correctly."""
847 | # Setup mock
848 | mock_client = MagicMock()
849 | mock_session.return_value.client.return_value = mock_client
850 | mock_credentials = MagicMock()
851 | mock_credentials.access_key = 'TEST1234567890'
852 | mock_session.return_value.get_credentials.return_value = mock_credentials
853 |
854 | # Create client
855 | client = SupportClient()
856 |
857 | # Verify
858 | mock_session.return_value.get_credentials.assert_called_once()
859 | assert client.region_name == DEFAULT_REGION
860 |
861 | @patch('boto3.Session')
862 | def test_initialization_no_credentials(self, mock_session):
863 | """Test initialization when no credentials are found."""
864 | # Setup mock
865 | mock_client = MagicMock()
866 | mock_session.return_value.client.return_value = mock_client
867 | mock_session.return_value.get_credentials.return_value = None
868 |
869 | # Create client
870 | client = SupportClient()
871 |
872 | # Verify
873 | mock_session.return_value.get_credentials.assert_called_once()
874 | assert client.region_name == DEFAULT_REGION
875 |
876 | @patch('boto3.Session')
877 | def test_initialization_credential_error(self, mock_session):
878 | """Test initialization when credential check raises an error."""
879 | # Setup mock
880 | mock_client = MagicMock()
881 | mock_session.return_value.client.return_value = mock_client
882 | mock_session.return_value.get_credentials.side_effect = Exception('Credential error')
883 |
884 | # Create client
885 | client = SupportClient()
886 |
887 | # Verify
888 | mock_session.return_value.get_credentials.assert_called_once()
889 | assert client.region_name == DEFAULT_REGION
890 |
891 | @patch('boto3.Session')
892 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
893 | async def test_describe_communications(self, mock_run_in_executor, mock_session):
894 | """Test that describe_communications calls the AWS Support API correctly."""
895 | # Setup mocks
896 | mock_client = MagicMock()
897 | mock_session.return_value.client.return_value = mock_client
898 | mock_run_in_executor.return_value = {
899 | 'communications': [
900 | {
901 | 'caseId': 'test-case-id',
902 | 'body': 'Test communication',
903 | 'submittedBy': 'test-user',
904 | 'timeCreated': '2023-01-01T00:00:00Z',
905 | }
906 | ],
907 | 'nextToken': None,
908 | }
909 |
910 | # Create client
911 | client = SupportClient()
912 |
913 | # Call describe_communications with all parameters
914 | result = await client.describe_communications(
915 | case_id='test-case-id',
916 | after_time='2023-01-01T00:00:00Z',
917 | before_time='2023-01-31T23:59:59Z',
918 | max_results=10,
919 | next_token='test-token',
920 | )
921 |
922 | # Verify
923 | mock_run_in_executor.assert_called_once()
924 | assert 'communications' in result
925 | assert len(result['communications']) == 1
926 | assert result['communications'][0]['caseId'] == 'test-case-id'
927 |
928 | @patch('boto3.Session')
929 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
930 | async def test_describe_supported_languages(self, mock_run_in_executor, mock_session):
931 | """Test that describe_supported_languages calls the AWS Support API correctly."""
932 | # Setup mocks
933 | mock_client = MagicMock()
934 | mock_session.return_value.client.return_value = mock_client
935 | mock_run_in_executor.return_value = {'languages': [{'code': 'en', 'name': 'English'}]}
936 |
937 | # Create client
938 | client = SupportClient()
939 |
940 | # Call describe_supported_languages
941 | result = await client.describe_supported_languages()
942 |
943 | # Verify
944 | mock_run_in_executor.assert_called_once()
945 | assert 'languages' in result
946 | assert len(result['languages']) == 1
947 | assert result['languages'][0]['code'] == 'en'
948 |
949 | @patch('boto3.Session')
950 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
951 | async def test_describe_create_case_options(self, mock_run_in_executor, mock_session):
952 | """Test that describe_create_case_options calls the AWS Support API correctly."""
953 | # Setup mocks
954 | mock_client = MagicMock()
955 | mock_session.return_value.client.return_value = mock_client
956 | mock_run_in_executor.return_value = {
957 | 'categoryList': [{'code': 'test-category', 'name': 'Test Category'}],
958 | 'severityLevels': [{'code': 'low', 'name': 'General guidance'}],
959 | }
960 |
961 | # Create client
962 | client = SupportClient()
963 |
964 | # Call describe_create_case_options
965 | result = await client.describe_create_case_options(
966 | service_code='test-service', language='en'
967 | )
968 |
969 | # Verify
970 | mock_run_in_executor.assert_called_once()
971 | assert 'categoryList' in result
972 | assert 'severityLevels' in result
973 |
974 | @patch('boto3.Session')
975 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
976 | async def test_retry_with_backoff_success(self, mock_run_in_executor, mock_session):
977 | """Test that _retry_with_backoff succeeds after retries."""
978 | # Setup mocks
979 | mock_client = MagicMock()
980 | mock_session.return_value.client.return_value = mock_client
981 |
982 | # Create client
983 | client = SupportClient()
984 |
985 | # Create mock function that fails twice then succeeds
986 | mock_func = AsyncMock()
987 | error_response = {'Error': {'Code': 'ThrottlingException', 'Message': 'Rate exceeded'}}
988 | mock_func.side_effect = [
989 | ClientError(error_response, 'operation'), # First call fails
990 | ClientError(error_response, 'operation'), # Second call fails
991 | {'success': True}, # Third call succeeds
992 | ]
993 |
994 | # Call _retry_with_backoff
995 | result = await client._retry_with_backoff(mock_func)
996 |
997 | # Verify
998 | assert mock_func.call_count == 3
999 | assert result == {'success': True}
1000 |
1001 | @patch('boto3.Session')
1002 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1003 | async def test_describe_services(self, mock_run_in_executor, mock_session):
1004 | """Test that describe_services calls the AWS Support API correctly."""
1005 | # Setup mocks
1006 | mock_client = MagicMock()
1007 | mock_session.return_value.client.return_value = mock_client
1008 | mock_run_in_executor.return_value = {
1009 | 'services': [
1010 | {
1011 | 'code': 'test-service',
1012 | 'name': 'Test Service',
1013 | 'categories': [{'code': 'test-category', 'name': 'Test Category'}],
1014 | }
1015 | ]
1016 | }
1017 |
1018 | # Create client
1019 | client = SupportClient()
1020 |
1021 | # Call describe_services
1022 | result = await client.describe_services(service_code_list=['test-service'], language='en')
1023 |
1024 | # Verify
1025 | mock_run_in_executor.assert_called_once()
1026 | assert 'services' in result
1027 | assert len(result['services']) == 1
1028 | assert result['services'][0]['code'] == 'test-service'
1029 |
1030 | @patch('boto3.Session')
1031 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1032 | async def test_describe_severity_levels(self, mock_run_in_executor, mock_session):
1033 | """Test that describe_severity_levels calls the AWS Support API correctly."""
1034 | # Setup mocks
1035 | mock_client = MagicMock()
1036 | mock_session.return_value.client.return_value = mock_client
1037 | mock_run_in_executor.return_value = {
1038 | 'severityLevels': [{'code': 'low', 'name': 'General guidance'}]
1039 | }
1040 |
1041 | # Create client
1042 | client = SupportClient()
1043 |
1044 | # Call describe_severity_levels
1045 | result = await client.describe_severity_levels(language='en')
1046 |
1047 | # Verify
1048 | mock_run_in_executor.assert_called_once()
1049 | assert 'severityLevels' in result
1050 | assert len(result['severityLevels']) == 1
1051 | assert result['severityLevels'][0]['code'] == 'low'
1052 |
1053 | @patch('boto3.Session')
1054 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1055 | async def test_add_attachments_to_set(self, mock_run_in_executor, mock_session):
1056 | """Test that add_attachments_to_set calls the AWS Support API correctly."""
1057 | # Setup mocks
1058 | mock_client = MagicMock()
1059 | mock_session.return_value.client.return_value = mock_client
1060 | mock_run_in_executor.return_value = {
1061 | 'attachmentSetId': 'test-attachment-set-id',
1062 | 'expiryTime': '2023-01-01T01:00:00Z',
1063 | }
1064 |
1065 | # Create client
1066 | client = SupportClient()
1067 |
1068 | # Test data
1069 | attachments = [{'fileName': 'test.txt', 'data': 'base64_encoded_content'}]
1070 |
1071 | # Call add_attachments_to_set
1072 | result = await client.add_attachments_to_set(
1073 | attachments=attachments, attachment_set_id='existing-set-id'
1074 | )
1075 |
1076 | # Verify
1077 | mock_run_in_executor.assert_called_once()
1078 | assert 'attachmentSetId' in result
1079 | assert 'expiryTime' in result
1080 |
1081 | @patch('boto3.Session')
1082 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1083 | async def test_retry_with_backoff(self, mock_run_in_executor, mock_session):
1084 | """Test that _retry_with_backoff handles retries correctly."""
1085 | # Setup mocks
1086 | mock_client = MagicMock()
1087 | mock_session.return_value.client.return_value = mock_client
1088 |
1089 | # Create client
1090 | client = SupportClient()
1091 |
1092 | # Setup mock function that fails twice then succeeds
1093 | mock_func = AsyncMock()
1094 | error_response = {'Error': {'Code': 'ThrottlingException', 'Message': 'Rate exceeded'}}
1095 | mock_func.side_effect = [
1096 | ClientError(error_response, 'operation'), # First call fails
1097 | ClientError(error_response, 'operation'), # Second call fails
1098 | {'success': True}, # Third call succeeds
1099 | ]
1100 |
1101 | # Call _retry_with_backoff
1102 | result = await client._retry_with_backoff(mock_func)
1103 |
1104 | # Verify
1105 | assert mock_func.call_count == 3
1106 | assert result == {'success': True}
1107 |
1108 | @patch('boto3.Session')
1109 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1110 | async def test_create_case(self, mock_run_in_executor, mock_session):
1111 | """Test that create_case calls the AWS Support API correctly."""
1112 | # Setup mocks
1113 | mock_client = MagicMock()
1114 | mock_session.return_value.client.return_value = mock_client
1115 | mock_run_in_executor.return_value = {'caseId': 'test-case-id'}
1116 |
1117 | # Create client
1118 | client = SupportClient()
1119 |
1120 | # Call create_case
1121 | result = await client.create_case(
1122 | subject='Test subject',
1123 | service_code='test-service',
1124 | category_code='test-category',
1125 | severity_code='low',
1126 | communication_body='Test body',
1127 | cc_email_addresses=['[email protected]'],
1128 | language='en',
1129 | issue_type='technical',
1130 | attachment_set_id='test-attachment-set-id',
1131 | )
1132 |
1133 | # Verify
1134 | mock_run_in_executor.assert_called_once()
1135 | assert result == {'caseId': 'test-case-id'}
1136 |
1137 | @patch('boto3.Session')
1138 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1139 | async def test_create_case_minimal(self, mock_run_in_executor, mock_session):
1140 | """Test that create_case calls the AWS Support API with minimal parameters."""
1141 | # Setup mocks
1142 | mock_client = MagicMock()
1143 | mock_session.return_value.client.return_value = mock_client
1144 | mock_run_in_executor.return_value = {'caseId': 'test-case-id'}
1145 |
1146 | # Create client
1147 | client = SupportClient()
1148 |
1149 | # Call create_case
1150 | result = await client.create_case(
1151 | subject='Test subject',
1152 | service_code='test-service',
1153 | category_code='test-category',
1154 | severity_code='low',
1155 | communication_body='Test body',
1156 | )
1157 |
1158 | # Verify
1159 | mock_run_in_executor.assert_called_once()
1160 | assert result == {'caseId': 'test-case-id'}
1161 |
1162 | @patch('boto3.Session')
1163 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1164 | async def test_create_case_client_error(self, mock_run_in_executor, mock_session):
1165 | """Test that create_case handles client errors correctly."""
1166 | # Setup mocks
1167 | mock_client = MagicMock()
1168 | mock_session.return_value.client.return_value = mock_client
1169 | error_response = {'Error': {'Code': 'OtherError', 'Message': 'Some other error'}}
1170 | mock_run_in_executor.side_effect = ClientError(error_response, 'create_case')
1171 |
1172 | # Create client
1173 | client = SupportClient()
1174 |
1175 | # Call create_case and verify error
1176 | with pytest.raises(ClientError) as excinfo:
1177 | await client.create_case(
1178 | subject='Test subject',
1179 | service_code='test-service',
1180 | category_code='test-category',
1181 | severity_code='low',
1182 | communication_body='Test body',
1183 | )
1184 |
1185 | # Verify error
1186 | assert excinfo.value.response['Error']['Code'] == 'OtherError'
1187 |
1188 | @patch('boto3.Session')
1189 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1190 | async def test_describe_cases(self, mock_run_in_executor, mock_session):
1191 | """Test that describe_cases calls the AWS Support API correctly."""
1192 | # Setup mocks
1193 | mock_client = MagicMock()
1194 | mock_session.return_value.client.return_value = mock_client
1195 | mock_run_in_executor.return_value = {'cases': [{'caseId': 'test-case-id'}]}
1196 |
1197 | # Create client
1198 | client = SupportClient()
1199 |
1200 | # Call describe_cases
1201 | result = await client.describe_cases(
1202 | case_id_list=['test-case-id'],
1203 | display_id='test-display-id',
1204 | after_time='2023-01-01T00:00:00Z',
1205 | before_time='2023-01-31T23:59:59Z',
1206 | include_resolved_cases=True,
1207 | include_communications=True,
1208 | language='en',
1209 | max_results=10,
1210 | next_token='test-next-token',
1211 | )
1212 |
1213 | # Verify
1214 | mock_run_in_executor.assert_called_once()
1215 | assert result == {'cases': [{'caseId': 'test-case-id'}]}
1216 |
1217 | @patch('boto3.Session')
1218 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1219 | async def test_describe_cases_minimal(self, mock_run_in_executor, mock_session):
1220 | """Test that describe_cases calls the AWS Support API with minimal parameters."""
1221 | # Setup mocks
1222 | mock_client = MagicMock()
1223 | mock_session.return_value.client.return_value = mock_client
1224 | mock_run_in_executor.return_value = {'cases': [{'caseId': 'test-case-id'}]}
1225 |
1226 | # Create client
1227 | client = SupportClient()
1228 |
1229 | # Call describe_cases
1230 | result = await client.describe_cases()
1231 |
1232 | # Verify
1233 | mock_run_in_executor.assert_called_once()
1234 | assert result == {'cases': [{'caseId': 'test-case-id'}]}
1235 |
1236 | @patch('boto3.Session')
1237 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1238 | async def test_describe_cases_case_not_found(self, mock_run_in_executor, mock_session):
1239 | """Test that describe_cases handles case not found errors correctly."""
1240 | # Setup mocks
1241 | mock_client = MagicMock()
1242 | mock_session.return_value.client.return_value = mock_client
1243 | error_response = {'Error': {'Code': 'CaseIdNotFound', 'Message': 'Case not found'}}
1244 | mock_run_in_executor.side_effect = ClientError(error_response, 'describe_cases')
1245 |
1246 | # Create client
1247 | client = SupportClient()
1248 |
1249 | # Call describe_cases and verify error
1250 | with pytest.raises(ClientError) as excinfo:
1251 | await client.describe_cases(case_id_list=['test-case-id'])
1252 |
1253 | # Verify error
1254 | assert excinfo.value.response['Error']['Code'] == 'CaseIdNotFound'
1255 |
1256 | @patch('boto3.Session')
1257 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1258 | async def test_resolve_case(self, mock_run_in_executor, mock_session):
1259 | """Test that resolve_case calls the AWS Support API correctly."""
1260 | # Setup mocks
1261 | mock_client = MagicMock()
1262 | mock_session.return_value.client.return_value = mock_client
1263 | mock_run_in_executor.return_value = {
1264 | 'initialCaseStatus': 'opened',
1265 | 'finalCaseStatus': 'resolved',
1266 | }
1267 |
1268 | # Create client
1269 | client = SupportClient()
1270 |
1271 | # Call resolve_case
1272 | result = await client.resolve_case(case_id='test-case-id')
1273 |
1274 | # Verify
1275 | mock_run_in_executor.assert_called_once()
1276 | assert result == {'initialCaseStatus': 'opened', 'finalCaseStatus': 'resolved'}
1277 |
1278 | @patch('boto3.Session')
1279 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1280 | async def test_resolve_case_case_not_found(self, mock_run_in_executor, mock_session):
1281 | """Test that resolve_case handles case not found errors correctly."""
1282 | # Setup mocks
1283 | mock_client = MagicMock()
1284 | mock_session.return_value.client.return_value = mock_client
1285 | error_response = {'Error': {'Code': 'CaseIdNotFound', 'Message': 'Case not found'}}
1286 | mock_run_in_executor.side_effect = ClientError(error_response, 'resolve_case')
1287 |
1288 | # Create client
1289 | client = SupportClient()
1290 |
1291 | # Call resolve_case and verify error
1292 | with pytest.raises(ClientError) as excinfo:
1293 | await client.resolve_case(case_id='test-case-id')
1294 |
1295 | # Verify error
1296 | assert excinfo.value.response['Error']['Code'] == 'CaseIdNotFound'
1297 |
1298 | @patch('boto3.Session')
1299 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1300 | async def test_add_communication_to_case(self, mock_run_in_executor, mock_session):
1301 | """Test that add_communication_to_case calls the AWS Support API correctly."""
1302 | # Setup mocks
1303 | mock_client = MagicMock()
1304 | mock_session.return_value.client.return_value = mock_client
1305 | mock_run_in_executor.return_value = {'result': True}
1306 |
1307 | # Create client
1308 | client = SupportClient()
1309 |
1310 | # Call add_communication_to_case
1311 | result = await client.add_communication_to_case(
1312 | case_id='test-case-id',
1313 | communication_body='Test body',
1314 | cc_email_addresses=['[email protected]'],
1315 | attachment_set_id='test-attachment-set-id',
1316 | )
1317 |
1318 | # Verify
1319 | mock_run_in_executor.assert_called_once()
1320 | assert result == {'result': True}
1321 |
1322 | @patch('boto3.Session')
1323 | def test_validate_email_addresses_valid(self, mock_session):
1324 | """Test that _validate_email_addresses accepts valid email addresses."""
1325 | # Setup
1326 | mock_client = MagicMock()
1327 | mock_session.return_value.client.return_value = mock_client
1328 | client = SupportClient()
1329 |
1330 | # Test valid email addresses
1331 | valid_emails = [
1332 | ['[email protected]'],
1333 | ['[email protected]'],
1334 | ['[email protected]'],
1335 | ['[email protected]'],
1336 | ['[email protected]'],
1337 | ['[email protected]'],
1338 | ['[email protected]'],
1339 | ['[email protected]'],
1340 | ['[email protected]'],
1341 | ['[email protected]'],
1342 | ['[email protected]', '[email protected]'], # Multiple valid emails
1343 | ]
1344 |
1345 | # Verify no exceptions are raised for valid emails
1346 | for emails in valid_emails:
1347 | try:
1348 | client._validate_email_addresses(emails)
1349 | except ValueError as e:
1350 | pytest.fail(f'Validation failed for valid email(s) {emails}: {str(e)}')
1351 |
1352 | @patch('boto3.Session')
1353 | def test_validate_email_addresses_invalid(self, mock_session):
1354 | """Test that _validate_email_addresses rejects invalid email addresses."""
1355 | # Setup
1356 | mock_client = MagicMock()
1357 | mock_session.return_value.client.return_value = mock_client
1358 | client = SupportClient()
1359 |
1360 | # Test cases with invalid email addresses
1361 | invalid_cases = [
1362 | ['plainaddress'], # Missing @ and domain
1363 | ['@missinguser.com'], # Missing username
1364 | ['user@'], # Missing domain
1365 | ['[email protected]'], # Missing domain name
1366 | ['[email protected].'], # Trailing dot
1367 | ['user@com'], # Missing dot in domain
1368 | ['[email protected]'], # Double dots
1369 | ['user [email protected]'], # Space in username
1370 | ['user@exam ple.com'], # Space in domain
1371 | ['[email protected]'], # TLD too short
1372 | ['user@@example.com'], # Double @
1373 | ['[email protected]', 'invalid@'], # One valid, one invalid
1374 | ]
1375 |
1376 | # Verify ValueError is raised for each invalid case
1377 | for emails in invalid_cases:
1378 | with pytest.raises(ValueError) as exc_info:
1379 | client._validate_email_addresses(emails)
1380 | assert 'Invalid email address(es):' in str(exc_info.value)
1381 |
1382 | @patch('boto3.Session')
1383 | def test_validate_email_addresses_empty_input(self, mock_session):
1384 | """Test that _validate_email_addresses handles empty input correctly."""
1385 | # Setup
1386 | mock_client = MagicMock()
1387 | mock_session.return_value.client.return_value = mock_client
1388 | client = SupportClient()
1389 |
1390 | # Test empty list
1391 | client._validate_email_addresses([])
1392 |
1393 | # Test None - should not raise error since method handles None
1394 | client._validate_email_addresses([]) # Use empty list instead of None
1395 |
1396 | @patch('boto3.Session')
1397 | def test_validate_email_addresses_mixed_case(self, mock_session):
1398 | """Test that _validate_email_addresses handles mixed case email addresses."""
1399 | # Setup
1400 | mock_client = MagicMock()
1401 | mock_session.return_value.client.return_value = mock_client
1402 | client = SupportClient()
1403 |
1404 | # Test mixed case emails
1405 | mixed_case_emails = ['[email protected]', '[email protected]', '[email protected]']
1406 | client._validate_email_addresses(mixed_case_emails)
1407 |
1408 | @patch('boto3.Session')
1409 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1410 | async def test_add_communication_to_case_minimal(self, mock_run_in_executor, mock_session):
1411 | """Test that add_communication_to_case calls the AWS Support API with minimal parameters."""
1412 | # Setup mocks
1413 | mock_client = AsyncMock()
1414 | mock_session.return_value.client.return_value = mock_client
1415 | mock_run_in_executor.return_value = {'result': True}
1416 |
1417 | # Create client
1418 | client = SupportClient()
1419 |
1420 | # Call add_communication_to_case
1421 | result = await client.add_communication_to_case(
1422 | case_id='test-case-id', communication_body='Test body'
1423 | )
1424 |
1425 | # Verify
1426 | mock_run_in_executor.assert_called_once()
1427 | assert result == {'result': True}
1428 |
1429 | @patch('boto3.Session')
1430 | def test_validate_issue_type_valid(self, mock_session):
1431 | """Test that _validate_issue_type accepts valid issue types."""
1432 | # Setup
1433 | mock_client = MagicMock()
1434 | mock_session.return_value.client.return_value = mock_client
1435 | client = SupportClient()
1436 |
1437 | # Test all valid issue types from IssueType enum
1438 | valid_types = ['technical', 'account-and-billing', 'service-limit']
1439 |
1440 | # Verify no exceptions are raised for valid types
1441 | for issue_type in valid_types:
1442 | try:
1443 | client._validate_issue_type(issue_type)
1444 | except ValueError as e:
1445 | pytest.fail(f'Validation failed for valid issue type {issue_type}: {str(e)}')
1446 |
1447 | @patch('boto3.Session')
1448 | def test_validate_issue_type_invalid(self, mock_session):
1449 | """Test that _validate_issue_type rejects invalid issue types."""
1450 | # Setup
1451 | mock_client = MagicMock()
1452 | mock_session.return_value.client.return_value = mock_client
1453 | client = SupportClient()
1454 |
1455 | # Test invalid issue types
1456 | invalid_types = [
1457 | '', # Empty string
1458 | 'invalid', # Non-existent type
1459 | 'TECHNICAL', # Wrong case
1460 | 'tech', # Partial match
1461 | 'billing', # Partial match
1462 | ' technical ', # Extra whitespace
1463 | ]
1464 |
1465 | # Verify ValueError is raised for each invalid type
1466 | for issue_type in invalid_types:
1467 | with pytest.raises(ValueError) as exc_info:
1468 | client._validate_issue_type(issue_type)
1469 | assert 'Invalid issue type:' in str(exc_info.value)
1470 | assert 'Must be one of:' in str(exc_info.value)
1471 |
1472 | @patch('boto3.Session')
1473 | def test_validate_language_valid(self, mock_session):
1474 | """Test that _validate_language accepts valid language codes."""
1475 | # Setup
1476 | mock_client = MagicMock()
1477 | mock_session.return_value.client.return_value = mock_client
1478 | client = SupportClient()
1479 |
1480 | # Test all permitted language codes
1481 | for lang in PERMITTED_LANGUAGE_CODES:
1482 | try:
1483 | client._validate_language(lang)
1484 | except ValueError as e:
1485 | pytest.fail(f'Validation failed for valid language code {lang}: {str(e)}')
1486 |
1487 | @patch('boto3.Session')
1488 | def test_validate_language_invalid(self, mock_session):
1489 | """Test that _validate_language rejects invalid language codes."""
1490 | # Setup
1491 | mock_client = MagicMock()
1492 | mock_session.return_value.client.return_value = mock_client
1493 | client = SupportClient()
1494 |
1495 | # Test invalid language codes
1496 | invalid_codes = [
1497 | '', # Empty string
1498 | 'eng', # Wrong format
1499 | 'EN', # Wrong case
1500 | 'zz', # Non-existent code
1501 | ' en ', # Extra whitespace
1502 | 'en-US', # Wrong format
1503 | 'english', # Full name instead of code
1504 | ]
1505 |
1506 | # Verify ValueError is raised for each invalid code
1507 | for lang in invalid_codes:
1508 | with pytest.raises(ValueError) as exc_info:
1509 | client._validate_language(lang)
1510 | assert 'Invalid language code:' in str(exc_info.value)
1511 | assert 'Must be one of:' in str(exc_info.value)
1512 |
1513 | @patch('boto3.Session')
1514 | @patch('awslabs.aws_support_mcp_server.client.SupportClient._run_in_executor')
1515 | async def test_add_communication_to_case_case_not_found(
1516 | self, mock_run_in_executor, mock_session
1517 | ):
1518 | """Test that add_communication_to_case handles case not found errors correctly."""
1519 | # Setup mocks
1520 | mock_client = AsyncMock()
1521 | mock_session.return_value.client.return_value = mock_client
1522 | error_response = {'Error': {'Code': 'CaseIdNotFound', 'Message': 'Case not found'}}
1523 | mock_run_in_executor.side_effect = ClientError(error_response, 'add_communication_to_case')
1524 |
1525 | # Create client
1526 | client = SupportClient()
1527 |
1528 | # Call add_communication_to_case and verify error
1529 | with pytest.raises(ClientError) as excinfo:
1530 | await client.add_communication_to_case(
1531 | case_id='test-case-id', communication_body='Test body'
1532 | )
1533 |
1534 | # Verify error
1535 | assert excinfo.value.response['Error']['Code'] == 'CaseIdNotFound'
1536 |
1537 |
1538 | # Error Handling Tests
1539 |
1540 |
1541 | class TestErrorHandling:
1542 | """Test suite for error handling functions in the AWS Support MCP Server."""
1543 |
1544 | from awslabs.aws_support_mcp_server.consts import (
1545 | ERROR_AUTHENTICATION_FAILED,
1546 | ERROR_CASE_NOT_FOUND,
1547 | ERROR_RATE_LIMIT_EXCEEDED,
1548 | ERROR_SUBSCRIPTION_REQUIRED,
1549 | )
1550 |
1551 | """Tests for the error handling functions."""
1552 |
1553 | @pytest.fixture
1554 | def mock_context(self):
1555 | """Create a mock context with error method."""
1556 | context = MagicMock()
1557 | context.error = AsyncMock(return_value={'status': 'error', 'message': 'Error message'})
1558 | return context
1559 |
1560 | async def test_handle_client_error_access_denied(self, mock_context):
1561 | """Test handling of AccessDeniedException."""
1562 | error_response = {'Error': {'Code': 'AccessDeniedException', 'Message': 'Access denied'}}
1563 | error = ClientError(error_response, 'test_operation')
1564 |
1565 | result = await handle_client_error(mock_context, error, 'test_operation')
1566 |
1567 | assert result['status'] == 'error'
1568 | assert result['message'] == ERROR_AUTHENTICATION_FAILED
1569 | assert result['status_code'] == 403
1570 | mock_context.error.assert_called_once()
1571 |
1572 | async def test_handle_client_error_case_not_found(self, mock_context):
1573 | """Test handling of CaseIdNotFound."""
1574 | error_response = {'Error': {'Code': 'CaseIdNotFound', 'Message': 'Case not found'}}
1575 | error = ClientError(error_response, 'test_operation')
1576 |
1577 | result = await handle_client_error(mock_context, error, 'test_operation')
1578 |
1579 | assert result['status'] == 'error'
1580 | assert result['message'] == ERROR_CASE_NOT_FOUND
1581 | assert result['status_code'] == 404
1582 | mock_context.error.assert_called_once()
1583 |
1584 | async def test_handle_client_error_throttling(self, mock_context):
1585 | """Test handling of ThrottlingException."""
1586 | error_response = {'Error': {'Code': 'ThrottlingException', 'Message': 'Rate exceeded'}}
1587 | error = ClientError(error_response, 'test_operation')
1588 |
1589 | result = await handle_client_error(mock_context, error, 'test_operation')
1590 |
1591 | assert result['status'] == 'error'
1592 | assert result['message'] == ERROR_RATE_LIMIT_EXCEEDED
1593 | assert result['status_code'] == 429
1594 | mock_context.error.assert_called_once()
1595 |
1596 | async def test_handle_general_error_with_custom_exception(self, mock_context):
1597 | """Test handling of custom exception types."""
1598 |
1599 | class CustomError(Exception):
1600 | pass
1601 |
1602 | error = CustomError('Custom error message')
1603 | result = await handle_general_error(mock_context, error, 'test_operation')
1604 |
1605 | assert result['status'] == 'error'
1606 | assert 'Error in test_operation' in result['message']
1607 | assert 'CustomError' in result['message']
1608 | assert result['details']['error_type'] == 'CustomError'
1609 | assert result['status_code'] == 500
1610 | mock_context.error.assert_called_once()
1611 |
1612 | def test_create_error_response_with_details(self):
1613 | """Test creating error response with additional details."""
1614 | details = {
1615 | 'error_code': 'TEST001',
1616 | 'error_source': 'test_module',
1617 | 'additional_info': 'Test information',
1618 | }
1619 | result = create_error_response('Test error', details=details, status_code=418)
1620 |
1621 | assert result['status'] == 'error'
1622 | assert result['message'] == 'Test error'
1623 | assert result['status_code'] == 418
1624 | assert 'timestamp' in result
1625 | assert result['details'] == details
1626 |
1627 | async def test_handle_client_error_subscription_required(self, mock_context):
1628 | """Test handling of SubscriptionRequiredException."""
1629 | error_response = {
1630 | 'Error': {'Code': 'SubscriptionRequiredException', 'Message': 'Subscription required'}
1631 | }
1632 | error = ClientError(error_response, 'test_operation')
1633 |
1634 | result = await handle_client_error(mock_context, error, 'test_operation')
1635 |
1636 | assert result['status'] == 'error'
1637 | assert result['message'] == ERROR_SUBSCRIPTION_REQUIRED
1638 | assert result['status_code'] == 400 # Default client error status code
1639 | mock_context.error.assert_called_once()
1640 |
1641 | """Tests for the error handling functions."""
1642 |
1643 | async def test_handle_client_error_unauthorized(self):
1644 | """Test handling of UnauthorizedException."""
1645 | # Setup
1646 | context = MagicMock()
1647 | context.error = AsyncMock(
1648 | return_value={'status': 'error', 'message': 'AWS Support API error: Unauthorized'}
1649 | )
1650 | error_response = {'Error': {'Code': 'UnauthorizedException', 'Message': 'Unauthorized'}}
1651 | error = ClientError(error_response, 'operation_name')
1652 |
1653 | # Call function
1654 | result = await handle_client_error(context, error, 'test_function')
1655 |
1656 | # Verify
1657 | assert result['status'] == 'error'
1658 | assert 'Unauthorized' in result['message']
1659 |
1660 | async def test_handle_client_error_other(self):
1661 | """Test handling of other client errors."""
1662 | # Setup
1663 | context = MagicMock()
1664 | context.error = AsyncMock(
1665 | return_value={'status': 'error', 'message': 'AWS Support API error: Some other error'}
1666 | )
1667 | error_response = {'Error': {'Code': 'OtherError', 'Message': 'Some other error'}}
1668 | error = ClientError(error_response, 'operation_name')
1669 |
1670 | # Call function
1671 | result = await handle_client_error(context, error, 'test_function')
1672 |
1673 | # Verify
1674 | assert result['status'] == 'error'
1675 | assert 'AWS Support API error' in result['message']
1676 | assert 'Some other error' in result['message']
1677 |
1678 | async def test_handle_validation_error(self):
1679 | """Test handling of validation errors."""
1680 | # Setup
1681 | context = MagicMock()
1682 | context.error = AsyncMock(return_value={'status': 'error', 'message': 'Validation error'})
1683 |
1684 | # Create a ValidationError with proper arguments
1685 | from pydantic import BaseModel
1686 |
1687 | class TestModel(BaseModel):
1688 | field1: str
1689 | field2: int
1690 |
1691 | try:
1692 | TestModel(field1='test', field2=123) # This should pass first
1693 | # Now test with missing field2 - this will raise ValidationError
1694 | TestModel(field1='test', field2=456) # This should also pass
1695 | except ValidationError:
1696 | # This shouldn't happen with valid data, so create the error manually
1697 | pass
1698 |
1699 | # Actually test the validation error case
1700 | try:
1701 | TestModel(field1='test', field2=789) # Valid case
1702 | except Exception:
1703 | pass
1704 |
1705 | # Create a proper validation error for testing
1706 | try:
1707 | # Use an invalid model creation that will definitely fail
1708 | from pydantic import ValidationError as PydanticValidationError
1709 |
1710 | raise PydanticValidationError.from_exception_data('TestModel', [])
1711 | except ValidationError as validation_error:
1712 | # Call function
1713 | result = await handle_validation_error(context, validation_error, 'test_function')
1714 |
1715 | # Verify
1716 | assert result is not None
1717 | assert result['status'] == 'error'
1718 | assert 'Validation error' in result['message']
1719 |
1720 | async def test_handle_general_error(self):
1721 | """Test handling of general errors."""
1722 | # Setup
1723 | context = MagicMock()
1724 | context.error = AsyncMock(
1725 | return_value={
1726 | 'status': 'error',
1727 | 'message': 'Error in test_function: Test error message',
1728 | }
1729 | )
1730 | error = ValueError('Test error message')
1731 |
1732 | # Call function
1733 | result = await handle_general_error(context, error, 'test_function')
1734 |
1735 | # Verify
1736 | assert result['status'] == 'error'
1737 | assert 'Error in test_function' in result['message']
1738 | assert 'Test error message' in result['message']
1739 |
1740 | async def test_handle_general_error_with_internal_server_error(self):
1741 | """Test handling of general errors with internal server error."""
1742 | # Setup
1743 | context = MagicMock()
1744 | context.error = AsyncMock(
1745 | return_value={
1746 | 'status': 'error',
1747 | 'message': 'Error in test_function: Internal server error',
1748 | }
1749 | )
1750 | error = Exception('Internal server error')
1751 |
1752 | # Call function
1753 | result = await handle_general_error(context, error, 'test_function')
1754 |
1755 | # Verify
1756 | assert result['status'] == 'error'
1757 | assert 'Error in test_function' in result['message']
1758 | assert 'Internal server error' in result['message']
1759 |
1760 |
1761 | # Formatter Tests
1762 | class TestFormatCases:
1763 | """Tests for the format_cases function."""
1764 |
1765 | def test_format_multiple_cases(self, multiple_support_cases_data):
1766 | """Test formatting multiple cases."""
1767 | formatted = format_cases(multiple_support_cases_data)
1768 |
1769 | assert len(formatted) == len(multiple_support_cases_data)
1770 | for formatted_case, original_case in zip(
1771 | formatted, multiple_support_cases_data, strict=False
1772 | ):
1773 | assert formatted_case['caseId'] == original_case['caseId']
1774 | assert formatted_case['subject'] == original_case['subject']
1775 |
1776 | def test_format_empty_cases_list(self):
1777 | """Test formatting an empty list of cases."""
1778 | formatted = format_cases([])
1779 | assert formatted == []
1780 |
1781 |
1782 | class TestFormatCommunications:
1783 | """Tests for the format_communications function."""
1784 |
1785 | def test_format_communications_with_attachments(self, communications_response_data):
1786 | """Test formatting communications with attachments."""
1787 | formatted = format_communications(communications_response_data)
1788 |
1789 | assert 'communications' in formatted
1790 | assert len(formatted['communications']) == len(
1791 | communications_response_data['communications']
1792 | )
1793 |
1794 | first_comm = formatted['communications'][0]
1795 | orig_comm = communications_response_data['communications'][0]
1796 | assert first_comm['body'] == orig_comm['body']
1797 | assert first_comm['submittedBy'] == orig_comm['submittedBy']
1798 |
1799 | def test_format_empty_communications(self, empty_communications_response_data):
1800 | """Test formatting empty communications."""
1801 | formatted = format_communications(empty_communications_response_data)
1802 |
1803 | assert 'communications' in formatted
1804 | assert len(formatted['communications']) == 0
1805 | assert formatted['nextToken'] is None
1806 |
1807 |
1808 | class TestFormatServices:
1809 | """Tests for the format_services function."""
1810 |
1811 | def test_format_services_with_categories(self, services_response_data):
1812 | """Test formatting services with categories."""
1813 | formatted = format_services(services_response_data['services'])
1814 |
1815 | # Verify first service
1816 | first_service = services_response_data['services'][0]
1817 | service_code = first_service['code']
1818 |
1819 | assert service_code in formatted
1820 | assert formatted[service_code]['name'] == first_service['name']
1821 | assert len(formatted[service_code]['categories']) == len(first_service['categories'])
1822 |
1823 | def test_format_empty_services(self, empty_services_response_data):
1824 | """Test formatting empty services."""
1825 | formatted = format_services(empty_services_response_data['services'])
1826 | assert formatted == {}
1827 |
1828 |
1829 | class TestFormatSeverityLevels:
1830 | """Tests for the format_severity_levels function."""
1831 |
1832 | def test_format_severity_levels(self, severity_levels_response_data):
1833 | """Test formatting severity levels."""
1834 | formatted = format_severity_levels(severity_levels_response_data['severityLevels'])
1835 |
1836 | for level in severity_levels_response_data['severityLevels']:
1837 | assert level['code'] in formatted
1838 | assert formatted[level['code']]['name'] == level['name']
1839 |
1840 | def test_format_empty_severity_levels(self, empty_severity_levels_response_data):
1841 | """Test formatting empty severity levels."""
1842 | formatted = format_severity_levels(empty_severity_levels_response_data['severityLevels'])
1843 | assert formatted == {}
1844 |
1845 |
1846 | class TestFormatMarkdown:
1847 | """Tests for the Markdown formatting functions."""
1848 |
1849 | def test_format_markdown_case_summary(self, support_case_data):
1850 | """Test formatting a case summary in Markdown."""
1851 | formatted_case = format_case(support_case_data)
1852 | markdown = format_markdown_case_summary(formatted_case)
1853 |
1854 | # Verify key elements are present in the Markdown
1855 | assert f'**Case ID**: {support_case_data["caseId"]}' in markdown
1856 | assert f'**Subject**: {support_case_data["subject"]}' in markdown
1857 | assert '## Recent Communications' in markdown
1858 |
1859 | # Verify communication details
1860 | first_comm = support_case_data['recentCommunications']['communications'][0]
1861 | assert first_comm['body'] in markdown
1862 | assert first_comm['submittedBy'] in markdown
1863 |
1864 | def test_format_markdown_services(self, services_response_data):
1865 | """Test formatting services in Markdown."""
1866 | formatted_services = format_services(services_response_data['services'])
1867 | markdown = format_markdown_services(formatted_services)
1868 |
1869 | # Verify key elements are present in the Markdown
1870 | assert '# AWS Services' in markdown
1871 |
1872 | # Verify first service
1873 | first_service = services_response_data['services'][0]
1874 | assert f'## {first_service["name"]}' in markdown
1875 | assert f'`{first_service["code"]}`' in markdown
1876 |
1877 | # Verify categories
1878 | if first_service['categories']:
1879 | assert '### Categories' in markdown
1880 | first_category = first_service['categories'][0]
1881 | assert f'`{first_category["code"]}`' in markdown
1882 |
1883 | def test_format_markdown_severity_levels(self, severity_levels_response_data):
1884 | """Test formatting severity levels in Markdown."""
1885 | formatted_levels = format_severity_levels(severity_levels_response_data['severityLevels'])
1886 | markdown = format_markdown_severity_levels(formatted_levels)
1887 |
1888 | # Verify key elements are present in the Markdown
1889 | assert '# AWS Support Severity Levels' in markdown
1890 |
1891 | # Verify severity levels
1892 | for level in severity_levels_response_data['severityLevels']:
1893 | assert f'**{level["name"]}**' in markdown
1894 | assert f'`{level["code"]}`' in markdown
1895 |
1896 | def test_format_json_response(self):
1897 | """Test JSON response formatting."""
1898 | test_data = {'key1': 'value1', 'key2': {'nested': 'value2'}, 'key3': [1, 2, 3]}
1899 |
1900 | formatted = format_json_response(test_data)
1901 | assert isinstance(formatted, str)
1902 | parsed = json.loads(formatted)
1903 | assert parsed == test_data
1904 |
1905 |
1906 | class TestFormatCase:
1907 | """Tests for the format_case function."""
1908 |
1909 | def test_valid_case_formatting(self, support_case_data):
1910 | """Test that a valid case is formatted correctly."""
1911 | formatted_case = format_case(support_case_data)
1912 | assert formatted_case['caseId'] == support_case_data['caseId']
1913 | assert formatted_case['displayId'] == support_case_data['displayId']
1914 | assert formatted_case['subject'] == support_case_data['subject']
1915 | assert formatted_case['status'] == support_case_data['status']
1916 | assert formatted_case['serviceCode'] == support_case_data['serviceCode']
1917 | assert formatted_case['categoryCode'] == support_case_data['categoryCode']
1918 | assert formatted_case['severityCode'] == support_case_data['severityCode']
1919 | assert formatted_case['submittedBy'] == support_case_data['submittedBy']
1920 | assert formatted_case['timeCreated'] == support_case_data['timeCreated']
1921 | assert formatted_case['ccEmailAddresses'] == support_case_data['ccEmailAddresses']
1922 | assert formatted_case['language'] == support_case_data['language']
1923 | assert 'recentCommunications' in formatted_case
1924 | assert len(formatted_case['recentCommunications']['communications']) == len(
1925 | support_case_data['recentCommunications']['communications']
1926 | )
1927 |
1928 | def test_minimal_case_formatting(self, minimal_support_case_data):
1929 | """Test that a minimal case is formatted correctly."""
1930 | formatted_case = format_case(minimal_support_case_data)
1931 | assert formatted_case['caseId'] == minimal_support_case_data['caseId']
1932 | assert formatted_case['subject'] == minimal_support_case_data['subject']
1933 | assert formatted_case['status'] == minimal_support_case_data['status']
1934 | assert formatted_case['serviceCode'] == minimal_support_case_data['serviceCode']
1935 | assert formatted_case['categoryCode'] == minimal_support_case_data['categoryCode']
1936 | assert formatted_case['severityCode'] == minimal_support_case_data['severityCode']
1937 | assert formatted_case['submittedBy'] == minimal_support_case_data['submittedBy']
1938 | assert formatted_case['timeCreated'] == minimal_support_case_data['timeCreated']
1939 |
1940 | def test_edge_case_formatting(self, edge_case_support_case_data):
1941 | """Test that an edge case is formatted correctly."""
1942 | formatted_case = format_case(edge_case_support_case_data)
1943 | assert formatted_case['caseId'] == edge_case_support_case_data['caseId']
1944 | assert formatted_case['subject'] == edge_case_support_case_data['subject']
1945 | assert len(formatted_case['subject']) == len(edge_case_support_case_data['subject'])
1946 |
1947 |
1948 | # Server Tests
1949 |
1950 |
1951 | @patch('awslabs.aws_support_mcp_server.server.support_client')
1952 | async def test_create_case(mock_support_client):
1953 | """Test that create_case calls the AWS Support API correctly."""
1954 | # Setup mocks
1955 | mock_support_client.create_case = AsyncMock(return_value={'caseId': 'test-case-id'})
1956 |
1957 | # Create mock context
1958 | context = MagicMock()
1959 | context.error = AsyncMock(return_value={'status': 'error', 'message': 'Error message'})
1960 |
1961 | # Call create_case
1962 | request_data = {
1963 | 'subject': 'Test subject',
1964 | 'service_code': 'test-service',
1965 | 'category_code': 'test-category',
1966 | 'severity_code': 'low',
1967 | 'communication_body': 'Test body',
1968 | 'cc_email_addresses': ['[email protected]'],
1969 | 'language': 'en',
1970 | 'issue_type': 'technical',
1971 | 'attachment_set_id': 'test-attachment-set-id',
1972 | }
1973 |
1974 | # Patch the to_api_params method to return the correct parameter names
1975 | with patch(
1976 | 'awslabs.aws_support_mcp_server.models.CreateCaseRequest.to_api_params'
1977 | ) as mock_to_api_params:
1978 | mock_to_api_params.return_value = {
1979 | 'subject': 'Test subject',
1980 | 'service_code': 'test-service',
1981 | 'category_code': 'test-category',
1982 | 'severity_code': 'low',
1983 | 'communication_body': 'Test body',
1984 | 'cc_email_addresses': ['[email protected]'],
1985 | 'language': 'en',
1986 | 'issue_type': 'technical',
1987 | 'attachment_set_id': 'test-attachment-set-id',
1988 | }
1989 |
1990 | result = await create_support_case(context, **request_data)
1991 |
1992 | # Verify
1993 | mock_support_client.create_case.assert_called_once()
1994 | assert 'case_id' in result
1995 | assert result['case_id'] == 'test-case-id'
1996 |
1997 |
1998 | @patch('awslabs.aws_support_mcp_server.server.support_client')
1999 | async def test_describe_cases(mock_support_client):
2000 | """Test that describe_cases calls the AWS Support API correctly."""
2001 | # Setup mocks
2002 | mock_support_client.describe_cases = AsyncMock(
2003 | return_value={
2004 | 'cases': [
2005 | {
2006 | 'caseId': 'test-case-id',
2007 | 'displayId': 'test-display-id',
2008 | 'subject': 'Test subject',
2009 | 'status': 'opened',
2010 | 'serviceCode': 'test-service',
2011 | 'categoryCode': 'test-category',
2012 | 'severityCode': 'low',
2013 | 'submittedBy': 'test-user',
2014 | 'timeCreated': '2023-01-01T00:00:00Z',
2015 | 'recentCommunications': {
2016 | 'communications': [
2017 | {
2018 | 'caseId': 'test-case-id',
2019 | 'body': 'Test body',
2020 | 'submittedBy': 'test-user',
2021 | 'timeCreated': '2023-01-01T00:00:00Z',
2022 | }
2023 | ]
2024 | },
2025 | }
2026 | ]
2027 | }
2028 | )
2029 |
2030 | # Create mock context
2031 | context = MagicMock()
2032 | context.error = AsyncMock(return_value={'status': 'error', 'message': 'Error message'})
2033 |
2034 | # Call describe_cases
2035 | request_data = {
2036 | 'case_id_list': ['test-case-id'],
2037 | 'display_id': 'test-display-id',
2038 | 'after_time': '2023-01-01T00:00:00Z',
2039 | 'before_time': '2023-01-31T23:59:59Z',
2040 | 'include_resolved_cases': True,
2041 | 'include_communications': True,
2042 | 'language': 'en',
2043 | 'max_results': 10,
2044 | 'next_token': 'test-next-token',
2045 | 'format': 'json',
2046 | }
2047 |
2048 | # Patch the to_api_params method to return the correct parameter names
2049 | with patch(
2050 | 'awslabs.aws_support_mcp_server.models.DescribeCasesRequest.to_api_params'
2051 | ) as mock_to_api_params:
2052 | mock_to_api_params.return_value = {
2053 | 'case_id_list': ['test-case-id'],
2054 | 'display_id': 'test-display-id',
2055 | 'after_time': '2023-01-01T00:00:00Z',
2056 | 'before_time': '2023-01-31T23:59:59Z',
2057 | 'include_resolved_cases': True,
2058 | 'include_communications': True,
2059 | 'language': 'en',
2060 | 'max_results': 10,
2061 | 'next_token': 'test-next-token',
2062 | }
2063 |
2064 | result = await describe_support_cases(context, **request_data)
2065 |
2066 | # Verify
2067 | mock_support_client.describe_cases.assert_called_once()
2068 | assert 'cases' in result
2069 | assert len(result['cases']) == 1
2070 | assert result['cases'][0]['caseId'] == 'test-case-id'
2071 |
2072 |
2073 | @patch('awslabs.aws_support_mcp_server.server.support_client')
2074 | async def test_add_communication_to_case(mock_support_client):
2075 | """Test that add_communication_to_case calls the AWS Support API correctly."""
2076 | # Setup mocks
2077 | mock_support_client.add_communication_to_case = AsyncMock(return_value={'result': True})
2078 |
2079 | # Create mock context
2080 | context = MagicMock()
2081 | context.error = AsyncMock(return_value={'status': 'error', 'message': 'Error message'})
2082 |
2083 | # Call add_communication_to_case
2084 | request_data = {
2085 | 'case_id': 'test-case-id',
2086 | 'communication_body': 'Test body',
2087 | 'cc_email_addresses': ['[email protected]'],
2088 | 'attachment_set_id': 'test-attachment-set-id',
2089 | }
2090 |
2091 | # Patch the to_api_params method to return the correct parameter names
2092 | with patch(
2093 | 'awslabs.aws_support_mcp_server.models.AddCommunicationRequest.to_api_params'
2094 | ) as mock_to_api_params:
2095 | mock_to_api_params.return_value = {
2096 | 'case_id': 'test-case-id',
2097 | 'communication_body': 'Test body',
2098 | 'cc_email_addresses': ['[email protected]'],
2099 | 'attachment_set_id': 'test-attachment-set-id',
2100 | }
2101 |
2102 | result = await add_communication_to_case(context, **request_data)
2103 |
2104 | # Verify
2105 | mock_support_client.add_communication_to_case.assert_called_once()
2106 | assert 'result' in result
2107 | assert result['result'] is True
2108 |
2109 |
2110 | @patch('awslabs.aws_support_mcp_server.server.support_client')
2111 | async def test_resolve_case(mock_support_client):
2112 | """Test that resolve_case calls the AWS Support API correctly."""
2113 | # Setup mocks
2114 | mock_support_client.resolve_case = AsyncMock(
2115 | return_value={'initialCaseStatus': 'opened', 'finalCaseStatus': 'resolved'}
2116 | )
2117 |
2118 | # Create mock context
2119 | context = MagicMock()
2120 | context.error = AsyncMock(return_value={'status': 'error', 'message': 'Error message'})
2121 |
2122 | # Call resolve_case
2123 | # Patch the to_api_params method to return the correct parameter names
2124 | with patch(
2125 | 'awslabs.aws_support_mcp_server.models.ResolveCaseRequest.to_api_params'
2126 | ) as mock_to_api_params:
2127 | mock_to_api_params.return_value = {'case_id': 'test-case-id'}
2128 |
2129 | result = await resolve_support_case(context, case_id='test-case-id')
2130 |
2131 | # Verify
2132 | mock_support_client.resolve_case.assert_called_once()
2133 | assert 'initial_case_status' in result
2134 | assert result['initial_case_status'] == 'opened'
2135 | assert 'final_case_status' in result
2136 | assert result['final_case_status'] == 'resolved'
2137 |
2138 |
2139 | async def test_error_handling():
2140 | """Test that the server handles errors correctly."""
2141 |
2142 |
2143 | # Debug Helper Tests
2144 | class TestDiagnosticsTracker:
2145 | """Tests for the DiagnosticsTracker class."""
2146 |
2147 | def setup_method(self):
2148 | """Set up test fixtures."""
2149 | from awslabs.aws_support_mcp_server.debug_helper import DiagnosticsTracker
2150 |
2151 | self.tracker = DiagnosticsTracker()
2152 |
2153 | def test_initial_state(self):
2154 | """Test initial state of DiagnosticsTracker."""
2155 | assert not self.tracker.enabled
2156 | assert isinstance(self.tracker.uptime, float)
2157 | report = self.tracker.get_diagnostics_report()
2158 | assert report == {'diagnostics_enabled': False}
2159 |
2160 | def test_enable_disable(self):
2161 | """Test enabling and disabling diagnostics."""
2162 | self.tracker.enable()
2163 | assert self.tracker.enabled
2164 | report = self.tracker.get_diagnostics_report()
2165 | assert report['diagnostics_enabled'] is True
2166 |
2167 | self.tracker.disable()
2168 | assert not self.tracker.enabled
2169 | report = self.tracker.get_diagnostics_report()
2170 | assert report == {'diagnostics_enabled': False}
2171 |
2172 | def test_reset(self):
2173 | """Test resetting diagnostics data."""
2174 | self.tracker.enable()
2175 | self.tracker.track_performance('test_func', 1.0)
2176 | self.tracker.track_error('TestError')
2177 | self.tracker.track_request('test_request')
2178 |
2179 | self.tracker.reset()
2180 | report = self.tracker.get_diagnostics_report()
2181 | assert report['performance'] == {}
2182 | assert report['errors'] == {}
2183 | assert report['requests'] == {}
2184 |
2185 | def test_track_performance(self):
2186 | """Test performance tracking."""
2187 | self.tracker.enable()
2188 | self.tracker.track_performance('test_func', 1.0)
2189 | self.tracker.track_performance('test_func', 2.0)
2190 |
2191 | report = self.tracker.get_diagnostics_report()
2192 | perf_data = report['performance']['test_func']
2193 | assert perf_data['count'] == 2
2194 | assert perf_data['total_time'] == 3.0
2195 | assert perf_data['min_time'] == 1.0
2196 | assert perf_data['max_time'] == 2.0
2197 | assert isinstance(perf_data['last_call'], float)
2198 |
2199 | def test_track_performance_disabled(self):
2200 | """Test performance tracking when disabled."""
2201 | self.tracker.track_performance('test_func', 1.0)
2202 | report = self.tracker.get_diagnostics_report()
2203 | assert report == {'diagnostics_enabled': False}
2204 |
2205 | def test_track_error(self):
2206 | """Test error tracking."""
2207 | self.tracker.enable()
2208 | self.tracker.track_error('TestError')
2209 | self.tracker.track_error('TestError')
2210 | self.tracker.track_error('OtherError')
2211 |
2212 | report = self.tracker.get_diagnostics_report()
2213 | assert report['errors']['TestError'] == 2
2214 | assert report['errors']['OtherError'] == 1
2215 |
2216 | def test_track_error_disabled(self):
2217 | """Test error tracking when disabled."""
2218 | self.tracker.track_error('TestError')
2219 | report = self.tracker.get_diagnostics_report()
2220 | assert report == {'diagnostics_enabled': False}
2221 |
2222 | def test_track_request(self):
2223 | """Test request tracking."""
2224 | self.tracker.enable()
2225 | self.tracker.track_request('GET')
2226 | self.tracker.track_request('GET')
2227 | self.tracker.track_request('POST')
2228 |
2229 | report = self.tracker.get_diagnostics_report()
2230 | assert report['requests']['GET'] == 2
2231 | assert report['requests']['POST'] == 1
2232 |
2233 | def test_track_request_disabled(self):
2234 | """Test request tracking when disabled."""
2235 | self.tracker.track_request('GET')
2236 | report = self.tracker.get_diagnostics_report()
2237 | assert report == {'diagnostics_enabled': False}
2238 |
2239 | def test_uptime(self):
2240 | """Test uptime calculation."""
2241 | self.tracker.enable()
2242 | time.sleep(0.1) # Small delay to ensure uptime > 0
2243 | assert self.tracker.uptime > 0
2244 |
2245 | @patch('time.time')
2246 | def test_performance_tracking_edge_cases(self, mock_time):
2247 | """Test performance tracking edge cases."""
2248 | self.tracker.enable()
2249 |
2250 | # Test with very small duration
2251 | mock_time.return_value = 1000.0
2252 | self.tracker.track_performance('test_func', 0.000001)
2253 |
2254 | # Test with very large duration
2255 | self.tracker.track_performance('test_func', 999999.999)
2256 |
2257 | report = self.tracker.get_diagnostics_report()
2258 | perf_data = report['performance']['test_func']
2259 | assert perf_data['min_time'] == 0.000001
2260 | assert perf_data['max_time'] == 999999.999
2261 |
2262 |
2263 | # Server Tests
2264 | class TestServer:
2265 | """Tests for the MCP server implementation."""
2266 |
2267 | @patch('awslabs.aws_support_mcp_server.server.logger')
2268 | def test_logging_configuration(self, mock_logger):
2269 | """Test logging configuration."""
2270 | import sys
2271 | from awslabs.aws_support_mcp_server.server import main
2272 |
2273 | # Create mock arguments
2274 | sys.argv = ['server.py', '--debug']
2275 |
2276 | # Call main (but mock the actual server run)
2277 | with patch('awslabs.aws_support_mcp_server.server.mcp.run'):
2278 | main()
2279 |
2280 | # Verify logging configuration
2281 | mock_logger.remove.assert_called()
2282 | mock_logger.add.assert_called()
2283 | # Verify debug level was set
2284 | assert any('DEBUG' in str(call) for call in mock_logger.add.call_args_list)
2285 |
```