#
tokens: 59263/50000 1/2448 files (page 507/522)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 507 of 522. Use http://codebase.md/awslabs/mcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .devcontainer
│   └── devcontainer.json
├── .github
│   ├── actions
│   │   ├── build-and-push-container-image
│   │   │   └── action.yml
│   │   └── clear-space-ubuntu-latest-agressively
│   │       └── action.yml
│   ├── codecov.yml
│   ├── CODEOWNERS
│   ├── dependabot.yml
│   ├── ISSUE_TEMPLATE
│   │   ├── bug_report.yml
│   │   ├── documentation.yml
│   │   ├── feature_request.yml
│   │   ├── rfc.yml
│   │   └── support_awslabs_mcp_servers.yml
│   ├── pull_request_template.md
│   ├── SECURITY
│   ├── SUPPORT
│   └── workflows
│       ├── aws-api-mcp-upgrade-version.yml
│       ├── bandit-requirements.txt
│       ├── bandit.yml
│       ├── cfn_nag.yml
│       ├── check-gh-pages-builds.yml
│       ├── check-license-header-hash.txt
│       ├── check-license-header.json
│       ├── check-license-header.yml
│       ├── checkov.yml
│       ├── codeql.yml
│       ├── dependency-review-action.yml
│       ├── detect-secrets-requirements.txt
│       ├── gh-pages.yml
│       ├── merge-prevention.yml
│       ├── powershell.yml
│       ├── pre-commit-requirements.txt
│       ├── pre-commit.yml
│       ├── pull-request-lint.yml
│       ├── python.yml
│       ├── RELEASE_INSTRUCTIONS.md
│       ├── release-initiate-branch.yml
│       ├── release-merge-tag.yml
│       ├── release.py
│       ├── release.yml
│       ├── scanners.yml
│       ├── scorecard-analysis.yml
│       ├── semgrep-requirements.txt
│       ├── semgrep.yml
│       ├── stale.yml
│       ├── trivy.yml
│       └── typescript.yml
├── .gitignore
├── .pre-commit-config.yaml
├── .python-version
├── .ruff.toml
├── .secrets.baseline
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── DESIGN_GUIDELINES.md
├── DEVELOPER_GUIDE.md
├── docs
│   └── images
│       └── root-readme
│           ├── cline-api-provider-filled.png
│           ├── cline-chat-interface.png
│           ├── cline-custom-instructions.png
│           ├── cline-select-aws-profile.png
│           ├── cline-select-bedrock.png
│           ├── configure-mcp-servers.png
│           ├── install-cline-extension.png
│           ├── mcp-servers-installed.png
│           └── select-mcp-servers.png
├── docusaurus
│   ├── .gitignore
│   ├── docs
│   │   ├── installation.md
│   │   ├── intro.md
│   │   ├── samples
│   │   │   ├── index.md
│   │   │   ├── mcp-integration-with-kb.md
│   │   │   ├── mcp-integration-with-nova-canvas.md
│   │   │   └── stepfunctions-tool-mcp-server.md
│   │   ├── servers
│   │   │   ├── amazon-bedrock-agentcore-mcp-server.md
│   │   │   ├── amazon-keyspaces-mcp-server.md
│   │   │   ├── amazon-mq-mcp-server.md
│   │   │   ├── amazon-neptune-mcp-server.md
│   │   │   ├── amazon-qbusiness-anonymous-mcp-server.md
│   │   │   ├── amazon-qindex-mcp-server.md
│   │   │   ├── amazon-sns-sqs-mcp-server.md
│   │   │   ├── aurora-dsql-mcp-server.md
│   │   │   ├── aws-api-mcp-server.md
│   │   │   ├── aws-appsync-mcp-server.md
│   │   │   ├── aws-bedrock-custom-model-import-mcp-server.md
│   │   │   ├── aws-bedrock-data-automation-mcp-server.md
│   │   │   ├── aws-dataprocessing-mcp-server.md
│   │   │   ├── aws-diagram-mcp-server.md
│   │   │   ├── aws-documentation-mcp-server.md
│   │   │   ├── aws-healthomics-mcp-server.md
│   │   │   ├── aws-iot-sitewise-mcp-server.md
│   │   │   ├── aws-knowledge-mcp-server.md
│   │   │   ├── aws-location-mcp-server.md
│   │   │   ├── aws-msk-mcp-server.md
│   │   │   ├── aws-pricing-mcp-server.md
│   │   │   ├── aws-serverless-mcp-server.md
│   │   │   ├── aws-support-mcp-server.md
│   │   │   ├── bedrock-kb-retrieval-mcp-server.md
│   │   │   ├── billing-cost-management-mcp-server.md
│   │   │   ├── ccapi-mcp-server.md
│   │   │   ├── cdk-mcp-server.md
│   │   │   ├── cfn-mcp-server.md
│   │   │   ├── cloudtrail-mcp-server.md
│   │   │   ├── cloudwatch-appsignals-mcp-server.md
│   │   │   ├── cloudwatch-mcp-server.md
│   │   │   ├── code-doc-gen-mcp-server.md
│   │   │   ├── core-mcp-server.md
│   │   │   ├── cost-explorer-mcp-server.md
│   │   │   ├── documentdb-mcp-server.md
│   │   │   ├── dynamodb-mcp-server.md
│   │   │   ├── ecs-mcp-server.md
│   │   │   ├── eks-mcp-server.md
│   │   │   ├── elasticache-mcp-server.md
│   │   │   ├── finch-mcp-server.md
│   │   │   ├── frontend-mcp-server.md
│   │   │   ├── git-repo-research-mcp-server.md
│   │   │   ├── healthlake-mcp-server.md
│   │   │   ├── iam-mcp-server.md
│   │   │   ├── kendra-index-mcp-server.md
│   │   │   ├── lambda-tool-mcp-server.md
│   │   │   ├── memcached-mcp-server.md
│   │   │   ├── mysql-mcp-server.md
│   │   │   ├── nova-canvas-mcp-server.md
│   │   │   ├── openapi-mcp-server.md
│   │   │   ├── postgres-mcp-server.md
│   │   │   ├── prometheus-mcp-server.md
│   │   │   ├── redshift-mcp-server.md
│   │   │   ├── s3-tables-mcp-server.md
│   │   │   ├── stepfunctions-tool-mcp-server.md
│   │   │   ├── syntheticdata-mcp-server.md
│   │   │   ├── terraform-mcp-server.md
│   │   │   ├── timestream-for-influxdb-mcp-server.md
│   │   │   ├── valkey-mcp-server.md
│   │   │   └── well-architected-security-mcp-server.mdx
│   │   └── vibe_coding.md
│   ├── docusaurus.config.ts
│   ├── package-lock.json
│   ├── package.json
│   ├── README.md
│   ├── sidebars.ts
│   ├── src
│   │   ├── components
│   │   │   ├── HomepageFeatures
│   │   │   │   └── styles.module.css
│   │   │   └── ServerCards
│   │   │       ├── index.tsx
│   │   │       └── styles.module.css
│   │   ├── css
│   │   │   ├── custom.css
│   │   │   └── doc-override.css
│   │   └── pages
│   │       ├── index.module.css
│   │       └── servers.tsx
│   ├── static
│   │   ├── .nojekyll
│   │   ├── assets
│   │   │   ├── icons
│   │   │   │   ├── activity.svg
│   │   │   │   ├── book-open.svg
│   │   │   │   ├── cpu.svg
│   │   │   │   ├── database.svg
│   │   │   │   ├── dollar-sign.svg
│   │   │   │   ├── help-circle.svg
│   │   │   │   ├── key.svg
│   │   │   │   ├── server.svg
│   │   │   │   ├── share-2.svg
│   │   │   │   ├── tool.svg
│   │   │   │   └── zap.svg
│   │   │   └── server-cards.json
│   │   └── img
│   │       ├── aws-logo.svg
│   │       └── logo.png
│   └── tsconfig.json
├── LICENSE
├── NOTICE
├── README.md
├── samples
│   ├── mcp-integration-with-kb
│   │   ├── .env.example
│   │   ├── .python-version
│   │   ├── assets
│   │   │   └── simplified-mcp-flow-diagram.png
│   │   ├── clients
│   │   │   └── client_server.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── user_interfaces
│   │   │   └── chat_bedrock_st.py
│   │   └── uv.lock
│   ├── mcp-integration-with-nova-canvas
│   │   ├── .env.example
│   │   ├── .python-version
│   │   ├── clients
│   │   │   └── client_server.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── user_interfaces
│   │   │   └── image_generator_st.py
│   │   └── uv.lock
│   ├── README.md
│   └── stepfunctions-tool-mcp-server
│       ├── README.md
│       └── sample_state_machines
│           ├── customer-create
│           │   └── app.py
│           ├── customer-id-from-email
│           │   └── app.py
│           ├── customer-info-from-id
│           │   └── app.py
│           └── template.yml
├── scripts
│   ├── README.md
│   └── verify_package_name.py
├── src
│   ├── amazon-bedrock-agentcore-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_bedrock_agentcore_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── config.py
│   │   │       ├── server.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── cache.py
│   │   │           ├── doc_fetcher.py
│   │   │           ├── indexer.py
│   │   │           ├── text_processor.py
│   │   │           └── url_validator.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── SECURITY.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_cache.py
│   │   │   ├── test_config.py
│   │   │   ├── test_doc_fetcher.py
│   │   │   ├── test_indexer.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_server.py
│   │   │   ├── test_text_processor.py
│   │   │   └── test_url_validator.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── amazon-kendra-index-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_kendra_index_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── server.py
│   │   │       └── util.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── amazon-keyspaces-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_keyspaces_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── client.py
│   │   │       ├── config.py
│   │   │       ├── consts.py
│   │   │       ├── llm_context.py
│   │   │       ├── models.py
│   │   │       ├── server.py
│   │   │       └── services.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_tests.sh
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_client.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_query_analysis_service.py
│   │   │   ├── test_server.py
│   │   │   └── test_services.py
│   │   └── uv.lock
│   ├── amazon-mq-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_mq_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── aws_service_mcp_generator.py
│   │   │       ├── consts.py
│   │   │       ├── rabbitmq
│   │   │       │   ├── __init__.py
│   │   │       │   ├── admin.py
│   │   │       │   ├── connection.py
│   │   │       │   ├── doc
│   │   │       │   │   ├── rabbitmq_broker_sizing_guide.md
│   │   │       │   │   ├── rabbitmq_performance_optimization_best_practice.md
│   │   │       │   │   ├── rabbitmq_production_deployment_guidelines.md
│   │   │       │   │   ├── rabbitmq_quorum_queue_migration_guide.md
│   │   │       │   │   └── rabbitmq_setup_best_practice.md
│   │   │       │   ├── handlers.py
│   │   │       │   └── module.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── example
│   │   │   └── sample_mcp_q_cli.json
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── rabbitmq
│   │   │   │   ├── __init__.py
│   │   │   │   ├── conftest.py
│   │   │   │   ├── test_admin.py
│   │   │   │   ├── test_connection.py
│   │   │   │   ├── test_handlers.py
│   │   │   │   └── test_module.py
│   │   │   ├── test_aws_service_mcp_generator.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── amazon-neptune-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_neptune_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── exceptions.py
│   │   │       ├── graph_store
│   │   │       │   ├── __init__.py
│   │   │       │   ├── analytics.py
│   │   │       │   ├── base.py
│   │   │       │   └── database.py
│   │   │       ├── models.py
│   │   │       ├── neptune.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_analytics.py
│   │   │   ├── test_database.py
│   │   │   ├── test_exceptions.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_models.py
│   │   │   ├── test_neptune.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── amazon-qbusiness-anonymous-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_qbusiness_anonymous_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── clients.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── amazon-qindex-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_qindex_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── clients.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_clients.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   └── test_server.py
│   │   └── uv.lock
│   ├── amazon-sns-sqs-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── amazon_sns_sqs_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── common.py
│   │   │       ├── consts.py
│   │   │       ├── generator.py
│   │   │       ├── server.py
│   │   │       ├── sns.py
│   │   │       └── sqs.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── print_tools.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_tests.sh
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── README.md
│   │   │   ├── test_common.py
│   │   │   ├── test_generator.py
│   │   │   ├── test_server.py
│   │   │   ├── test_sns.py
│   │   │   └── test_sqs.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aurora-dsql-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aurora_dsql_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── consts.py
│   │   │       ├── mutable_sql_detector.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_connection_reuse.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_profile_option.py
│   │   │   ├── test_readonly_enforcement.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-api-mcp-server
│   │   ├── .gitattributes
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_api_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── core
│   │   │       │   ├── __init__.py
│   │   │       │   ├── agent_scripts
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── manager.py
│   │   │       │   │   ├── models.py
│   │   │       │   │   └── registry
│   │   │       │   │       ├── __init__.py
│   │   │       │   │       ├── application-failure-troubleshooting.script.md
│   │   │       │   │       ├── cloudtral-mutli-region-setup.script.md
│   │   │       │   │       ├── create_amazon_aurora_db_cluster_with_instances.script.md
│   │   │       │   │       ├── lambda-timeout-debugging.script.md
│   │   │       │   │       ├── scripts_format.md
│   │   │       │   │       └── troubleshoot-permissions-with-cloudtrail-events.script.md
│   │   │       │   ├── aws
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── driver.py
│   │   │       │   │   ├── pagination.py
│   │   │       │   │   ├── regions.py
│   │   │       │   │   ├── service.py
│   │   │       │   │   └── services.py
│   │   │       │   ├── common
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── command_metadata.py
│   │   │       │   │   ├── command.py
│   │   │       │   │   ├── config.py
│   │   │       │   │   ├── errors.py
│   │   │       │   │   ├── file_operations.py
│   │   │       │   │   ├── file_system_controls.py
│   │   │       │   │   ├── helpers.py
│   │   │       │   │   ├── models.py
│   │   │       │   │   └── py.typed
│   │   │       │   ├── data
│   │   │       │   │   └── api_metadata.json
│   │   │       │   ├── metadata
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   └── read_only_operations_list.py
│   │   │       │   ├── parser
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── custom_validators
│   │   │       │   │   │   ├── __init__.py
│   │   │       │   │   │   ├── botocore_param_validator.py
│   │   │       │   │   │   ├── ec2_validator.py
│   │   │       │   │   │   └── ssm_validator.py
│   │   │       │   │   ├── interpretation.py
│   │   │       │   │   ├── lexer.py
│   │   │       │   │   └── parser.py
│   │   │       │   ├── py.typed
│   │   │       │   └── security
│   │   │       │       ├── __init__.py
│   │   │       │       ├── aws_api_customization.json
│   │   │       │       └── policy.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── agent_scripts
│   │   │   │   ├── __init__.py
│   │   │   │   ├── test_manager.py
│   │   │   │   └── test_registry
│   │   │   │       ├── another_valid_script.script.md
│   │   │   │       ├── test_script.script.md
│   │   │   │       └── valid_script.script.md
│   │   │   ├── aws
│   │   │   │   ├── __init__.py
│   │   │   │   ├── test_driver.py
│   │   │   │   ├── test_pagination.py
│   │   │   │   ├── test_service.py
│   │   │   │   └── test_services.py
│   │   │   ├── common
│   │   │   │   ├── test_command.py
│   │   │   │   ├── test_config.py
│   │   │   │   ├── test_file_operations.py
│   │   │   │   ├── test_file_system_controls.py
│   │   │   │   ├── test_file_validation.py
│   │   │   │   └── test_helpers.py
│   │   │   ├── fixtures.py
│   │   │   ├── history_handler.py
│   │   │   ├── metadata
│   │   │   │   ├── __init__.py
│   │   │   │   └── test_read_only_operations_list.py
│   │   │   ├── parser
│   │   │   │   ├── __init__.py
│   │   │   │   ├── test_file_path_detection.py
│   │   │   │   ├── test_lexer.py
│   │   │   │   ├── test_parser_customizations.py
│   │   │   │   └── test_parser.py
│   │   │   ├── test_security_policy.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-appsync-mcp-server
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_appsync_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── decorators.py
│   │   │       ├── helpers.py
│   │   │       ├── operations
│   │   │       │   ├── __init__.py
│   │   │       │   ├── create_api_cache.py
│   │   │       │   ├── create_api_key.py
│   │   │       │   ├── create_api.py
│   │   │       │   ├── create_channel_namespace.py
│   │   │       │   ├── create_datasource.py
│   │   │       │   ├── create_domain_name.py
│   │   │       │   ├── create_function.py
│   │   │       │   ├── create_graphql_api.py
│   │   │       │   ├── create_resolver.py
│   │   │       │   └── create_schema.py
│   │   │       ├── server.py
│   │   │       ├── tools
│   │   │       │   ├── __init__.py
│   │   │       │   ├── create_api_cache.py
│   │   │       │   ├── create_api_key.py
│   │   │       │   ├── create_api.py
│   │   │       │   ├── create_channel_namespace.py
│   │   │       │   ├── create_datasource.py
│   │   │       │   ├── create_domain_name.py
│   │   │       │   ├── create_function.py
│   │   │       │   ├── create_graphql_api.py
│   │   │       │   ├── create_resolver.py
│   │   │       │   └── create_schema.py
│   │   │       └── validators.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_all_create_tools_write_protection.py
│   │   │   ├── test_create_api_cache.py
│   │   │   ├── test_create_api_key.py
│   │   │   ├── test_create_api.py
│   │   │   ├── test_create_channel_namespace.py
│   │   │   ├── test_create_datasource_tool.py
│   │   │   ├── test_create_datasource.py
│   │   │   ├── test_create_domain_name.py
│   │   │   ├── test_create_function.py
│   │   │   ├── test_create_graphql_api.py
│   │   │   ├── test_create_resolver.py
│   │   │   ├── test_create_schema_tool.py
│   │   │   ├── test_create_schema.py
│   │   │   ├── test_helpers.py
│   │   │   ├── test_server.py
│   │   │   ├── test_validators.py
│   │   │   └── test_write_operation.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-bedrock-custom-model-import-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_bedrock_custom_model_import_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── client.py
│   │   │       ├── llm_context.py
│   │   │       ├── models.py
│   │   │       ├── prompts.py
│   │   │       ├── server.py
│   │   │       ├── services
│   │   │       │   ├── __init__.py
│   │   │       │   ├── imported_model_service.py
│   │   │       │   └── model_import_service.py
│   │   │       ├── tools
│   │   │       │   ├── create_model_import_job.py
│   │   │       │   ├── delete_imported_model.py
│   │   │       │   ├── get_imported_model.py
│   │   │       │   ├── get_model_import_job.py
│   │   │       │   ├── list_imported_models.py
│   │   │       │   └── list_model_import_jobs.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── aws.py
│   │   │           ├── config.py
│   │   │           ├── consts.py
│   │   │           └── matching.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── services
│   │   │   │   ├── test_imported_model_service.py
│   │   │   │   └── test_model_import_service.py
│   │   │   ├── test_client.py
│   │   │   ├── test_init.py
│   │   │   ├── test_llm_context.py
│   │   │   ├── test_prompts.py
│   │   │   ├── test_server.py
│   │   │   ├── tools
│   │   │   │   ├── test_create_model_import_job.py
│   │   │   │   ├── test_delete_imported_model.py
│   │   │   │   ├── test_get_imported_model.py
│   │   │   │   ├── test_get_model_import_job.py
│   │   │   │   ├── test_list_imported_models.py
│   │   │   │   └── test_list_model_import_jobs.py
│   │   │   └── utils
│   │   │       ├── test_aws.py
│   │   │       ├── test_config.py
│   │   │       └── test_matching.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-bedrock-data-automation-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_bedrock_data_automation_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── helpers.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_helpers.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-dataprocessing-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_dataprocessing_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── core
│   │   │       │   ├── __init__.py
│   │   │       │   └── glue_data_catalog
│   │   │       │       ├── __init__.py
│   │   │       │       ├── data_catalog_database_manager.py
│   │   │       │       ├── data_catalog_handler.py
│   │   │       │       └── data_catalog_table_manager.py
│   │   │       ├── handlers
│   │   │       │   ├── __init__.py
│   │   │       │   ├── athena
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── athena_data_catalog_handler.py
│   │   │       │   │   ├── athena_query_handler.py
│   │   │       │   │   └── athena_workgroup_handler.py
│   │   │       │   ├── commons
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   └── common_resource_handler.py
│   │   │       │   ├── emr
│   │   │       │   │   ├── emr_ec2_cluster_handler.py
│   │   │       │   │   ├── emr_ec2_instance_handler.py
│   │   │       │   │   └── emr_ec2_steps_handler.py
│   │   │       │   └── glue
│   │   │       │       ├── __init__.py
│   │   │       │       ├── crawler_handler.py
│   │   │       │       ├── data_catalog_handler.py
│   │   │       │       ├── glue_commons_handler.py
│   │   │       │       ├── glue_etl_handler.py
│   │   │       │       ├── interactive_sessions_handler.py
│   │   │       │       └── worklows_handler.py
│   │   │       ├── models
│   │   │       │   ├── __init__.py
│   │   │       │   ├── athena_models.py
│   │   │       │   ├── common_resource_models.py
│   │   │       │   ├── data_catalog_models.py
│   │   │       │   ├── emr_models.py
│   │   │       │   └── glue_models.py
│   │   │       ├── server.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── aws_helper.py
│   │   │           ├── consts.py
│   │   │           ├── logging_helper.py
│   │   │           └── mutable_sql_detector.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── core
│   │   │   │   ├── __init__.py
│   │   │   │   └── glue_data_catalog
│   │   │   │       ├── __init__.py
│   │   │   │       ├── test_data_catalog_database_manager.py
│   │   │   │       ├── test_data_catalog_handler.py
│   │   │   │       └── test_data_catalog_table_manager.py
│   │   │   ├── handlers
│   │   │   │   ├── __init__.py
│   │   │   │   ├── athena
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── test_athena_data_catalog_handler.py
│   │   │   │   │   ├── test_athena_query_handler.py
│   │   │   │   │   ├── test_athena_workgroup_handler.py
│   │   │   │   │   └── test_custom_tags_athena.py
│   │   │   │   ├── commons
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   └── test_common_resource_handler.py
│   │   │   │   ├── emr
│   │   │   │   │   ├── __init__.py
│   │   │   │   │   ├── test_custom_tags_emr.py
│   │   │   │   │   ├── test_emr_ec2_cluster_handler.py
│   │   │   │   │   ├── test_emr_ec2_instance_handler.py
│   │   │   │   │   └── test_emr_ec2_steps_handler.py
│   │   │   │   └── glue
│   │   │   │       ├── __init__.py
│   │   │   │       ├── test_crawler_handler.py
│   │   │   │       ├── test_custom_tags_glue.py
│   │   │   │       ├── test_data_catalog_handler.py
│   │   │   │       ├── test_glue_commons_handler.py
│   │   │   │       ├── test_glue_etl_handler.py
│   │   │   │       ├── test_glue_interactive_sessions_handler.py
│   │   │   │       └── test_glue_workflows_handler.py
│   │   │   ├── models
│   │   │   │   ├── __init__.py
│   │   │   │   ├── test_athena_models.py
│   │   │   │   ├── test_common_resource_models.py
│   │   │   │   ├── test_data_catalog_models.py
│   │   │   │   ├── test_emr_models.py
│   │   │   │   ├── test_glue_models.py
│   │   │   │   ├── test_interactive_sessions_models.py
│   │   │   │   └── test_workflows_models.py
│   │   │   ├── test_init.py
│   │   │   ├── test_server.py
│   │   │   └── utils
│   │   │       ├── __init__.py
│   │   │       ├── test_aws_helper.py
│   │   │       ├── test_custom_tags.py
│   │   │       └── test_logging_helper.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-diagram-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_diagram_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── diagrams_tools.py
│   │   │       ├── models.py
│   │   │       ├── scanner.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── conftest.py
│   │   │   ├── README.md
│   │   │   ├── resources
│   │   │   │   ├── __init__.py
│   │   │   │   └── example_diagrams
│   │   │   │       ├── __init__.py
│   │   │   │       ├── aws_example.py
│   │   │   │       ├── flow_example.py
│   │   │   │       └── sequence_example.py
│   │   │   ├── test_diagrams.py
│   │   │   ├── test_models.py
│   │   │   ├── test_sarif_fix.py
│   │   │   ├── test_scanner.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-documentation-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_documentation_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── models.py
│   │   │       ├── server_aws_cn.py
│   │   │       ├── server_aws.py
│   │   │       ├── server_utils.py
│   │   │       ├── server.py
│   │   │       └── util.py
│   │   ├── basic-usage.gif
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── constants.py
│   │   │   ├── resources
│   │   │   │   └── lambda_sns_raw.html
│   │   │   ├── test_aws_cn_get_available_services_live.py
│   │   │   ├── test_aws_cn_read_documentation_live.py
│   │   │   ├── test_aws_read_documentation_live.py
│   │   │   ├── test_aws_recommend_live.py
│   │   │   ├── test_aws_search_live.py
│   │   │   ├── test_metadata_handling.py
│   │   │   ├── test_models.py
│   │   │   ├── test_server_aws_cn.py
│   │   │   ├── test_server_aws.py
│   │   │   ├── test_server_utils.py
│   │   │   ├── test_server.py
│   │   │   └── test_util.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-healthomics-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_healthomics_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── consts.py
│   │   │       ├── models.py
│   │   │       ├── server.py
│   │   │       ├── tools
│   │   │       │   ├── __init__.py
│   │   │       │   ├── helper_tools.py
│   │   │       │   ├── run_analysis.py
│   │   │       │   ├── troubleshooting.py
│   │   │       │   ├── workflow_analysis.py
│   │   │       │   ├── workflow_execution.py
│   │   │       │   ├── workflow_linting.py
│   │   │       │   └── workflow_management.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── aws_utils.py
│   │   │           ├── s3_utils.py
│   │   │           └── validation_utils.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── docs
│   │   │   └── workflow_linting.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   ├── test_aws_utils.py
│   │   │   ├── test_consts.py
│   │   │   ├── test_helper_tools.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_models.py
│   │   │   ├── test_run_analysis.py
│   │   │   ├── test_s3_utils.py
│   │   │   ├── test_server.py
│   │   │   ├── test_troubleshooting.py
│   │   │   ├── test_workflow_analysis.py
│   │   │   ├── test_workflow_execution.py
│   │   │   ├── test_workflow_linting.py
│   │   │   ├── test_workflow_management.py
│   │   │   └── test_workflow_tools.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-iot-sitewise-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_iot_sitewise_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── client.py
│   │   │       ├── models.py
│   │   │       ├── prompts
│   │   │       │   ├── __init__.py
│   │   │       │   ├── asset_hierarchy.py
│   │   │       │   ├── bulk_import_workflow.py
│   │   │       │   ├── data_exploration.py
│   │   │       │   └── data_ingestion.py
│   │   │       ├── server.py
│   │   │       ├── tool_metadata.py
│   │   │       ├── tools
│   │   │       │   ├── __init__.py
│   │   │       │   ├── sitewise_access.py
│   │   │       │   ├── sitewise_asset_models.py
│   │   │       │   ├── sitewise_assets.py
│   │   │       │   ├── sitewise_data.py
│   │   │       │   ├── sitewise_gateways.py
│   │   │       │   └── sitewise_metadata_transfer.py
│   │   │       └── validation.py
│   │   ├── CHANGELOG.md
│   │   ├── DEVELOPMENT.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── examples
│   │   │   └── wind_farm_example.py
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_server.py
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_client.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_models.py
│   │   │   ├── test_server.py
│   │   │   ├── test_sitewise_access.py
│   │   │   ├── test_sitewise_asset_models.py
│   │   │   ├── test_sitewise_assets.py
│   │   │   ├── test_sitewise_data.py
│   │   │   ├── test_sitewise_gateways.py
│   │   │   ├── test_sitewise_metadata_transfer.py
│   │   │   └── test_validation.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-knowledge-mcp-server
│   │   └── README.md
│   ├── aws-location-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_location_server
│   │   │       ├── __init__.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_server_integration.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-msk-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_msk_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── server.py
│   │   │       └── tools
│   │   │           ├── __init__.py
│   │   │           ├── common_functions
│   │   │           │   ├── __init__.py
│   │   │           │   ├── client_manager.py
│   │   │           │   └── common_functions.py
│   │   │           ├── logs_and_telemetry
│   │   │           │   ├── __init__.py
│   │   │           │   ├── cluster_metrics_tools.py
│   │   │           │   ├── list_customer_iam_access.py
│   │   │           │   └── metric_config.py
│   │   │           ├── mutate_cluster
│   │   │           │   ├── __init__.py
│   │   │           │   ├── batch_associate_scram_secret.py
│   │   │           │   ├── batch_disassociate_scram_secret.py
│   │   │           │   ├── create_cluster_v2.py
│   │   │           │   ├── put_cluster_policy.py
│   │   │           │   ├── reboot_broker.py
│   │   │           │   ├── update_broker_count.py
│   │   │           │   ├── update_broker_storage.py
│   │   │           │   ├── update_broker_type.py
│   │   │           │   ├── update_cluster_configuration.py
│   │   │           │   ├── update_monitoring.py
│   │   │           │   └── update_security.py
│   │   │           ├── mutate_config
│   │   │           │   ├── __init__.py
│   │   │           │   ├── create_configuration.py
│   │   │           │   ├── tag_resource.py
│   │   │           │   ├── untag_resource.py
│   │   │           │   └── update_configuration.py
│   │   │           ├── mutate_vpc
│   │   │           │   ├── __init__.py
│   │   │           │   ├── create_vpc_connection.py
│   │   │           │   ├── delete_vpc_connection.py
│   │   │           │   └── reject_client_vpc_connection.py
│   │   │           ├── read_cluster
│   │   │           │   ├── __init__.py
│   │   │           │   ├── describe_cluster_operation.py
│   │   │           │   ├── describe_cluster.py
│   │   │           │   ├── get_bootstrap_brokers.py
│   │   │           │   ├── get_cluster_policy.py
│   │   │           │   ├── get_compatible_kafka_versions.py
│   │   │           │   ├── list_client_vpc_connections.py
│   │   │           │   ├── list_cluster_operations.py
│   │   │           │   ├── list_nodes.py
│   │   │           │   └── list_scram_secrets.py
│   │   │           ├── read_config
│   │   │           │   ├── __init__.py
│   │   │           │   ├── describe_configuration_revision.py
│   │   │           │   ├── describe_configuration.py
│   │   │           │   ├── list_configuration_revisions.py
│   │   │           │   └── list_tags_for_resource.py
│   │   │           ├── read_global
│   │   │           │   ├── __init__.py
│   │   │           │   ├── list_clusters.py
│   │   │           │   ├── list_configurations.py
│   │   │           │   ├── list_kafka_versions.py
│   │   │           │   └── list_vpc_connections.py
│   │   │           ├── read_vpc
│   │   │           │   ├── __init__.py
│   │   │           │   └── describe_vpc_connection.py
│   │   │           └── static_tools
│   │   │               ├── __init__.py
│   │   │               └── cluster_best_practices.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_client_manager.py
│   │   │   ├── test_cluster_metrics_tools.py
│   │   │   ├── test_common_functions.py
│   │   │   ├── test_create_cluster_v2.py
│   │   │   ├── test_create_configuration.py
│   │   │   ├── test_create_vpc_connection.py
│   │   │   ├── test_delete_vpc_connection.py
│   │   │   ├── test_describe_cluster_operation.py
│   │   │   ├── test_describe_cluster.py
│   │   │   ├── test_describe_configuration_revision.py
│   │   │   ├── test_describe_configuration.py
│   │   │   ├── test_describe_vpc_connection.py
│   │   │   ├── test_get_bootstrap_brokers.py
│   │   │   ├── test_get_cluster_policy.py
│   │   │   ├── test_get_compatible_kafka_versions.py
│   │   │   ├── test_init.py
│   │   │   ├── test_list_client_vpc_connections.py
│   │   │   ├── test_list_cluster_operations.py
│   │   │   ├── test_list_clusters.py
│   │   │   ├── test_list_configuration_revisions.py
│   │   │   ├── test_list_configurations.py
│   │   │   ├── test_list_customer_iam_access.py
│   │   │   ├── test_list_kafka_versions.py
│   │   │   ├── test_list_nodes.py
│   │   │   ├── test_list_scram_secrets.py
│   │   │   ├── test_list_tags_for_resource.py
│   │   │   ├── test_list_vpc_connections.py
│   │   │   ├── test_logs_and_telemetry.py
│   │   │   ├── test_main.py
│   │   │   ├── test_mutate_cluster_init.py
│   │   │   ├── test_mutate_cluster_success_cases.py
│   │   │   ├── test_mutate_cluster.py
│   │   │   ├── test_mutate_config_init.py
│   │   │   ├── test_mutate_vpc_init.py
│   │   │   ├── test_read_cluster_init_updated.py
│   │   │   ├── test_read_cluster_init.py
│   │   │   ├── test_read_config_init.py
│   │   │   ├── test_read_global_init.py
│   │   │   ├── test_read_vpc_init.py
│   │   │   ├── test_reject_client_vpc_connection.py
│   │   │   ├── test_server.py
│   │   │   ├── test_static_tools_init.py
│   │   │   ├── test_tag_resource.py
│   │   │   ├── test_tool_descriptions.py
│   │   │   ├── test_untag_resource.py
│   │   │   └── test_update_configuration.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-pricing-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_pricing_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── cdk_analyzer.py
│   │   │       ├── consts.py
│   │   │       ├── helpers.py
│   │   │       ├── models.py
│   │   │       ├── pricing_client.py
│   │   │       ├── pricing_transformer.py
│   │   │       ├── report_generator.py
│   │   │       ├── server.py
│   │   │       ├── static
│   │   │       │   ├── __init__.py
│   │   │       │   ├── COST_REPORT_TEMPLATE.md
│   │   │       │   └── patterns
│   │   │       │       ├── __init__.py
│   │   │       │       └── BEDROCK.md
│   │   │       └── terraform_analyzer.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_cdk_analyzer.py
│   │   │   ├── test_helpers.py
│   │   │   ├── test_pricing_client.py
│   │   │   ├── test_pricing_transformer.py
│   │   │   ├── test_report_generator.py
│   │   │   ├── test_server.py
│   │   │   └── test_terraform_analyzer.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── aws-serverless-mcp-server
│   │   ├── .pre-commit.config.yaml
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_serverless_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── models.py
│   │   │       ├── resources
│   │   │       │   ├── __init__.py
│   │   │       │   ├── deployment_details.py
│   │   │       │   ├── deployment_list.py
│   │   │       │   ├── template_details.py
│   │   │       │   └── template_list.py
│   │   │       ├── server.py
│   │   │       ├── template
│   │   │       │   ├── __init__.py
│   │   │       │   ├── registry.py
│   │   │       │   ├── renderer.py
│   │   │       │   └── templates
│   │   │       │       ├── backend.j2
│   │   │       │       ├── frontend.j2
│   │   │       │       ├── fullstack.j2
│   │   │       │       └── README.md
│   │   │       ├── tools
│   │   │       │   ├── common
│   │   │       │   │   └── base_tool.py
│   │   │       │   ├── guidance
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── deploy_serverless_app_help.py
│   │   │       │   │   ├── get_iac_guidance.py
│   │   │       │   │   ├── get_lambda_event_schemas.py
│   │   │       │   │   ├── get_lambda_guidance.py
│   │   │       │   │   └── get_serverless_templates.py
│   │   │       │   ├── poller
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── esm_diagnosis.py
│   │   │       │   │   ├── esm_guidance.py
│   │   │       │   │   └── esm_recommend.py
│   │   │       │   ├── sam
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── sam_build.py
│   │   │       │   │   ├── sam_deploy.py
│   │   │       │   │   ├── sam_init.py
│   │   │       │   │   ├── sam_local_invoke.py
│   │   │       │   │   └── sam_logs.py
│   │   │       │   ├── schemas
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── describe_schema.py
│   │   │       │   │   ├── list_registries.py
│   │   │       │   │   └── search_schema.py
│   │   │       │   └── webapps
│   │   │       │       ├── __init__.py
│   │   │       │       ├── configure_domain.py
│   │   │       │       ├── deploy_webapp.py
│   │   │       │       ├── get_metrics.py
│   │   │       │       ├── update_webapp_frontend.py
│   │   │       │       ├── utils
│   │   │       │       │   ├── deploy_service.py
│   │   │       │       │   ├── frontend_uploader.py
│   │   │       │       │   └── startup_script_generator.py
│   │   │       │       └── webapp_deployment_help.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── aws_client_helper.py
│   │   │           ├── cloudformation.py
│   │   │           ├── const.py
│   │   │           ├── deployment_manager.py
│   │   │           ├── github.py
│   │   │           └── process.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── README.md
│   │   │   ├── test_cloudformation.py
│   │   │   ├── test_configure_domain.py
│   │   │   ├── test_deploy_serverless_app_help.py
│   │   │   ├── test_deploy_service.py
│   │   │   ├── test_deploy_webapp.py
│   │   │   ├── test_deployment_details.py
│   │   │   ├── test_deployment_help.py
│   │   │   ├── test_deployment_list.py
│   │   │   ├── test_deployment_manager.py
│   │   │   ├── test_esm_diagnosis.py
│   │   │   ├── test_esm_guidance.py
│   │   │   ├── test_esm_recommend.py
│   │   │   ├── test_frontend_uploader.py
│   │   │   ├── test_get_iac_guidance.py
│   │   │   ├── test_get_lambda_event_schemas.py
│   │   │   ├── test_get_lambda_guidance.py
│   │   │   ├── test_get_metrics.py
│   │   │   ├── test_get_serverless_templates.py
│   │   │   ├── test_github.py
│   │   │   ├── test_models.py
│   │   │   ├── test_process.py
│   │   │   ├── test_sam_build.py
│   │   │   ├── test_sam_deploy.py
│   │   │   ├── test_sam_init.py
│   │   │   ├── test_sam_local_invoke.py
│   │   │   ├── test_sam_logs.py
│   │   │   ├── test_schemas.py
│   │   │   ├── test_server.py
│   │   │   ├── test_startup_script_generator.py
│   │   │   ├── test_template_details.py
│   │   │   ├── test_template_list.py
│   │   │   ├── test_template_registry.py
│   │   │   ├── test_template_renderer.py
│   │   │   └── test_update_webapp_frontend.py
│   │   └── uv.lock
│   ├── aws-support-mcp-server
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── aws_support_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── client.py
│   │   │       ├── consts.py
│   │   │       ├── debug_helper.py
│   │   │       ├── errors.py
│   │   │       ├── formatters.py
│   │   │       ├── models.py
│   │   │       └── server.py
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftests.py
│   │   │   ├── test_aws_support_mcp_server.py
│   │   │   └── test_models.py
│   │   └── uv.lock
│   ├── bedrock-kb-retrieval-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── bedrock_kb_retrieval_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── knowledgebases
│   │   │       │   ├── __init__.py
│   │   │       │   ├── clients.py
│   │   │       │   ├── discovery.py
│   │   │       │   └── retrieval.py
│   │   │       ├── models.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_tests.sh
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── conftest.py
│   │   │   ├── README.md
│   │   │   ├── test_clients.py
│   │   │   ├── test_discovery.py
│   │   │   ├── test_env_config.py
│   │   │   ├── test_models.py
│   │   │   ├── test_retrieval.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── billing-cost-management-mcp-server
│   │   ├── __init__.py
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── billing_cost_management_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── models.py
│   │   │       ├── prompts
│   │   │       │   ├── __init__.py
│   │   │       │   ├── decorator.py
│   │   │       │   ├── graviton_migration.py
│   │   │       │   ├── README.md
│   │   │       │   ├── savings_plans.py
│   │   │       │   └── types.py
│   │   │       ├── server.py
│   │   │       ├── templates
│   │   │       │   └── recommendation_templates
│   │   │       │       ├── ebs_volume.template
│   │   │       │       ├── ec2_asg.template
│   │   │       │       ├── ec2_instance.template
│   │   │       │       ├── ecs_service.template
│   │   │       │       ├── idle.template
│   │   │       │       ├── lambda_function.template
│   │   │       │       ├── rds_database.template
│   │   │       │       ├── reserved_instances.template
│   │   │       │       └── savings_plans.template
│   │   │       ├── tools
│   │   │       │   ├── __init__.py
│   │   │       │   ├── aws_pricing_operations.py
│   │   │       │   ├── aws_pricing_tools.py
│   │   │       │   ├── bcm_pricing_calculator_tools.py
│   │   │       │   ├── budget_tools.py
│   │   │       │   ├── compute_optimizer_tools.py
│   │   │       │   ├── cost_anomaly_tools.py
│   │   │       │   ├── cost_comparison_tools.py
│   │   │       │   ├── cost_explorer_operations.py
│   │   │       │   ├── cost_explorer_tools.py
│   │   │       │   ├── cost_optimization_hub_helpers.py
│   │   │       │   ├── cost_optimization_hub_tools.py
│   │   │       │   ├── free_tier_usage_tools.py
│   │   │       │   ├── recommendation_details_tools.py
│   │   │       │   ├── ri_performance_tools.py
│   │   │       │   ├── sp_performance_tools.py
│   │   │       │   ├── storage_lens_tools.py
│   │   │       │   └── unified_sql_tools.py
│   │   │       └── utilities
│   │   │           ├── __init__.py
│   │   │           ├── aws_service_base.py
│   │   │           ├── constants.py
│   │   │           ├── logging_utils.py
│   │   │           └── sql_utils.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── requirements.txt
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── prompts
│   │   │   │   ├── __init__.py
│   │   │   │   └── test_prompts.py
│   │   │   ├── README.md
│   │   │   ├── test_models.py
│   │   │   ├── test_server.py
│   │   │   ├── tools
│   │   │   │   ├── __init__.py
│   │   │   │   ├── fixtures.py
│   │   │   │   ├── test_aws_bcm_pricing_calculator_tools.py
│   │   │   │   ├── test_aws_pricing_tools.py
│   │   │   │   ├── test_budget_tools.py
│   │   │   │   ├── test_compute_optimizer_tools.py
│   │   │   │   ├── test_cost_anomaly_tools_enhanced.py
│   │   │   │   ├── test_cost_anomaly_tools.py
│   │   │   │   ├── test_cost_comparison_tools.py
│   │   │   │   ├── test_cost_explorer_operations.py
│   │   │   │   ├── test_cost_explorer_tools.py
│   │   │   │   ├── test_cost_optimization_hub_helpers.py
│   │   │   │   ├── test_cost_optimization_hub_tools.py
│   │   │   │   ├── test_free_tier_usage_tools_new.py
│   │   │   │   ├── test_recommendation_details_tools.py
│   │   │   │   ├── test_ri_performance_tools.py
│   │   │   │   ├── test_sp_performance_tools.py
│   │   │   │   ├── test_storage_lens_tools.py
│   │   │   │   └── test_unified_sql_tools.py
│   │   │   └── utilities
│   │   │       ├── test_aws_service_base.py
│   │   │       └── test_sql_utils.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── ccapi-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── ccapi_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── aws_client.py
│   │   │       ├── cloud_control_utils.py
│   │   │       ├── context.py
│   │   │       ├── errors.py
│   │   │       ├── iac_generator.py
│   │   │       ├── impl
│   │   │       │   ├── __init__.py
│   │   │       │   ├── tools
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── explanation.py
│   │   │       │   │   ├── infrastructure_generation.py
│   │   │       │   │   ├── resource_operations.py
│   │   │       │   │   ├── security_scanning.py
│   │   │       │   │   └── session_management.py
│   │   │       │   └── utils
│   │   │       │       ├── __init__.py
│   │   │       │       └── validation.py
│   │   │       ├── infrastructure_generator.py
│   │   │       ├── models
│   │   │       │   ├── __init__.py
│   │   │       │   └── models.py
│   │   │       ├── schema_manager.py
│   │   │       ├── server.py
│   │   │       └── static
│   │   │           └── __init__.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_tests.sh
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_aws_client.py
│   │   │   ├── test_checkov_install.py
│   │   │   ├── test_cloud_control_utils.py
│   │   │   ├── test_context.py
│   │   │   ├── test_errors.py
│   │   │   ├── test_explanation.py
│   │   │   ├── test_iac_generator.py
│   │   │   ├── test_infrastructure_generation.py
│   │   │   ├── test_infrastructure_generator.py
│   │   │   ├── test_models.py
│   │   │   ├── test_resource_operations.py
│   │   │   ├── test_schema_manager.py
│   │   │   ├── test_security_scanning.py
│   │   │   ├── test_server.py
│   │   │   ├── test_session_management.py
│   │   │   └── test_validation.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── cdk-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── cdk_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── core
│   │   │       │   ├── __init__.py
│   │   │       │   ├── resources.py
│   │   │       │   ├── search_utils.py
│   │   │       │   ├── server.py
│   │   │       │   └── tools.py
│   │   │       ├── data
│   │   │       │   ├── __init__.py
│   │   │       │   ├── cdk_nag_parser.py
│   │   │       │   ├── construct_descriptions.py
│   │   │       │   ├── genai_cdk_loader.py
│   │   │       │   ├── lambda_layer_parser.py
│   │   │       │   ├── lambda_powertools_loader.py
│   │   │       │   ├── schema_generator.py
│   │   │       │   └── solutions_constructs_parser.py
│   │   │       ├── server.py
│   │   │       └── static
│   │   │           ├── __init__.py
│   │   │           ├── CDK_GENERAL_GUIDANCE.md
│   │   │           ├── CDK_NAG_GUIDANCE.md
│   │   │           └── lambda_powertools
│   │   │               ├── bedrock.md
│   │   │               ├── cdk.md
│   │   │               ├── dependencies.md
│   │   │               ├── index.md
│   │   │               ├── insights.md
│   │   │               ├── logging.md
│   │   │               ├── metrics.md
│   │   │               └── tracing.md
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── core
│   │   │   │   ├── test_resources_enhanced.py
│   │   │   │   ├── test_resources.py
│   │   │   │   ├── test_search_utils.py
│   │   │   │   ├── test_server.py
│   │   │   │   └── test_tools.py
│   │   │   └── data
│   │   │       ├── test_cdk_nag_parser.py
│   │   │       ├── test_genai_cdk_loader.py
│   │   │       ├── test_lambda_powertools_loader.py
│   │   │       ├── test_schema_generator.py
│   │   │       └── test_solutions_constructs_parser.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── cfn-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── cfn_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── aws_client.py
│   │   │       ├── cloud_control_utils.py
│   │   │       ├── context.py
│   │   │       ├── errors.py
│   │   │       ├── iac_generator.py
│   │   │       ├── schema_manager.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_tests.sh
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_aws_client.py
│   │   │   ├── test_cloud_control_utils.py
│   │   │   ├── test_errors.py
│   │   │   ├── test_iac_generator.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_schema_manager.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── cloudtrail-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── cloudtrail_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── common.py
│   │   │       ├── models.py
│   │   │       ├── server.py
│   │   │       └── tools.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_models.py
│   │   │   ├── test_server.py
│   │   │   └── test_tools.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── cloudwatch-appsignals-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── cloudwatch_appsignals_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── audit_presentation_utils.py
│   │   │       ├── audit_utils.py
│   │   │       ├── aws_clients.py
│   │   │       ├── canary_utils.py
│   │   │       ├── server.py
│   │   │       ├── service_audit_utils.py
│   │   │       ├── service_tools.py
│   │   │       ├── sli_report_client.py
│   │   │       ├── slo_tools.py
│   │   │       ├── trace_tools.py
│   │   │       └── utils.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   ├── test_audit_presentation_utils.py
│   │   │   ├── test_audit_utils.py
│   │   │   ├── test_aws_profile.py
│   │   │   ├── test_canary_utils.py
│   │   │   ├── test_initialization.py
│   │   │   ├── test_server_audit_functions.py
│   │   │   ├── test_server_audit_tools.py
│   │   │   ├── test_server.py
│   │   │   ├── test_service_audit_utils.py
│   │   │   ├── test_service_tools_operations.py
│   │   │   ├── test_sli_report_client.py
│   │   │   ├── test_slo_tools.py
│   │   │   └── test_utils.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── cloudwatch-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── cloudwatch_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── cloudwatch_alarms
│   │   │       │   ├── models.py
│   │   │       │   └── tools.py
│   │   │       ├── cloudwatch_logs
│   │   │       │   ├── models.py
│   │   │       │   └── tools.py
│   │   │       ├── cloudwatch_metrics
│   │   │       │   ├── data
│   │   │       │   │   └── metric_metadata.json
│   │   │       │   ├── models.py
│   │   │       │   └── tools.py
│   │   │       ├── common.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── cloudwatch_alarms
│   │   │   │   ├── test_active_alarms.py
│   │   │   │   ├── test_alarm_history_integration.py
│   │   │   │   ├── test_alarm_history.py
│   │   │   │   └── test_alarms_error_handling.py
│   │   │   ├── cloudwatch_logs
│   │   │   │   ├── test_logs_error_handling.py
│   │   │   │   ├── test_logs_models.py
│   │   │   │   └── test_logs_server.py
│   │   │   ├── cloudwatch_metrics
│   │   │   │   ├── test_metrics_error_handling.py
│   │   │   │   ├── test_metrics_models.py
│   │   │   │   ├── test_metrics_server.py
│   │   │   │   └── test_validation_error.py
│   │   │   ├── test_common_and_server.py
│   │   │   ├── test_init.py
│   │   │   └── test_main.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── code-doc-gen-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── code_doc_gen_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── server.py
│   │   │       └── utils
│   │   │           ├── doc_generator.py
│   │   │           ├── models.py
│   │   │           ├── repomix_manager.py
│   │   │           └── templates.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_doc_generator_edge_cases.py
│   │   │   ├── test_doc_generator.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_repomix_manager_scenarios.py
│   │   │   ├── test_repomix_manager.py
│   │   │   ├── test_repomix_statistics.py
│   │   │   ├── test_server_extended.py
│   │   │   ├── test_server.py
│   │   │   └── test_templates.py
│   │   └── uv.lock
│   ├── core-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── core_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── server.py
│   │   │       └── static
│   │   │           ├── __init__.py
│   │   │           └── PROMPT_UNDERSTANDING.md
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── README.md
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_response_types.py
│   │   │   ├── test_server.py
│   │   │   └── test_static.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── cost-explorer-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── cost_explorer_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── comparison_handler.py
│   │   │       ├── constants.py
│   │   │       ├── cost_usage_handler.py
│   │   │       ├── forecasting_handler.py
│   │   │       ├── helpers.py
│   │   │       ├── metadata_handler.py
│   │   │       ├── models.py
│   │   │       ├── server.py
│   │   │       └── utility_handler.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_comparison_handler.py
│   │   │   ├── test_cost_usage_handler.py
│   │   │   ├── test_forecasting_handler.py
│   │   │   ├── test_helpers.py
│   │   │   ├── test_metadata_handler.py
│   │   │   ├── test_models.py
│   │   │   ├── test_server.py
│   │   │   └── test_utility_handler.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── documentdb-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   └── documentdb_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── analytic_tools.py
│   │   │       ├── config.py
│   │   │       ├── connection_tools.py
│   │   │       ├── db_management_tools.py
│   │   │       ├── query_tools.py
│   │   │       ├── server.py
│   │   │       └── write_tools.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   ├── test_analytic_tools.py
│   │   │   ├── test_connection_tools.py
│   │   │   ├── test_db_management_tools.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_query_tools.py
│   │   │   └── test_write_tools.py
│   │   └── uv.lock
│   ├── dynamodb-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── dynamodb_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── common.py
│   │   │       ├── database_analysis_queries.py
│   │   │       ├── database_analyzers.py
│   │   │       ├── prompts
│   │   │       │   └── dynamodb_architect.md
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── evals
│   │   │   │   ├── dynamic_evaluators.py
│   │   │   │   ├── evaluation_registry.py
│   │   │   │   ├── logging_config.py
│   │   │   │   ├── multiturn_evaluator.py
│   │   │   │   ├── README.md
│   │   │   │   ├── scenarios.py
│   │   │   │   └── test_dspy_evals.py
│   │   │   ├── test_dynamodb_server.py
│   │   │   └── test_source_db_integration.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── ecs-mcp-server
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── ecs_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── api
│   │   │       │   ├── __init__.py
│   │   │       │   ├── containerize.py
│   │   │       │   ├── delete.py
│   │   │       │   ├── ecs_troubleshooting.py
│   │   │       │   ├── infrastructure.py
│   │   │       │   ├── resource_management.py
│   │   │       │   ├── status.py
│   │   │       │   └── troubleshooting_tools
│   │   │       │       ├── __init__.py
│   │   │       │       ├── detect_image_pull_failures.py
│   │   │       │       ├── fetch_cloudformation_status.py
│   │   │       │       ├── fetch_network_configuration.py
│   │   │       │       ├── fetch_service_events.py
│   │   │       │       ├── fetch_task_failures.py
│   │   │       │       ├── fetch_task_logs.py
│   │   │       │       ├── get_ecs_troubleshooting_guidance.py
│   │   │       │       └── utils.py
│   │   │       ├── main.py
│   │   │       ├── modules
│   │   │       │   ├── __init__.py
│   │   │       │   ├── aws_knowledge_proxy.py
│   │   │       │   ├── containerize.py
│   │   │       │   ├── delete.py
│   │   │       │   ├── deployment_status.py
│   │   │       │   ├── infrastructure.py
│   │   │       │   ├── resource_management.py
│   │   │       │   └── troubleshooting.py
│   │   │       ├── templates
│   │   │       │   ├── ecr_infrastructure.json
│   │   │       │   └── ecs_infrastructure.json
│   │   │       └── utils
│   │   │           ├── arn_parser.py
│   │   │           ├── aws.py
│   │   │           ├── config.py
│   │   │           ├── docker.py
│   │   │           ├── security.py
│   │   │           ├── templates.py
│   │   │           └── time_utils.py
│   │   ├── DEVELOPMENT.md
│   │   ├── pyproject.toml
│   │   ├── pyrightconfig.json
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── integ
│   │   │   │   └── mcp-inspector
│   │   │   │       ├── .gitignore
│   │   │   │       ├── README.md
│   │   │   │       ├── run-tests.sh
│   │   │   │       └── scenarios
│   │   │   │           ├── 01_comprehensive_troubleshooting
│   │   │   │           │   ├── 01_create.sh
│   │   │   │           │   ├── 02_validate.sh
│   │   │   │           │   ├── 03_cleanup.sh
│   │   │   │           │   ├── description.txt
│   │   │   │           │   └── utils
│   │   │   │           │       ├── mcp_helpers.sh
│   │   │   │           │       └── validation_helpers.sh
│   │   │   │           └── 02_test_knowledge_proxy_tools
│   │   │   │               ├── 01_create.sh
│   │   │   │               ├── 02_validate.sh
│   │   │   │               ├── 03_cleanup.sh
│   │   │   │               ├── description.txt
│   │   │   │               └── utils
│   │   │   │                   ├── knowledge_validation_helpers.sh
│   │   │   │                   └── mcp_knowledge_helpers.sh
│   │   │   ├── llm_testing
│   │   │   │   ├── invalid_cfn_template.yaml
│   │   │   │   ├── README.md
│   │   │   │   ├── run_tests.sh
│   │   │   │   ├── scenarios
│   │   │   │   │   ├── 01_cloudformation_failure
│   │   │   │   │   │   ├── 01_create.sh
│   │   │   │   │   │   ├── 02_validate.sh
│   │   │   │   │   │   ├── 03_prompts.txt
│   │   │   │   │   │   ├── 04_evaluation.md
│   │   │   │   │   │   ├── 05_cleanup.sh
│   │   │   │   │   │   └── description.txt
│   │   │   │   │   ├── 02_service_failure
│   │   │   │   │   │   ├── 01_create.sh
│   │   │   │   │   │   ├── 02_validate.sh
│   │   │   │   │   │   ├── 03_prompts.txt
│   │   │   │   │   │   ├── 04_evaluation.md
│   │   │   │   │   │   ├── 05_cleanup.sh
│   │   │   │   │   │   └── description.txt
│   │   │   │   │   ├── 03_task_exit_failure
│   │   │   │   │   │   ├── 01_create.sh
│   │   │   │   │   │   ├── 02_validate.sh
│   │   │   │   │   │   ├── 03_prompts.txt
│   │   │   │   │   │   ├── 04_evaluation.md
│   │   │   │   │   │   ├── 05_cleanup.sh
│   │   │   │   │   │   └── description.txt
│   │   │   │   │   ├── 04_network_configuration_failure
│   │   │   │   │   │   ├── 01_create.sh
│   │   │   │   │   │   ├── 02_validate.sh
│   │   │   │   │   │   ├── 03_prompts.txt
│   │   │   │   │   │   ├── 05_cleanup.sh
│   │   │   │   │   │   └── description.txt
│   │   │   │   │   ├── 05_resource_constraint_failure
│   │   │   │   │   │   ├── 01_create.sh
│   │   │   │   │   │   ├── 02_validate.sh
│   │   │   │   │   │   ├── 03_prompts.txt
│   │   │   │   │   │   ├── 05_cleanup.sh
│   │   │   │   │   │   └── description.txt
│   │   │   │   │   └── 06_load_balancer_failure
│   │   │   │   │       ├── 01_create.sh
│   │   │   │   │       ├── 02_validate.sh
│   │   │   │   │       ├── 03_prompts.txt
│   │   │   │   │       ├── 05_cleanup.sh
│   │   │   │   │       └── description.txt
│   │   │   │   ├── SCRIPT_IMPROVEMENTS.md
│   │   │   │   └── utils
│   │   │   │       ├── aws_helpers.sh
│   │   │   │       └── evaluation_template.md
│   │   │   └── unit
│   │   │       ├── __init__.py
│   │   │       ├── api
│   │   │       │   ├── conftest.py
│   │   │       │   ├── test_delete_api.py
│   │   │       │   ├── test_ecs_troubleshooting.py
│   │   │       │   ├── test_resource_management_api.py
│   │   │       │   └── troubleshooting_tools
│   │   │       │       └── test_fetch_network_configuration.py
│   │   │       ├── conftest.py
│   │   │       ├── modules
│   │   │       │   ├── test_aws_knowledge_proxy.py
│   │   │       │   └── test_resource_management_module.py
│   │   │       ├── test_aws_role_utils.py
│   │   │       ├── test_aws_utils.py
│   │   │       ├── test_containerize.py
│   │   │       ├── test_delete.py
│   │   │       ├── test_docker_utils.py
│   │   │       ├── test_docker_with_role.py
│   │   │       ├── test_image_pull_failure_extended.py
│   │   │       ├── test_image_pull_failure.py
│   │   │       ├── test_infrastructure_role.py
│   │   │       ├── test_infrastructure.py
│   │   │       ├── test_integration.py
│   │   │       ├── test_main.py
│   │   │       ├── test_resource_management_api_operation.py
│   │   │       ├── test_resource_management_tool.py
│   │   │       ├── test_resource_management.py
│   │   │       ├── test_security_integration.py
│   │   │       ├── test_status_pytest.py
│   │   │       ├── test_status.py
│   │   │       ├── troubleshooting_tools
│   │   │       │   ├── __init__.py
│   │   │       │   ├── conftest.py
│   │   │       │   ├── test_detect_image_pull_failures.py
│   │   │       │   ├── test_fetch_cloudformation_status.py
│   │   │       │   ├── test_fetch_service_events.py
│   │   │       │   ├── test_fetch_task_failures.py
│   │   │       │   ├── test_fetch_task_logs.py
│   │   │       │   ├── test_get_ecs_troubleshooting_guidance.py
│   │   │       │   ├── test_is_ecr_image_security.py
│   │   │       │   └── test_utils.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── async_test_utils.py
│   │   │           ├── test_arn_parser.py
│   │   │           ├── test_config.py
│   │   │           ├── test_docker.py
│   │   │           ├── test_response_sanitization.py
│   │   │           ├── test_security_extended.py
│   │   │           ├── test_security.py
│   │   │           ├── test_templates.py
│   │   │           └── test_time_utils.py
│   │   └── uv.lock
│   ├── eks-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── eks_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── aws_helper.py
│   │   │       ├── cloudwatch_handler.py
│   │   │       ├── cloudwatch_metrics_guidance_handler.py
│   │   │       ├── consts.py
│   │   │       ├── data
│   │   │       │   └── eks_cloudwatch_metrics_guidance.json
│   │   │       ├── eks_kb_handler.py
│   │   │       ├── eks_stack_handler.py
│   │   │       ├── iam_handler.py
│   │   │       ├── insights_handler.py
│   │   │       ├── k8s_apis.py
│   │   │       ├── k8s_client_cache.py
│   │   │       ├── k8s_handler.py
│   │   │       ├── logging_helper.py
│   │   │       ├── models.py
│   │   │       ├── scripts
│   │   │       │   └── update_eks_cloudwatch_metrics_guidance.py
│   │   │       ├── server.py
│   │   │       ├── templates
│   │   │       │   ├── eks-templates
│   │   │       │   │   └── eks-with-vpc.yaml
│   │   │       │   └── k8s-templates
│   │   │       │       ├── deployment.yaml
│   │   │       │       └── service.yaml
│   │   │       └── vpc_config_handler.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_aws_helper.py
│   │   │   ├── test_cloudwatch_handler.py
│   │   │   ├── test_cloudwatch_metrics_guidance_handler.py
│   │   │   ├── test_eks_kb_handler.py
│   │   │   ├── test_eks_stack_handler.py
│   │   │   ├── test_iam_handler.py
│   │   │   ├── test_init.py
│   │   │   ├── test_insights_handler.py
│   │   │   ├── test_k8s_apis.py
│   │   │   ├── test_k8s_client_cache.py
│   │   │   ├── test_k8s_handler.py
│   │   │   ├── test_logging_helper.py
│   │   │   ├── test_main.py
│   │   │   ├── test_models.py
│   │   │   ├── test_server.py
│   │   │   └── test_vpc_config_handler.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── elasticache-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── elasticache_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── common
│   │   │       │   ├── __init__.py
│   │   │       │   ├── connection.py
│   │   │       │   ├── decorators.py
│   │   │       │   └── server.py
│   │   │       ├── context.py
│   │   │       ├── main.py
│   │   │       └── tools
│   │   │           ├── __init__.py
│   │   │           ├── cc
│   │   │           │   ├── __init__.py
│   │   │           │   ├── connect.py
│   │   │           │   ├── create.py
│   │   │           │   ├── delete.py
│   │   │           │   ├── describe.py
│   │   │           │   ├── modify.py
│   │   │           │   ├── parsers.py
│   │   │           │   └── processors.py
│   │   │           ├── ce
│   │   │           │   ├── __init__.py
│   │   │           │   └── get_cost_and_usage.py
│   │   │           ├── cw
│   │   │           │   ├── __init__.py
│   │   │           │   └── get_metric_statistics.py
│   │   │           ├── cwlogs
│   │   │           │   ├── __init__.py
│   │   │           │   ├── create_log_group.py
│   │   │           │   ├── describe_log_groups.py
│   │   │           │   ├── describe_log_streams.py
│   │   │           │   ├── filter_log_events.py
│   │   │           │   └── get_log_events.py
│   │   │           ├── firehose
│   │   │           │   ├── __init__.py
│   │   │           │   └── list_delivery_streams.py
│   │   │           ├── misc
│   │   │           │   ├── __init__.py
│   │   │           │   ├── batch_apply_update_action.py
│   │   │           │   ├── batch_stop_update_action.py
│   │   │           │   ├── describe_cache_engine_versions.py
│   │   │           │   ├── describe_engine_default_parameters.py
│   │   │           │   ├── describe_events.py
│   │   │           │   └── describe_service_updates.py
│   │   │           ├── rg
│   │   │           │   ├── __init__.py
│   │   │           │   ├── complete_migration.py
│   │   │           │   ├── connect.py
│   │   │           │   ├── create.py
│   │   │           │   ├── delete.py
│   │   │           │   ├── describe.py
│   │   │           │   ├── modify.py
│   │   │           │   ├── parsers.py
│   │   │           │   ├── processors.py
│   │   │           │   ├── start_migration.py
│   │   │           │   └── test_migration.py
│   │   │           └── serverless
│   │   │               ├── __init__.py
│   │   │               ├── connect.py
│   │   │               ├── create.py
│   │   │               ├── delete.py
│   │   │               ├── describe.py
│   │   │               ├── models.py
│   │   │               └── modify.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_connection.py
│   │   │   ├── test_decorators.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   └── tools
│   │   │       ├── cc
│   │   │       │   ├── __init__.py
│   │   │       │   ├── test_connect_additional.py
│   │   │       │   ├── test_connect_coverage_additional.py
│   │   │       │   ├── test_connect_coverage.py
│   │   │       │   ├── test_connect.py
│   │   │       │   ├── test_create_additional.py
│   │   │       │   ├── test_create.py
│   │   │       │   ├── test_delete.py
│   │   │       │   ├── test_describe.py
│   │   │       │   ├── test_modify.py
│   │   │       │   ├── test_parsers.py
│   │   │       │   └── test_processors.py
│   │   │       ├── ce
│   │   │       │   ├── __init__.py
│   │   │       │   └── test_get_cost_and_usage.py
│   │   │       ├── cw
│   │   │       │   └── test_get_metric_statistics.py
│   │   │       ├── cwlogs
│   │   │       │   ├── __init__.py
│   │   │       │   ├── test_create_log_group.py
│   │   │       │   ├── test_describe_log_groups.py
│   │   │       │   ├── test_describe_log_streams.py
│   │   │       │   ├── test_filter_log_events.py
│   │   │       │   └── test_get_log_events.py
│   │   │       ├── firehose
│   │   │       │   └── test_list_delivery_streams.py
│   │   │       ├── misc
│   │   │       │   ├── __init__.py
│   │   │       │   ├── test_batch_apply_update_action.py
│   │   │       │   ├── test_batch_stop_update_action.py
│   │   │       │   ├── test_describe_cache_engine_versions.py
│   │   │       │   ├── test_describe_engine_default_parameters.py
│   │   │       │   ├── test_describe_events.py
│   │   │       │   └── test_describe_service_updates.py
│   │   │       ├── rg
│   │   │       │   ├── __init__.py
│   │   │       │   ├── test_complete_migration.py
│   │   │       │   ├── test_connect_additional.py
│   │   │       │   ├── test_connect_coverage_additional.py
│   │   │       │   ├── test_connect_optional_fields.py
│   │   │       │   ├── test_connect_partial_coverage.py
│   │   │       │   ├── test_connect.py
│   │   │       │   ├── test_create.py
│   │   │       │   ├── test_delete.py
│   │   │       │   ├── test_describe.py
│   │   │       │   ├── test_modify.py
│   │   │       │   ├── test_parsers.py
│   │   │       │   ├── test_processors.py
│   │   │       │   ├── test_start_migration.py
│   │   │       │   └── test_test_migration.py
│   │   │       └── serverless
│   │   │           ├── test_connect_additional.py
│   │   │           ├── test_connect_coverage_additional.py
│   │   │           ├── test_connect_optional_fields.py
│   │   │           ├── test_connect.py
│   │   │           ├── test_create.py
│   │   │           ├── test_delete.py
│   │   │           ├── test_describe.py
│   │   │           └── test_modify.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── finch-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── finch_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── consts.py
│   │   │       ├── models.py
│   │   │       ├── server.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── build.py
│   │   │           ├── common.py
│   │   │           ├── ecr.py
│   │   │           ├── push.py
│   │   │           └── vm.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── test_cli_flags.py
│   │   │   ├── test_logging_configuration.py
│   │   │   ├── test_server.py
│   │   │   ├── test_utils_build.py
│   │   │   ├── test_utils_common.py
│   │   │   ├── test_utils_ecr.py
│   │   │   ├── test_utils_push.py
│   │   │   └── test_utils_vm.py
│   │   └── uv.lock
│   ├── frontend-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── frontend_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── server.py
│   │   │       ├── static
│   │   │       │   └── react
│   │   │       │       ├── essential-knowledge.md
│   │   │       │       └── troubleshooting.md
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           └── file_utils.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_file_utils.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   └── test_server.py
│   │   └── uv.lock
│   ├── git-repo-research-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── git_repo_research_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── defaults.py
│   │   │       ├── embeddings.py
│   │   │       ├── github_search.py
│   │   │       ├── indexer.py
│   │   │       ├── models.py
│   │   │       ├── repository.py
│   │   │       ├── search.py
│   │   │       ├── server.py
│   │   │       └── utils.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_tests.sh
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_errors_repository.py
│   │   │   ├── test_github_search_edge_cases.py
│   │   │   ├── test_graphql_github_search.py
│   │   │   ├── test_local_repository.py
│   │   │   ├── test_repository_utils.py
│   │   │   ├── test_rest_github_search.py
│   │   │   ├── test_search.py
│   │   │   ├── test_server.py
│   │   │   └── test_url_repository.py
│   │   └── uv.lock
│   ├── healthlake-mcp-server
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── healthlake_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── fhir_operations.py
│   │   │       ├── main.py
│   │   │       ├── models.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── CONTRIBUTING.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── examples
│   │   │   ├── mcp_config.json
│   │   │   └── README.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   ├── test_fhir_client_comprehensive.py
│   │   │   ├── test_fhir_error_scenarios.py
│   │   │   ├── test_fhir_operations.py
│   │   │   ├── test_integration_mock_based.py
│   │   │   ├── test_main_edge_cases.py
│   │   │   ├── test_main.py
│   │   │   ├── test_mcp_integration_coverage.py
│   │   │   ├── test_models_edge_cases.py
│   │   │   ├── test_models.py
│   │   │   ├── test_readonly_mode.py
│   │   │   ├── test_server_core.py
│   │   │   ├── test_server_error_handling.py
│   │   │   ├── test_server_mcp_handlers.py
│   │   │   ├── test_server_toolhandler.py
│   │   │   └── test_server_validation.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── iam-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── iam_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── aws_client.py
│   │   │       ├── context.py
│   │   │       ├── errors.py
│   │   │       ├── models.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── DESIGN_COMPLIANCE.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── examples
│   │   │   ├── get_policy_document_example.py
│   │   │   └── inline_policy_demo.py
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── run_tests.sh
│   │   ├── tests
│   │   │   ├── test_context.py
│   │   │   ├── test_errors.py
│   │   │   ├── test_inline_policies.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── lambda-tool-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── lambda_tool_mcp_server
│   │   │       ├── __init__.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── examples
│   │   │   ├── README.md
│   │   │   └── sample_functions
│   │   │       ├── customer-create
│   │   │       │   └── app.py
│   │   │       ├── customer-id-from-email
│   │   │       │   └── app.py
│   │   │       ├── customer-info-from-id
│   │   │       │   └── app.py
│   │   │       └── template.yml
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── conftest.py
│   │   │   ├── README.md
│   │   │   ├── test_format_lambda_response.py
│   │   │   ├── test_integration_coverage.py
│   │   │   ├── test_integration.py
│   │   │   ├── test_register_lambda_functions.py
│   │   │   ├── test_schema_integration.py
│   │   │   ├── test_server_coverage_additional.py
│   │   │   ├── test_server_coverage.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── mcp-lambda-handler
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   └── mcp_lambda_handler
│   │   │       ├── __init__.py
│   │   │       ├── mcp_lambda_handler.py
│   │   │       ├── session.py
│   │   │       └── types.py
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   └── test_lambda_handler.py
│   │   └── uv.lock
│   ├── memcached-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── memcached_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── common
│   │   │       │   ├── config.py
│   │   │       │   ├── connection.py
│   │   │       │   └── server.py
│   │   │       ├── context.py
│   │   │       ├── main.py
│   │   │       └── tools
│   │   │           └── cache.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── ELASTICACHECONNECT.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_cache_readonly.py
│   │   │   ├── test_cache.py
│   │   │   ├── test_connection.py
│   │   │   ├── test_init.py
│   │   │   └── test_main.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── mysql-mcp-server
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── mysql_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── mutable_sql_detector.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── nova-canvas-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── nova_canvas_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── consts.py
│   │   │       ├── models.py
│   │   │       ├── novacanvas.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── conftest.py
│   │   │   ├── README.md
│   │   │   ├── test_models.py
│   │   │   ├── test_novacanvas.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── openapi-mcp-server
│   │   ├── .coveragerc
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── AUTHENTICATION.md
│   │   ├── AWS_BEST_PRACTICES.md
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── openapi_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── api
│   │   │       │   ├── __init__.py
│   │   │       │   └── config.py
│   │   │       ├── auth
│   │   │       │   ├── __init__.py
│   │   │       │   ├── api_key_auth.py
│   │   │       │   ├── auth_cache.py
│   │   │       │   ├── auth_errors.py
│   │   │       │   ├── auth_factory.py
│   │   │       │   ├── auth_protocol.py
│   │   │       │   ├── auth_provider.py
│   │   │       │   ├── base_auth.py
│   │   │       │   ├── basic_auth.py
│   │   │       │   ├── bearer_auth.py
│   │   │       │   ├── cognito_auth.py
│   │   │       │   └── register.py
│   │   │       ├── patch
│   │   │       │   └── __init__.py
│   │   │       ├── prompts
│   │   │       │   ├── __init__.py
│   │   │       │   ├── generators
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── operation_prompts.py
│   │   │       │   │   └── workflow_prompts.py
│   │   │       │   ├── models.py
│   │   │       │   └── prompt_manager.py
│   │   │       ├── server.py
│   │   │       └── utils
│   │   │           ├── __init__.py
│   │   │           ├── cache_provider.py
│   │   │           ├── config.py
│   │   │           ├── error_handler.py
│   │   │           ├── http_client.py
│   │   │           ├── metrics_provider.py
│   │   │           ├── openapi_validator.py
│   │   │           └── openapi.py
│   │   ├── CHANGELOG.md
│   │   ├── DEPLOYMENT.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── OBSERVABILITY.md
│   │   ├── pyproject.toml
│   │   ├── pyrightconfig.json
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── api
│   │   │   │   └── test_config.py
│   │   │   ├── auth
│   │   │   │   ├── test_api_key_auth.py
│   │   │   │   ├── test_auth_cache.py
│   │   │   │   ├── test_auth_errors.py
│   │   │   │   ├── test_auth_factory_caching.py
│   │   │   │   ├── test_auth_factory_coverage.py
│   │   │   │   ├── test_auth_factory.py
│   │   │   │   ├── test_auth_protocol_additional.py
│   │   │   │   ├── test_auth_protocol_boost.py
│   │   │   │   ├── test_auth_protocol_coverage.py
│   │   │   │   ├── test_auth_protocol_extended.py
│   │   │   │   ├── test_auth_protocol_improved.py
│   │   │   │   ├── test_auth_protocol.py
│   │   │   │   ├── test_auth_provider_additional.py
│   │   │   │   ├── test_base_auth_coverage.py
│   │   │   │   ├── test_base_auth.py
│   │   │   │   ├── test_basic_auth.py
│   │   │   │   ├── test_bearer_auth.py
│   │   │   │   ├── test_cognito_auth_additional_coverage.py
│   │   │   │   ├── test_cognito_auth_boost_coverage.py
│   │   │   │   ├── test_cognito_auth_client_credentials.py
│   │   │   │   ├── test_cognito_auth_coverage_boost.py
│   │   │   │   ├── test_cognito_auth_exceptions.py
│   │   │   │   ├── test_cognito_auth.py
│   │   │   │   ├── test_register_coverage.py
│   │   │   │   └── test_register.py
│   │   │   ├── prompts
│   │   │   │   ├── standalone
│   │   │   │   │   ├── test_operation_prompt.py
│   │   │   │   │   ├── test_prompt_arguments.py
│   │   │   │   │   └── test_secure_operation_prompt.py
│   │   │   │   ├── test_mcp_prompt_manager_integration.py
│   │   │   │   ├── test_mcp_prompt_manager.py
│   │   │   │   ├── test_models_dict_method.py
│   │   │   │   ├── test_operation_prompts_extended.py
│   │   │   │   ├── test_prompt_manager_additional.py
│   │   │   │   ├── test_prompt_manager_comprehensive.py
│   │   │   │   ├── test_prompt_manager_coverage.py
│   │   │   │   └── test_prompt_registration.py
│   │   │   ├── README.md
│   │   │   ├── test_api_name.py
│   │   │   ├── test_cache_coverage_89.py
│   │   │   ├── test_client.py
│   │   │   ├── test_coverage_boost.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main_extended.py
│   │   │   ├── test_main.py
│   │   │   ├── test_openapi_coverage_89.py
│   │   │   ├── test_server_auth_errors.py
│   │   │   ├── test_server_coverage_boost_2.py
│   │   │   ├── test_server_coverage_boost.py
│   │   │   ├── test_server_exception_handling.py
│   │   │   ├── test_server_extended.py
│   │   │   ├── test_server_httpx_version.py
│   │   │   ├── test_server_part1.py
│   │   │   ├── test_server_route_logging.py
│   │   │   ├── test_server_signal_handlers.py
│   │   │   ├── test_server.py
│   │   │   └── utils
│   │   │       ├── test_cache_provider.py
│   │   │       ├── test_error_handler_boost.py
│   │   │       ├── test_error_handler_extended.py
│   │   │       ├── test_error_handler_fix.py
│   │   │       ├── test_error_handler.py
│   │   │       ├── test_http_client_comprehensive.py
│   │   │       ├── test_http_client_extended.py
│   │   │       ├── test_http_client_extended2.py
│   │   │       ├── test_http_client_import_error.py
│   │   │       ├── test_http_client.py
│   │   │       ├── test_metrics_provider_decorators.py
│   │   │       ├── test_metrics_provider_extended2.py
│   │   │       ├── test_metrics_provider_prometheus.py
│   │   │       ├── test_metrics_provider.py
│   │   │       ├── test_openapi_validator.py
│   │   │       └── test_openapi.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── postgres-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── postgres_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── connection
│   │   │       │   ├── __init__.py
│   │   │       │   ├── abstract_db_connection.py
│   │   │       │   ├── db_connection_singleton.py
│   │   │       │   ├── psycopg_pool_connection.py
│   │   │       │   └── rds_api_connection.py
│   │   │       ├── mutable_sql_detector.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   ├── test_psycopg_connector.py
│   │   │   ├── test_server.py
│   │   │   └── test_singleton.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── prometheus-mcp-server
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── prometheus_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── consts.py
│   │   │       ├── models.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── conftest.py
│   │   │   ├── test_aws_credentials.py
│   │   │   ├── test_config_manager.py
│   │   │   ├── test_consts.py
│   │   │   ├── test_coverage_gaps.py
│   │   │   ├── test_coverage_improvement.py
│   │   │   ├── test_final_coverage.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_models.py
│   │   │   ├── test_prometheus_client.py
│   │   │   ├── test_prometheus_connection.py
│   │   │   ├── test_security_validator.py
│   │   │   ├── test_server_coverage.py
│   │   │   ├── test_tools.py
│   │   │   └── test_workspace_config.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── redshift-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── redshift_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── consts.py
│   │   │       ├── models.py
│   │   │       ├── redshift.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_redshift.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── s3-tables-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── s3_tables_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── constants.py
│   │   │       ├── database.py
│   │   │       ├── engines
│   │   │       │   ├── __init__.py
│   │   │       │   └── pyiceberg.py
│   │   │       ├── file_processor
│   │   │       │   ├── __init__.py
│   │   │       │   ├── csv.py
│   │   │       │   ├── parquet.py
│   │   │       │   └── utils.py
│   │   │       ├── models.py
│   │   │       ├── namespaces.py
│   │   │       ├── resources.py
│   │   │       ├── s3_operations.py
│   │   │       ├── server.py
│   │   │       ├── table_buckets.py
│   │   │       ├── tables.py
│   │   │       └── utils.py
│   │   ├── CHANGELOG.md
│   │   ├── CONTEXT.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_csv.py
│   │   │   ├── test_database.py
│   │   │   ├── test_file_processor_utils.py
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   ├── test_namespaces.py
│   │   │   ├── test_parquet.py
│   │   │   ├── test_pyiceberg.py
│   │   │   ├── test_resources.py
│   │   │   ├── test_s3_operations.py
│   │   │   ├── test_server.py
│   │   │   ├── test_table_buckets.py
│   │   │   ├── test_tables.py
│   │   │   └── test_utils.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── stepfunctions-tool-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── stepfunctions_tool_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── aws_helper.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── README.md
│   │   │   ├── test_aws_helper.py
│   │   │   ├── test_create_state_machine_tool.py
│   │   │   ├── test_filter_state_machines_by_tag.py
│   │   │   ├── test_format_state_machine_response.py
│   │   │   ├── test_get_schema_arn_from_state_machine_arn.py
│   │   │   ├── test_get_schema_from_registry.py
│   │   │   ├── test_invoke_express_state_machine_impl.py
│   │   │   ├── test_invoke_standard_state_machine_impl.py
│   │   │   ├── test_main.py
│   │   │   ├── test_register_state_machines.py
│   │   │   ├── test_sanitize_tool_name.py
│   │   │   ├── test_server.py
│   │   │   └── test_validate_state_machine_name.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── syntheticdata-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── syntheticdata_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── pandas_interpreter.py
│   │   │       ├── server.py
│   │   │       └── storage
│   │   │           ├── __init__.py
│   │   │           ├── base.py
│   │   │           ├── loader.py
│   │   │           └── s3.py
│   │   ├── CHANGELOG.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── conftest.py
│   │   │   ├── test_constants.py
│   │   │   ├── test_pandas_interpreter.py
│   │   │   ├── test_server.py
│   │   │   └── test_storage
│   │   │       ├── __init__.py
│   │   │       ├── test_loader.py
│   │   │       └── test_s3.py
│   │   └── uv.lock
│   ├── terraform-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── terraform_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── impl
│   │   │       │   ├── resources
│   │   │       │   │   ├── __init__.py
│   │   │       │   │   ├── terraform_aws_provider_resources_listing.py
│   │   │       │   │   └── terraform_awscc_provider_resources_listing.py
│   │   │       │   └── tools
│   │   │       │       ├── __init__.py
│   │   │       │       ├── execute_terraform_command.py
│   │   │       │       ├── execute_terragrunt_command.py
│   │   │       │       ├── run_checkov_scan.py
│   │   │       │       ├── search_aws_provider_docs.py
│   │   │       │       ├── search_awscc_provider_docs.py
│   │   │       │       ├── search_specific_aws_ia_modules.py
│   │   │       │       ├── search_user_provided_module.py
│   │   │       │       └── utils.py
│   │   │       ├── models
│   │   │       │   ├── __init__.py
│   │   │       │   └── models.py
│   │   │       ├── scripts
│   │   │       │   ├── generate_aws_provider_resources.py
│   │   │       │   ├── generate_awscc_provider_resources.py
│   │   │       │   └── scrape_aws_terraform_best_practices.py
│   │   │       ├── server.py
│   │   │       └── static
│   │   │           ├── __init__.py
│   │   │           ├── AWS_PROVIDER_RESOURCES.md
│   │   │           ├── AWS_TERRAFORM_BEST_PRACTICES.md
│   │   │           ├── AWSCC_PROVIDER_RESOURCES.md
│   │   │           ├── MCP_INSTRUCTIONS.md
│   │   │           └── TERRAFORM_WORKFLOW_GUIDE.md
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── __init__.py
│   │   │   ├── .gitignore
│   │   │   ├── conftest.py
│   │   │   ├── README.md
│   │   │   ├── test_command_impl.py
│   │   │   ├── test_execute_terraform_command.py
│   │   │   ├── test_execute_terragrunt_command.py
│   │   │   ├── test_models.py
│   │   │   ├── test_parameter_annotations.py
│   │   │   ├── test_resources.py
│   │   │   ├── test_run_checkov_scan.py
│   │   │   ├── test_search_user_provided_module.py
│   │   │   ├── test_server.py
│   │   │   ├── test_tool_implementations.py
│   │   │   ├── test_utils_additional.py
│   │   │   └── test_utils.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── timestream-for-influxdb-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── timestream_for_influxdb_mcp_server
│   │   │       ├── __init__.py
│   │   │       └── server.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_init.py
│   │   │   ├── test_main.py
│   │   │   └── test_server.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   ├── valkey-mcp-server
│   │   ├── .gitignore
│   │   ├── .python-version
│   │   ├── awslabs
│   │   │   ├── __init__.py
│   │   │   └── valkey_mcp_server
│   │   │       ├── __init__.py
│   │   │       ├── common
│   │   │       │   ├── __init__.py
│   │   │       │   ├── config.py
│   │   │       │   ├── connection.py
│   │   │       │   └── server.py
│   │   │       ├── context.py
│   │   │       ├── main.py
│   │   │       ├── tools
│   │   │       │   ├── __init__.py
│   │   │       │   ├── bitmap.py
│   │   │       │   ├── hash.py
│   │   │       │   ├── hyperloglog.py
│   │   │       │   ├── json.py
│   │   │       │   ├── list.py
│   │   │       │   ├── misc.py
│   │   │       │   ├── server_management.py
│   │   │       │   ├── set.py
│   │   │       │   ├── sorted_set.py
│   │   │       │   ├── stream.py
│   │   │       │   └── string.py
│   │   │       └── version.py
│   │   ├── CHANGELOG.md
│   │   ├── docker-healthcheck.sh
│   │   ├── Dockerfile
│   │   ├── ELASTICACHECONNECT.md
│   │   ├── LICENSE
│   │   ├── NOTICE
│   │   ├── pyproject.toml
│   │   ├── README.md
│   │   ├── tests
│   │   │   ├── test_bitmap.py
│   │   │   ├── test_config.py
│   │   │   ├── test_connection.py
│   │   │   ├── test_hash.py
│   │   │   ├── test_hyperloglog.py
│   │   │   ├── test_init.py
│   │   │   ├── test_json_additional.py
│   │   │   ├── test_json_readonly.py
│   │   │   ├── test_json.py
│   │   │   ├── test_list_additional.py
│   │   │   ├── test_list_readonly.py
│   │   │   ├── test_list.py
│   │   │   ├── test_main.py
│   │   │   ├── test_misc.py
│   │   │   ├── test_server_management.py
│   │   │   ├── test_set_readonly.py
│   │   │   ├── test_set.py
│   │   │   ├── test_sorted_set_additional.py
│   │   │   ├── test_sorted_set_readonly.py
│   │   │   ├── test_sorted_set.py
│   │   │   ├── test_stream_additional.py
│   │   │   ├── test_stream_readonly.py
│   │   │   ├── test_stream.py
│   │   │   └── test_string.py
│   │   ├── uv-requirements.txt
│   │   └── uv.lock
│   └── well-architected-security-mcp-server
│       ├── .python-version
│       ├── awslabs
│       │   └── well_architected_security_mcp_server
│       │       ├── __init__.py
│       │       ├── consts.py
│       │       ├── server.py
│       │       └── util
│       │           ├── __init__.py
│       │           ├── network_security.py
│       │           ├── prompt_utils.py
│       │           ├── resource_utils.py
│       │           ├── security_services.py
│       │           └── storage_security.py
│       ├── PROMPT_TEMPLATE.md
│       ├── pyproject.toml
│       ├── README.md
│       ├── tests
│       │   ├── __init__.py
│       │   ├── conftest.py
│       │   ├── README.md
│       │   ├── test_access_analyzer_fix.py
│       │   ├── test_network_security_additional.py
│       │   ├── test_network_security.py
│       │   ├── test_prompt_utils_coverage.py
│       │   ├── test_prompt_utils.py
│       │   ├── test_resource_utils_fix.py
│       │   ├── test_resource_utils.py
│       │   ├── test_security_services_additional.py
│       │   ├── test_security_services_coverage.py
│       │   ├── test_security_services.py
│       │   ├── test_server_additional.py
│       │   ├── test_server_coverage.py
│       │   ├── test_server_prompts.py
│       │   ├── test_server_security_findings.py
│       │   ├── test_server.py
│       │   ├── test_storage_security_additional.py
│       │   ├── test_storage_security_comprehensive.py
│       │   ├── test_storage_security_edge_cases.py
│       │   ├── test_storage_security_recommendations.py
│       │   ├── test_storage_security.py
│       │   └── test_user_agent_config.py
│       └── uv.lock
└── VIBE_CODING_TIPS_TRICKS.md
```

# Files

--------------------------------------------------------------------------------
/src/aws-dataprocessing-mcp-server/tests/handlers/commons/test_common_resource_handler.py:
--------------------------------------------------------------------------------

```python
   1 | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
   2 | #
   3 | # Licensed under the Apache License, Version 2.0 (the "License");
   4 | # you may not use this file except in compliance with the License.
   5 | # You may obtain a copy of the License at
   6 | #
   7 | #     http://www.apache.org/licenses/LICENSE-2.0
   8 | #
   9 | # Unless required by applicable law or agreed to in writing, software
  10 | # distributed under the License is distributed on an "AS IS" BASIS,
  11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 | # See the License for the specific language governing permissions and
  13 | # limitations under the License.
  14 | 
  15 | import json
  16 | import pytest
  17 | from awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler import (
  18 |     CommonResourceHandler,
  19 | )
  20 | from botocore.exceptions import ClientError
  21 | from datetime import datetime, timedelta
  22 | from mcp.server.fastmcp import Context
  23 | from typing import Type
  24 | from unittest.mock import Mock, patch
  25 | 
  26 | 
  27 | class Exceptions:
  28 |     """Mock exceptions class for IAM client testing."""
  29 | 
  30 |     class NoSuchEntityException(ClientError):
  31 |         """Mock NoSuchEntityException for testing IAM client exceptions."""
  32 | 
  33 |         def __init__(self):
  34 |             """Initialize the NoSuchEntityException with appropriate error response."""
  35 |             operation_name = 'GetRolePolicy'
  36 |             error_response = {
  37 |                 'Error': {'Code': 'NoSuchEntity', 'Message': 'Role policy not found'}
  38 |             }
  39 |             super().__init__(error_response, operation_name)
  40 | 
  41 | 
  42 | class MockIAMClient(Mock):
  43 |     """Mock IAM client for testing with exception handling capabilities."""
  44 | 
  45 |     exceptions: Type[Exceptions]
  46 | 
  47 |     def __init__(self, *args, **kwargs):
  48 |         """Initialize the MockIAMClient with exceptions property."""
  49 |         super().__init__(*args, **kwargs)
  50 |         # Set up exceptions as a property
  51 |         self.exceptions = Exceptions
  52 | 
  53 | 
  54 | @pytest.fixture
  55 | def mock_iam_client():
  56 |     """Create a mock IAM client instance for testing."""
  57 |     return Mock()
  58 | 
  59 | 
  60 | @pytest.fixture
  61 | def mock_s3_client():
  62 |     """Create a mock S3 client instance for testing."""
  63 |     return Mock()
  64 | 
  65 | 
  66 | @pytest.fixture
  67 | def mock_aws_helper():
  68 |     """Create a mock AwsHelper instance for testing."""
  69 |     with patch(
  70 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
  71 |     ) as mock:
  72 |         mock.create_boto3_client.return_value = Mock()
  73 |         yield mock
  74 | 
  75 | 
  76 | @pytest.fixture
  77 | def handler(mock_aws_helper):
  78 |     """Create a mock CommonResourceHandler instance for testing."""
  79 |     mcp = Mock()
  80 |     return CommonResourceHandler(mcp, allow_write=True)
  81 | 
  82 | 
  83 | @pytest.fixture
  84 | def read_only_handler(mock_aws_helper):
  85 |     """Create a mock CommonResourceHandler instance with read-only access for testing."""
  86 |     mcp = Mock()
  87 |     return CommonResourceHandler(mcp, allow_write=False)
  88 | 
  89 | 
  90 | @pytest.fixture
  91 | def mock_context():
  92 |     """Create a mock context instance for testing."""
  93 |     return Mock(spec=Context)
  94 | 
  95 | 
  96 | # ============================================================================
  97 | # IAM Operations Tests
  98 | # ============================================================================
  99 | 
 100 | 
 101 | @pytest.mark.asyncio
 102 | async def test_get_policies_for_role_success(handler, mock_iam_client):
 103 |     """Test successful retrieval of policies for a role."""
 104 |     handler.iam_client = mock_iam_client
 105 | 
 106 |     # Mock role response
 107 |     mock_iam_client.get_role.return_value = {
 108 |         'Role': {
 109 |             'Arn': 'arn:aws:iam::123456789012:role/test-role',
 110 |             'AssumeRolePolicyDocument': {
 111 |                 'Version': '2012-10-17',
 112 |                 'Statement': [
 113 |                     {
 114 |                         'Effect': 'Allow',
 115 |                         'Principal': {'Service': 'glue.amazonaws.com'},
 116 |                         'Action': 'sts:AssumeRole',
 117 |                     }
 118 |                 ],
 119 |             },
 120 |             'Description': 'Test role description',
 121 |         }
 122 |     }
 123 | 
 124 |     # Mock managed policies
 125 |     mock_iam_client.list_attached_role_policies.return_value = {
 126 |         'AttachedPolicies': [
 127 |             {
 128 |                 'PolicyName': 'TestManagedPolicy',
 129 |                 'PolicyArn': 'arn:aws:iam::aws:policy/TestManagedPolicy',
 130 |             }
 131 |         ]
 132 |     }
 133 | 
 134 |     mock_iam_client.get_policy.return_value = {
 135 |         'Policy': {'DefaultVersionId': 'v1', 'Description': 'Test managed policy'}
 136 |     }
 137 | 
 138 |     mock_iam_client.get_policy_version.return_value = {
 139 |         'PolicyVersion': {
 140 |             'Document': {
 141 |                 'Version': '2012-10-17',
 142 |                 'Statement': [{'Effect': 'Allow', 'Action': 's3:GetObject', 'Resource': '*'}],
 143 |             }
 144 |         }
 145 |     }
 146 | 
 147 |     # Mock inline policies
 148 |     mock_iam_client.list_role_policies.return_value = {'PolicyNames': ['TestInlinePolicy']}
 149 | 
 150 |     mock_iam_client.get_role_policy.return_value = {
 151 |         'PolicyDocument': {
 152 |             'Version': '2012-10-17',
 153 |             'Statement': [{'Effect': 'Allow', 'Action': 's3:PutObject', 'Resource': '*'}],
 154 |         }
 155 |     }
 156 | 
 157 |     ctx = Mock()
 158 |     response = await handler.get_policies_for_role(ctx, role_name='test-role')
 159 | 
 160 |     assert not response.isError
 161 |     assert response.role_arn == 'arn:aws:iam::123456789012:role/test-role'
 162 |     assert response.description == 'Test role description'
 163 |     assert len(response.managed_policies) == 1
 164 |     assert len(response.inline_policies) == 1
 165 |     assert response.managed_policies[0].policy_type == 'Managed'
 166 |     assert response.inline_policies[0].policy_type == 'Inline'
 167 | 
 168 | 
 169 | @pytest.mark.asyncio
 170 | async def test_get_policies_for_role_with_string_assume_role_policy(handler, mock_iam_client):
 171 |     """Test retrieval of policies for a role with string assume role policy document."""
 172 |     handler.iam_client = mock_iam_client
 173 | 
 174 |     # Mock role response with string assume role policy document
 175 |     assume_role_policy_str = json.dumps(
 176 |         {
 177 |             'Version': '2012-10-17',
 178 |             'Statement': [
 179 |                 {
 180 |                     'Effect': 'Allow',
 181 |                     'Principal': {'Service': 'glue.amazonaws.com'},
 182 |                     'Action': 'sts:AssumeRole',
 183 |                 }
 184 |             ],
 185 |         }
 186 |     )
 187 | 
 188 |     mock_iam_client.get_role.return_value = {
 189 |         'Role': {
 190 |             'Arn': 'arn:aws:iam::123456789012:role/test-role',
 191 |             'AssumeRolePolicyDocument': assume_role_policy_str,
 192 |             'Description': 'Test role description',
 193 |         }
 194 |     }
 195 | 
 196 |     # Mock empty policies
 197 |     mock_iam_client.list_attached_role_policies.return_value = {'AttachedPolicies': []}
 198 |     mock_iam_client.list_role_policies.return_value = {'PolicyNames': []}
 199 | 
 200 |     ctx = Mock()
 201 |     response = await handler.get_policies_for_role(ctx, role_name='test-role')
 202 | 
 203 |     assert not response.isError
 204 |     assert response.assume_role_policy_document['Version'] == '2012-10-17'
 205 |     assert len(response.assume_role_policy_document['Statement']) == 1
 206 | 
 207 | 
 208 | @pytest.mark.asyncio
 209 | async def test_get_policies_for_role_error_handling(handler, mock_iam_client):
 210 |     """Test error handling when getting policies for a role fails."""
 211 |     handler.iam_client = mock_iam_client
 212 |     mock_iam_client.get_role.side_effect = ClientError(
 213 |         {'Error': {'Code': 'NoSuchEntity', 'Message': 'Role not found'}}, 'GetRole'
 214 |     )
 215 | 
 216 |     ctx = Mock()
 217 |     response = await handler.get_policies_for_role(ctx, role_name='nonexistent-role')
 218 | 
 219 |     assert response.isError
 220 |     assert 'Failed to describe IAM role' in response.content[0].text
 221 |     assert response.role_arn == ''
 222 | 
 223 | 
 224 | @pytest.mark.asyncio
 225 | async def test_add_inline_policy_success(handler):
 226 |     """Test successful addition of an inline policy."""
 227 |     mock_iam_local_client = MockIAMClient()
 228 |     mock_iam_local_client.get_role_policy.side_effect = (
 229 |         mock_iam_local_client.exceptions.NoSuchEntityException()
 230 |     )
 231 |     handler.iam_client = mock_iam_local_client
 232 | 
 233 |     permissions = {
 234 |         'Effect': 'Allow',
 235 |         'Action': ['s3:GetObject', 's3:PutObject'],
 236 |         'Resource': 'arn:aws:s3:::test-bucket/*',
 237 |     }
 238 | 
 239 |     ctx = Mock()
 240 |     response = await handler.add_inline_policy(
 241 |         ctx, policy_name='test-policy', role_name='test-role', permissions=permissions
 242 |     )
 243 | 
 244 |     assert not response.isError
 245 |     assert response.policy_name == 'test-policy'
 246 |     assert response.role_name == 'test-role'
 247 |     assert response.permissions_added == permissions
 248 |     mock_iam_local_client.put_role_policy.assert_called_once()
 249 | 
 250 | 
 251 | @pytest.mark.asyncio
 252 | async def test_add_inline_policy_with_list_permissions(handler):
 253 |     """Test successful addition of an inline policy with list of permissions."""
 254 |     mock_iam_local_client = MockIAMClient()
 255 |     mock_iam_local_client.get_role_policy.side_effect = (
 256 |         mock_iam_local_client.exceptions.NoSuchEntityException()
 257 |     )
 258 |     mock_iam_local_client.put_role_policy.return_value = {
 259 |         'ResponseMetadata': {
 260 |             'test': 'dummy',
 261 |         },
 262 |     }
 263 |     handler.iam_client = mock_iam_local_client
 264 | 
 265 |     permissions = [
 266 |         {'Effect': 'Allow', 'Action': ['s3:GetObject'], 'Resource': 'arn:aws:s3:::test-bucket/*'},
 267 |         {'Effect': 'Allow', 'Action': ['s3:PutObject'], 'Resource': 'arn:aws:s3:::test-bucket/*'},
 268 |     ]
 269 | 
 270 |     ctx = Mock()
 271 |     response = await handler.add_inline_policy(
 272 |         ctx, policy_name='test-policy', role_name='test-role', permissions=permissions
 273 |     )
 274 | 
 275 |     assert not response.isError
 276 |     assert response.policy_name == 'test-policy'
 277 |     assert response.role_name == 'test-role'
 278 |     assert response.permissions_added == permissions
 279 | 
 280 | 
 281 | @pytest.mark.asyncio
 282 | async def test_add_inline_policy_without_write_permission(read_only_handler):
 283 |     """Test that adding inline policy fails when write access is disabled."""
 284 |     ctx = Mock()
 285 |     response = await read_only_handler.add_inline_policy(
 286 |         ctx,
 287 |         policy_name='test-policy',
 288 |         role_name='test-role',
 289 |         permissions={'Effect': 'Allow', 'Action': 's3:GetObject', 'Resource': '*'},
 290 |     )
 291 | 
 292 |     assert response.isError
 293 |     assert 'requires --allow-write flag' in response.content[0].text
 294 | 
 295 | 
 296 | @pytest.mark.asyncio
 297 | async def test_add_inline_policy_already_exists(handler, mock_iam_client):
 298 |     """Test that adding inline policy fails when policy already exists."""
 299 |     handler.iam_client = mock_iam_client
 300 | 
 301 |     # Mock that policy already exists
 302 |     mock_iam_client.get_role_policy.return_value = {
 303 |         'PolicyDocument': {'Version': '2012-10-17', 'Statement': []}
 304 |     }
 305 | 
 306 |     ctx = Mock()
 307 |     response = await handler.add_inline_policy(
 308 |         ctx,
 309 |         policy_name='existing-policy',
 310 |         role_name='test-role',
 311 |         permissions={'Effect': 'Allow', 'Action': 's3:GetObject', 'Resource': '*'},
 312 |     )
 313 | 
 314 |     assert response.isError
 315 |     assert 'already exists' in response.content[0].text
 316 | 
 317 | 
 318 | @pytest.mark.asyncio
 319 | async def test_create_data_processing_role_glue_success(handler, mock_iam_client):
 320 |     """Test successful creation of a Glue data processing role."""
 321 |     handler.iam_client = mock_iam_client
 322 | 
 323 |     mock_iam_client.create_role.return_value = {
 324 |         'Role': {'Arn': 'arn:aws:iam::123456789012:role/test-glue-role'}
 325 |     }
 326 | 
 327 |     ctx = Mock()
 328 |     response = await handler.create_data_processing_role(
 329 |         ctx,
 330 |         role_name='test-glue-role',
 331 |         service_type='glue',
 332 |         description='Test Glue role',
 333 |         managed_policy_arns=['arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole'],
 334 |     )
 335 | 
 336 |     assert not response.isError
 337 |     assert response.role_name == 'test-glue-role'
 338 |     assert response.role_arn == 'arn:aws:iam::123456789012:role/test-glue-role'
 339 | 
 340 |     # Verify create_role was called with correct trust relationship
 341 |     create_role_call = mock_iam_client.create_role.call_args
 342 |     assume_role_policy = json.loads(create_role_call[1]['AssumeRolePolicyDocument'])
 343 |     assert assume_role_policy['Statement'][0]['Principal']['Service'] == 'glue.amazonaws.com'
 344 | 
 345 |     # Verify managed policy was attached
 346 |     mock_iam_client.attach_role_policy.assert_called_once_with(
 347 |         RoleName='test-glue-role',
 348 |         PolicyArn='arn:aws:iam::aws:policy/service-role/AWSGlueServiceRole',
 349 |     )
 350 | 
 351 | 
 352 | @pytest.mark.asyncio
 353 | async def test_create_data_processing_role_emr_success(handler, mock_iam_client):
 354 |     """Test successful creation of an EMR data processing role."""
 355 |     handler.iam_client = mock_iam_client
 356 | 
 357 |     mock_iam_client.create_role.return_value = {
 358 |         'Role': {'Arn': 'arn:aws:iam::123456789012:role/test-emr-role'}
 359 |     }
 360 | 
 361 |     ctx = Mock()
 362 |     response = await handler.create_data_processing_role(
 363 |         ctx, role_name='test-emr-role', service_type='emr'
 364 |     )
 365 | 
 366 |     assert not response.isError
 367 |     assert response.role_name == 'test-emr-role'
 368 | 
 369 |     # Verify create_role was called with correct trust relationship
 370 |     create_role_call = mock_iam_client.create_role.call_args
 371 |     assume_role_policy = json.loads(create_role_call[1]['AssumeRolePolicyDocument'])
 372 |     assert (
 373 |         assume_role_policy['Statement'][0]['Principal']['Service']
 374 |         == 'elasticmapreduce.amazonaws.com'
 375 |     )
 376 | 
 377 | 
 378 | @pytest.mark.asyncio
 379 | async def test_create_data_processing_role_athena_success(handler, mock_iam_client):
 380 |     """Test successful creation of an Athena data processing role."""
 381 |     handler.iam_client = mock_iam_client
 382 | 
 383 |     mock_iam_client.create_role.return_value = {
 384 |         'Role': {'Arn': 'arn:aws:iam::123456789012:role/test-athena-role'}
 385 |     }
 386 | 
 387 |     ctx = Mock()
 388 |     response = await handler.create_data_processing_role(
 389 |         ctx, role_name='test-athena-role', service_type='athena'
 390 |     )
 391 | 
 392 |     assert not response.isError
 393 |     assert response.role_name == 'test-athena-role'
 394 | 
 395 |     # Verify create_role was called with correct trust relationship
 396 |     create_role_call = mock_iam_client.create_role.call_args
 397 |     assume_role_policy = json.loads(create_role_call[1]['AssumeRolePolicyDocument'])
 398 |     assert assume_role_policy['Statement'][0]['Principal']['Service'] == 'athena.amazonaws.com'
 399 | 
 400 | 
 401 | @pytest.mark.asyncio
 402 | async def test_create_data_processing_role_with_inline_policy(handler, mock_iam_client):
 403 |     """Test successful creation of a role with inline policy."""
 404 |     handler.iam_client = mock_iam_client
 405 | 
 406 |     mock_iam_client.create_role.return_value = {
 407 |         'Role': {'Arn': 'arn:aws:iam::123456789012:role/test-role'}
 408 |     }
 409 | 
 410 |     inline_policy = {
 411 |         'Effect': 'Allow',
 412 |         'Action': ['s3:GetObject'],
 413 |         'Resource': 'arn:aws:s3:::test-bucket/*',
 414 |     }
 415 | 
 416 |     ctx = Mock()
 417 |     response = await handler.create_data_processing_role(
 418 |         ctx, role_name='test-role', service_type='glue', inline_policy=inline_policy
 419 |     )
 420 | 
 421 |     assert not response.isError
 422 | 
 423 |     # Verify inline policy was added
 424 |     mock_iam_client.put_role_policy.assert_called_once()
 425 |     put_policy_call = mock_iam_client.put_role_policy.call_args
 426 |     policy_document = json.loads(put_policy_call[1]['PolicyDocument'])
 427 |     assert policy_document['Statement'][0]['Action'] == ['s3:GetObject']
 428 | 
 429 | 
 430 | @pytest.mark.asyncio
 431 | async def test_create_data_processing_role_invalid_service_type(handler):
 432 |     """Test that creating role fails with invalid service type."""
 433 |     ctx = Mock()
 434 |     response = await handler.create_data_processing_role(
 435 |         ctx, role_name='test-role', service_type='invalid-service'
 436 |     )
 437 | 
 438 |     assert response.isError
 439 |     assert 'Invalid service type' in response.content[0].text
 440 | 
 441 | 
 442 | @pytest.mark.asyncio
 443 | async def test_create_data_processing_role_without_write_permission(read_only_handler):
 444 |     """Test that creating role fails when write access is disabled."""
 445 |     ctx = Mock()
 446 |     response = await read_only_handler.create_data_processing_role(
 447 |         ctx, role_name='test-role', service_type='glue'
 448 |     )
 449 | 
 450 |     assert response.isError
 451 |     assert 'requires --allow-write flag' in response.content[0].text
 452 | 
 453 | 
 454 | @pytest.mark.asyncio
 455 | async def test_get_roles_for_service_success(handler, mock_iam_client):
 456 |     """Test successful retrieval of roles for a service."""
 457 |     handler.iam_client = mock_iam_client
 458 | 
 459 |     # Mock paginator
 460 |     mock_paginator = Mock()
 461 |     mock_iam_client.get_paginator.return_value = mock_paginator
 462 | 
 463 |     # Mock role data
 464 |     mock_paginator.paginate.return_value = [
 465 |         {
 466 |             'Roles': [
 467 |                 {
 468 |                     'RoleName': 'glue-role-1',
 469 |                     'Arn': 'arn:aws:iam::123456789012:role/glue-role-1',
 470 |                     'Description': 'Glue role 1',
 471 |                     'CreateDate': datetime(2023, 1, 1),
 472 |                     'AssumeRolePolicyDocument': {
 473 |                         'Version': '2012-10-17',
 474 |                         'Statement': [
 475 |                             {
 476 |                                 'Effect': 'Allow',
 477 |                                 'Principal': {'Service': 'glue.amazonaws.com'},
 478 |                                 'Action': 'sts:AssumeRole',
 479 |                             }
 480 |                         ],
 481 |                     },
 482 |                 },
 483 |                 {
 484 |                     'RoleName': 'emr-role-1',
 485 |                     'Arn': 'arn:aws:iam::123456789012:role/emr-role-1',
 486 |                     'CreateDate': datetime(2023, 1, 2),
 487 |                     'AssumeRolePolicyDocument': {
 488 |                         'Version': '2012-10-17',
 489 |                         'Statement': [
 490 |                             {
 491 |                                 'Effect': 'Allow',
 492 |                                 'Principal': {'Service': 'elasticmapreduce.amazonaws.com'},
 493 |                                 'Action': 'sts:AssumeRole',
 494 |                             }
 495 |                         ],
 496 |                     },
 497 |                 },
 498 |             ]
 499 |         }
 500 |     ]
 501 | 
 502 |     ctx = Mock()
 503 |     response = await handler.get_roles_for_service(ctx, service_type='glue')
 504 | 
 505 |     assert not response.isError
 506 |     assert response.service_type == 'glue'
 507 |     assert len(response.roles) == 1  # Only the Glue role should be returned
 508 |     assert response.roles[0].role_name == 'glue-role-1'
 509 | 
 510 | 
 511 | @pytest.mark.asyncio
 512 | async def test_get_roles_for_service_with_string_assume_role_policy(handler, mock_iam_client):
 513 |     """Test retrieval of roles for a service with string assume role policy document."""
 514 |     handler.iam_client = mock_iam_client
 515 | 
 516 |     # Mock paginator
 517 |     mock_paginator = Mock()
 518 |     mock_iam_client.get_paginator.return_value = mock_paginator
 519 | 
 520 |     # Mock role data with string assume role policy document
 521 |     assume_role_policy_str = json.dumps(
 522 |         {
 523 |             'Version': '2012-10-17',
 524 |             'Statement': [
 525 |                 {
 526 |                     'Effect': 'Allow',
 527 |                     'Principal': {'Service': 'glue.amazonaws.com'},
 528 |                     'Action': 'sts:AssumeRole',
 529 |                 }
 530 |             ],
 531 |         }
 532 |     )
 533 | 
 534 |     mock_paginator.paginate.return_value = [
 535 |         {
 536 |             'Roles': [
 537 |                 {
 538 |                     'RoleName': 'glue-role-1',
 539 |                     'Arn': 'arn:aws:iam::123456789012:role/glue-role-1',
 540 |                     'CreateDate': datetime(2023, 1, 1),
 541 |                     'AssumeRolePolicyDocument': assume_role_policy_str,
 542 |                 }
 543 |             ]
 544 |         }
 545 |     ]
 546 | 
 547 |     ctx = Mock()
 548 |     response = await handler.get_roles_for_service(ctx, service_type='glue')
 549 | 
 550 |     assert not response.isError
 551 |     assert len(response.roles) == 1
 552 |     assert response.roles[0].role_name == 'glue-role-1'
 553 | 
 554 | 
 555 | @pytest.mark.asyncio
 556 | async def test_get_roles_for_service_error_handling(handler, mock_iam_client):
 557 |     """Test error handling when getting roles for a service fails."""
 558 |     handler.iam_client = mock_iam_client
 559 |     mock_iam_client.get_paginator.side_effect = ClientError(
 560 |         {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'ListRoles'
 561 |     )
 562 | 
 563 |     ctx = Mock()
 564 |     response = await handler.get_roles_for_service(ctx, service_type='glue')
 565 | 
 566 |     assert response.isError
 567 |     assert 'Failed to list IAM roles' in response.content[0].text
 568 | 
 569 | 
 570 | # ============================================================================
 571 | # S3 Operations Tests
 572 | # ============================================================================
 573 | 
 574 | 
 575 | @pytest.mark.asyncio
 576 | async def test_list_s3_buckets_success(handler, mock_s3_client):
 577 |     """Test successful listing of S3 buckets."""
 578 |     handler.s3_client = mock_s3_client
 579 | 
 580 |     # Mock list_buckets response
 581 |     mock_s3_client.list_buckets.return_value = {
 582 |         'Buckets': [
 583 |             {'Name': 'test-glue-bucket', 'CreationDate': datetime(2023, 1, 1)},
 584 |             {'Name': 'other-bucket', 'CreationDate': datetime(2023, 1, 2)},
 585 |         ]
 586 |     }
 587 | 
 588 |     # Mock bucket location
 589 |     mock_s3_client.get_bucket_location.return_value = {'LocationConstraint': 'us-east-1'}
 590 | 
 591 |     # Mock list_objects_v2 response
 592 |     mock_s3_client.list_objects_v2.return_value = {
 593 |         'KeyCount': 5,
 594 |         'Contents': [{'LastModified': datetime(2023, 6, 1)}],
 595 |     }
 596 | 
 597 |     ctx = Mock()
 598 |     response = await handler.list_s3_buckets(ctx, region='us-east-1')
 599 | 
 600 |     assert not response.isError
 601 |     assert response.region == 'us-east-1'
 602 |     assert response.bucket_count == 1  # Only the bucket with 'glue' in name
 603 |     assert len(response.buckets) == 1
 604 |     assert response.buckets[0].name == 'test-glue-bucket'
 605 | 
 606 | 
 607 | @pytest.mark.asyncio
 608 | async def test_list_s3_buckets_with_environment_region(handler, mock_s3_client):
 609 |     """Test listing S3 buckets using environment region."""
 610 |     handler.s3_client = mock_s3_client
 611 | 
 612 |     with patch('os.getenv', return_value='us-west-2'):
 613 |         mock_s3_client.list_buckets.return_value = {'Buckets': []}
 614 | 
 615 |         ctx = Mock()
 616 |         response = await handler.list_s3_buckets(ctx)
 617 | 
 618 |         assert not response.isError
 619 |         assert response.region == 'us-west-2'
 620 | 
 621 | 
 622 | @pytest.mark.asyncio
 623 | async def test_list_s3_buckets_error_handling(handler, mock_s3_client):
 624 |     """Test error handling when listing S3 buckets fails."""
 625 |     handler.s3_client = mock_s3_client
 626 |     mock_s3_client.list_buckets.side_effect = ClientError(
 627 |         {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'ListBuckets'
 628 |     )
 629 | 
 630 |     ctx = Mock()
 631 |     response = await handler.list_s3_buckets(ctx)
 632 | 
 633 |     assert response.isError
 634 |     assert 'AWS Error' in response.content[0].text
 635 | 
 636 | 
 637 | @pytest.mark.asyncio
 638 | async def test_analyze_s3_usage_glue_connections_error(handler, mock_s3_client):
 639 |     """Test error handling when Glue connections check fails in analyze_s3_usage_for_data_processing."""
 640 |     handler.s3_client = mock_s3_client
 641 | 
 642 |     # Mock list_buckets response
 643 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
 644 | 
 645 |     # Mock list_objects_v2 response
 646 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
 647 | 
 648 |     # Mock AWS service clients
 649 |     with patch(
 650 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
 651 |     ) as mock_aws_helper:
 652 |         mock_glue_client = Mock()
 653 |         mock_athena_client = Mock()
 654 |         mock_emr_client = Mock()
 655 | 
 656 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
 657 |             'glue': mock_glue_client,
 658 |             'athena': mock_athena_client,
 659 |             'emr': mock_emr_client,
 660 |         }[service]
 661 | 
 662 |         # Mock Glue connections to raise an exception
 663 |         mock_glue_client.get_connections.side_effect = ClientError(
 664 |             {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'GetConnections'
 665 |         )
 666 | 
 667 |         # Mock other service responses
 668 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
 669 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
 670 | 
 671 |         ctx = Mock()
 672 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
 673 | 
 674 |         assert not response.isError
 675 |         # Should still return results but with error details in the text
 676 |         assert 'Error checking Glue usage' in response.analysis_summary
 677 | 
 678 | 
 679 | @pytest.mark.asyncio
 680 | async def test_analyze_s3_usage_athena_workgroups_error(handler, mock_s3_client):
 681 |     """Test error handling when Athena workgroups check fails in analyze_s3_usage_for_data_processing."""
 682 |     handler.s3_client = mock_s3_client
 683 | 
 684 |     # Mock list_buckets response
 685 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
 686 | 
 687 |     # Mock list_objects_v2 response
 688 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
 689 | 
 690 |     # Mock AWS service clients
 691 |     with patch(
 692 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
 693 |     ) as mock_aws_helper:
 694 |         mock_glue_client = Mock()
 695 |         mock_athena_client = Mock()
 696 |         mock_emr_client = Mock()
 697 | 
 698 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
 699 |             'glue': mock_glue_client,
 700 |             'athena': mock_athena_client,
 701 |             'emr': mock_emr_client,
 702 |         }[service]
 703 | 
 704 |         # Mock service responses
 705 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
 706 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
 707 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
 708 | 
 709 |         # Mock Athena list_work_groups to raise an exception
 710 |         mock_athena_client.list_work_groups.side_effect = ClientError(
 711 |             {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'ListWorkGroups'
 712 |         )
 713 | 
 714 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
 715 | 
 716 |         ctx = Mock()
 717 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
 718 | 
 719 |         assert not response.isError
 720 |         # Should still return results but with error details in the text
 721 |         assert 'Error checking Athena usage' in response.analysis_summary
 722 | 
 723 | 
 724 | @pytest.mark.asyncio
 725 | async def test_analyze_s3_usage_athena_workgroup_details_error(handler, mock_s3_client):
 726 |     """Test error handling when getting Athena workgroup details fails in analyze_s3_usage_for_data_processing."""
 727 |     handler.s3_client = mock_s3_client
 728 | 
 729 |     # Mock list_buckets response
 730 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
 731 | 
 732 |     # Mock list_objects_v2 response
 733 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
 734 | 
 735 |     # Mock AWS service clients
 736 |     with patch(
 737 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
 738 |     ) as mock_aws_helper:
 739 |         mock_glue_client = Mock()
 740 |         mock_athena_client = Mock()
 741 |         mock_emr_client = Mock()
 742 | 
 743 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
 744 |             'glue': mock_glue_client,
 745 |             'athena': mock_athena_client,
 746 |             'emr': mock_emr_client,
 747 |         }[service]
 748 | 
 749 |         # Mock service responses
 750 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
 751 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
 752 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
 753 | 
 754 |         # Mock Athena workgroups
 755 |         mock_athena_client.list_work_groups.return_value = {
 756 |             'WorkGroups': [{'Name': 'test-workgroup'}]
 757 |         }
 758 | 
 759 |         # Mock get_work_group to raise an exception
 760 |         mock_athena_client.get_work_group.side_effect = ClientError(
 761 |             {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'GetWorkGroup'
 762 |         )
 763 | 
 764 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
 765 | 
 766 |         ctx = Mock()
 767 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
 768 | 
 769 |         assert not response.isError
 770 |         # Should still return results but with warning about workgroup check
 771 |         assert 'Warning: Could not check workgroup test-workgroup' in response.analysis_summary
 772 | 
 773 | 
 774 | @pytest.mark.asyncio
 775 | async def test_analyze_s3_usage_emr_clusters_error(handler, mock_s3_client):
 776 |     """Test error handling when EMR clusters check fails in analyze_s3_usage_for_data_processing."""
 777 |     handler.s3_client = mock_s3_client
 778 | 
 779 |     # Mock list_buckets response
 780 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
 781 | 
 782 |     # Mock list_objects_v2 response
 783 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
 784 | 
 785 |     # Mock AWS service clients
 786 |     with patch(
 787 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
 788 |     ) as mock_aws_helper:
 789 |         mock_glue_client = Mock()
 790 |         mock_athena_client = Mock()
 791 |         mock_emr_client = Mock()
 792 | 
 793 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
 794 |             'glue': mock_glue_client,
 795 |             'athena': mock_athena_client,
 796 |             'emr': mock_emr_client,
 797 |         }[service]
 798 | 
 799 |         # Mock service responses
 800 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
 801 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
 802 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
 803 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
 804 | 
 805 |         # Mock EMR list_clusters to raise an exception
 806 |         mock_emr_client.list_clusters.side_effect = ClientError(
 807 |             {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'ListClusters'
 808 |         )
 809 | 
 810 |         ctx = Mock()
 811 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
 812 | 
 813 |         assert not response.isError
 814 |         # Should still return results but with error details in the text
 815 |         assert 'Error checking EMR usage' in response.analysis_summary
 816 | 
 817 | 
 818 | @pytest.mark.asyncio
 819 | async def test_analyze_s3_usage_emr_cluster_details_error(handler, mock_s3_client):
 820 |     """Test error handling when getting EMR cluster details fails in analyze_s3_usage_for_data_processing."""
 821 |     handler.s3_client = mock_s3_client
 822 | 
 823 |     # Mock list_buckets response
 824 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
 825 | 
 826 |     # Mock list_objects_v2 response
 827 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
 828 | 
 829 |     # Mock AWS service clients
 830 |     with patch(
 831 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
 832 |     ) as mock_aws_helper:
 833 |         mock_glue_client = Mock()
 834 |         mock_athena_client = Mock()
 835 |         mock_emr_client = Mock()
 836 | 
 837 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
 838 |             'glue': mock_glue_client,
 839 |             'athena': mock_athena_client,
 840 |             'emr': mock_emr_client,
 841 |         }[service]
 842 | 
 843 |         # Mock service responses
 844 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
 845 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
 846 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
 847 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
 848 | 
 849 |         # Mock EMR clusters
 850 |         mock_emr_client.list_clusters.return_value = {
 851 |             'Clusters': [{'Id': 'j-1234567890123', 'Name': 'test-cluster'}]
 852 |         }
 853 | 
 854 |         # Mock describe_cluster to raise an exception
 855 |         mock_emr_client.describe_cluster.side_effect = ClientError(
 856 |             {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'DescribeCluster'
 857 |         )
 858 | 
 859 |         ctx = Mock()
 860 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
 861 | 
 862 |         assert not response.isError
 863 |         # Should still return results but with warning about cluster check
 864 |         assert 'Warning: Could not check cluster j-1234567890123' in response.analysis_summary
 865 | 
 866 | 
 867 | @pytest.mark.asyncio
 868 | async def test_analyze_s3_usage_last_activity_error(handler, mock_s3_client):
 869 |     """Test error handling when checking last activity fails in analyze_s3_usage_for_data_processing."""
 870 |     handler.s3_client = mock_s3_client
 871 | 
 872 |     # Mock list_buckets response
 873 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
 874 | 
 875 |     # Mock list_objects_v2 to raise an exception
 876 |     mock_s3_client.list_objects_v2.side_effect = ClientError(
 877 |         {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'ListObjectsV2'
 878 |     )
 879 | 
 880 |     # Mock AWS service clients
 881 |     with patch(
 882 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
 883 |     ) as mock_aws_helper:
 884 |         mock_glue_client = Mock()
 885 |         mock_athena_client = Mock()
 886 |         mock_emr_client = Mock()
 887 | 
 888 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
 889 |             'glue': mock_glue_client,
 890 |             'athena': mock_athena_client,
 891 |             'emr': mock_emr_client,
 892 |         }[service]
 893 | 
 894 |         # Mock service responses
 895 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
 896 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
 897 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
 898 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
 899 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
 900 | 
 901 |         ctx = Mock()
 902 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
 903 | 
 904 |         assert not response.isError
 905 |         # Should still return results but with error details in the text
 906 |         assert 'Error checking last activity' in response.analysis_summary
 907 | 
 908 | 
 909 | @pytest.mark.asyncio
 910 | async def test_analyze_s3_usage_bucket_name_hints(handler, mock_s3_client):
 911 |     """Test bucket name hint detection in analyze_s3_usage_for_data_processing."""
 912 |     handler.s3_client = mock_s3_client
 913 | 
 914 |     # Mock list_buckets response with buckets that have hints in their names
 915 |     mock_s3_client.list_buckets.return_value = {
 916 |         'Buckets': [
 917 |             {'Name': 'my-glue-etl-bucket'},
 918 |             {'Name': 'athena-query-results'},
 919 |             {'Name': 'emr-hadoop-logs'},
 920 |             {'Name': 'random-bucket-name'},
 921 |         ]
 922 |     }
 923 | 
 924 |     # Mock list_objects_v2 response
 925 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
 926 | 
 927 |     # Mock AWS service clients
 928 |     with patch(
 929 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
 930 |     ) as mock_aws_helper:
 931 |         mock_glue_client = Mock()
 932 |         mock_athena_client = Mock()
 933 |         mock_emr_client = Mock()
 934 | 
 935 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
 936 |             'glue': mock_glue_client,
 937 |             'athena': mock_athena_client,
 938 |             'emr': mock_emr_client,
 939 |         }[service]
 940 | 
 941 |         # Mock service responses - no active usage detected
 942 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
 943 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
 944 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
 945 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
 946 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
 947 | 
 948 |         ctx = Mock()
 949 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
 950 | 
 951 |         assert not response.isError
 952 |         # Should detect bucket name hints
 953 |         assert (
 954 |             'Likely Glue bucket (based on name) but no active usage detected'
 955 |             in response.analysis_summary
 956 |         )
 957 |         assert (
 958 |             'Likely Athena bucket (based on name) but no active usage detected'
 959 |             in response.analysis_summary
 960 |         )
 961 |         assert (
 962 |             'Likely EMR bucket (based on name) but no active usage detected'
 963 |             in response.analysis_summary
 964 |         )
 965 |         assert 'No data processing service usage detected' in response.analysis_summary
 966 | 
 967 | 
 968 | @pytest.mark.asyncio
 969 | async def test_upload_to_s3_success(handler, mock_s3_client):
 970 |     """Test successful upload to S3."""
 971 |     handler.s3_client = mock_s3_client
 972 | 
 973 |     # Mock bucket location
 974 |     mock_s3_client.get_bucket_location.return_value = {'LocationConstraint': 'us-east-1'}
 975 | 
 976 |     code_content = "print('Hello, World!')"
 977 | 
 978 |     ctx = Mock()
 979 |     response = await handler.upload_to_s3(
 980 |         ctx, code_content=code_content, bucket_name='test-bucket', s3_key='scripts/test.py'
 981 |     )
 982 | 
 983 |     assert not response.isError
 984 |     assert response.s3_uri == 's3://test-bucket/scripts/test.py'
 985 |     assert response.bucket_name == 'test-bucket'
 986 |     assert response.s3_key == 'scripts/test.py'
 987 | 
 988 |     # Verify put_object was called
 989 |     mock_s3_client.put_object.assert_called_once_with(
 990 |         Body=code_content, Bucket='test-bucket', Key='scripts/test.py', ContentType='text/x-python'
 991 |     )
 992 | 
 993 | 
 994 | @pytest.mark.asyncio
 995 | async def test_upload_to_s3_make_public(handler, mock_s3_client):
 996 |     """Test successful upload to S3 with public access."""
 997 |     handler.s3_client = mock_s3_client
 998 | 
 999 |     # Mock bucket location
1000 |     mock_s3_client.get_bucket_location.return_value = {'LocationConstraint': 'us-east-1'}
1001 | 
1002 |     code_content = "print('Hello, World!')"
1003 | 
1004 |     ctx = Mock()
1005 |     response = await handler.upload_to_s3(
1006 |         ctx,
1007 |         code_content=code_content,
1008 |         bucket_name='test-bucket',
1009 |         s3_key='scripts/test.py',
1010 |         make_public=True,
1011 |     )
1012 | 
1013 |     assert not response.isError
1014 | 
1015 |     # Verify put_object_acl was called
1016 |     mock_s3_client.put_object_acl.assert_called_once_with(
1017 |         Bucket='test-bucket', Key='scripts/test.py', ACL='public-read'
1018 |     )
1019 | 
1020 | 
1021 | @pytest.mark.asyncio
1022 | async def test_upload_to_s3_without_write_permission(read_only_handler):
1023 |     """Test that uploading to S3 fails when write access is disabled."""
1024 |     ctx = Mock()
1025 |     response = await read_only_handler.upload_to_s3(
1026 |         ctx, code_content="print('test')", bucket_name='test-bucket', s3_key='test.py'
1027 |     )
1028 | 
1029 |     assert response.isError
1030 |     assert 'requires --allow-write flag' in response.content[0].text
1031 | 
1032 | 
1033 | @pytest.mark.asyncio
1034 | async def test_upload_to_s3_bucket_not_found(handler, mock_s3_client):
1035 |     """Test upload to S3 when bucket doesn't exist."""
1036 |     handler.s3_client = mock_s3_client
1037 | 
1038 |     # Mock bucket not found
1039 |     mock_s3_client.head_bucket.side_effect = ClientError(
1040 |         {'Error': {'Code': '404', 'Message': 'Not Found'}}, 'HeadBucket'
1041 |     )
1042 | 
1043 |     ctx = Mock()
1044 |     response = await handler.upload_to_s3(
1045 |         ctx, code_content="print('test')", bucket_name='nonexistent-bucket', s3_key='test.py'
1046 |     )
1047 | 
1048 |     assert response.isError
1049 |     assert 'does not exist' in response.content[0].text
1050 | 
1051 | 
1052 | @pytest.mark.asyncio
1053 | async def test_analyze_s3_usage_for_data_processing_success(handler, mock_s3_client):
1054 |     """Test successful S3 usage analysis."""
1055 |     handler.s3_client = mock_s3_client
1056 | 
1057 |     # Mock list_buckets response
1058 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-glue-bucket'}]}
1059 | 
1060 |     # Mock list_objects_v2 response
1061 |     mock_s3_client.list_objects_v2.return_value = {
1062 |         'KeyCount': 1,
1063 |         'Contents': [{'LastModified': datetime(2023, 6, 1)}],
1064 |     }
1065 | 
1066 |     # Mock AWS service clients
1067 |     with patch(
1068 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
1069 |     ) as mock_aws_helper:
1070 |         mock_glue_client = Mock()
1071 |         mock_athena_client = Mock()
1072 |         mock_emr_client = Mock()
1073 | 
1074 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
1075 |             'glue': mock_glue_client,
1076 |             'athena': mock_athena_client,
1077 |             'emr': mock_emr_client,
1078 |         }[service]
1079 | 
1080 |         # Mock service responses
1081 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1082 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
1083 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
1084 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
1085 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
1086 | 
1087 |         ctx = Mock()
1088 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
1089 | 
1090 |         assert not response.isError
1091 |         assert 'S3 Usage Analysis' in response.analysis_summary
1092 |         assert response.service_usage is not None
1093 |         assert 'glue' in response.service_usage
1094 |         assert 'athena' in response.service_usage
1095 |         assert 'emr' in response.service_usage
1096 |         assert 'idle' in response.service_usage
1097 |         assert 'unknown' in response.service_usage
1098 | 
1099 | 
1100 | @pytest.mark.asyncio
1101 | async def test_analyze_s3_usage_specific_bucket(handler, mock_s3_client):
1102 |     """Test S3 usage analysis for a specific bucket."""
1103 |     handler.s3_client = mock_s3_client
1104 | 
1105 |     # Mock list_objects_v2 response
1106 |     mock_s3_client.list_objects_v2.return_value = {
1107 |         'KeyCount': 1,
1108 |         'Contents': [{'LastModified': datetime(2023, 6, 1)}],
1109 |     }
1110 | 
1111 |     # Mock AWS service clients
1112 |     with patch(
1113 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
1114 |     ) as mock_aws_helper:
1115 |         mock_glue_client = Mock()
1116 |         mock_athena_client = Mock()
1117 |         mock_emr_client = Mock()
1118 | 
1119 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
1120 |             'glue': mock_glue_client,
1121 |             'athena': mock_athena_client,
1122 |             'emr': mock_emr_client,
1123 |         }[service]
1124 | 
1125 |         # Mock service responses
1126 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1127 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
1128 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
1129 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
1130 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
1131 | 
1132 |         ctx = Mock()
1133 |         response = await handler.analyze_s3_usage_for_data_processing(
1134 |             ctx, bucket_name='test-bucket'
1135 |         )
1136 | 
1137 |         assert not response.isError
1138 |         assert 'S3 Usage Analysis' in response.analysis_summary
1139 | 
1140 | 
1141 | @pytest.mark.asyncio
1142 | async def test_analyze_s3_usage_bucket_not_found(handler, mock_s3_client):
1143 |     """Test S3 usage analysis when specific bucket doesn't exist."""
1144 |     handler.s3_client = mock_s3_client
1145 | 
1146 |     # Mock bucket not found
1147 |     mock_s3_client.head_bucket.side_effect = ClientError(
1148 |         {'Error': {'Code': '404', 'Message': 'Not Found'}}, 'HeadBucket'
1149 |     )
1150 | 
1151 |     ctx = Mock()
1152 |     response = await handler.analyze_s3_usage_for_data_processing(
1153 |         ctx, bucket_name='nonexistent-bucket'
1154 |     )
1155 | 
1156 |     assert response.isError
1157 |     assert 'does not exist or is not accessible' in response.content[0].text
1158 | 
1159 | 
1160 | @pytest.mark.asyncio
1161 | async def test_analyze_s3_usage_error_handling(handler, mock_s3_client):
1162 |     """Test error handling when S3 usage analysis fails."""
1163 |     handler.s3_client = mock_s3_client
1164 |     mock_s3_client.list_buckets.side_effect = ClientError(
1165 |         {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'ListBuckets'
1166 |     )
1167 | 
1168 |     ctx = Mock()
1169 |     response = await handler.analyze_s3_usage_for_data_processing(ctx)
1170 | 
1171 |     assert response.isError
1172 |     assert 'AWS Error' in response.content[0].text
1173 | 
1174 | 
1175 | # ============================================================================
1176 | # Helper Methods Tests
1177 | # ============================================================================
1178 | 
1179 | 
1180 | def test_get_trust_relationship_for_service_glue(handler):
1181 |     """Test trust relationship generation for Glue service."""
1182 |     trust_relationship = handler._get_trust_relationship_for_service('glue')
1183 | 
1184 |     assert trust_relationship['Version'] == '2012-10-17'
1185 |     assert len(trust_relationship['Statement']) == 1
1186 |     assert trust_relationship['Statement'][0]['Effect'] == 'Allow'
1187 |     assert trust_relationship['Statement'][0]['Principal']['Service'] == 'glue.amazonaws.com'
1188 |     assert trust_relationship['Statement'][0]['Action'] == 'sts:AssumeRole'
1189 | 
1190 | 
1191 | def test_get_trust_relationship_for_service_emr(handler):
1192 |     """Test trust relationship generation for EMR service."""
1193 |     trust_relationship = handler._get_trust_relationship_for_service('emr')
1194 | 
1195 |     assert (
1196 |         trust_relationship['Statement'][0]['Principal']['Service']
1197 |         == 'elasticmapreduce.amazonaws.com'
1198 |     )
1199 | 
1200 | 
1201 | def test_get_trust_relationship_for_service_athena(handler):
1202 |     """Test trust relationship generation for Athena service."""
1203 |     trust_relationship = handler._get_trust_relationship_for_service('athena')
1204 | 
1205 |     assert trust_relationship['Statement'][0]['Principal']['Service'] == 'athena.amazonaws.com'
1206 | 
1207 | 
1208 | def test_get_service_principal_known_services(handler):
1209 |     """Test service principal mapping for known services."""
1210 |     assert handler._get_service_principal('glue') == 'glue.amazonaws.com'
1211 |     assert handler._get_service_principal('emr') == 'elasticmapreduce.amazonaws.com'
1212 |     assert handler._get_service_principal('athena') == 'athena.amazonaws.com'
1213 |     assert handler._get_service_principal('lambda') == 'lambda.amazonaws.com'
1214 |     assert handler._get_service_principal('ec2') == 'ec2.amazonaws.com'
1215 | 
1216 | 
1217 | def test_get_service_principal_unknown_service(handler):
1218 |     """Test service principal mapping for unknown services."""
1219 |     assert handler._get_service_principal('unknown-service') == 'unknown-service.amazonaws.com'
1220 | 
1221 | 
1222 | def test_can_be_assumed_by_service_single_service(handler):
1223 |     """Test checking if role can be assumed by service with single service principal."""
1224 |     assume_role_policy = {
1225 |         'Version': '2012-10-17',
1226 |         'Statement': [
1227 |             {
1228 |                 'Effect': 'Allow',
1229 |                 'Principal': {'Service': 'glue.amazonaws.com'},
1230 |                 'Action': 'sts:AssumeRole',
1231 |             }
1232 |         ],
1233 |     }
1234 | 
1235 |     assert handler._can_be_assumed_by_service(assume_role_policy, 'glue.amazonaws.com')
1236 |     assert not handler._can_be_assumed_by_service(assume_role_policy, 'emr.amazonaws.com')
1237 | 
1238 | 
1239 | def test_can_be_assumed_by_service_multiple_services(handler):
1240 |     """Test checking if role can be assumed by service with multiple service principals."""
1241 |     assume_role_policy = {
1242 |         'Version': '2012-10-17',
1243 |         'Statement': [
1244 |             {
1245 |                 'Effect': 'Allow',
1246 |                 'Principal': {'Service': ['glue.amazonaws.com', 'emr.amazonaws.com']},
1247 |                 'Action': 'sts:AssumeRole',
1248 |             }
1249 |         ],
1250 |     }
1251 | 
1252 |     assert handler._can_be_assumed_by_service(assume_role_policy, 'glue.amazonaws.com')
1253 |     assert handler._can_be_assumed_by_service(assume_role_policy, 'emr.amazonaws.com')
1254 |     assert not handler._can_be_assumed_by_service(assume_role_policy, 'athena.amazonaws.com')
1255 | 
1256 | 
1257 | def test_can_be_assumed_by_service_string_action(handler):
1258 |     """Test checking if role can be assumed by service with string action."""
1259 |     assume_role_policy = {
1260 |         'Version': '2012-10-17',
1261 |         'Statement': [
1262 |             {
1263 |                 'Effect': 'Allow',
1264 |                 'Principal': {'Service': 'glue.amazonaws.com'},
1265 |                 'Action': 'sts:AssumeRole',
1266 |             }
1267 |         ],
1268 |     }
1269 | 
1270 |     assert handler._can_be_assumed_by_service(assume_role_policy, 'glue.amazonaws.com')
1271 | 
1272 | 
1273 | def test_can_be_assumed_by_service_deny_effect(handler):
1274 |     """Test checking if role can be assumed by service with Deny effect."""
1275 |     assume_role_policy = {
1276 |         'Version': '2012-10-17',
1277 |         'Statement': [
1278 |             {
1279 |                 'Effect': 'Deny',
1280 |                 'Principal': {'Service': 'glue.amazonaws.com'},
1281 |                 'Action': 'sts:AssumeRole',
1282 |             }
1283 |         ],
1284 |     }
1285 | 
1286 |     # The implementation correctly ignores Deny statements and only processes Allow statements
1287 |     assert not handler._can_be_assumed_by_service(assume_role_policy, 'glue.amazonaws.com')
1288 | 
1289 | 
1290 | def test_can_be_assumed_by_service_wrong_action(handler):
1291 |     """Test checking if role can be assumed by service with wrong action."""
1292 |     assume_role_policy = {
1293 |         'Version': '2012-10-17',
1294 |         'Statement': [
1295 |             {
1296 |                 'Effect': 'Allow',
1297 |                 'Principal': {'Service': 'glue.amazonaws.com'},
1298 |                 'Action': 'sts:GetCallerIdentity',
1299 |             }
1300 |         ],
1301 |     }
1302 | 
1303 |     assert not handler._can_be_assumed_by_service(assume_role_policy, 'glue.amazonaws.com')
1304 | 
1305 | 
1306 | def test_can_be_assumed_by_service_empty_policy(handler):
1307 |     """Test checking if role can be assumed by service with empty policy."""
1308 |     assert not handler._can_be_assumed_by_service({}, 'glue.amazonaws.com')
1309 |     assert not handler._can_be_assumed_by_service({'Statement': []}, 'glue.amazonaws.com')
1310 | 
1311 | 
1312 | def test_add_permissions_to_document_single_statement(handler):
1313 |     """Test adding single permission statement to policy document."""
1314 |     policy_document = {'Version': '2012-10-17', 'Statement': []}
1315 |     permissions = {
1316 |         'Effect': 'Allow',
1317 |         'Action': ['s3:GetObject'],
1318 |         'Resource': 'arn:aws:s3:::test-bucket/*',
1319 |     }
1320 | 
1321 |     handler._add_permissions_to_document(policy_document, permissions)
1322 | 
1323 |     assert len(policy_document['Statement']) == 1
1324 |     assert policy_document['Statement'][0] == permissions
1325 | 
1326 | 
1327 | def test_add_permissions_to_document_multiple_statements(handler):
1328 |     """Test adding multiple permission statements to policy document."""
1329 |     policy_document = {'Version': '2012-10-17', 'Statement': []}
1330 |     permissions = [
1331 |         {'Effect': 'Allow', 'Action': ['s3:GetObject'], 'Resource': 'arn:aws:s3:::test-bucket/*'},
1332 |         {'Effect': 'Allow', 'Action': ['s3:PutObject'], 'Resource': 'arn:aws:s3:::test-bucket/*'},
1333 |     ]
1334 | 
1335 |     handler._add_permissions_to_document(policy_document, permissions)
1336 | 
1337 |     assert len(policy_document['Statement']) == 2
1338 |     assert policy_document['Statement'][0] == permissions[0]
1339 |     assert policy_document['Statement'][1] == permissions[1]
1340 | 
1341 | 
1342 | # ============================================================================
1343 | # Initialization Tests
1344 | # ============================================================================
1345 | 
1346 | 
1347 | @pytest.mark.asyncio
1348 | async def test_initialization_parameters(mock_aws_helper):
1349 |     """Test initialization of parameters for CommonResourceHandler object."""
1350 |     mcp = Mock()
1351 |     handler = CommonResourceHandler(mcp, allow_write=True)
1352 | 
1353 |     assert handler.allow_write
1354 |     assert handler.mcp == mcp
1355 | 
1356 | 
1357 | @pytest.mark.asyncio
1358 | async def test_initialization_registers_tools(mock_aws_helper):
1359 |     """Test that initialization registers the tools with the MCP server."""
1360 |     mcp = Mock()
1361 |     CommonResourceHandler(mcp)
1362 | 
1363 |     # Verify IAM tools are registered
1364 |     mcp.tool.assert_any_call(name='add_inline_policy')
1365 |     mcp.tool.assert_any_call(name='get_policies_for_role')
1366 |     mcp.tool.assert_any_call(name='create_data_processing_role')
1367 |     mcp.tool.assert_any_call(name='get_roles_for_service')
1368 | 
1369 |     # Verify S3 tools are registered
1370 |     mcp.tool.assert_any_call(name='list_s3_buckets')
1371 |     mcp.tool.assert_any_call(name='upload_to_s3')
1372 |     mcp.tool.assert_any_call(name='analyze_s3_usage_for_data_processing')
1373 | 
1374 | 
1375 | @pytest.mark.asyncio
1376 | async def test_initialization_default_parameters(mock_aws_helper):
1377 |     """Test initialization with default parameters."""
1378 |     mcp = Mock()
1379 |     handler = CommonResourceHandler(mcp)
1380 | 
1381 |     assert not handler.allow_write  # Default should be False
1382 |     assert handler.mcp == mcp
1383 | 
1384 | 
1385 | @pytest.mark.asyncio
1386 | async def test_get_managed_policies_error_handling(handler, mock_iam_client):
1387 |     """Test error handling in _get_managed_policies method."""
1388 |     handler.iam_client = mock_iam_client
1389 | 
1390 |     # Mock successful list_attached_role_policies
1391 |     mock_iam_client.list_attached_role_policies.return_value = {
1392 |         'AttachedPolicies': [
1393 |             {
1394 |                 'PolicyName': 'TestManagedPolicy',
1395 |                 'PolicyArn': 'arn:aws:iam::aws:policy/TestManagedPolicy',
1396 |             }
1397 |         ]
1398 |     }
1399 | 
1400 |     # Mock successful get_policy
1401 |     mock_iam_client.get_policy.return_value = {
1402 |         'Policy': {'DefaultVersionId': 'v1', 'Description': 'Test managed policy'}
1403 |     }
1404 | 
1405 |     # Mock get_policy_version to raise an exception
1406 |     mock_iam_client.get_policy_version.side_effect = ClientError(
1407 |         {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'GetPolicyVersion'
1408 |     )
1409 | 
1410 |     ctx = Mock()
1411 |     managed_policies = handler._get_managed_policies(ctx, 'test-role')
1412 | 
1413 |     # Should still return policy summary even if policy version fails
1414 |     assert len(managed_policies) == 1
1415 |     assert managed_policies[0].policy_type == 'Managed'
1416 |     assert managed_policies[0].policy_document is None
1417 | 
1418 | 
1419 | @pytest.mark.asyncio
1420 | async def test_create_data_processing_role_create_role_error(handler, mock_iam_client):
1421 |     """Test error handling when create_role fails in create_data_processing_role."""
1422 |     handler.iam_client = mock_iam_client
1423 | 
1424 |     # Mock create_role to raise an exception
1425 |     mock_iam_client.create_role.side_effect = ClientError(
1426 |         {'Error': {'Code': 'EntityAlreadyExists', 'Message': 'Role already exists'}}, 'CreateRole'
1427 |     )
1428 | 
1429 |     ctx = Mock()
1430 |     response = await handler.create_data_processing_role(
1431 |         ctx, role_name='existing-role', service_type='glue'
1432 |     )
1433 | 
1434 |     assert response.isError
1435 |     assert 'Failed to create IAM role' in response.content[0].text
1436 | 
1437 | 
1438 | @pytest.mark.asyncio
1439 | async def test_analyze_s3_usage_idle_bucket_detection(handler, mock_s3_client):
1440 |     """Test idle bucket detection in analyze_s3_usage_for_data_processing."""
1441 |     handler.s3_client = mock_s3_client
1442 | 
1443 |     # Mock list_buckets response with a bucket that has old activity
1444 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'old-bucket'}]}
1445 | 
1446 |     # Mock list_objects_v2 response with old last modified date (>90 days ago)
1447 |     old_date = datetime.now() - timedelta(days=100)
1448 |     mock_s3_client.list_objects_v2.return_value = {
1449 |         'KeyCount': 1,
1450 |         'Contents': [{'LastModified': old_date}],
1451 |     }
1452 | 
1453 |     # Mock AWS service clients
1454 |     with patch(
1455 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
1456 |     ) as mock_aws_helper:
1457 |         mock_glue_client = Mock()
1458 |         mock_athena_client = Mock()
1459 |         mock_emr_client = Mock()
1460 | 
1461 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
1462 |             'glue': mock_glue_client,
1463 |             'athena': mock_athena_client,
1464 |             'emr': mock_emr_client,
1465 |         }[service]
1466 | 
1467 |         # Mock service responses - no active usage detected
1468 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1469 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
1470 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
1471 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
1472 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
1473 | 
1474 |         ctx = Mock()
1475 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
1476 | 
1477 |         assert not response.isError
1478 |         # Should detect idle bucket
1479 |         assert (
1480 |             'IDLE: No data processing service usage detected and no activity for 90+ days'
1481 |             in response.analysis_summary
1482 |         )
1483 | 
1484 | 
1485 | @pytest.mark.asyncio
1486 | async def test_analyze_s3_usage_glue_job_detection(handler, mock_s3_client):
1487 |     """Test Glue job bucket detection in analyze_s3_usage_for_data_processing."""
1488 |     handler.s3_client = mock_s3_client
1489 | 
1490 |     # Mock list_buckets response
1491 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
1492 | 
1493 |     # Mock list_objects_v2 response
1494 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
1495 | 
1496 |     # Mock AWS service clients
1497 |     with patch(
1498 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
1499 |     ) as mock_aws_helper:
1500 |         mock_glue_client = Mock()
1501 |         mock_athena_client = Mock()
1502 |         mock_emr_client = Mock()
1503 | 
1504 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
1505 |             'glue': mock_glue_client,
1506 |             'athena': mock_athena_client,
1507 |             'emr': mock_emr_client,
1508 |         }[service]
1509 | 
1510 |         # Mock Glue job with bucket reference in DefaultArguments
1511 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1512 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
1513 |         mock_glue_client.get_jobs.return_value = {
1514 |             'Jobs': [
1515 |                 {
1516 |                     'Name': 'test-job',
1517 |                     'DefaultArguments': {
1518 |                         '--TempDir': 's3://test-bucket/temp/',
1519 |                         '--job-bookmark-option': 'job-bookmark-enable',
1520 |                     },
1521 |                 }
1522 |             ]
1523 |         }
1524 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
1525 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
1526 | 
1527 |         ctx = Mock()
1528 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
1529 | 
1530 |         assert not response.isError
1531 |         # Should detect Glue usage
1532 |         assert '✅ Used by AWS Glue' in response.analysis_summary
1533 | 
1534 | 
1535 | @pytest.mark.asyncio
1536 | async def test_analyze_s3_usage_glue_crawler_detection(handler, mock_s3_client):
1537 |     """Test Glue crawler bucket detection in analyze_s3_usage_for_data_processing."""
1538 |     handler.s3_client = mock_s3_client
1539 | 
1540 |     # Mock list_buckets response
1541 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
1542 | 
1543 |     # Mock list_objects_v2 response
1544 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
1545 | 
1546 |     # Mock AWS service clients
1547 |     with patch(
1548 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
1549 |     ) as mock_aws_helper:
1550 |         mock_glue_client = Mock()
1551 |         mock_athena_client = Mock()
1552 |         mock_emr_client = Mock()
1553 | 
1554 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
1555 |             'glue': mock_glue_client,
1556 |             'athena': mock_athena_client,
1557 |             'emr': mock_emr_client,
1558 |         }[service]
1559 | 
1560 |         # Mock Glue crawler with S3 target
1561 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1562 |         mock_glue_client.get_crawlers.return_value = {
1563 |             'Crawlers': [
1564 |                 {
1565 |                     'Name': 'test-crawler',
1566 |                     'Targets': {'S3Targets': [{'Path': 's3://test-bucket/data/'}]},
1567 |                 }
1568 |             ]
1569 |         }
1570 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
1571 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
1572 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
1573 | 
1574 |         ctx = Mock()
1575 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
1576 | 
1577 |         assert not response.isError
1578 |         # Should detect Glue usage
1579 |         assert '✅ Used by AWS Glue' in response.analysis_summary
1580 | 
1581 | 
1582 | @pytest.mark.asyncio
1583 | async def test_analyze_s3_usage_athena_workgroup_detection(handler, mock_s3_client):
1584 |     """Test Athena workgroup bucket detection in analyze_s3_usage_for_data_processing."""
1585 |     handler.s3_client = mock_s3_client
1586 | 
1587 |     # Mock list_buckets response
1588 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
1589 | 
1590 |     # Mock list_objects_v2 response
1591 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
1592 | 
1593 |     # Mock AWS service clients
1594 |     with patch(
1595 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
1596 |     ) as mock_aws_helper:
1597 |         mock_glue_client = Mock()
1598 |         mock_athena_client = Mock()
1599 |         mock_emr_client = Mock()
1600 | 
1601 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
1602 |             'glue': mock_glue_client,
1603 |             'athena': mock_athena_client,
1604 |             'emr': mock_emr_client,
1605 |         }[service]
1606 | 
1607 |         # Mock service responses
1608 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1609 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
1610 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
1611 | 
1612 |         # Mock Athena workgroup with output location
1613 |         mock_athena_client.list_work_groups.return_value = {
1614 |             'WorkGroups': [{'Name': 'test-workgroup'}]
1615 |         }
1616 |         mock_athena_client.get_work_group.return_value = {
1617 |             'WorkGroup': {
1618 |                 'Configuration': {
1619 |                     'ResultConfiguration': {'OutputLocation': 's3://test-bucket/athena-results/'}
1620 |                 }
1621 |             }
1622 |         }
1623 | 
1624 |         mock_emr_client.list_clusters.return_value = {'Clusters': []}
1625 | 
1626 |         ctx = Mock()
1627 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
1628 | 
1629 |         assert not response.isError
1630 |         # Should detect Athena usage
1631 |         assert '✅ Used by Amazon Athena' in response.analysis_summary
1632 | 
1633 | 
1634 | @pytest.mark.asyncio
1635 | async def test_analyze_s3_usage_emr_cluster_detection(handler, mock_s3_client):
1636 |     """Test EMR cluster bucket detection in analyze_s3_usage_for_data_processing."""
1637 |     handler.s3_client = mock_s3_client
1638 | 
1639 |     # Mock list_buckets response
1640 |     mock_s3_client.list_buckets.return_value = {'Buckets': [{'Name': 'test-bucket'}]}
1641 | 
1642 |     # Mock list_objects_v2 response
1643 |     mock_s3_client.list_objects_v2.return_value = {'KeyCount': 0}
1644 | 
1645 |     # Mock AWS service clients
1646 |     with patch(
1647 |         'awslabs.aws_dataprocessing_mcp_server.handlers.commons.common_resource_handler.AwsHelper'
1648 |     ) as mock_aws_helper:
1649 |         mock_glue_client = Mock()
1650 |         mock_athena_client = Mock()
1651 |         mock_emr_client = Mock()
1652 | 
1653 |         mock_aws_helper.create_boto3_client.side_effect = lambda service: {
1654 |             'glue': mock_glue_client,
1655 |             'athena': mock_athena_client,
1656 |             'emr': mock_emr_client,
1657 |         }[service]
1658 | 
1659 |         # Mock service responses
1660 |         mock_glue_client.get_connections.return_value = {'ConnectionList': []}
1661 |         mock_glue_client.get_crawlers.return_value = {'Crawlers': []}
1662 |         mock_glue_client.get_jobs.return_value = {'Jobs': []}
1663 |         mock_athena_client.list_work_groups.return_value = {'WorkGroups': []}
1664 | 
1665 |         # Mock EMR cluster with log URI
1666 |         mock_emr_client.list_clusters.return_value = {
1667 |             'Clusters': [{'Id': 'j-1234567890123', 'Name': 'test-cluster'}]
1668 |         }
1669 |         mock_emr_client.describe_cluster.return_value = {
1670 |             'Cluster': {'LogUri': 's3://test-bucket/emr-logs/'}
1671 |         }
1672 | 
1673 |         ctx = Mock()
1674 |         response = await handler.analyze_s3_usage_for_data_processing(ctx)
1675 | 
1676 |         assert not response.isError
1677 |         # Should detect EMR usage
1678 |         assert '✅ Used by Amazon EMR' in response.analysis_summary
1679 | 
1680 | 
1681 | @pytest.mark.asyncio
1682 | async def test_list_s3_buckets_us_east_1_location_constraint(handler, mock_s3_client):
1683 |     """Test list_s3_buckets with us-east-1 location constraint (None)."""
1684 |     handler.s3_client = mock_s3_client
1685 | 
1686 |     # Mock list_buckets response
1687 |     mock_s3_client.list_buckets.return_value = {
1688 |         'Buckets': [{'Name': 'test-glue-bucket', 'CreationDate': datetime(2023, 1, 1)}]
1689 |     }
1690 | 
1691 |     # Mock bucket location returning None (us-east-1 case)
1692 |     mock_s3_client.get_bucket_location.return_value = {'LocationConstraint': None}
1693 | 
1694 |     # Mock list_objects_v2 response
1695 |     mock_s3_client.list_objects_v2.return_value = {
1696 |         'KeyCount': 5,
1697 |         'Contents': [{'LastModified': datetime(2023, 6, 1)}],
1698 |     }
1699 | 
1700 |     ctx = Mock()
1701 |     response = await handler.list_s3_buckets(ctx, region='us-east-1')
1702 | 
1703 |     assert not response.isError
1704 |     assert response.region == 'us-east-1'
1705 |     assert response.bucket_count == 1
1706 |     assert len(response.buckets) == 1
1707 |     assert response.buckets[0].name == 'test-glue-bucket'
1708 | 
1709 | 
1710 | @pytest.mark.asyncio
1711 | async def test_list_s3_buckets_truncated_objects(handler, mock_s3_client):
1712 |     """Test list_s3_buckets with truncated object list."""
1713 |     handler.s3_client = mock_s3_client
1714 | 
1715 |     # Mock list_buckets response
1716 |     mock_s3_client.list_buckets.return_value = {
1717 |         'Buckets': [{'Name': 'test-glue-bucket', 'CreationDate': datetime(2023, 1, 1)}]
1718 |     }
1719 | 
1720 |     # Mock bucket location
1721 |     mock_s3_client.get_bucket_location.return_value = {'LocationConstraint': 'us-east-1'}
1722 | 
1723 |     # Mock list_objects_v2 response with truncated results
1724 |     mock_s3_client.list_objects_v2.return_value = {
1725 |         'KeyCount': 1000,
1726 |         'IsTruncated': True,
1727 |         'Contents': [{'LastModified': datetime(2023, 6, 1)}],
1728 |     }
1729 | 
1730 |     ctx = Mock()
1731 |     response = await handler.list_s3_buckets(ctx, region='us-east-1')
1732 | 
1733 |     assert not response.isError
1734 |     assert response.region == 'us-east-1'
1735 |     assert response.bucket_count == 1
1736 |     assert len(response.buckets) == 1
1737 |     assert response.buckets[0].name == 'test-glue-bucket'
1738 |     # Should show truncated count
1739 |     assert '1000+ (truncated)' in response.content[0].text
1740 | 
1741 | 
1742 | @pytest.mark.asyncio
1743 | async def test_upload_to_s3_us_east_1_location_constraint(handler, mock_s3_client):
1744 |     """Test upload_to_s3 with us-east-1 location constraint (None)."""
1745 |     handler.s3_client = mock_s3_client
1746 | 
1747 |     # Mock successful head_bucket
1748 |     mock_s3_client.head_bucket.return_value = {}
1749 | 
1750 |     # Mock bucket location returning None (us-east-1 case)
1751 |     mock_s3_client.get_bucket_location.return_value = {'LocationConstraint': None}
1752 | 
1753 |     code_content = "print('Hello, World!')"
1754 | 
1755 |     ctx = Mock()
1756 |     response = await handler.upload_to_s3(
1757 |         ctx, code_content=code_content, bucket_name='test-bucket', s3_key='scripts/test.py'
1758 |     )
1759 | 
1760 |     assert not response.isError
1761 |     assert response.s3_uri == 's3://test-bucket/scripts/test.py'
1762 |     assert response.bucket_name == 'test-bucket'
1763 |     assert response.s3_key == 'scripts/test.py'
1764 | 
1765 |     # Verify put_object was called
1766 |     mock_s3_client.put_object.assert_called_once_with(
1767 |         Body=code_content, Bucket='test-bucket', Key='scripts/test.py', ContentType='text/x-python'
1768 |     )
1769 | 
1770 | 
1771 | def test_can_be_assumed_by_service_list_actions(handler):
1772 |     """Test checking if role can be assumed by service with list of actions."""
1773 |     assume_role_policy = {
1774 |         'Version': '2012-10-17',
1775 |         'Statement': [
1776 |             {
1777 |                 'Effect': 'Allow',
1778 |                 'Principal': {'Service': 'glue.amazonaws.com'},
1779 |                 'Action': ['sts:AssumeRole', 'sts:GetCallerIdentity'],
1780 |             }
1781 |         ],
1782 |     }
1783 | 
1784 |     assert handler._can_be_assumed_by_service(assume_role_policy, 'glue.amazonaws.com')
1785 | 
1786 | 
1787 | def test_can_be_assumed_by_service_no_principal_service(handler):
1788 |     """Test checking if role can be assumed by service with no Principal.Service."""
1789 |     assume_role_policy = {
1790 |         'Version': '2012-10-17',
1791 |         'Statement': [
1792 |             {
1793 |                 'Effect': 'Allow',
1794 |                 'Principal': {'AWS': 'arn:aws:iam::123456789012:root'},
1795 |                 'Action': 'sts:AssumeRole',
1796 |             }
1797 |         ],
1798 |     }
1799 | 
1800 |     assert not handler._can_be_assumed_by_service(assume_role_policy, 'glue.amazonaws.com')
1801 | 
1802 | 
1803 | @pytest.mark.asyncio
1804 | async def test_list_s3_buckets_bucket_location_error(handler, mock_s3_client):
1805 |     """Test error handling when get_bucket_location fails in list_s3_buckets."""
1806 |     handler.s3_client = mock_s3_client
1807 | 
1808 |     # Mock list_buckets response
1809 |     mock_s3_client.list_buckets.return_value = {
1810 |         'Buckets': [{'Name': 'test-glue-bucket', 'CreationDate': datetime(2023, 1, 1)}]
1811 |     }
1812 | 
1813 |     # Mock get_bucket_location to raise an exception
1814 |     mock_s3_client.get_bucket_location.side_effect = ClientError(
1815 |         {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'GetBucketLocation'
1816 |     )
1817 | 
1818 |     ctx = Mock()
1819 |     response = await handler.list_s3_buckets(ctx, region='us-east-1')
1820 | 
1821 |     assert not response.isError
1822 |     # Should still return results but with error details in the text
1823 |     assert 'Error getting details' in response.content[0].text
1824 | 
1825 | 
1826 | @pytest.mark.asyncio
1827 | async def test_list_s3_buckets_list_objects_error(handler, mock_s3_client):
1828 |     """Test error handling when list_objects_v2 fails in list_s3_buckets."""
1829 |     handler.s3_client = mock_s3_client
1830 | 
1831 |     # Mock list_buckets response
1832 |     mock_s3_client.list_buckets.return_value = {
1833 |         'Buckets': [{'Name': 'test-glue-bucket', 'CreationDate': datetime(2023, 1, 1)}]
1834 |     }
1835 | 
1836 |     # Mock successful get_bucket_location
1837 |     mock_s3_client.get_bucket_location.return_value = {'LocationConstraint': 'us-east-1'}
1838 | 
1839 |     # Mock list_objects_v2 to raise an exception
1840 |     mock_s3_client.list_objects_v2.side_effect = ClientError(
1841 |         {'Error': {'Code': 'AccessDenied', 'Message': 'Access denied'}}, 'ListObjectsV2'
1842 |     )
1843 | 
1844 |     ctx = Mock()
1845 |     response = await handler.list_s3_buckets(ctx, region='us-east-1')
1846 | 
1847 |     assert not response.isError
1848 |     # Should still return results but with error details in the text
1849 |     assert 'Error getting details' in response.content[0].text
1850 | 
1851 | 
1852 | @pytest.mark.asyncio
1853 | async def test_upload_to_s3_bucket_access_denied(handler, mock_s3_client):
1854 |     """Test upload to S3 when access is denied to bucket."""
1855 |     handler.s3_client = mock_s3_client
1856 | 
1857 |     # Mock bucket access denied
1858 |     mock_s3_client.head_bucket.side_effect = ClientError(
1859 |         {'Error': {'Code': '403', 'Message': 'Forbidden'}}, 'HeadBucket'
1860 |     )
1861 | 
1862 |     ctx = Mock()
1863 |     response = await handler.upload_to_s3(
1864 |         ctx, code_content="print('test')", bucket_name='forbidden-bucket', s3_key='test.py'
1865 |     )
1866 | 
1867 |     assert response.isError
1868 |     assert 'Access denied to bucket' in response.content[0].text
1869 | 
1870 | 
1871 | @pytest.mark.asyncio
1872 | async def test_create_data_processing_role_attach_policy_error(handler, mock_iam_client):
1873 |     """Test error handling when attach_role_policy fails in create_data_processing_role."""
1874 |     handler.iam_client = mock_iam_client
1875 | 
1876 |     # Mock successful create_role
1877 |     mock_iam_client.create_role.return_value = {
1878 |         'Role': {'Arn': 'arn:aws:iam::123456789012:role/test-role'}
1879 |     }
1880 | 
1881 |     # Mock attach_role_policy to raise an exception
1882 |     mock_iam_client.attach_role_policy.side_effect = ClientError(
1883 |         {'Error': {'Code': 'NoSuchEntity', 'Message': 'Policy not found'}}, 'AttachRolePolicy'
1884 |     )
1885 | 
1886 |     ctx = Mock()
1887 |     response = await handler.create_data_processing_role(
1888 |         ctx,
1889 |         role_name='test-role',
1890 |         service_type='glue',
1891 |         managed_policy_arns=['arn:aws:iam::aws:policy/NonExistentPolicy'],
1892 |     )
1893 | 
1894 |     assert response.isError
1895 |     assert 'Failed to create IAM role' in response.content[0].text
1896 | 
1897 | 
1898 | @pytest.mark.asyncio
1899 | async def test_create_data_processing_role_inline_policy_error(handler, mock_iam_client):
1900 |     """Test error handling when put_role_policy fails in create_data_processing_role."""
1901 |     handler.iam_client = mock_iam_client
1902 | 
1903 |     # Mock successful create_role
1904 |     mock_iam_client.create_role.return_value = {
1905 |         'Role': {'Arn': 'arn:aws:iam::123456789012:role/test-role'}
1906 |     }
1907 | 
1908 |     # Mock put_role_policy to raise an exception
1909 |     mock_iam_client.put_role_policy.side_effect = ClientError(
1910 |         {'Error': {'Code': 'MalformedPolicyDocument', 'Message': 'Invalid policy'}},
1911 |         'PutRolePolicy',
1912 |     )
1913 | 
1914 |     inline_policy = {
1915 |         'Effect': 'Allow',
1916 |         'Action': ['s3:GetObject'],
1917 |         'Resource': 'arn:aws:s3:::test-bucket/*',
1918 |     }
1919 | 
1920 |     ctx = Mock()
1921 |     response = await handler.create_data_processing_role(
1922 |         ctx, role_name='test-role', service_type='glue', inline_policy=inline_policy
1923 |     )
1924 | 
1925 |     assert response.isError
1926 |     assert 'Failed to create IAM role' in response.content[0].text
1927 | 
```
Page 507/522FirstPrevNextLast