This is page 509 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/billing-cost-management-mcp-server/tests/tools/test_aws_bcm_pricing_calculator_tools.py:
--------------------------------------------------------------------------------
```python
1 | """Tests for BCM Pricing Calculator Tools.
2 |
3 | This module contains comprehensive tests for all methods in the BCM Pricing Calculator Tools,
4 | ensuring complete code coverage and proper error handling.
5 | """
6 |
7 | import pytest
8 | from awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools import (
9 | PREFERENCES_NOT_CONFIGURED_ERROR,
10 | bcm_pricing_calc_core,
11 | bcm_pricing_calculator_server,
12 | format_usage_item_response,
13 | format_workload_estimate_response,
14 | get_preferences,
15 | get_workload_estimate,
16 | list_workload_estimate_usage,
17 | list_workload_estimates,
18 | )
19 | from botocore.exceptions import BotoCoreError, ClientError
20 | from datetime import datetime
21 | from fastmcp import Context
22 | from unittest.mock import AsyncMock, MagicMock, patch
23 |
24 |
25 | @pytest.fixture
26 | def mock_context():
27 | """Create a mock MCP context."""
28 | context = MagicMock(spec=Context)
29 | context.info = AsyncMock()
30 | context.error = AsyncMock()
31 | return context
32 |
33 |
34 | @pytest.fixture
35 | def mock_bcm_pricing_calculator_client():
36 | """Create a mock BCM Pricing Calculator boto3 client."""
37 | mock_client = MagicMock()
38 |
39 | # Set up mock responses for different operations
40 | mock_client.get_preferences.return_value = {
41 | 'managementAccountRateTypeSelections': ['BEFORE_DISCOUNTS'],
42 | 'memberAccountRateTypeSelections': ['BEFORE_DISCOUNTS'],
43 | 'standaloneAccountRateTypeSelections': ['BEFORE_DISCOUNTS'],
44 | }
45 |
46 | mock_client.list_workload_estimates.return_value = {
47 | 'items': [
48 | {
49 | 'id': 'estimate-123',
50 | 'name': 'Test Workload Estimate',
51 | 'status': 'VALID',
52 | 'rateType': 'BEFORE_DISCOUNTS',
53 | 'createdAt': datetime(2023, 1, 1, 12, 0, 0),
54 | 'expiresAt': datetime(2023, 12, 31, 23, 59, 59),
55 | 'rateTimestamp': datetime(2023, 1, 1, 0, 0, 0),
56 | 'totalCost': 1500.50,
57 | 'costCurrency': 'USD',
58 | },
59 | {
60 | 'id': 'estimate-456',
61 | 'name': 'Another Estimate',
62 | 'status': 'UPDATING',
63 | 'rateType': 'AFTER_DISCOUNTS',
64 | 'createdAt': datetime(2023, 2, 1, 10, 0, 0),
65 | 'expiresAt': datetime(2023, 12, 31, 23, 59, 59),
66 | 'rateTimestamp': datetime(2023, 2, 1, 0, 0, 0),
67 | 'totalCost': 2000.75,
68 | 'costCurrency': 'USD',
69 | },
70 | ],
71 | 'nextToken': None,
72 | }
73 |
74 | mock_client.get_workload_estimate.return_value = {
75 | 'id': 'estimate-123',
76 | 'name': 'Test Workload Estimate',
77 | 'status': 'VALID',
78 | 'rateType': 'BEFORE_DISCOUNTS',
79 | 'createdAt': datetime(2023, 1, 1, 12, 0, 0),
80 | 'expiresAt': datetime(2023, 12, 31, 23, 59, 59),
81 | 'rateTimestamp': datetime(2023, 1, 1, 0, 0, 0),
82 | 'totalCost': 1500.50,
83 | 'costCurrency': 'USD',
84 | }
85 |
86 | mock_client.list_workload_estimate_usage.return_value = {
87 | 'items': [
88 | {
89 | 'id': 'usage-123',
90 | 'serviceCode': 'AmazonEC2',
91 | 'usageType': 'BoxUsage:t3.medium',
92 | 'operation': 'RunInstances',
93 | 'location': 'US East (N. Virginia)',
94 | 'usageAccountId': '123456789012',
95 | 'group': 'EC2-Instance',
96 | 'status': 'VALID',
97 | 'currency': 'USD',
98 | 'quantity': {
99 | 'amount': 744.0,
100 | 'unit': 'Hrs',
101 | },
102 | 'cost': 50.25,
103 | 'historicalUsage': {
104 | 'serviceCode': 'AmazonEC2',
105 | 'usageType': 'BoxUsage:t3.medium',
106 | 'operation': 'RunInstances',
107 | 'location': 'US East (N. Virginia)',
108 | 'usageAccountId': '123456789012',
109 | 'billInterval': {
110 | 'start': datetime(2023, 1, 1),
111 | 'end': datetime(2023, 1, 31),
112 | },
113 | },
114 | },
115 | ],
116 | 'nextToken': None,
117 | }
118 |
119 | return mock_client
120 |
121 |
122 | @pytest.mark.asyncio
123 | class TestGetPreferences:
124 | """Tests for get_preferences function."""
125 |
126 | @patch(
127 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
128 | )
129 | async def test_get_preferences_success_management_account(
130 | self, mock_create_client, mock_context, mock_bcm_pricing_calculator_client
131 | ):
132 | """Test get_preferences returns dict with account_types when management account preferences are configured."""
133 | # Setup
134 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
135 | mock_bcm_pricing_calculator_client.get_preferences.return_value = {
136 | 'managementAccountRateTypeSelections': ['BEFORE_DISCOUNTS']
137 | }
138 |
139 | # Execute
140 | result = await get_preferences(mock_context)
141 |
142 | # Assert
143 | mock_create_client.assert_called_once_with(
144 | 'bcm-pricing-calculator', region_name='us-east-1'
145 | )
146 | mock_bcm_pricing_calculator_client.get_preferences.assert_called_once()
147 | assert 'account_types' in result
148 | assert 'management account' in result['account_types']
149 | mock_context.info.assert_called()
150 |
151 | @patch(
152 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
153 | )
154 | async def test_get_preferences_success_member_account(
155 | self, mock_create_client, mock_context, mock_bcm_pricing_calculator_client
156 | ):
157 | """Test get_preferences returns dict with account_types when member account preferences are configured."""
158 | # Setup
159 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
160 | mock_bcm_pricing_calculator_client.get_preferences.return_value = {
161 | 'memberAccountRateTypeSelections': ['AFTER_DISCOUNTS']
162 | }
163 |
164 | # Execute
165 | result = await get_preferences(mock_context)
166 |
167 | # Assert
168 | assert 'account_types' in result
169 | assert 'member account' in result['account_types']
170 |
171 | @patch(
172 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
173 | )
174 | async def test_get_preferences_success_standalone_account(
175 | self, mock_create_client, mock_context, mock_bcm_pricing_calculator_client
176 | ):
177 | """Test get_preferences returns dict with account_types when standalone account preferences are configured."""
178 | # Setup
179 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
180 | mock_bcm_pricing_calculator_client.get_preferences.return_value = {
181 | 'standaloneAccountRateTypeSelections': ['AFTER_DISCOUNTS_AND_COMMITMENTS']
182 | }
183 |
184 | # Execute
185 | result = await get_preferences(mock_context)
186 |
187 | # Assert
188 | assert 'account_types' in result
189 | assert 'standalone account' in result['account_types']
190 |
191 | @patch(
192 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
193 | )
194 | async def test_get_preferences_not_configured(
195 | self, mock_create_client, mock_context, mock_bcm_pricing_calculator_client
196 | ):
197 | """Test get_preferences returns dict with error when no preferences are configured."""
198 | # Setup
199 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
200 | mock_bcm_pricing_calculator_client.get_preferences.return_value = {}
201 |
202 | # Execute
203 | result = await get_preferences(mock_context)
204 |
205 | # Assert
206 | assert 'error' in result
207 | assert 'BCM Pricing Calculator preferences are not configured' in result['error']
208 | mock_context.error.assert_called()
209 |
210 | @patch(
211 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
212 | )
213 | @patch(
214 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.handle_aws_error'
215 | )
216 | async def test_get_preferences_exception(
217 | self, mock_handle_error, mock_create_client, mock_context
218 | ):
219 | """Test get_preferences handles exceptions properly."""
220 | # Setup
221 | error = ClientError(
222 | {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'GetPreferences'
223 | )
224 | mock_create_client.side_effect = error
225 | mock_handle_error.return_value = {'data': {'error': 'Access denied'}}
226 |
227 | # Execute
228 | result = await get_preferences(mock_context)
229 |
230 | # Assert
231 | mock_handle_error.assert_called_once_with(
232 | mock_context, error, 'get_preferences', 'BCM Pricing Calculator'
233 | )
234 | assert 'error' in result
235 | assert (
236 | 'Failed to check BCM Pricing Calculator preferences: Access denied' in result['error']
237 | )
238 | mock_context.error.assert_called()
239 |
240 |
241 | @pytest.mark.asyncio
242 | class TestListWorkloadEstimates:
243 | """Tests for list_workload_estimates function."""
244 |
245 | @patch(
246 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
247 | )
248 | @patch(
249 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
250 | )
251 | async def test_list_workload_estimates_success(
252 | self,
253 | mock_create_client,
254 | mock_get_preferences,
255 | mock_context,
256 | mock_bcm_pricing_calculator_client,
257 | ):
258 | """Test list_workload_estimates returns formatted estimates."""
259 | # Setup
260 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
261 | mock_get_preferences.return_value = {'account_types': 'management account'}
262 |
263 | # Execute
264 | result = await list_workload_estimates(mock_context, max_results=50)
265 |
266 | # Assert
267 | mock_create_client.assert_called_once_with('bcm-pricing-calculator')
268 | mock_get_preferences.assert_called_once()
269 | mock_bcm_pricing_calculator_client.list_workload_estimates.assert_called_once()
270 |
271 | assert result['status'] == 'success'
272 | assert 'workload_estimates' in result['data']
273 | assert len(result['data']['workload_estimates']) == 2
274 | assert result['data']['total_count'] == 2
275 | assert result['data']['has_more_results'] is False
276 |
277 | # Check first estimate details
278 | first_estimate = result['data']['workload_estimates'][0]
279 | assert first_estimate['id'] == 'estimate-123'
280 | assert first_estimate['name'] == 'Test Workload Estimate'
281 | assert first_estimate['status'] == 'VALID'
282 | assert first_estimate['status_indicator'] == 'Valid'
283 |
284 | @patch(
285 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
286 | )
287 | @patch(
288 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
289 | )
290 | async def test_list_workload_estimates_with_filters(
291 | self,
292 | mock_create_client,
293 | mock_get_preferences,
294 | mock_context,
295 | mock_bcm_pricing_calculator_client,
296 | ):
297 | """Test list_workload_estimates with various filters."""
298 | # Setup
299 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
300 | mock_get_preferences.return_value = {'account_types': 'management account'}
301 |
302 | # Execute
303 | result = await list_workload_estimates(
304 | mock_context,
305 | created_after='2023-01-01T00:00:00Z',
306 | created_before='2023-12-31T23:59:59Z',
307 | expires_after='2023-06-01T00:00:00Z',
308 | expires_before='2024-01-01T00:00:00Z',
309 | status_filter='VALID',
310 | name_filter='Test',
311 | name_match_option='CONTAINS',
312 | max_results=25,
313 | )
314 |
315 | # Assert
316 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
317 | assert call_kwargs['maxResults'] == 25
318 | assert 'createdAtFilter' in call_kwargs
319 | assert 'expiresAtFilter' in call_kwargs
320 | assert 'filters' in call_kwargs
321 | assert len(call_kwargs['filters']) == 2 # status and name filters
322 |
323 | assert result['status'] == 'success'
324 |
325 | @patch(
326 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
327 | )
328 | async def test_list_workload_estimates_preferences_not_configured(
329 | self, mock_get_preferences, mock_context
330 | ):
331 | """Test list_workload_estimates when preferences are not configured."""
332 | # Setup
333 | mock_get_preferences.return_value = {
334 | 'error': 'BCM Pricing Calculator preferences are not configured'
335 | }
336 |
337 | # Execute
338 | result = await list_workload_estimates(mock_context)
339 |
340 | # Assert
341 | assert result['status'] == 'error'
342 | assert result['data']['error_code'] == 'PREFERENCES_NOT_CONFIGURED'
343 |
344 | @patch(
345 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
346 | )
347 | @patch(
348 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
349 | )
350 | @patch(
351 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.handle_aws_error'
352 | )
353 | async def test_list_workload_estimates_exception(
354 | self, mock_handle_error, mock_create_client, mock_get_preferences, mock_context
355 | ):
356 | """Test list_workload_estimates handles exceptions properly."""
357 | # Setup
358 | error = ClientError(
359 | {'Error': {'Code': 'ValidationException', 'Message': 'Invalid parameter'}},
360 | 'ListWorkloadEstimates',
361 | )
362 | mock_get_preferences.return_value = {'account_types': 'management account'}
363 | mock_create_client.return_value.list_workload_estimates.side_effect = error
364 | mock_handle_error.return_value = {'status': 'error', 'message': 'Invalid parameter'}
365 |
366 | # Execute
367 | result = await list_workload_estimates(mock_context)
368 |
369 | # Assert
370 | mock_handle_error.assert_called_once_with(
371 | mock_context, error, 'list_workload_estimates', 'BCM Pricing Calculator'
372 | )
373 | assert result['status'] == 'error'
374 |
375 |
376 | @pytest.mark.asyncio
377 | class TestGetWorkloadEstimate:
378 | """Tests for get_workload_estimate function."""
379 |
380 | @patch(
381 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
382 | )
383 | @patch(
384 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
385 | )
386 | async def test_get_workload_estimate_success(
387 | self,
388 | mock_create_client,
389 | mock_get_preferences,
390 | mock_context,
391 | mock_bcm_pricing_calculator_client,
392 | ):
393 | """Test get_workload_estimate returns formatted estimate."""
394 | # Setup
395 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
396 | mock_get_preferences.return_value = {'account_types': 'management account'}
397 |
398 | # Execute
399 | result = await get_workload_estimate(mock_context, identifier='estimate-123')
400 |
401 | # Assert
402 | mock_create_client.assert_called_once_with('bcm-pricing-calculator')
403 | mock_get_preferences.assert_called_once()
404 | mock_bcm_pricing_calculator_client.get_workload_estimate.assert_called_once_with(
405 | identifier='estimate-123'
406 | )
407 |
408 | assert result['status'] == 'success'
409 | assert 'workload_estimate' in result['data']
410 | assert result['data']['identifier'] == 'estimate-123'
411 |
412 | estimate = result['data']['workload_estimate']
413 | assert estimate['id'] == 'estimate-123'
414 | assert estimate['name'] == 'Test Workload Estimate'
415 | assert estimate['status'] == 'VALID'
416 |
417 | async def test_get_workload_estimate_missing_identifier(self, mock_context):
418 | """Test get_workload_estimate returns error when identifier is missing."""
419 | # Execute
420 | result = await get_workload_estimate(mock_context, identifier=None)
421 |
422 | # Assert
423 | assert result['status'] == 'error'
424 | assert 'Identifier is required' in result['data']['error']
425 | assert result['data']['error_code'] == 'MISSING_PARAMETER'
426 |
427 | @patch(
428 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
429 | )
430 | async def test_get_workload_estimate_preferences_not_configured(
431 | self, mock_get_preferences, mock_context
432 | ):
433 | """Test get_workload_estimate when preferences are not configured."""
434 | # Setup
435 | mock_get_preferences.return_value = {
436 | 'error': 'BCM Pricing Calculator preferences are not configured'
437 | }
438 |
439 | # Execute
440 | result = await get_workload_estimate(mock_context, identifier='estimate-123')
441 |
442 | # Assert
443 | assert result['status'] == 'error'
444 | assert result['data']['error_code'] == 'PREFERENCES_NOT_CONFIGURED'
445 |
446 |
447 | @pytest.mark.asyncio
448 | class TestListWorkloadEstimateUsage:
449 | """Tests for list_workload_estimate_usage function."""
450 |
451 | @patch(
452 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
453 | )
454 | @patch(
455 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
456 | )
457 | async def test_list_workload_estimate_usage_success(
458 | self,
459 | mock_create_client,
460 | mock_get_preferences,
461 | mock_context,
462 | mock_bcm_pricing_calculator_client,
463 | ):
464 | """Test list_workload_estimate_usage returns formatted usage items."""
465 | # Setup
466 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
467 | mock_get_preferences.return_value = {'account_types': ['management account']}
468 |
469 | # Execute
470 | result = await list_workload_estimate_usage(
471 | mock_context,
472 | workload_estimate_id='estimate-123',
473 | service_code_filter='AmazonEC2',
474 | max_results=50,
475 | )
476 |
477 | # Assert
478 | mock_create_client.assert_called_once_with('bcm-pricing-calculator')
479 | mock_get_preferences.assert_called_once()
480 | mock_bcm_pricing_calculator_client.list_workload_estimate_usage.assert_called_once()
481 |
482 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimate_usage.call_args[1]
483 | assert call_kwargs['workloadEstimateId'] == 'estimate-123'
484 | assert call_kwargs['maxResults'] == 50
485 | assert 'filters' in call_kwargs
486 | assert len(call_kwargs['filters']) == 1 # service_code_filter
487 |
488 | assert result['status'] == 'success'
489 | assert 'usage_items' in result['data']
490 | assert len(result['data']['usage_items']) == 1
491 | assert result['data']['workload_estimate_id'] == 'estimate-123'
492 |
493 | # Check usage item details
494 | usage_item = result['data']['usage_items'][0]
495 | assert usage_item['id'] == 'usage-123'
496 | assert usage_item['service_code'] == 'AmazonEC2'
497 | assert usage_item['usage_type'] == 'BoxUsage:t3.medium'
498 |
499 | async def test_list_workload_estimate_usage_missing_id(self, mock_context):
500 | """Test list_workload_estimate_usage returns error when workload_estimate_id is missing."""
501 | # Execute
502 | result = await list_workload_estimate_usage(mock_context, workload_estimate_id=None)
503 |
504 | # Assert
505 | assert result['status'] == 'error'
506 | assert 'workload_estimate_id is required' in result['data']['error']
507 | assert result['data']['error_code'] == 'MISSING_PARAMETER'
508 |
509 | @patch(
510 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
511 | )
512 | @patch(
513 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
514 | )
515 | async def test_list_workload_estimate_usage_with_all_filters(
516 | self,
517 | mock_create_client,
518 | mock_get_preferences,
519 | mock_context,
520 | mock_bcm_pricing_calculator_client,
521 | ):
522 | """Test list_workload_estimate_usage with all possible filters."""
523 | # Setup
524 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
525 | mock_get_preferences.return_value = {'account_types': ['management account']}
526 |
527 | # Execute
528 | result = await list_workload_estimate_usage(
529 | mock_context,
530 | workload_estimate_id='estimate-123',
531 | usage_account_id_filter='123456789012',
532 | service_code_filter='AmazonEC2',
533 | usage_type_filter='BoxUsage',
534 | operation_filter='RunInstances',
535 | location_filter='US East (N. Virginia)',
536 | usage_group_filter='EC2-Instance',
537 | max_results=100,
538 | )
539 |
540 | # Assert
541 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimate_usage.call_args[1]
542 | assert len(call_kwargs['filters']) == 6 # All filters applied
543 | assert result['status'] == 'success'
544 |
545 |
546 | class TestFormatWorkloadEstimateResponse:
547 | """Tests for format_workload_estimate_response function."""
548 |
549 | def test_format_workload_estimate_response_basic(self):
550 | """Test format_workload_estimate_response with basic fields."""
551 | # Setup
552 | estimate = {
553 | 'id': 'estimate-123',
554 | 'name': 'Test Estimate',
555 | 'status': 'VALID',
556 | 'rateType': 'BEFORE_DISCOUNTS',
557 | }
558 |
559 | # Execute
560 | result = format_workload_estimate_response(estimate)
561 |
562 | # Assert
563 | assert result['id'] == 'estimate-123'
564 | assert result['name'] == 'Test Estimate'
565 | assert result['status'] == 'VALID'
566 | assert result['rate_type'] == 'BEFORE_DISCOUNTS'
567 | assert result['status_indicator'] == 'Valid'
568 |
569 | def test_format_workload_estimate_response_with_timestamps(self):
570 | """Test format_workload_estimate_response with timestamp fields."""
571 | # Setup
572 | created_at = datetime(2023, 1, 1, 12, 0, 0)
573 | expires_at = datetime(2023, 12, 31, 23, 59, 59)
574 | rate_timestamp = datetime(2023, 1, 1, 0, 0, 0)
575 |
576 | estimate = {
577 | 'id': 'estimate-123',
578 | 'name': 'Test Estimate',
579 | 'status': 'UPDATING',
580 | 'createdAt': created_at,
581 | 'expiresAt': expires_at,
582 | 'rateTimestamp': rate_timestamp,
583 | }
584 |
585 | # Execute
586 | result = format_workload_estimate_response(estimate)
587 |
588 | # Assert
589 | assert 'created_at' in result
590 | assert result['created_at']['timestamp'] == created_at.isoformat()
591 | assert result['created_at']['formatted'] == '2023-01-01 12:00:00 UTC'
592 |
593 | assert 'expires_at' in result
594 | assert result['expires_at']['timestamp'] == expires_at.isoformat()
595 |
596 | assert 'rate_timestamp' in result
597 | assert result['rate_timestamp']['timestamp'] == rate_timestamp.isoformat()
598 |
599 | assert result['status_indicator'] == 'Updating'
600 |
601 | def test_format_workload_estimate_response_with_cost(self):
602 | """Test format_workload_estimate_response with cost information."""
603 | # Setup
604 | estimate = {
605 | 'id': 'estimate-123',
606 | 'name': 'Test Estimate',
607 | 'status': 'VALID',
608 | 'totalCost': 1500.50,
609 | 'costCurrency': 'USD',
610 | }
611 |
612 | # Execute
613 | result = format_workload_estimate_response(estimate)
614 |
615 | # Assert
616 | assert 'cost' in result
617 | assert result['cost']['amount'] == 1500.50
618 | assert result['cost']['currency'] == 'USD'
619 | assert result['cost']['formatted'] == 'USD 1,500.50'
620 |
621 | def test_format_workload_estimate_response_with_failure_message(self):
622 | """Test format_workload_estimate_response with failure message."""
623 | # Setup
624 | estimate = {
625 | 'id': 'estimate-123',
626 | 'name': 'Test Estimate',
627 | 'status': 'INVALID',
628 | 'failureMessage': 'Invalid configuration detected',
629 | }
630 |
631 | # Execute
632 | result = format_workload_estimate_response(estimate)
633 |
634 | # Assert
635 | assert result['failure_message'] == 'Invalid configuration detected'
636 | assert result['status_indicator'] == 'Invalid'
637 |
638 | def test_format_workload_estimate_response_action_needed_status(self):
639 | """Test format_workload_estimate_response with ACTION_NEEDED status."""
640 | # Setup
641 | estimate = {
642 | 'id': 'estimate-123',
643 | 'name': 'Test Estimate',
644 | 'status': 'ACTION_NEEDED',
645 | }
646 |
647 | # Execute
648 | result = format_workload_estimate_response(estimate)
649 |
650 | # Assert
651 | assert result['status_indicator'] == 'Action Needed'
652 |
653 | def test_format_workload_estimate_response_unknown_status(self):
654 | """Test format_workload_estimate_response with unknown status."""
655 | # Setup
656 | estimate = {
657 | 'id': 'estimate-123',
658 | 'name': 'Test Estimate',
659 | 'status': 'UNKNOWN_STATUS',
660 | }
661 |
662 | # Execute
663 | result = format_workload_estimate_response(estimate)
664 |
665 | # Assert
666 | assert result['status_indicator'] == '❓ UNKNOWN_STATUS'
667 |
668 |
669 | class TestFormatUsageItemResponse:
670 | """Tests for format_usage_item_response function."""
671 |
672 | def test_format_usage_item_response_basic(self):
673 | """Test format_usage_item_response with basic fields."""
674 | # Setup
675 | usage_item = {
676 | 'id': 'usage-123',
677 | 'serviceCode': 'AmazonEC2',
678 | 'usageType': 'BoxUsage:t3.medium',
679 | 'operation': 'RunInstances',
680 | 'location': 'US East (N. Virginia)',
681 | 'usageAccountId': '123456789012',
682 | 'group': 'EC2-Instance',
683 | 'status': 'VALID',
684 | 'currency': 'USD',
685 | }
686 |
687 | # Execute
688 | result = format_usage_item_response(usage_item)
689 |
690 | # Assert
691 | assert result['id'] == 'usage-123'
692 | assert result['service_code'] == 'AmazonEC2'
693 | assert result['usage_type'] == 'BoxUsage:t3.medium'
694 | assert result['operation'] == 'RunInstances'
695 | assert result['location'] == 'US East (N. Virginia)'
696 | assert result['usage_account_id'] == '123456789012'
697 | assert result['group'] == 'EC2-Instance'
698 | assert result['status'] == 'VALID'
699 | assert result['currency'] == 'USD'
700 | assert result['status_indicator'] == 'Valid'
701 |
702 | def test_format_usage_item_response_with_quantity(self):
703 | """Test format_usage_item_response with quantity information."""
704 | # Setup
705 | usage_item = {
706 | 'id': 'usage-123',
707 | 'serviceCode': 'AmazonEC2',
708 | 'quantity': {
709 | 'amount': 744.0,
710 | 'unit': 'Hrs',
711 | },
712 | }
713 |
714 | # Execute
715 | result = format_usage_item_response(usage_item)
716 |
717 | # Assert
718 | assert 'quantity' in result
719 | assert result['quantity']['amount'] == 744.0
720 | assert result['quantity']['unit'] == 'Hrs'
721 | assert result['quantity']['formatted'] == '744.00 Hrs'
722 |
723 | def test_format_usage_item_response_with_cost(self):
724 | """Test format_usage_item_response with cost information."""
725 | # Setup
726 | usage_item = {
727 | 'id': 'usage-123',
728 | 'serviceCode': 'AmazonEC2',
729 | 'cost': 50.25,
730 | 'currency': 'USD',
731 | }
732 |
733 | # Execute
734 | result = format_usage_item_response(usage_item)
735 |
736 | # Assert
737 | assert 'cost' in result
738 | assert result['cost']['amount'] == 50.25
739 | assert result['cost']['currency'] == 'USD'
740 | assert result['cost']['formatted'] == 'USD 50.25'
741 |
742 | def test_format_usage_item_response_with_historical_usage(self):
743 | """Test format_usage_item_response with historical usage information."""
744 | # Setup
745 | usage_item = {
746 | 'id': 'usage-123',
747 | 'serviceCode': 'AmazonEC2',
748 | 'historicalUsage': {
749 | 'serviceCode': 'AmazonEC2',
750 | 'usageType': 'BoxUsage:t3.medium',
751 | 'operation': 'RunInstances',
752 | 'location': 'US East (N. Virginia)',
753 | 'usageAccountId': '123456789012',
754 | 'billInterval': {
755 | 'start': datetime(2023, 1, 1),
756 | 'end': datetime(2023, 1, 31),
757 | },
758 | },
759 | }
760 |
761 | # Execute
762 | result = format_usage_item_response(usage_item)
763 |
764 | # Assert
765 | assert 'historical_usage' in result
766 | historical = result['historical_usage']
767 | assert historical['service_code'] == 'AmazonEC2'
768 | assert historical['usage_type'] == 'BoxUsage:t3.medium'
769 | assert historical['operation'] == 'RunInstances'
770 | assert historical['location'] == 'US East (N. Virginia)'
771 | assert historical['usage_account_id'] == '123456789012'
772 | assert 'bill_interval' in historical
773 | assert historical['bill_interval']['start'] == '2023-01-01T00:00:00'
774 | assert historical['bill_interval']['end'] == '2023-01-31T00:00:00'
775 |
776 | def test_format_usage_item_response_quantity_none_amount(self):
777 | """Test format_usage_item_response with None quantity amount."""
778 | # Setup
779 | usage_item = {
780 | 'id': 'usage-123',
781 | 'serviceCode': 'AmazonEC2',
782 | 'quantity': {
783 | 'amount': None,
784 | 'unit': 'Hrs',
785 | },
786 | }
787 |
788 | # Execute
789 | result = format_usage_item_response(usage_item)
790 |
791 | # Assert
792 | assert 'quantity' in result
793 | assert result['quantity']['amount'] is None
794 | assert result['quantity']['unit'] == 'Hrs'
795 | assert result['quantity']['formatted'] is None
796 |
797 | def test_format_usage_item_response_stale_status(self):
798 | """Test format_usage_item_response with STALE status."""
799 | # Setup
800 | usage_item = {
801 | 'id': 'usage-123',
802 | 'serviceCode': 'AmazonEC2',
803 | 'status': 'STALE',
804 | }
805 |
806 | # Execute
807 | result = format_usage_item_response(usage_item)
808 |
809 | # Assert
810 | assert result['status_indicator'] == 'Stale'
811 |
812 | def test_format_usage_item_response_invalid_status(self):
813 | """Test format_usage_item_response with INVALID status."""
814 | # Setup
815 | usage_item = {
816 | 'id': 'usage-123',
817 | 'serviceCode': 'AmazonEC2',
818 | 'status': 'INVALID',
819 | }
820 |
821 | # Execute
822 | result = format_usage_item_response(usage_item)
823 |
824 | # Assert
825 | assert result['status_indicator'] == 'Invalid'
826 |
827 | def test_format_usage_item_response_unknown_status(self):
828 | """Test format_usage_item_response with unknown status."""
829 | # Setup
830 | usage_item = {
831 | 'id': 'usage-123',
832 | 'serviceCode': 'AmazonEC2',
833 | 'status': 'UNKNOWN_STATUS',
834 | }
835 |
836 | # Execute
837 | result = format_usage_item_response(usage_item)
838 |
839 | # Assert
840 | assert result['status_indicator'] == '❓ UNKNOWN_STATUS'
841 |
842 |
843 | def test_bcm_pricing_calculator_server_initialization():
844 | """Test that the bcm_pricing_calculator_server is properly initialized."""
845 | # Verify the server name
846 | assert bcm_pricing_calculator_server.name == 'bcm-pricing-calc-tools'
847 |
848 | # Verify the server instructions
849 | instructions = bcm_pricing_calculator_server.instructions
850 | assert instructions is not None
851 | assert 'BCM Pricing Calculator tools' in instructions
852 |
853 |
854 | class TestAdditionalFormattingCases:
855 | """Tests for additional formatting edge cases to achieve complete coverage."""
856 |
857 | def test_format_usage_item_response_no_quantity(self):
858 | """Test format_usage_item_response with no quantity field."""
859 | # Setup
860 | usage_item = {
861 | 'id': 'usage-123',
862 | 'serviceCode': 'AmazonEC2',
863 | 'status': 'VALID',
864 | }
865 |
866 | # Execute
867 | result = format_usage_item_response(usage_item)
868 |
869 | # Assert
870 | assert 'quantity' not in result
871 | assert result['id'] == 'usage-123'
872 | assert result['service_code'] == 'AmazonEC2'
873 | assert result['status'] == 'VALID'
874 |
875 | def test_format_usage_item_response_no_cost(self):
876 | """Test format_usage_item_response with no cost field."""
877 | # Setup
878 | usage_item = {
879 | 'id': 'usage-123',
880 | 'serviceCode': 'AmazonEC2',
881 | 'status': 'VALID',
882 | }
883 |
884 | # Execute
885 | result = format_usage_item_response(usage_item)
886 |
887 | # Assert
888 | assert 'cost' not in result
889 | assert result['id'] == 'usage-123'
890 | assert result['service_code'] == 'AmazonEC2'
891 |
892 | def test_format_usage_item_response_no_status(self):
893 | """Test format_usage_item_response with no status field."""
894 | # Setup
895 | usage_item = {
896 | 'id': 'usage-123',
897 | 'serviceCode': 'AmazonEC2',
898 | }
899 |
900 | # Execute
901 | result = format_usage_item_response(usage_item)
902 |
903 | # Assert
904 | assert 'status_indicator' not in result
905 | assert result['id'] == 'usage-123'
906 | assert result['service_code'] == 'AmazonEC2'
907 |
908 | def test_format_usage_item_response_default_currency(self):
909 | """Test format_usage_item_response uses default USD currency."""
910 | # Setup
911 | usage_item = {
912 | 'id': 'usage-123',
913 | 'serviceCode': 'AmazonEC2',
914 | # No currency field provided
915 | }
916 |
917 | # Execute
918 | result = format_usage_item_response(usage_item)
919 |
920 | # Assert
921 | assert result['currency'] == 'USD'
922 |
923 | def test_format_usage_item_response_historical_usage_no_bill_interval_start_end(self):
924 | """Test format_usage_item_response with historical usage but no start/end in bill interval."""
925 | # Setup
926 | usage_item = {
927 | 'id': 'usage-123',
928 | 'serviceCode': 'AmazonEC2',
929 | 'historicalUsage': {
930 | 'serviceCode': 'AmazonEC2',
931 | 'usageType': 'BoxUsage:t3.medium',
932 | 'operation': 'RunInstances',
933 | 'location': 'US East (N. Virginia)',
934 | 'usageAccountId': '123456789012',
935 | 'billInterval': {
936 | 'start': None,
937 | 'end': None,
938 | },
939 | },
940 | }
941 |
942 | # Execute
943 | result = format_usage_item_response(usage_item)
944 |
945 | # Assert
946 | assert 'historical_usage' in result
947 | historical = result['historical_usage']
948 | assert 'bill_interval' in historical
949 | assert historical['bill_interval']['start'] is None
950 | assert historical['bill_interval']['end'] is None
951 |
952 | def test_format_workload_estimate_response_no_status(self):
953 | """Test format_workload_estimate_response with no status field."""
954 | # Setup
955 | estimate = {
956 | 'id': 'estimate-123',
957 | 'name': 'Test Estimate',
958 | 'rateType': 'BEFORE_DISCOUNTS',
959 | }
960 |
961 | # Execute
962 | result = format_workload_estimate_response(estimate)
963 |
964 | # Assert
965 | assert 'status_indicator' not in result
966 | assert result['id'] == 'estimate-123'
967 | assert result['name'] == 'Test Estimate'
968 |
969 | def test_format_workload_estimate_response_no_failure_message(self):
970 | """Test format_workload_estimate_response with no failure message."""
971 | # Setup
972 | estimate = {
973 | 'id': 'estimate-123',
974 | 'name': 'Test Estimate',
975 | 'status': 'VALID',
976 | }
977 |
978 | # Execute
979 | result = format_workload_estimate_response(estimate)
980 |
981 | # Assert
982 | assert 'failure_message' not in result
983 | assert result['id'] == 'estimate-123'
984 | assert result['status'] == 'VALID'
985 |
986 |
987 | @pytest.mark.asyncio
988 | class TestMissingCoverageBranches:
989 | """Tests specifically targeting lines 100-148 that are missing coverage."""
990 |
991 | @patch(
992 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
993 | )
994 | async def test_get_preferences_management_account_only(self, mock_create_client, mock_context):
995 | """Test get_preferences with only management account preferences (covers lines ~100-110)."""
996 | # Setup - only management account preferences
997 | mock_client = MagicMock()
998 | mock_client.get_preferences.return_value = {
999 | 'managementAccountRateTypeSelections': [
1000 | 'BEFORE_DISCOUNTS',
1001 | 'AFTER_DISCOUNTS_AND_COMMITMENTS',
1002 | ]
1003 | # No member or standalone account selections
1004 | }
1005 | mock_create_client.return_value = mock_client
1006 |
1007 | # Execute
1008 | result = await get_preferences(mock_context)
1009 |
1010 | # Assert
1011 | assert 'account_types' in result
1012 | assert 'management account' in result['account_types']
1013 | mock_context.info.assert_called()
1014 | # Verify the specific log message for management account
1015 | info_calls = [call.args[0] for call in mock_context.info.call_args_list]
1016 | assert any('management account' in call for call in info_calls)
1017 |
1018 | @patch(
1019 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1020 | )
1021 | async def test_get_preferences_member_account_only(self, mock_create_client, mock_context):
1022 | """Test get_preferences with only member account preferences (covers lines ~100-110)."""
1023 | # Setup - only member account preferences
1024 | mock_client = MagicMock()
1025 | mock_client.get_preferences.return_value = {
1026 | 'memberAccountRateTypeSelections': ['BEFORE_DISCOUNTS']
1027 | # No management or standalone account selections
1028 | }
1029 | mock_create_client.return_value = mock_client
1030 |
1031 | # Execute
1032 | result = await get_preferences(mock_context)
1033 |
1034 | # Assert
1035 | assert 'account_types' in result
1036 | assert 'member account' in result['account_types']
1037 | mock_context.info.assert_called()
1038 | # Verify the specific log message for member account
1039 | info_calls = [call.args[0] for call in mock_context.info.call_args_list]
1040 | assert any('member account' in call for call in info_calls)
1041 |
1042 | @patch(
1043 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1044 | )
1045 | async def test_get_preferences_standalone_account_only(self, mock_create_client, mock_context):
1046 | """Test get_preferences with only standalone account preferences (covers lines ~100-110)."""
1047 | # Setup - only standalone account preferences
1048 | mock_client = MagicMock()
1049 | mock_client.get_preferences.return_value = {
1050 | 'standaloneAccountRateTypeSelections': ['AFTER_DISCOUNTS_AND_COMMITMENTS']
1051 | # No management or member account selections
1052 | }
1053 | mock_create_client.return_value = mock_client
1054 |
1055 | # Execute
1056 | result = await get_preferences(mock_context)
1057 |
1058 | # Assert
1059 | assert 'account_types' in result
1060 | assert 'standalone account' in result['account_types']
1061 | mock_context.info.assert_called()
1062 | # Verify the specific log message for standalone account
1063 | info_calls = [call.args[0] for call in mock_context.info.call_args_list]
1064 | assert any('standalone account' in call for call in info_calls)
1065 |
1066 | @patch(
1067 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1068 | )
1069 | async def test_get_preferences_multiple_account_types(self, mock_create_client, mock_context):
1070 | """Test get_preferences with multiple account type preferences (covers lines ~100-110)."""
1071 | # Setup - multiple account type preferences
1072 | mock_client = MagicMock()
1073 | mock_client.get_preferences.return_value = {
1074 | 'managementAccountRateTypeSelections': ['BEFORE_DISCOUNTS'],
1075 | 'memberAccountRateTypeSelections': ['AFTER_DISCOUNTS'],
1076 | 'standaloneAccountRateTypeSelections': ['AFTER_DISCOUNTS_AND_COMMITMENTS'],
1077 | }
1078 | mock_create_client.return_value = mock_client
1079 |
1080 | # Execute
1081 | result = await get_preferences(mock_context)
1082 |
1083 | # Assert
1084 | assert 'account_types' in result
1085 | assert 'management account' in result['account_types']
1086 | assert 'member account' in result['account_types']
1087 | assert 'standalone account' in result['account_types']
1088 | mock_context.info.assert_called()
1089 | # Verify the log message contains all account types
1090 | info_calls = [call.args[0] for call in mock_context.info.call_args_list]
1091 | combined_message = ' '.join(info_calls)
1092 | assert 'management account' in combined_message
1093 | assert 'member account' in combined_message
1094 | assert 'standalone account' in combined_message
1095 |
1096 | @patch(
1097 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1098 | )
1099 | @patch(
1100 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1101 | )
1102 | async def test_list_workload_estimates_datetime_parsing_created_after_only(
1103 | self,
1104 | mock_create_client,
1105 | mock_get_preferences,
1106 | mock_context,
1107 | mock_bcm_pricing_calculator_client,
1108 | ):
1109 | """Test list_workload_estimates datetime parsing for created_after only (covers lines ~120-130)."""
1110 | # Setup
1111 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1112 | mock_get_preferences.return_value = {'account_types': ['management account']}
1113 |
1114 | # Execute with only created_after
1115 | result = await list_workload_estimates(mock_context, created_after='2023-01-01T00:00:00Z')
1116 |
1117 | # Assert
1118 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
1119 | assert 'createdAtFilter' in call_kwargs
1120 | created_filter = call_kwargs['createdAtFilter']
1121 | assert 'afterTimestamp' in created_filter
1122 | assert 'beforeTimestamp' not in created_filter
1123 | assert result['status'] == 'success'
1124 |
1125 | @patch(
1126 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1127 | )
1128 | @patch(
1129 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1130 | )
1131 | async def test_list_workload_estimates_datetime_parsing_created_before_only(
1132 | self,
1133 | mock_create_client,
1134 | mock_get_preferences,
1135 | mock_context,
1136 | mock_bcm_pricing_calculator_client,
1137 | ):
1138 | """Test list_workload_estimates datetime parsing for created_before only (covers lines ~120-130)."""
1139 | # Setup
1140 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1141 | mock_get_preferences.return_value = {'account_types': ['management account']}
1142 |
1143 | # Execute with only created_before
1144 | result = await list_workload_estimates(mock_context, created_before='2023-12-31T23:59:59Z')
1145 |
1146 | # Assert
1147 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
1148 | assert 'createdAtFilter' in call_kwargs
1149 | created_filter = call_kwargs['createdAtFilter']
1150 | assert 'beforeTimestamp' in created_filter
1151 | assert 'afterTimestamp' not in created_filter
1152 | assert result['status'] == 'success'
1153 |
1154 | @patch(
1155 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1156 | )
1157 | @patch(
1158 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1159 | )
1160 | async def test_list_workload_estimates_datetime_parsing_expires_after_only(
1161 | self,
1162 | mock_create_client,
1163 | mock_get_preferences,
1164 | mock_context,
1165 | mock_bcm_pricing_calculator_client,
1166 | ):
1167 | """Test list_workload_estimates datetime parsing for expires_after only (covers lines ~130-140)."""
1168 | # Setup
1169 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1170 | mock_get_preferences.return_value = {'account_types': ['management account']}
1171 |
1172 | # Execute with only expires_after
1173 | result = await list_workload_estimates(mock_context, expires_after='2023-06-01T00:00:00Z')
1174 |
1175 | # Assert
1176 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
1177 | assert 'expiresAtFilter' in call_kwargs
1178 | expires_filter = call_kwargs['expiresAtFilter']
1179 | assert 'afterTimestamp' in expires_filter
1180 | assert 'beforeTimestamp' not in expires_filter
1181 | assert result['status'] == 'success'
1182 |
1183 | @patch(
1184 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1185 | )
1186 | @patch(
1187 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1188 | )
1189 | async def test_list_workload_estimates_datetime_parsing_expires_before_only(
1190 | self,
1191 | mock_create_client,
1192 | mock_get_preferences,
1193 | mock_context,
1194 | mock_bcm_pricing_calculator_client,
1195 | ):
1196 | """Test list_workload_estimates datetime parsing for expires_before only (covers lines ~130-140)."""
1197 | # Setup
1198 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1199 | mock_get_preferences.return_value = {'account_types': ['management account']}
1200 |
1201 | # Execute with only expires_before
1202 | result = await list_workload_estimates(mock_context, expires_before='2024-01-01T00:00:00Z')
1203 |
1204 | # Assert
1205 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
1206 | assert 'expiresAtFilter' in call_kwargs
1207 | expires_filter = call_kwargs['expiresAtFilter']
1208 | assert 'beforeTimestamp' in expires_filter
1209 | assert 'afterTimestamp' not in expires_filter
1210 | assert result['status'] == 'success'
1211 |
1212 | @patch(
1213 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1214 | )
1215 | @patch(
1216 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1217 | )
1218 | async def test_list_workload_estimates_filter_building_status_only(
1219 | self,
1220 | mock_create_client,
1221 | mock_get_preferences,
1222 | mock_context,
1223 | mock_bcm_pricing_calculator_client,
1224 | ):
1225 | """Test list_workload_estimates filter building for status only (covers lines ~140-148)."""
1226 | # Setup
1227 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1228 | mock_get_preferences.return_value = {'account_types': ['management account']}
1229 |
1230 | # Execute with only status filter
1231 | result = await list_workload_estimates(mock_context, status_filter='VALID')
1232 |
1233 | # Assert
1234 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
1235 | assert 'filters' in call_kwargs
1236 | filters = call_kwargs['filters']
1237 | assert len(filters) == 1
1238 | assert filters[0]['name'] == 'STATUS'
1239 | assert filters[0]['values'] == ['VALID']
1240 | assert filters[0]['matchOption'] == 'EQUALS'
1241 | assert result['status'] == 'success'
1242 |
1243 | @patch(
1244 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1245 | )
1246 | @patch(
1247 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1248 | )
1249 | async def test_list_workload_estimates_filter_building_name_only(
1250 | self,
1251 | mock_create_client,
1252 | mock_get_preferences,
1253 | mock_context,
1254 | mock_bcm_pricing_calculator_client,
1255 | ):
1256 | """Test list_workload_estimates filter building for name only (covers lines ~140-148)."""
1257 | # Setup
1258 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1259 | mock_get_preferences.return_value = {'account_types': ['management account']}
1260 |
1261 | # Execute with only name filter
1262 | result = await list_workload_estimates(
1263 | mock_context, name_filter='Test', name_match_option='STARTS_WITH'
1264 | )
1265 |
1266 | # Assert
1267 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
1268 | assert 'filters' in call_kwargs
1269 | filters = call_kwargs['filters']
1270 | assert len(filters) == 1
1271 | assert filters[0]['name'] == 'NAME'
1272 | assert filters[0]['values'] == ['Test']
1273 | assert filters[0]['matchOption'] == 'STARTS_WITH'
1274 | assert result['status'] == 'success'
1275 |
1276 | @patch(
1277 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1278 | )
1279 | @patch(
1280 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1281 | )
1282 | async def test_list_workload_estimates_no_filters_applied(
1283 | self,
1284 | mock_create_client,
1285 | mock_get_preferences,
1286 | mock_context,
1287 | mock_bcm_pricing_calculator_client,
1288 | ):
1289 | """Test list_workload_estimates with no filters (covers the filters conditional logic)."""
1290 | # Setup
1291 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1292 | mock_get_preferences.return_value = {'account_types': ['management account']}
1293 |
1294 | # Execute with no filters
1295 | result = await list_workload_estimates(mock_context)
1296 |
1297 | # Assert
1298 | call_kwargs = mock_bcm_pricing_calculator_client.list_workload_estimates.call_args[1]
1299 | # Should not have filters key when no filters are applied
1300 | assert 'filters' not in call_kwargs or not call_kwargs.get('filters')
1301 | assert result['status'] == 'success'
1302 |
1303 |
1304 | @pytest.mark.asyncio
1305 | class TestAdditionalConditionalBranches:
1306 | """Tests for additional conditional branches to achieve complete coverage."""
1307 |
1308 |
1309 | @pytest.mark.asyncio
1310 | class TestListWorkloadEstimateUsagePreferencesNotConfigured:
1311 | """Test for line 476 - preferences not configured in list_workload_estimate_usage."""
1312 |
1313 | @patch(
1314 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1315 | )
1316 | async def test_list_workload_estimate_usage_preferences_not_configured(
1317 | self, mock_get_preferences, mock_context
1318 | ):
1319 | """Test list_workload_estimate_usage when preferences are not configured (line 476)."""
1320 | # Setup
1321 | mock_get_preferences.return_value = {
1322 | 'error': 'BCM Pricing Calculator preferences are not configured - no rate type selections found'
1323 | }
1324 |
1325 | # Execute
1326 | result = await list_workload_estimate_usage(
1327 | mock_context, workload_estimate_id='estimate-123'
1328 | )
1329 |
1330 | # Assert
1331 | assert result['status'] == 'error'
1332 | assert (
1333 | result['data']['error']
1334 | == 'BCM Pricing Calculator preferences are not configured - no rate type selections found'
1335 | )
1336 | assert result['data']['error_code'] == 'PREFERENCES_NOT_CONFIGURED'
1337 |
1338 |
1339 | class TestEdgeCases:
1340 | """Tests for edge cases and error conditions."""
1341 |
1342 | @pytest.mark.asyncio
1343 | @patch(
1344 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1345 | )
1346 | @patch(
1347 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1348 | )
1349 | @patch(
1350 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.paginate_aws_response'
1351 | )
1352 | async def test_list_workload_estimates_with_pagination(
1353 | self,
1354 | mock_paginate_aws_response,
1355 | mock_create_client,
1356 | mock_get_preferences,
1357 | mock_context,
1358 | mock_bcm_pricing_calculator_client,
1359 | ):
1360 | """Test list_workload_estimates with pagination token."""
1361 | # Setup
1362 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1363 | mock_get_preferences.return_value = {'account_types': ['management account']}
1364 |
1365 | # Mock the paginate_aws_response function to prevent infinite loop
1366 | mock_paginate_aws_response.return_value = (
1367 | [], # results
1368 | { # pagination_metadata
1369 | 'total_count': 0,
1370 | 'next_token': 'next-page-token',
1371 | 'has_more_results': True,
1372 | 'pages_fetched': 1,
1373 | },
1374 | )
1375 |
1376 | # Execute
1377 | result = await list_workload_estimates(
1378 | mock_context, next_token='current-token', max_pages=2
1379 | )
1380 |
1381 | # Assert
1382 | mock_paginate_aws_response.assert_called_once()
1383 | assert result['status'] == 'success'
1384 | assert result['data']['pagination']['next_token'] == 'next-page-token'
1385 | assert result['data']['pagination']['has_more_results'] is True
1386 |
1387 | @pytest.mark.asyncio
1388 | @patch(
1389 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1390 | )
1391 | @patch(
1392 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1393 | )
1394 | @patch(
1395 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.paginate_aws_response'
1396 | )
1397 | async def test_list_workload_estimate_usage_with_pagination(
1398 | self,
1399 | mock_paginate_aws_response,
1400 | mock_create_client,
1401 | mock_get_preferences,
1402 | mock_context,
1403 | mock_bcm_pricing_calculator_client,
1404 | ):
1405 | """Test list_workload_estimate_usage with pagination token."""
1406 | # Setup
1407 | mock_create_client.return_value = mock_bcm_pricing_calculator_client
1408 | mock_get_preferences.return_value = {'account_types': ['management account']}
1409 |
1410 | # Mock the paginate_aws_response function to prevent infinite loop
1411 | mock_paginate_aws_response.return_value = (
1412 | [], # results
1413 | { # pagination_metadata
1414 | 'total_count': 0,
1415 | 'next_token': 'usage-next-token',
1416 | 'has_more_results': True,
1417 | 'pages_fetched': 1,
1418 | },
1419 | )
1420 |
1421 | # Execute
1422 | result = await list_workload_estimate_usage(
1423 | mock_context,
1424 | workload_estimate_id='estimate-123',
1425 | next_token='usage-current-token',
1426 | max_pages=2,
1427 | )
1428 |
1429 | # Assert
1430 | mock_paginate_aws_response.assert_called_once()
1431 | assert result['status'] == 'success'
1432 | assert result['data']['pagination']['next_token'] == 'usage-next-token'
1433 | assert result['data']['pagination']['has_more_results'] is True
1434 |
1435 | def test_format_workload_estimate_response_with_string_timestamps(self):
1436 | """Test format_workload_estimate_response with string timestamps."""
1437 | # Setup
1438 | estimate = {
1439 | 'id': 'estimate-123',
1440 | 'name': 'Test Estimate',
1441 | 'status': 'VALID',
1442 | 'createdAt': '2023-01-01T12:00:00Z',
1443 | 'expiresAt': '2023-12-31T23:59:59Z',
1444 | 'rateTimestamp': '2023-01-01T00:00:00Z',
1445 | }
1446 |
1447 | # Execute
1448 | result = format_workload_estimate_response(estimate)
1449 |
1450 | # Assert
1451 | assert result['created_at']['timestamp'] == '2023-01-01T12:00:00Z'
1452 | assert result['created_at']['formatted'] == '2023-01-01T12:00:00Z'
1453 | assert result['expires_at']['timestamp'] == '2023-12-31T23:59:59Z'
1454 | assert result['rate_timestamp']['timestamp'] == '2023-01-01T00:00:00Z'
1455 |
1456 | def test_format_workload_estimate_response_none_cost(self):
1457 | """Test format_workload_estimate_response with None total cost."""
1458 | # Setup
1459 | estimate = {
1460 | 'id': 'estimate-123',
1461 | 'name': 'Test Estimate',
1462 | 'status': 'VALID',
1463 | 'totalCost': None,
1464 | 'costCurrency': 'USD',
1465 | }
1466 |
1467 | # Execute
1468 | result = format_workload_estimate_response(estimate)
1469 |
1470 | # Assert
1471 | assert 'cost' in result
1472 | assert result['cost']['amount'] is None
1473 | assert result['cost']['currency'] == 'USD'
1474 | assert result['cost']['formatted'] is None
1475 |
1476 | def test_format_usage_item_response_no_historical_bill_interval(self):
1477 | """Test format_usage_item_response with historical usage but no bill interval."""
1478 | # Setup
1479 | usage_item = {
1480 | 'id': 'usage-123',
1481 | 'serviceCode': 'AmazonEC2',
1482 | 'historicalUsage': {
1483 | 'serviceCode': 'AmazonEC2',
1484 | 'usageType': 'BoxUsage:t3.medium',
1485 | 'operation': 'RunInstances',
1486 | 'location': 'US East (N. Virginia)',
1487 | 'usageAccountId': '123456789012',
1488 | # No billInterval
1489 | },
1490 | }
1491 |
1492 | # Execute
1493 | result = format_usage_item_response(usage_item)
1494 |
1495 | # Assert
1496 | assert 'historical_usage' in result
1497 | historical = result['historical_usage']
1498 | assert 'bill_interval' not in historical
1499 |
1500 | def test_format_usage_item_response_empty_historical_usage(self):
1501 | """Test format_usage_item_response with empty historical usage."""
1502 | # Setup
1503 | usage_item = {
1504 | 'id': 'usage-123',
1505 | 'serviceCode': 'AmazonEC2',
1506 | 'historicalUsage': {},
1507 | }
1508 |
1509 | # Execute
1510 | result = format_usage_item_response(usage_item)
1511 |
1512 | # Assert
1513 | # Empty historicalUsage dict should not add historical_usage to result
1514 | assert 'historical_usage' not in result
1515 | assert result['id'] == 'usage-123'
1516 | assert result['service_code'] == 'AmazonEC2'
1517 |
1518 | @patch(
1519 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1520 | )
1521 | @patch(
1522 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1523 | )
1524 | @patch(
1525 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.handle_aws_error'
1526 | )
1527 | async def test_get_workload_estimate_exception(
1528 | self, mock_handle_error, mock_create_client, mock_get_preferences, mock_context
1529 | ):
1530 | """Test get_workload_estimate handles exceptions properly."""
1531 | # Setup
1532 | error = ClientError(
1533 | {'Error': {'Code': 'ResourceNotFoundException', 'Message': 'Estimate not found'}},
1534 | 'GetWorkloadEstimate',
1535 | )
1536 | mock_get_preferences.return_value = {'account_types': ['management account']}
1537 | mock_create_client.return_value.get_workload_estimate.side_effect = error
1538 | mock_handle_error.return_value = {'status': 'error', 'message': 'Estimate not found'}
1539 |
1540 | # Execute
1541 | result = await get_workload_estimate(mock_context, identifier='nonexistent-estimate')
1542 |
1543 | # Assert
1544 | mock_handle_error.assert_called_once_with(
1545 | mock_context, error, 'get_workload_estimate', 'BCM Pricing Calculator'
1546 | )
1547 | assert result['status'] == 'error'
1548 |
1549 | @patch(
1550 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1551 | )
1552 | @patch(
1553 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.create_aws_client'
1554 | )
1555 | @patch(
1556 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.handle_aws_error'
1557 | )
1558 | async def test_list_workload_estimate_usage_exception(
1559 | self, mock_handle_error, mock_create_client, mock_get_preferences, mock_context
1560 | ):
1561 | """Test list_workload_estimate_usage handles exceptions properly."""
1562 | # Setup
1563 | error = BotoCoreError()
1564 | mock_get_preferences.return_value = {'account_types': ['management account']}
1565 | mock_create_client.return_value.list_workload_estimate_usage.side_effect = error
1566 | mock_handle_error.return_value = {'status': 'error', 'message': 'Connection error'}
1567 |
1568 | # Execute
1569 | result = await list_workload_estimate_usage(
1570 | mock_context, workload_estimate_id='estimate-123'
1571 | )
1572 |
1573 | # Assert
1574 | mock_handle_error.assert_called_once_with(
1575 | mock_context, error, 'list_workload_estimate_usage', 'BCM Pricing Calculator'
1576 | )
1577 | assert result['status'] == 'error'
1578 |
1579 |
1580 | @pytest.mark.parametrize(
1581 | 'status,expected_indicator',
1582 | [
1583 | ('VALID', 'Valid'),
1584 | ('UPDATING', 'Updating'),
1585 | ('INVALID', 'Invalid'),
1586 | ('ACTION_NEEDED', 'Action Needed'),
1587 | ('UNKNOWN', '❓ UNKNOWN'),
1588 | ],
1589 | )
1590 | def test_format_workload_estimate_response_status_indicators(status, expected_indicator):
1591 | """Test format_workload_estimate_response status indicators."""
1592 | # Setup
1593 | estimate = {
1594 | 'id': 'estimate-123',
1595 | 'name': 'Test Estimate',
1596 | 'status': status,
1597 | }
1598 |
1599 | # Execute
1600 | result = format_workload_estimate_response(estimate)
1601 |
1602 | # Assert
1603 | assert result['status_indicator'] == expected_indicator
1604 |
1605 |
1606 | @pytest.mark.parametrize(
1607 | 'status,expected_indicator',
1608 | [
1609 | ('VALID', 'Valid'),
1610 | ('INVALID', 'Invalid'),
1611 | ('STALE', 'Stale'),
1612 | ('UNKNOWN', '❓ UNKNOWN'),
1613 | ],
1614 | )
1615 | def test_format_usage_item_response_status_indicators(status, expected_indicator):
1616 | """Test format_usage_item_response status indicators."""
1617 | # Setup
1618 | usage_item = {
1619 | 'id': 'usage-123',
1620 | 'serviceCode': 'AmazonEC2',
1621 | 'status': status,
1622 | }
1623 |
1624 | # Execute
1625 | result = format_usage_item_response(usage_item)
1626 |
1627 | # Assert
1628 | assert result['status_indicator'] == expected_indicator
1629 |
1630 |
1631 | @pytest.mark.asyncio
1632 | class TestBcmPricingCalcCoreFunction:
1633 | """Tests for the core bcm_pricing_calc_core function (lines 101-149)."""
1634 |
1635 | async def test_bcm_pricing_calc_core_invalid_operation(self, mock_context):
1636 | """Test bcm_pricing_calc_core with invalid operation (covers lines 106-113)."""
1637 | # Execute - call the core function directly
1638 | result = await bcm_pricing_calc_core(mock_context, operation='invalid_operation')
1639 |
1640 | # Assert
1641 | assert result['status'] == 'error'
1642 | assert 'Invalid operation' in result['message']
1643 | assert 'invalid_parameter' in result['data']
1644 | mock_context.info.assert_called_with(
1645 | 'Received BCM Pricing Calculator operation: invalid_operation'
1646 | )
1647 |
1648 | @patch(
1649 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_workload_estimate'
1650 | )
1651 | async def test_bcm_pricing_calc_core_get_workload_estimate_operation(
1652 | self, mock_get_workload_estimate, mock_context
1653 | ):
1654 | """Test bcm_pricing_calc_core with get_workload_estimate operation (covers lines 115-117)."""
1655 | # Setup
1656 | mock_get_workload_estimate.return_value = {
1657 | 'status': 'success',
1658 | 'data': {'workload_estimate': {}},
1659 | }
1660 |
1661 | # Execute - call the core function directly
1662 | result = await bcm_pricing_calc_core(
1663 | mock_context, operation='get_workload_estimate', identifier='estimate-123'
1664 | )
1665 |
1666 | # Assert
1667 | mock_get_workload_estimate.assert_called_once_with(mock_context, 'estimate-123')
1668 | assert result['status'] == 'success'
1669 | mock_context.info.assert_called_with(
1670 | 'Received BCM Pricing Calculator operation: get_workload_estimate'
1671 | )
1672 |
1673 | @patch(
1674 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.list_workload_estimates'
1675 | )
1676 | async def test_bcm_pricing_calc_core_list_workload_estimates_operation(
1677 | self, mock_list_workload_estimates, mock_context
1678 | ):
1679 | """Test bcm_pricing_calc_core with list_workload_estimates operation (covers lines 118-121)."""
1680 | # Setup
1681 | mock_list_workload_estimates.return_value = {
1682 | 'status': 'success',
1683 | 'data': {'workload_estimates': []},
1684 | }
1685 |
1686 | # Execute - call the core function directly
1687 | result = await bcm_pricing_calc_core(
1688 | mock_context,
1689 | operation='list_workload_estimates',
1690 | created_after='2023-01-01T00:00:00Z',
1691 | created_before='2023-12-31T23:59:59Z',
1692 | expires_after='2023-06-01T00:00:00Z',
1693 | expires_before='2024-01-01T00:00:00Z',
1694 | status_filter='VALID',
1695 | name_filter='Test',
1696 | name_match_option='CONTAINS',
1697 | next_token='token123',
1698 | max_results=50,
1699 | )
1700 |
1701 | # Assert
1702 | mock_list_workload_estimates.assert_called_once_with(
1703 | mock_context,
1704 | '2023-01-01T00:00:00Z',
1705 | '2023-12-31T23:59:59Z',
1706 | '2023-06-01T00:00:00Z',
1707 | '2024-01-01T00:00:00Z',
1708 | 'VALID',
1709 | 'Test',
1710 | 'CONTAINS',
1711 | 'token123',
1712 | 50,
1713 | None,
1714 | )
1715 | assert result['status'] == 'success'
1716 | mock_context.info.assert_called_with(
1717 | 'Received BCM Pricing Calculator operation: list_workload_estimates'
1718 | )
1719 |
1720 | @patch(
1721 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.list_workload_estimate_usage'
1722 | )
1723 | async def test_bcm_pricing_calc_core_list_workload_estimate_usage_operation(
1724 | self, mock_list_usage, mock_context
1725 | ):
1726 | """Test bcm_pricing_calc_core with list_workload_estimate_usage operation (covers lines 122-125)."""
1727 | # Setup
1728 | mock_list_usage.return_value = {'status': 'success', 'data': {'usage_items': []}}
1729 |
1730 | # Execute - call the core function directly
1731 | result = await bcm_pricing_calc_core(
1732 | mock_context,
1733 | operation='list_workload_estimate_usage',
1734 | identifier='estimate-123',
1735 | usage_account_id_filter='123456789012',
1736 | service_code_filter='AmazonEC2',
1737 | usage_type_filter='BoxUsage',
1738 | operation_filter='RunInstances',
1739 | location_filter='US East (N. Virginia)',
1740 | usage_group_filter='EC2-Instance',
1741 | next_token='usage-token',
1742 | max_results=100,
1743 | )
1744 |
1745 | # Assert
1746 | mock_list_usage.assert_called_once_with(
1747 | mock_context,
1748 | 'estimate-123',
1749 | '123456789012',
1750 | 'AmazonEC2',
1751 | 'BoxUsage',
1752 | 'RunInstances',
1753 | 'US East (N. Virginia)',
1754 | 'EC2-Instance',
1755 | 'usage-token',
1756 | 100,
1757 | None,
1758 | )
1759 | assert result['status'] == 'success'
1760 | mock_context.info.assert_called_with(
1761 | 'Received BCM Pricing Calculator operation: list_workload_estimate_usage'
1762 | )
1763 |
1764 | @patch(
1765 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1766 | )
1767 | async def test_bcm_pricing_calc_core_get_preferences_operation_success(
1768 | self, mock_get_preferences, mock_context
1769 | ):
1770 | """Test bcm_pricing_calc_core with get_preferences operation - success case (covers lines 126-133)."""
1771 | # Setup
1772 | mock_get_preferences.return_value = {'account_types': ['management account']}
1773 |
1774 | # Execute - call the core function directly
1775 | result = await bcm_pricing_calc_core(mock_context, operation='get_preferences')
1776 |
1777 | # Assert
1778 | mock_get_preferences.assert_called_once_with(mock_context)
1779 | assert result['status'] == 'success'
1780 | assert result['data']['message'] == 'Preferences are properly configured'
1781 | mock_context.info.assert_called_with(
1782 | 'Received BCM Pricing Calculator operation: get_preferences'
1783 | )
1784 |
1785 | @patch(
1786 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_preferences'
1787 | )
1788 | async def test_bcm_pricing_calc_core_get_preferences_operation_not_configured(
1789 | self, mock_get_preferences, mock_context
1790 | ):
1791 | """Test bcm_pricing_calc_core with get_preferences operation - not configured case (covers lines 127-131)."""
1792 | # Setup
1793 | mock_get_preferences.return_value = {
1794 | 'error': 'BCM Pricing Calculator preferences are not configured. Please configure preferences before using this service.'
1795 | }
1796 |
1797 | # Execute - call the core function directly
1798 | result = await bcm_pricing_calc_core(mock_context, operation='get_preferences')
1799 |
1800 | # Assert
1801 | mock_get_preferences.assert_called_once_with(mock_context)
1802 | assert result['status'] == 'error'
1803 | assert result['data']['error'] == PREFERENCES_NOT_CONFIGURED_ERROR
1804 | assert result['message'] == PREFERENCES_NOT_CONFIGURED_ERROR
1805 | mock_context.info.assert_called_with(
1806 | 'Received BCM Pricing Calculator operation: get_preferences'
1807 | )
1808 |
1809 | @patch(
1810 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.get_workload_estimate'
1811 | )
1812 | @patch(
1813 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.handle_aws_error'
1814 | )
1815 | async def test_bcm_pricing_calc_core_exception_handling(
1816 | self, mock_handle_error, mock_get_workload_estimate, mock_context
1817 | ):
1818 | """Test bcm_pricing_calc_core exception handling (covers lines 137-149)."""
1819 | # Setup
1820 | test_error = Exception('Test error')
1821 | mock_get_workload_estimate.side_effect = test_error
1822 | mock_handle_error.return_value = {
1823 | 'data': {'error': 'Test error message'},
1824 | 'status': 'error',
1825 | }
1826 |
1827 | # Execute - call the core function directly
1828 | result = await bcm_pricing_calc_core(
1829 | mock_context, operation='get_workload_estimate', identifier='estimate-123'
1830 | )
1831 |
1832 | # Assert
1833 | mock_handle_error.assert_called_once_with(
1834 | mock_context,
1835 | test_error,
1836 | 'get_workload_estimate',
1837 | 'AWS Billing and Cost Management Pricing Calculator',
1838 | )
1839 | mock_context.error.assert_called_once()
1840 | error_call_args = mock_context.error.call_args[0][0]
1841 | assert (
1842 | 'Failed to process AWS Billing and Cost Management Pricing Calculator request'
1843 | in error_call_args
1844 | )
1845 | assert 'Test error message' in error_call_args
1846 |
1847 | assert result['status'] == 'error'
1848 | assert result['data']['error'] == 'Test error message'
1849 | assert (
1850 | 'Failed to process AWS Billing and Cost Management Pricing Calculator request'
1851 | in result['message']
1852 | )
1853 |
1854 | @patch(
1855 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.list_workload_estimates'
1856 | )
1857 | @patch(
1858 | 'awslabs.billing_cost_management_mcp_server.tools.bcm_pricing_calculator_tools.handle_aws_error'
1859 | )
1860 | async def test_bcm_pricing_calc_core_exception_handling_no_error_in_response(
1861 | self, mock_handle_error, mock_list_estimates, mock_context
1862 | ):
1863 | """Test bcm_pricing_calc_core exception handling when error response has no error field (covers lines 137-149)."""
1864 | # Setup
1865 | test_error = Exception('Direct error message')
1866 | mock_list_estimates.side_effect = test_error
1867 | mock_handle_error.return_value = {
1868 | 'data': {}, # No error field in data
1869 | 'status': 'error',
1870 | }
1871 |
1872 | # Execute - call the core function directly
1873 | result = await bcm_pricing_calc_core(mock_context, operation='list_workload_estimates')
1874 |
1875 | # Assert
1876 | mock_handle_error.assert_called_once_with(
1877 | mock_context,
1878 | test_error,
1879 | 'list_workload_estimates',
1880 | 'AWS Billing and Cost Management Pricing Calculator',
1881 | )
1882 | mock_context.error.assert_called_once()
1883 | error_call_args = mock_context.error.call_args[0][0]
1884 | assert (
1885 | 'Failed to process AWS Billing and Cost Management Pricing Calculator request'
1886 | in error_call_args
1887 | )
1888 | assert 'Direct error message' in error_call_args
1889 |
1890 | assert result['status'] == 'error'
1891 | assert result['data']['error'] == 'Direct error message'
1892 | assert (
1893 | 'Failed to process AWS Billing and Cost Management Pricing Calculator request'
1894 | in result['message']
1895 | )
1896 |
```