#
tokens: 69975/50000 1/2431 files (page 499/503)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 499 of 503. 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
├── 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
│   │   │       ├── prompts
│   │   │       │   ├── __init__.py
│   │   │       │   ├── asset_hierarchy.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
│   │   │       └── 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_init.py
│   │   │   ├── test_main.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_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
│   │   │       │   ├── 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_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
│   │   │       │   ├── 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_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/glue/test_glue_workflows_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"). You may not use this file except in compliance
   4 | # with the License. A copy of the License is located at
   5 | #
   6 | #    http://www.apache.org/licenses/LICENSE-2.0
   7 | #
   8 | # or in the 'license' file accompanying this file. This file is distributed on an 'AS IS' BASIS, WITHOUT WARRANTIES
   9 | # OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions
  10 | # and limitations under the License.
  11 | # ruff: noqa: D101, D102, D103
  12 | """Tests for the Glue Workflows and Triggers handler."""
  13 | 
  14 | import pytest
  15 | from awslabs.aws_dataprocessing_mcp_server.handlers.glue.worklows_handler import (
  16 |     GlueWorkflowAndTriggerHandler,
  17 | )
  18 | from botocore.exceptions import ClientError
  19 | from mcp.server.fastmcp import Context
  20 | from unittest.mock import MagicMock, patch
  21 | 
  22 | 
  23 | @pytest.mark.asyncio
  24 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
  25 | async def test_glue_workflow_handler_initialization(mock_create_client):
  26 |     # Create a mock Glue client
  27 |     mock_glue_client = MagicMock()
  28 |     mock_create_client.return_value = mock_glue_client
  29 | 
  30 |     # Create a mock MCP server
  31 |     mock_mcp = MagicMock()
  32 | 
  33 |     # Initialize the Glue Workflow handler with the mock MCP server
  34 |     GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
  35 | 
  36 |     # Verify that create_boto3_client was called with 'glue'
  37 |     mock_create_client.assert_called_once_with('glue')
  38 | 
  39 |     # Verify that all tools were registered
  40 |     assert mock_mcp.tool.call_count == 2
  41 | 
  42 |     # Get all call args
  43 |     call_args_list = mock_mcp.tool.call_args_list
  44 | 
  45 |     # Get all tool names that were registered
  46 |     tool_names = [call_args[1]['name'] for call_args in call_args_list]
  47 | 
  48 |     # Verify that all expected tools were registered
  49 |     assert 'manage_aws_glue_workflows' in tool_names
  50 |     assert 'manage_aws_glue_triggers' in tool_names
  51 | 
  52 | 
  53 | # Tests for manage_aws_glue_workflows method
  54 | 
  55 | 
  56 | @pytest.mark.asyncio
  57 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
  58 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
  59 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
  60 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
  61 | async def test_create_workflow_success(
  62 |     mock_get_account_id, mock_get_region, mock_prepare_tags, mock_create_client
  63 | ):
  64 |     # Create a mock Glue client
  65 |     mock_glue_client = MagicMock()
  66 |     mock_create_client.return_value = mock_glue_client
  67 | 
  68 |     # Mock the resource tags
  69 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
  70 | 
  71 |     # Create a mock MCP server
  72 |     mock_mcp = MagicMock()
  73 | 
  74 |     # Initialize the Glue Workflow handler with the mock MCP server
  75 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
  76 |     handler.glue_client = mock_glue_client
  77 | 
  78 |     # Create a mock context
  79 |     mock_ctx = MagicMock(spec=Context)
  80 | 
  81 |     # Mock the create_workflow response
  82 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
  83 | 
  84 |     # Call the manage_aws_glue_workflows method with create-workflow operation
  85 |     result = await handler.manage_aws_glue_workflows(
  86 |         mock_ctx,
  87 |         operation='create-workflow',
  88 |         workflow_name='test-workflow',
  89 |         workflow_definition={
  90 |             'Description': 'Test workflow',
  91 |             'DefaultRunProperties': {'ENV': 'test'},
  92 |             'MaxConcurrentRuns': 1,
  93 |         },
  94 |     )
  95 | 
  96 |     # Verify the result
  97 |     assert not result.isError
  98 |     assert len(result.content) == 1
  99 |     assert result.content[0].type == 'text'
 100 |     assert 'Successfully created workflow test-workflow' in result.content[0].text
 101 |     assert result.workflow_name == 'test-workflow'
 102 | 
 103 |     # Verify that create_workflow was called with the correct parameters
 104 |     mock_glue_client.create_workflow.assert_called_once()
 105 |     args, kwargs = mock_glue_client.create_workflow.call_args
 106 |     assert kwargs['Name'] == 'test-workflow'
 107 |     assert kwargs['Description'] == 'Test workflow'
 108 |     assert kwargs['DefaultRunProperties'] == {'ENV': 'test'}
 109 |     assert kwargs['MaxConcurrentRuns'] == 1
 110 |     assert kwargs['Tags'] == {'ManagedBy': 'MCP'}
 111 | 
 112 | 
 113 | @pytest.mark.asyncio
 114 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 115 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
 116 | async def test_create_workflow_with_user_tags(mock_prepare_tags, mock_create_client):
 117 |     """Test creating a workflow with user-provided tags."""
 118 |     # Create a mock Glue client
 119 |     mock_glue_client = MagicMock()
 120 |     mock_create_client.return_value = mock_glue_client
 121 | 
 122 |     # Mock the resource tags
 123 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
 124 | 
 125 |     # Create a mock MCP server
 126 |     mock_mcp = MagicMock()
 127 | 
 128 |     # Initialize the Glue Workflow handler with the mock MCP server
 129 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 130 |     handler.glue_client = mock_glue_client
 131 | 
 132 |     # Create a mock context
 133 |     mock_ctx = MagicMock(spec=Context)
 134 | 
 135 |     # Mock the create_workflow response
 136 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
 137 | 
 138 |     # Call the manage_aws_glue_workflows method with create-workflow operation and user tags
 139 |     result = await handler.manage_aws_glue_workflows(
 140 |         mock_ctx,
 141 |         operation='create-workflow',
 142 |         workflow_name='test-workflow',
 143 |         workflow_definition={
 144 |             'Description': 'Test workflow',
 145 |             'Tags': {'Environment': 'Test', 'Project': 'UnitTest'},
 146 |         },
 147 |     )
 148 | 
 149 |     # Verify the result
 150 |     assert not result.isError
 151 |     assert result.workflow_name == 'test-workflow'
 152 | 
 153 |     # Verify that create_workflow was called with merged tags
 154 |     mock_glue_client.create_workflow.assert_called_once()
 155 |     args, kwargs = mock_glue_client.create_workflow.call_args
 156 |     assert kwargs['Tags'] == {'Environment': 'Test', 'Project': 'UnitTest', 'ManagedBy': 'MCP'}
 157 | 
 158 | 
 159 | @pytest.mark.asyncio
 160 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 161 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
 162 | async def test_create_workflow_with_only_description(mock_prepare_tags, mock_create_client):
 163 |     """Test creating a workflow with only description parameter."""
 164 |     # Create a mock Glue client
 165 |     mock_glue_client = MagicMock()
 166 |     mock_create_client.return_value = mock_glue_client
 167 | 
 168 |     # Mock the resource tags
 169 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
 170 | 
 171 |     # Create a mock MCP server
 172 |     mock_mcp = MagicMock()
 173 | 
 174 |     # Initialize the Glue Workflow handler with the mock MCP server
 175 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 176 |     handler.glue_client = mock_glue_client
 177 | 
 178 |     # Create a mock context
 179 |     mock_ctx = MagicMock(spec=Context)
 180 | 
 181 |     # Mock the create_workflow response
 182 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
 183 | 
 184 |     # Call the manage_aws_glue_workflows method with create-workflow operation and only description
 185 |     result = await handler.manage_aws_glue_workflows(
 186 |         mock_ctx,
 187 |         operation='create-workflow',
 188 |         workflow_name='test-workflow',
 189 |         workflow_definition={
 190 |             'Description': 'Test workflow',
 191 |         },
 192 |     )
 193 | 
 194 |     # Verify the result
 195 |     assert not result.isError
 196 |     assert result.workflow_name == 'test-workflow'
 197 | 
 198 |     # Verify that create_workflow was called with the correct parameters
 199 |     mock_glue_client.create_workflow.assert_called_once()
 200 |     args, kwargs = mock_glue_client.create_workflow.call_args
 201 |     assert kwargs['Description'] == 'Test workflow'
 202 |     assert 'DefaultRunProperties' not in kwargs
 203 |     assert kwargs['Tags'] == {'ManagedBy': 'MCP'}
 204 | 
 205 | 
 206 | @pytest.mark.asyncio
 207 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 208 | async def test_create_workflow_missing_parameters(mock_create_client):
 209 |     """Test creating a workflow with missing required parameters."""
 210 |     # Create a mock Glue client
 211 |     mock_glue_client = MagicMock()
 212 |     mock_create_client.return_value = mock_glue_client
 213 | 
 214 |     # Create a mock MCP server
 215 |     mock_mcp = MagicMock()
 216 | 
 217 |     # Initialize the Glue Workflow handler with the mock MCP server
 218 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 219 |     handler.glue_client = mock_glue_client
 220 | 
 221 |     # Create a mock context
 222 |     mock_ctx = MagicMock(spec=Context)
 223 | 
 224 |     # Test missing workflow_definition
 225 |     with pytest.raises(ValueError) as excinfo:
 226 |         await handler.manage_aws_glue_workflows(
 227 |             mock_ctx,
 228 |             operation='create-workflow',
 229 |             workflow_name='test-workflow',
 230 |             workflow_definition=None,
 231 |         )
 232 |     assert 'workflow_name and workflow_definition are required' in str(excinfo.value)
 233 | 
 234 |     # Test missing workflow_name
 235 |     with pytest.raises(ValueError) as excinfo:
 236 |         await handler.manage_aws_glue_workflows(
 237 |             mock_ctx,
 238 |             operation='create-workflow',
 239 |             workflow_name=None,
 240 |             workflow_definition={'Description': 'Test workflow'},
 241 |         )
 242 |     assert 'workflow_name and workflow_definition are required' in str(excinfo.value)
 243 | 
 244 | 
 245 | @pytest.mark.asyncio
 246 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 247 | async def test_get_workflow_with_include_graph_false(mock_create_client):
 248 |     """Test getting a workflow with include_graph parameter set to False."""
 249 |     # Create a mock Glue client
 250 |     mock_glue_client = MagicMock()
 251 |     mock_create_client.return_value = mock_glue_client
 252 | 
 253 |     # Create a mock MCP server
 254 |     mock_mcp = MagicMock()
 255 | 
 256 |     # Initialize the Glue Workflow handler with the mock MCP server
 257 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
 258 |     handler.glue_client = mock_glue_client
 259 | 
 260 |     # Create a mock context
 261 |     mock_ctx = MagicMock(spec=Context)
 262 | 
 263 |     # Mock the get_workflow response
 264 |     mock_workflow_details = {
 265 |         'Name': 'test-workflow',
 266 |         'Description': 'Test workflow',
 267 |         'CreatedOn': '2023-01-01T00:00:00Z',
 268 |     }
 269 |     mock_glue_client.get_workflow.return_value = {'Workflow': mock_workflow_details}
 270 | 
 271 |     # Call the manage_aws_glue_workflows method with get-workflow operation and include_graph=False
 272 |     result = await handler.manage_aws_glue_workflows(
 273 |         mock_ctx,
 274 |         operation='get-workflow',
 275 |         workflow_name='test-workflow',
 276 |         workflow_definition={'include_graph': False},
 277 |     )
 278 | 
 279 |     # Verify the result
 280 |     assert not result.isError
 281 |     assert result.workflow_name == 'test-workflow'
 282 |     assert result.workflow_details == mock_workflow_details
 283 | 
 284 |     # Verify that get_workflow was called without IncludeGraph parameter
 285 |     mock_glue_client.get_workflow.assert_called_once_with(Name='test-workflow')
 286 | 
 287 | 
 288 | @pytest.mark.asyncio
 289 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 290 | async def test_create_workflow_no_write_access(mock_create_client):
 291 |     # Create a mock Glue client
 292 |     mock_glue_client = MagicMock()
 293 |     mock_create_client.return_value = mock_glue_client
 294 | 
 295 |     # Create a mock MCP server
 296 |     mock_mcp = MagicMock()
 297 | 
 298 |     # Initialize the Glue Workflow handler with the mock MCP server without write access
 299 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=False)
 300 |     handler.glue_client = mock_glue_client
 301 | 
 302 |     # Create a mock context
 303 |     mock_ctx = MagicMock(spec=Context)
 304 | 
 305 |     # Call the manage_aws_glue_workflows method with create-workflow operation
 306 |     result = await handler.manage_aws_glue_workflows(
 307 |         mock_ctx,
 308 |         operation='create-workflow',
 309 |         workflow_name='test-workflow',
 310 |         workflow_definition={'Description': 'Test workflow'},
 311 |     )
 312 | 
 313 |     # Verify the result indicates an error due to no write access
 314 |     assert result.isError
 315 |     assert len(result.content) == 1
 316 |     assert result.content[0].type == 'text'
 317 |     assert (
 318 |         'Operation create-workflow is not allowed without write access' in result.content[0].text
 319 |     )
 320 |     assert result.workflow_name == ''
 321 | 
 322 |     # Verify that create_workflow was NOT called
 323 |     mock_glue_client.create_workflow.assert_not_called()
 324 | 
 325 | 
 326 | @pytest.mark.asyncio
 327 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 328 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
 329 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
 330 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
 331 | async def test_delete_workflow_success(
 332 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
 333 | ):
 334 |     # Create a mock Glue client
 335 |     mock_glue_client = MagicMock()
 336 |     mock_create_client.return_value = mock_glue_client
 337 | 
 338 |     # Mock the region and account ID
 339 |     mock_get_region.return_value = 'us-east-1'
 340 |     mock_get_account_id.return_value = '123456789012'
 341 | 
 342 |     # Mock the is_resource_mcp_managed to return True
 343 |     mock_is_mcp_managed.return_value = True
 344 | 
 345 |     # Create a mock MCP server
 346 |     mock_mcp = MagicMock()
 347 | 
 348 |     # Initialize the Glue Workflow handler with the mock MCP server
 349 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 350 |     handler.glue_client = mock_glue_client
 351 | 
 352 |     # Create a mock context
 353 |     mock_ctx = MagicMock(spec=Context)
 354 | 
 355 |     # Mock the get_workflow response
 356 |     mock_glue_client.get_workflow.return_value = {
 357 |         'Workflow': {'Name': 'test-workflow', 'Tags': {'ManagedBy': 'MCP'}}
 358 |     }
 359 | 
 360 |     # Call the manage_aws_glue_workflows method with delete-workflow operation
 361 |     result = await handler.manage_aws_glue_workflows(
 362 |         mock_ctx, operation='delete-workflow', workflow_name='test-workflow'
 363 |     )
 364 | 
 365 |     # Verify the result
 366 |     assert not result.isError
 367 |     assert len(result.content) == 1
 368 |     assert result.content[0].type == 'text'
 369 |     assert 'Successfully deleted workflow test-workflow' in result.content[0].text
 370 |     assert result.workflow_name == 'test-workflow'
 371 | 
 372 |     # Verify that delete_workflow was called with the correct parameters
 373 |     mock_glue_client.delete_workflow.assert_called_once_with(Name='test-workflow')
 374 | 
 375 | 
 376 | @pytest.mark.asyncio
 377 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 378 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
 379 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
 380 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
 381 | async def test_delete_workflow_not_mcp_managed(
 382 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
 383 | ):
 384 |     # Create a mock Glue client
 385 |     mock_glue_client = MagicMock()
 386 |     mock_create_client.return_value = mock_glue_client
 387 | 
 388 |     # Mock the region and account ID
 389 |     mock_get_region.return_value = 'us-east-1'
 390 |     mock_get_account_id.return_value = '123456789012'
 391 | 
 392 |     # Mock the is_resource_mcp_managed to return False
 393 |     mock_is_mcp_managed.return_value = False
 394 | 
 395 |     # Create a mock MCP server
 396 |     mock_mcp = MagicMock()
 397 | 
 398 |     # Initialize the Glue Workflow handler with the mock MCP server
 399 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 400 |     handler.glue_client = mock_glue_client
 401 | 
 402 |     # Create a mock context
 403 |     mock_ctx = MagicMock(spec=Context)
 404 | 
 405 |     # Mock the get_workflow response
 406 |     mock_glue_client.get_workflow.return_value = {
 407 |         'Workflow': {
 408 |             'Name': 'test-workflow',
 409 |             'Tags': {},  # No MCP tags
 410 |         }
 411 |     }
 412 | 
 413 |     # Call the manage_aws_glue_workflows method with delete-workflow operation
 414 |     result = await handler.manage_aws_glue_workflows(
 415 |         mock_ctx, operation='delete-workflow', workflow_name='test-workflow'
 416 |     )
 417 | 
 418 |     # Verify the result indicates an error because the workflow is not MCP managed
 419 |     assert result.isError
 420 |     assert len(result.content) == 1
 421 |     assert result.content[0].type == 'text'
 422 |     assert (
 423 |         'Cannot delete workflow test-workflow - it is not managed by the MCP server'
 424 |         in result.content[0].text
 425 |     )
 426 |     assert result.workflow_name == 'test-workflow'
 427 | 
 428 |     # Verify that delete_workflow was NOT called
 429 |     mock_glue_client.delete_workflow.assert_not_called()
 430 | 
 431 | 
 432 | @pytest.mark.asyncio
 433 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 434 | async def test_get_workflow_success(mock_create_client):
 435 |     # Create a mock Glue client
 436 |     mock_glue_client = MagicMock()
 437 |     mock_create_client.return_value = mock_glue_client
 438 | 
 439 |     # Create a mock MCP server
 440 |     mock_mcp = MagicMock()
 441 | 
 442 |     # Initialize the Glue Workflow handler with the mock MCP server
 443 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
 444 |     handler.glue_client = mock_glue_client
 445 | 
 446 |     # Create a mock context
 447 |     mock_ctx = MagicMock(spec=Context)
 448 | 
 449 |     # Mock the get_workflow response
 450 |     mock_workflow_details = {
 451 |         'Name': 'test-workflow',
 452 |         'Description': 'Test workflow',
 453 |         'CreatedOn': '2023-01-01T00:00:00Z',
 454 |     }
 455 |     mock_glue_client.get_workflow.return_value = {'Workflow': mock_workflow_details}
 456 | 
 457 |     # Call the manage_aws_glue_workflows method with get-workflow operation
 458 |     result = await handler.manage_aws_glue_workflows(
 459 |         mock_ctx, operation='get-workflow', workflow_name='test-workflow'
 460 |     )
 461 | 
 462 |     # Verify the result
 463 |     assert not result.isError
 464 |     assert len(result.content) == 1
 465 |     assert result.content[0].type == 'text'
 466 |     assert 'Successfully retrieved workflow test-workflow' in result.content[0].text
 467 |     assert result.workflow_name == 'test-workflow'
 468 |     assert result.workflow_details == mock_workflow_details
 469 | 
 470 |     # Verify that get_workflow was called with the correct parameters
 471 |     mock_glue_client.get_workflow.assert_called_once_with(Name='test-workflow')
 472 | 
 473 | 
 474 | @pytest.mark.asyncio
 475 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 476 | async def test_get_workflow_with_include_graph(mock_create_client):
 477 |     # Create a mock Glue client
 478 |     mock_glue_client = MagicMock()
 479 |     mock_create_client.return_value = mock_glue_client
 480 | 
 481 |     # Create a mock MCP server
 482 |     mock_mcp = MagicMock()
 483 | 
 484 |     # Initialize the Glue Workflow handler with the mock MCP server
 485 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
 486 |     handler.glue_client = mock_glue_client
 487 | 
 488 |     # Create a mock context
 489 |     mock_ctx = MagicMock(spec=Context)
 490 | 
 491 |     # Mock the get_workflow response
 492 |     mock_workflow_details = {
 493 |         'Name': 'test-workflow',
 494 |         'Description': 'Test workflow',
 495 |         'CreatedOn': '2023-01-01T00:00:00Z',
 496 |         'Graph': {'Nodes': [{'Type': 'JOB', 'Name': 'test-job'}], 'Edges': []},
 497 |     }
 498 |     mock_glue_client.get_workflow.return_value = {'Workflow': mock_workflow_details}
 499 | 
 500 |     # Call the manage_aws_glue_workflows method with get-workflow operation and include_graph
 501 |     result = await handler.manage_aws_glue_workflows(
 502 |         mock_ctx,
 503 |         operation='get-workflow',
 504 |         workflow_name='test-workflow',
 505 |         workflow_definition={'include_graph': True},
 506 |     )
 507 | 
 508 |     # Verify the result
 509 |     assert not result.isError
 510 |     assert len(result.content) == 1
 511 |     assert result.content[0].type == 'text'
 512 |     assert 'Successfully retrieved workflow test-workflow' in result.content[0].text
 513 |     assert result.workflow_name == 'test-workflow'
 514 |     assert result.workflow_details == mock_workflow_details
 515 | 
 516 |     # Verify that get_workflow was called with the correct parameters
 517 |     mock_glue_client.get_workflow.assert_called_once_with(Name='test-workflow', IncludeGraph=True)
 518 | 
 519 | 
 520 | @pytest.mark.asyncio
 521 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 522 | async def test_list_workflows_success(mock_create_client):
 523 |     # Create a mock Glue client
 524 |     mock_glue_client = MagicMock()
 525 |     mock_create_client.return_value = mock_glue_client
 526 | 
 527 |     # Create a mock MCP server
 528 |     mock_mcp = MagicMock()
 529 | 
 530 |     # Initialize the Glue Workflow handler with the mock MCP server
 531 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
 532 |     handler.glue_client = mock_glue_client
 533 | 
 534 |     # Create a mock context
 535 |     mock_ctx = MagicMock(spec=Context)
 536 | 
 537 |     # Mock the list_workflows response - AWS API returns workflow names as strings
 538 |     mock_glue_client.list_workflows.return_value = {
 539 |         'Workflows': ['workflow1', 'workflow2'],
 540 |         'NextToken': 'next-token',
 541 |     }
 542 | 
 543 |     # Call the manage_aws_glue_workflows method with list-workflows operation
 544 |     result = await handler.manage_aws_glue_workflows(
 545 |         mock_ctx, operation='list-workflows', max_results=10, next_token='token'
 546 |     )
 547 | 
 548 |     # Verify the result
 549 |     assert not result.isError
 550 |     assert len(result.content) == 1
 551 |     assert result.content[0].type == 'text'
 552 |     assert 'Successfully retrieved workflows' in result.content[0].text
 553 |     assert len(result.workflows) == 2
 554 |     assert result.workflows[0]['Name'] == 'workflow1'
 555 |     assert result.workflows[1]['Name'] == 'workflow2'
 556 |     assert result.next_token == 'next-token'
 557 | 
 558 |     # Verify that list_workflows was called with the correct parameters
 559 |     mock_glue_client.list_workflows.assert_called_once_with(MaxResults=10, NextToken='token')
 560 | 
 561 | 
 562 | @pytest.mark.asyncio
 563 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 564 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
 565 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
 566 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
 567 | async def test_start_workflow_run_success(
 568 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
 569 | ):
 570 |     # Create a mock Glue client
 571 |     mock_glue_client = MagicMock()
 572 |     mock_create_client.return_value = mock_glue_client
 573 | 
 574 |     # Mock the region and account ID
 575 |     mock_get_region.return_value = 'us-east-1'
 576 |     mock_get_account_id.return_value = '123456789012'
 577 | 
 578 |     # Mock the is_resource_mcp_managed to return True
 579 |     mock_is_mcp_managed.return_value = True
 580 | 
 581 |     # Create a mock MCP server
 582 |     mock_mcp = MagicMock()
 583 | 
 584 |     # Initialize the Glue Workflow handler with the mock MCP server
 585 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 586 |     handler.glue_client = mock_glue_client
 587 | 
 588 |     # Create a mock context
 589 |     mock_ctx = MagicMock(spec=Context)
 590 | 
 591 |     # Mock the get_workflow response
 592 |     mock_glue_client.get_workflow.return_value = {
 593 |         'Workflow': {'Name': 'test-workflow', 'Tags': {'ManagedBy': 'MCP'}}
 594 |     }
 595 | 
 596 |     # Mock the start_workflow_run response
 597 |     mock_glue_client.start_workflow_run.return_value = {'RunId': 'run-123'}
 598 | 
 599 |     # Call the manage_aws_glue_workflows method with start-workflow-run operation
 600 |     result = await handler.manage_aws_glue_workflows(
 601 |         mock_ctx,
 602 |         operation='start-workflow-run',
 603 |         workflow_name='test-workflow',
 604 |         workflow_definition={'run_properties': {'ENV': 'test'}},
 605 |     )
 606 | 
 607 |     # Verify the result
 608 |     assert not result.isError
 609 |     assert len(result.content) == 1
 610 |     assert result.content[0].type == 'text'
 611 |     assert 'Successfully started workflow run for test-workflow' in result.content[0].text
 612 |     assert result.workflow_name == 'test-workflow'
 613 |     assert result.run_id == 'run-123'
 614 | 
 615 |     # Verify that start_workflow_run was called with the correct parameters
 616 |     mock_glue_client.start_workflow_run.assert_called_once_with(
 617 |         Name='test-workflow', RunProperties={'ENV': 'test'}
 618 |     )
 619 | 
 620 | 
 621 | @pytest.mark.asyncio
 622 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 623 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
 624 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
 625 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
 626 | async def test_start_workflow_run_not_mcp_managed(
 627 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
 628 | ):
 629 |     """Test starting a workflow run for a workflow that is not MCP managed."""
 630 |     # Create a mock Glue client
 631 |     mock_glue_client = MagicMock()
 632 |     mock_create_client.return_value = mock_glue_client
 633 | 
 634 |     # Mock the region and account ID
 635 |     mock_get_region.return_value = 'us-east-1'
 636 |     mock_get_account_id.return_value = '123456789012'
 637 | 
 638 |     # Mock the is_resource_mcp_managed to return False
 639 |     mock_is_mcp_managed.return_value = False
 640 | 
 641 |     # Create a mock MCP server
 642 |     mock_mcp = MagicMock()
 643 | 
 644 |     # Initialize the Glue Workflow handler with the mock MCP server
 645 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 646 |     handler.glue_client = mock_glue_client
 647 | 
 648 |     # Create a mock context
 649 |     mock_ctx = MagicMock(spec=Context)
 650 | 
 651 |     # Mock the get_workflow response
 652 |     mock_glue_client.get_workflow.return_value = {
 653 |         'Workflow': {'Name': 'test-workflow', 'Tags': {}}  # No MCP tags
 654 |     }
 655 | 
 656 |     # Call the manage_aws_glue_workflows method with start-workflow-run operation
 657 |     result = await handler.manage_aws_glue_workflows(
 658 |         mock_ctx,
 659 |         operation='start-workflow-run',
 660 |         workflow_name='test-workflow',
 661 |     )
 662 | 
 663 |     # Verify the result indicates an error because the workflow is not MCP managed
 664 |     assert result.isError
 665 |     assert len(result.content) == 1
 666 |     assert result.content[0].type == 'text'
 667 |     assert (
 668 |         'Cannot start workflow run for test-workflow - it is not managed by the MCP server'
 669 |         in result.content[0].text
 670 |     )
 671 | 
 672 |     # Verify that start_workflow_run was NOT called
 673 |     mock_glue_client.start_workflow_run.assert_not_called()
 674 | 
 675 | 
 676 | @pytest.mark.asyncio
 677 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 678 | async def test_start_workflow_run_no_write_access(mock_create_client):
 679 |     """Test starting a workflow run without write access."""
 680 |     # Create a mock Glue client
 681 |     mock_glue_client = MagicMock()
 682 |     mock_create_client.return_value = mock_glue_client
 683 | 
 684 |     # Create a mock MCP server
 685 |     mock_mcp = MagicMock()
 686 | 
 687 |     # Initialize the Glue Workflow handler with the mock MCP server without write access
 688 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=False)
 689 |     handler.glue_client = mock_glue_client
 690 | 
 691 |     # Create a mock context
 692 |     mock_ctx = MagicMock(spec=Context)
 693 | 
 694 |     # Call the manage_aws_glue_workflows method with start-workflow-run operation
 695 |     result = await handler.manage_aws_glue_workflows(
 696 |         mock_ctx,
 697 |         operation='start-workflow-run',
 698 |         workflow_name='test-workflow',
 699 |     )
 700 | 
 701 |     # Verify the result indicates an error due to no write access
 702 |     assert result.isError
 703 |     assert len(result.content) == 1
 704 |     assert result.content[0].type == 'text'
 705 |     assert (
 706 |         'Operation start-workflow-run is not allowed without write access'
 707 |         in result.content[0].text
 708 |     )
 709 | 
 710 |     # Verify that start_workflow_run was NOT called
 711 |     mock_glue_client.start_workflow_run.assert_not_called()
 712 | 
 713 | 
 714 | @pytest.mark.asyncio
 715 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 716 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
 717 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
 718 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
 719 | async def test_start_workflow_run_not_found(
 720 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
 721 | ):
 722 |     """Test starting a workflow run for a workflow that doesn't exist."""
 723 |     # Create a mock Glue client
 724 |     mock_glue_client = MagicMock()
 725 |     mock_create_client.return_value = mock_glue_client
 726 | 
 727 |     # Mock the region and account ID
 728 |     mock_get_region.return_value = 'us-east-1'
 729 |     mock_get_account_id.return_value = '123456789012'
 730 | 
 731 |     # Create a mock MCP server
 732 |     mock_mcp = MagicMock()
 733 | 
 734 |     # Initialize the Glue Workflow handler with the mock MCP server
 735 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 736 |     handler.glue_client = mock_glue_client
 737 | 
 738 |     # Create a mock context
 739 |     mock_ctx = MagicMock(spec=Context)
 740 | 
 741 |     # Mock the get_workflow to raise EntityNotFoundException
 742 |     mock_glue_client.exceptions.EntityNotFoundException = ClientError(
 743 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Workflow not found'}},
 744 |         'get_workflow',
 745 |     )
 746 |     mock_glue_client.get_workflow.side_effect = mock_glue_client.exceptions.EntityNotFoundException
 747 | 
 748 |     # Call the manage_aws_glue_workflows method with start-workflow-run operation
 749 |     result = await handler.manage_aws_glue_workflows(
 750 |         mock_ctx,
 751 |         operation='start-workflow-run',
 752 |         workflow_name='test-workflow',
 753 |     )
 754 | 
 755 |     # Verify the result indicates an error because the workflow was not found
 756 |     assert result.isError
 757 |     assert len(result.content) == 1
 758 |     assert result.content[0].type == 'text'
 759 |     assert 'Workflow test-workflow not found' in result.content[0].text
 760 | 
 761 |     # Verify that start_workflow_run was NOT called
 762 |     mock_glue_client.start_workflow_run.assert_not_called()
 763 | 
 764 | 
 765 | @pytest.mark.asyncio
 766 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 767 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
 768 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
 769 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
 770 | async def test_start_workflow_run_without_run_properties(
 771 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
 772 | ):
 773 |     """Test starting a workflow run without run properties."""
 774 |     # Create a mock Glue client
 775 |     mock_glue_client = MagicMock()
 776 |     mock_create_client.return_value = mock_glue_client
 777 | 
 778 |     # Mock the region and account ID
 779 |     mock_get_region.return_value = 'us-east-1'
 780 |     mock_get_account_id.return_value = '123456789012'
 781 | 
 782 |     # Mock the is_resource_mcp_managed to return True
 783 |     mock_is_mcp_managed.return_value = True
 784 | 
 785 |     # Create a mock MCP server
 786 |     mock_mcp = MagicMock()
 787 | 
 788 |     # Initialize the Glue Workflow handler with the mock MCP server
 789 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 790 |     handler.glue_client = mock_glue_client
 791 | 
 792 |     # Create a mock context
 793 |     mock_ctx = MagicMock(spec=Context)
 794 | 
 795 |     # Mock the get_workflow response
 796 |     mock_glue_client.get_workflow.return_value = {
 797 |         'Workflow': {'Name': 'test-workflow', 'Tags': {'ManagedBy': 'MCP'}}
 798 |     }
 799 | 
 800 |     # Mock the start_workflow_run response
 801 |     mock_glue_client.start_workflow_run.return_value = {'RunId': 'run-123'}
 802 | 
 803 |     # Call the manage_aws_glue_workflows method with start-workflow-run operation without run_properties
 804 |     result = await handler.manage_aws_glue_workflows(
 805 |         mock_ctx,
 806 |         operation='start-workflow-run',
 807 |         workflow_name='test-workflow',
 808 |         workflow_definition={},  # Empty definition, no run_properties
 809 |     )
 810 | 
 811 |     # Verify the result
 812 |     assert not result.isError
 813 |     assert result.workflow_name == 'test-workflow'
 814 |     assert result.run_id == 'run-123'
 815 | 
 816 |     # Verify that start_workflow_run was called with just the Name parameter
 817 |     mock_glue_client.start_workflow_run.assert_called_once_with(Name='test-workflow')
 818 | 
 819 | 
 820 | @pytest.mark.asyncio
 821 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 822 | async def test_manage_aws_glue_workflows_general_exception(mock_create_client):
 823 |     """Test handling of general exceptions in manage_aws_glue_workflows."""
 824 |     # Create a mock Glue client that raises an exception
 825 |     mock_glue_client = MagicMock()
 826 |     mock_glue_client.get_workflow.side_effect = Exception('Test exception')
 827 |     mock_create_client.return_value = mock_glue_client
 828 | 
 829 |     # Create a mock MCP server
 830 |     mock_mcp = MagicMock()
 831 | 
 832 |     # Initialize the Glue Workflow handler with the mock MCP server
 833 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
 834 |     handler.glue_client = mock_glue_client
 835 | 
 836 |     # Create a mock context
 837 |     mock_ctx = MagicMock(spec=Context)
 838 | 
 839 |     # Call the manage_aws_glue_workflows method with get-workflow operation
 840 |     result = await handler.manage_aws_glue_workflows(
 841 |         mock_ctx, operation='get-workflow', workflow_name='test-workflow'
 842 |     )
 843 | 
 844 |     # Verify the result indicates an error
 845 |     assert result.isError
 846 |     assert len(result.content) == 1
 847 |     assert result.content[0].type == 'text'
 848 |     assert 'Error in manage_aws_glue_workflows: Test exception' in result.content[0].text
 849 | 
 850 | 
 851 | @pytest.mark.asyncio
 852 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 853 | async def test_invalid_operation(mock_create_client):
 854 |     # Create a mock Glue client
 855 |     mock_glue_client = MagicMock()
 856 |     mock_create_client.return_value = mock_glue_client
 857 | 
 858 |     # Create a mock MCP server
 859 |     mock_mcp = MagicMock()
 860 | 
 861 |     # Initialize the Glue Workflow handler with the mock MCP server
 862 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
 863 |     handler.glue_client = mock_glue_client
 864 | 
 865 |     # Create a mock context
 866 |     mock_ctx = MagicMock(spec=Context)
 867 | 
 868 |     # Call the manage_aws_glue_workflows method with an invalid operation
 869 |     result = await handler.manage_aws_glue_workflows(
 870 |         mock_ctx, operation='invalid-operation', workflow_name='test-workflow'
 871 |     )
 872 | 
 873 |     # Verify the result indicates an error due to invalid operation
 874 |     assert result.isError
 875 |     assert len(result.content) == 1
 876 |     assert result.content[0].type == 'text'
 877 |     assert 'Invalid operation: invalid-operation' in result.content[0].text
 878 |     assert result.workflow_name == 'test-workflow'
 879 | 
 880 | 
 881 | @pytest.mark.asyncio
 882 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 883 | async def test_workflow_not_found(mock_create_client):
 884 |     # Create a mock Glue client
 885 |     mock_glue_client = MagicMock()
 886 |     mock_create_client.return_value = mock_glue_client
 887 | 
 888 |     # Create a mock MCP server
 889 |     mock_mcp = MagicMock()
 890 | 
 891 |     # Initialize the Glue Workflow handler with the mock MCP server
 892 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 893 |     handler.glue_client = mock_glue_client
 894 | 
 895 |     # Create a mock context
 896 |     mock_ctx = MagicMock(spec=Context)
 897 | 
 898 |     # Mock the get_workflow to raise EntityNotFoundException
 899 |     mock_glue_client.exceptions.EntityNotFoundException = ClientError(
 900 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Workflow not found'}},
 901 |         'get_workflow',
 902 |     )
 903 |     mock_glue_client.get_workflow.side_effect = mock_glue_client.exceptions.EntityNotFoundException
 904 | 
 905 |     # Call the manage_aws_glue_workflows method with delete-workflow operation
 906 |     result = await handler.manage_aws_glue_workflows(
 907 |         mock_ctx, operation='delete-workflow', workflow_name='test-workflow'
 908 |     )
 909 | 
 910 |     # Verify the result indicates an error because the workflow was not found
 911 |     assert result.isError
 912 |     assert len(result.content) == 1
 913 |     assert result.content[0].type == 'text'
 914 |     assert 'Workflow test-workflow not found' in result.content[0].text
 915 |     assert result.workflow_name == 'test-workflow'
 916 | 
 917 |     # Verify that delete_workflow was NOT called
 918 |     mock_glue_client.delete_workflow.assert_not_called()
 919 | 
 920 | 
 921 | # Tests for manage_aws_glue_triggers method
 922 | 
 923 | 
 924 | @pytest.mark.asyncio
 925 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 926 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
 927 | async def test_create_trigger_success(mock_prepare_tags, mock_create_client):
 928 |     # Create a mock Glue client
 929 |     mock_glue_client = MagicMock()
 930 |     mock_create_client.return_value = mock_glue_client
 931 | 
 932 |     # Mock the resource tags
 933 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
 934 | 
 935 |     # Create a mock MCP server
 936 |     mock_mcp = MagicMock()
 937 | 
 938 |     # Initialize the Glue Workflow handler with the mock MCP server
 939 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 940 |     handler.glue_client = mock_glue_client
 941 | 
 942 |     # Create a mock context
 943 |     mock_ctx = MagicMock(spec=Context)
 944 | 
 945 |     # Mock the create_trigger response
 946 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
 947 | 
 948 |     # Call the manage_aws_glue_triggers method with create-trigger operation
 949 |     result = await handler.manage_aws_glue_triggers(
 950 |         mock_ctx,
 951 |         operation='create-trigger',
 952 |         trigger_name='test-trigger',
 953 |         trigger_definition={
 954 |             'Type': 'SCHEDULED',
 955 |             'Schedule': 'cron(0 12 * * ? *)',
 956 |             'Actions': [{'JobName': 'test-job'}],
 957 |             'Description': 'Test trigger',
 958 |             'StartOnCreation': True,
 959 |         },
 960 |     )
 961 | 
 962 |     # Verify the result
 963 |     assert not result.isError
 964 |     assert len(result.content) == 1
 965 |     assert result.content[0].type == 'text'
 966 |     assert 'Successfully created trigger test-trigger' in result.content[0].text
 967 |     assert result.trigger_name == 'test-trigger'
 968 | 
 969 |     # Verify that create_trigger was called with the correct parameters
 970 |     mock_glue_client.create_trigger.assert_called_once()
 971 |     args, kwargs = mock_glue_client.create_trigger.call_args
 972 |     assert kwargs['Name'] == 'test-trigger'
 973 |     assert kwargs['Type'] == 'SCHEDULED'
 974 |     assert kwargs['Schedule'] == 'cron(0 12 * * ? *)'
 975 |     assert kwargs['Actions'] == [{'JobName': 'test-job'}]
 976 |     assert kwargs['Description'] == 'Test trigger'
 977 |     assert kwargs['StartOnCreation']
 978 |     assert kwargs['Tags'] == {'ManagedBy': 'MCP'}
 979 | 
 980 | 
 981 | @pytest.mark.asyncio
 982 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
 983 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
 984 | async def test_create_trigger_with_user_tags(mock_prepare_tags, mock_create_client):
 985 |     """Test creating a trigger with user-provided tags."""
 986 |     # Create a mock Glue client
 987 |     mock_glue_client = MagicMock()
 988 |     mock_create_client.return_value = mock_glue_client
 989 | 
 990 |     # Mock the resource tags
 991 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
 992 | 
 993 |     # Create a mock MCP server
 994 |     mock_mcp = MagicMock()
 995 | 
 996 |     # Initialize the Glue Workflow handler with the mock MCP server
 997 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
 998 |     handler.glue_client = mock_glue_client
 999 | 
1000 |     # Create a mock context
1001 |     mock_ctx = MagicMock(spec=Context)
1002 | 
1003 |     # Mock the create_trigger response
1004 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
1005 | 
1006 |     # Call the manage_aws_glue_triggers method with create-trigger operation and user tags
1007 |     result = await handler.manage_aws_glue_triggers(
1008 |         mock_ctx,
1009 |         operation='create-trigger',
1010 |         trigger_name='test-trigger',
1011 |         trigger_definition={
1012 |             'Type': 'SCHEDULED',
1013 |             'Actions': [{'JobName': 'test-job'}],
1014 |             'Tags': {'Environment': 'Test', 'Project': 'UnitTest'},
1015 |         },
1016 |     )
1017 | 
1018 |     # Verify the result
1019 |     assert not result.isError
1020 |     assert result.trigger_name == 'test-trigger'
1021 | 
1022 |     # Verify that create_trigger was called with merged tags
1023 |     mock_glue_client.create_trigger.assert_called_once()
1024 |     args, kwargs = mock_glue_client.create_trigger.call_args
1025 |     assert kwargs['Tags'] == {'Environment': 'Test', 'Project': 'UnitTest', 'ManagedBy': 'MCP'}
1026 | 
1027 | 
1028 | @pytest.mark.asyncio
1029 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1030 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1031 | async def test_create_trigger_with_workflow_name(mock_prepare_tags, mock_create_client):
1032 |     """Test creating a trigger with workflow_name parameter."""
1033 |     # Create a mock Glue client
1034 |     mock_glue_client = MagicMock()
1035 |     mock_create_client.return_value = mock_glue_client
1036 | 
1037 |     # Mock the resource tags
1038 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1039 | 
1040 |     # Create a mock MCP server
1041 |     mock_mcp = MagicMock()
1042 | 
1043 |     # Initialize the Glue Workflow handler with the mock MCP server
1044 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1045 |     handler.glue_client = mock_glue_client
1046 | 
1047 |     # Create a mock context
1048 |     mock_ctx = MagicMock(spec=Context)
1049 | 
1050 |     # Mock the create_trigger response
1051 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
1052 | 
1053 |     # Call the manage_aws_glue_triggers method with create-trigger operation and workflow_name
1054 |     result = await handler.manage_aws_glue_triggers(
1055 |         mock_ctx,
1056 |         operation='create-trigger',
1057 |         trigger_name='test-trigger',
1058 |         trigger_definition={
1059 |             'Type': 'SCHEDULED',
1060 |             'Actions': [{'JobName': 'test-job'}],
1061 |             'WorkflowName': 'test-workflow',
1062 |         },
1063 |     )
1064 | 
1065 |     # Verify the result
1066 |     assert not result.isError
1067 |     assert result.trigger_name == 'test-trigger'
1068 | 
1069 |     # Verify that create_trigger was called with workflow_name
1070 |     mock_glue_client.create_trigger.assert_called_once()
1071 |     args, kwargs = mock_glue_client.create_trigger.call_args
1072 |     assert kwargs['WorkflowName'] == 'test-workflow'
1073 | 
1074 | 
1075 | @pytest.mark.asyncio
1076 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1077 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1078 | async def test_create_trigger_with_predicate(mock_prepare_tags, mock_create_client):
1079 |     """Test creating a trigger with predicate parameter."""
1080 |     # Create a mock Glue client
1081 |     mock_glue_client = MagicMock()
1082 |     mock_create_client.return_value = mock_glue_client
1083 | 
1084 |     # Mock the resource tags
1085 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1086 | 
1087 |     # Create a mock MCP server
1088 |     mock_mcp = MagicMock()
1089 | 
1090 |     # Initialize the Glue Workflow handler with the mock MCP server
1091 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1092 |     handler.glue_client = mock_glue_client
1093 | 
1094 |     # Create a mock context
1095 |     mock_ctx = MagicMock(spec=Context)
1096 | 
1097 |     # Mock the create_trigger response
1098 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
1099 | 
1100 |     # Call the manage_aws_glue_triggers method with create-trigger operation and predicate
1101 |     result = await handler.manage_aws_glue_triggers(
1102 |         mock_ctx,
1103 |         operation='create-trigger',
1104 |         trigger_name='test-trigger',
1105 |         trigger_definition={
1106 |             'Type': 'CONDITIONAL',
1107 |             'Actions': [{'JobName': 'test-job'}],
1108 |             'Predicate': {
1109 |                 'Conditions': [
1110 |                     {
1111 |                         'LogicalOperator': 'EQUALS',
1112 |                         'JobName': 'crawl-job',
1113 |                         'State': 'SUCCEEDED',
1114 |                     }
1115 |                 ]
1116 |             },
1117 |         },
1118 |     )
1119 | 
1120 |     # Verify the result
1121 |     assert not result.isError
1122 |     assert result.trigger_name == 'test-trigger'
1123 | 
1124 |     # Verify that create_trigger was called with predicate
1125 |     mock_glue_client.create_trigger.assert_called_once()
1126 |     args, kwargs = mock_glue_client.create_trigger.call_args
1127 |     assert kwargs['Predicate']['Conditions'][0]['LogicalOperator'] == 'EQUALS'
1128 |     assert kwargs['Predicate']['Conditions'][0]['JobName'] == 'crawl-job'
1129 |     assert kwargs['Predicate']['Conditions'][0]['State'] == 'SUCCEEDED'
1130 | 
1131 | 
1132 | @pytest.mark.asyncio
1133 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1134 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1135 | async def test_create_trigger_with_event_batching_condition(mock_prepare_tags, mock_create_client):
1136 |     """Test creating a trigger with event_batching_condition parameter."""
1137 |     # Create a mock Glue client
1138 |     mock_glue_client = MagicMock()
1139 |     mock_create_client.return_value = mock_glue_client
1140 | 
1141 |     # Mock the resource tags
1142 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1143 | 
1144 |     # Create a mock MCP server
1145 |     mock_mcp = MagicMock()
1146 | 
1147 |     # Initialize the Glue Workflow handler with the mock MCP server
1148 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1149 |     handler.glue_client = mock_glue_client
1150 | 
1151 |     # Create a mock context
1152 |     mock_ctx = MagicMock(spec=Context)
1153 | 
1154 |     # Mock the create_trigger response
1155 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
1156 | 
1157 |     # Call the manage_aws_glue_triggers method with create-trigger operation and event_batching_condition
1158 |     result = await handler.manage_aws_glue_triggers(
1159 |         mock_ctx,
1160 |         operation='create-trigger',
1161 |         trigger_name='test-trigger',
1162 |         trigger_definition={
1163 |             'Type': 'EVENT',
1164 |             'Actions': [{'JobName': 'test-job'}],
1165 |             'EventBatchingCondition': {'BatchSize': 5, 'BatchWindow': 900},
1166 |         },
1167 |     )
1168 | 
1169 |     # Verify the result
1170 |     assert not result.isError
1171 |     assert result.trigger_name == 'test-trigger'
1172 | 
1173 |     # Verify that create_trigger was called with event_batching_condition
1174 |     mock_glue_client.create_trigger.assert_called_once()
1175 |     args, kwargs = mock_glue_client.create_trigger.call_args
1176 |     assert kwargs['EventBatchingCondition']['BatchSize'] == 5
1177 |     assert kwargs['EventBatchingCondition']['BatchWindow'] == 900
1178 | 
1179 | 
1180 | @pytest.mark.asyncio
1181 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1182 | async def test_create_trigger_missing_parameters(mock_create_client):
1183 |     """Test creating a trigger with missing required parameters."""
1184 |     # Create a mock Glue client
1185 |     mock_glue_client = MagicMock()
1186 |     mock_create_client.return_value = mock_glue_client
1187 | 
1188 |     # Create a mock MCP server
1189 |     mock_mcp = MagicMock()
1190 | 
1191 |     # Initialize the Glue Workflow handler with the mock MCP server
1192 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1193 |     handler.glue_client = mock_glue_client
1194 | 
1195 |     # Create a mock context
1196 |     mock_ctx = MagicMock(spec=Context)
1197 | 
1198 |     # Test missing trigger_definition
1199 |     with pytest.raises(ValueError) as excinfo:
1200 |         await handler.manage_aws_glue_triggers(
1201 |             mock_ctx,
1202 |             operation='create-trigger',
1203 |             trigger_name='test-trigger',
1204 |             trigger_definition=None,
1205 |         )
1206 |     assert 'trigger_name and trigger_definition are required' in str(excinfo.value)
1207 | 
1208 |     # Test missing trigger_name
1209 |     with pytest.raises(ValueError) as excinfo:
1210 |         await handler.manage_aws_glue_triggers(
1211 |             mock_ctx,
1212 |             operation='create-trigger',
1213 |             trigger_name=None,
1214 |             trigger_definition={'Type': 'SCHEDULED', 'Actions': [{'JobName': 'test-job'}]},
1215 |         )
1216 |     assert 'trigger_name and trigger_definition are required' in str(excinfo.value)
1217 | 
1218 | 
1219 | @pytest.mark.asyncio
1220 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1221 | async def test_create_trigger_no_write_access(mock_create_client):
1222 |     # Create a mock Glue client
1223 |     mock_glue_client = MagicMock()
1224 |     mock_create_client.return_value = mock_glue_client
1225 | 
1226 |     # Create a mock MCP server
1227 |     mock_mcp = MagicMock()
1228 | 
1229 |     # Initialize the Glue Workflow handler with the mock MCP server without write access
1230 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=False)
1231 |     handler.glue_client = mock_glue_client
1232 | 
1233 |     # Create a mock context
1234 |     mock_ctx = MagicMock(spec=Context)
1235 | 
1236 |     # Call the manage_aws_glue_triggers method with create-trigger operation
1237 |     result = await handler.manage_aws_glue_triggers(
1238 |         mock_ctx,
1239 |         operation='create-trigger',
1240 |         trigger_name='test-trigger',
1241 |         trigger_definition={'Type': 'SCHEDULED', 'Actions': [{'JobName': 'test-job'}]},
1242 |     )
1243 | 
1244 |     # Verify the result indicates an error due to no write access
1245 |     assert result.isError
1246 |     assert len(result.content) == 1
1247 |     assert result.content[0].type == 'text'
1248 |     assert 'Operation create-trigger is not allowed without write access' in result.content[0].text
1249 |     assert result.trigger_name == ''
1250 | 
1251 |     # Verify that create_trigger was NOT called
1252 |     mock_glue_client.create_trigger.assert_not_called()
1253 | 
1254 | 
1255 | @pytest.mark.asyncio
1256 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1257 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1258 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1259 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
1260 | async def test_delete_trigger_success(
1261 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
1262 | ):
1263 |     # Create a mock Glue client
1264 |     mock_glue_client = MagicMock()
1265 |     mock_create_client.return_value = mock_glue_client
1266 | 
1267 |     # Mock the region and account ID
1268 |     mock_get_region.return_value = 'us-east-1'
1269 |     mock_get_account_id.return_value = '123456789012'
1270 | 
1271 |     # Mock the is_resource_mcp_managed to return True
1272 |     mock_is_mcp_managed.return_value = True
1273 | 
1274 |     # Create a mock MCP server
1275 |     mock_mcp = MagicMock()
1276 | 
1277 |     # Initialize the Glue Workflow handler with the mock MCP server
1278 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1279 |     handler.glue_client = mock_glue_client
1280 | 
1281 |     # Create a mock context
1282 |     mock_ctx = MagicMock(spec=Context)
1283 | 
1284 |     # Mock the get_trigger response
1285 |     mock_glue_client.get_trigger.return_value = {
1286 |         'Trigger': {'Name': 'test-trigger', 'Tags': {'ManagedBy': 'MCP'}}
1287 |     }
1288 | 
1289 |     # Call the manage_aws_glue_triggers method with delete-trigger operation
1290 |     result = await handler.manage_aws_glue_triggers(
1291 |         mock_ctx, operation='delete-trigger', trigger_name='test-trigger'
1292 |     )
1293 | 
1294 |     # Verify the result
1295 |     assert not result.isError
1296 |     assert len(result.content) == 1
1297 |     assert result.content[0].type == 'text'
1298 |     assert 'Successfully deleted trigger test-trigger' in result.content[0].text
1299 |     assert result.trigger_name == 'test-trigger'
1300 | 
1301 |     # Verify that delete_trigger was called with the correct parameters
1302 |     mock_glue_client.delete_trigger.assert_called_once_with(Name='test-trigger')
1303 | 
1304 | 
1305 | @pytest.mark.asyncio
1306 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1307 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1308 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1309 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
1310 | async def test_delete_trigger_not_mcp_managed(
1311 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
1312 | ):
1313 |     # Create a mock Glue client
1314 |     mock_glue_client = MagicMock()
1315 |     mock_create_client.return_value = mock_glue_client
1316 | 
1317 |     # Mock the region and account ID
1318 |     mock_get_region.return_value = 'us-east-1'
1319 |     mock_get_account_id.return_value = '123456789012'
1320 | 
1321 |     # Mock the is_resource_mcp_managed to return False
1322 |     mock_is_mcp_managed.return_value = False
1323 | 
1324 |     # Create a mock MCP server
1325 |     mock_mcp = MagicMock()
1326 | 
1327 |     # Initialize the Glue Workflow handler with the mock MCP server
1328 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1329 |     handler.glue_client = mock_glue_client
1330 | 
1331 |     # Create a mock context
1332 |     mock_ctx = MagicMock(spec=Context)
1333 | 
1334 |     # Mock the get_trigger response
1335 |     mock_glue_client.get_trigger.return_value = {
1336 |         'Trigger': {
1337 |             'Name': 'test-trigger',
1338 |             'Tags': {},  # No MCP tags
1339 |         }
1340 |     }
1341 | 
1342 |     # Call the manage_aws_glue_triggers method with delete-trigger operation
1343 |     result = await handler.manage_aws_glue_triggers(
1344 |         mock_ctx, operation='delete-trigger', trigger_name='test-trigger'
1345 |     )
1346 | 
1347 |     # Verify the result indicates an error because the trigger is not MCP managed
1348 |     assert result.isError
1349 |     assert len(result.content) == 1
1350 |     assert result.content[0].type == 'text'
1351 |     assert (
1352 |         'Cannot delete trigger test-trigger - it is not managed by the MCP server'
1353 |         in result.content[0].text
1354 |     )
1355 |     assert result.trigger_name == 'test-trigger'
1356 | 
1357 |     # Verify that delete_trigger was NOT called
1358 |     mock_glue_client.delete_trigger.assert_not_called()
1359 | 
1360 | 
1361 | @pytest.mark.asyncio
1362 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1363 | async def test_get_trigger_success(mock_create_client):
1364 |     # Create a mock Glue client
1365 |     mock_glue_client = MagicMock()
1366 |     mock_create_client.return_value = mock_glue_client
1367 | 
1368 |     # Create a mock MCP server
1369 |     mock_mcp = MagicMock()
1370 | 
1371 |     # Initialize the Glue Workflow handler with the mock MCP server
1372 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
1373 |     handler.glue_client = mock_glue_client
1374 | 
1375 |     # Create a mock context
1376 |     mock_ctx = MagicMock(spec=Context)
1377 | 
1378 |     # Mock the get_trigger response
1379 |     mock_trigger_details = {
1380 |         'Name': 'test-trigger',
1381 |         'Type': 'SCHEDULED',
1382 |         'Schedule': 'cron(0 12 * * ? *)',
1383 |         'Actions': [{'JobName': 'test-job'}],
1384 |         'Description': 'Test trigger',
1385 |     }
1386 |     mock_glue_client.get_trigger.return_value = {'Trigger': mock_trigger_details}
1387 | 
1388 |     # Call the manage_aws_glue_triggers method with get-trigger operation
1389 |     result = await handler.manage_aws_glue_triggers(
1390 |         mock_ctx, operation='get-trigger', trigger_name='test-trigger'
1391 |     )
1392 | 
1393 |     # Verify the result
1394 |     assert not result.isError
1395 |     assert len(result.content) == 1
1396 |     assert result.content[0].type == 'text'
1397 |     assert 'Successfully retrieved trigger test-trigger' in result.content[0].text
1398 |     assert result.trigger_name == 'test-trigger'
1399 |     assert result.trigger_details == mock_trigger_details
1400 | 
1401 |     # Verify that get_trigger was called with the correct parameters
1402 |     mock_glue_client.get_trigger.assert_called_once_with(Name='test-trigger')
1403 | 
1404 | 
1405 | @pytest.mark.asyncio
1406 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1407 | async def test_get_triggers_success(mock_create_client):
1408 |     # Create a mock Glue client
1409 |     mock_glue_client = MagicMock()
1410 |     mock_create_client.return_value = mock_glue_client
1411 | 
1412 |     # Create a mock MCP server
1413 |     mock_mcp = MagicMock()
1414 | 
1415 |     # Initialize the Glue Workflow handler with the mock MCP server
1416 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
1417 |     handler.glue_client = mock_glue_client
1418 | 
1419 |     # Create a mock context
1420 |     mock_ctx = MagicMock(spec=Context)
1421 | 
1422 |     # Mock the get_triggers response
1423 |     mock_glue_client.get_triggers.return_value = {
1424 |         'Triggers': [
1425 |             {'Name': 'trigger1', 'Type': 'SCHEDULED'},
1426 |             {'Name': 'trigger2', 'Type': 'CONDITIONAL'},
1427 |         ],
1428 |         'NextToken': 'next-token',
1429 |     }
1430 | 
1431 |     # Call the manage_aws_glue_triggers method with get-triggers operation
1432 |     result = await handler.manage_aws_glue_triggers(
1433 |         mock_ctx, operation='get-triggers', max_results=10, next_token='token'
1434 |     )
1435 | 
1436 |     # Verify the result
1437 |     assert not result.isError
1438 |     assert len(result.content) == 1
1439 |     assert result.content[0].type == 'text'
1440 |     assert 'Successfully retrieved triggers' in result.content[0].text
1441 |     assert len(result.triggers) == 2
1442 |     assert result.triggers[0]['Name'] == 'trigger1'
1443 |     assert result.triggers[1]['Name'] == 'trigger2'
1444 |     assert result.next_token == 'next-token'
1445 | 
1446 |     # Verify that get_triggers was called with the correct parameters
1447 |     mock_glue_client.get_triggers.assert_called_once_with(MaxResults=10, NextToken='token')
1448 | 
1449 | 
1450 | @pytest.mark.asyncio
1451 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1452 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1453 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1454 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
1455 | async def test_start_trigger_success(
1456 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
1457 | ):
1458 |     # Create a mock Glue client
1459 |     mock_glue_client = MagicMock()
1460 |     mock_create_client.return_value = mock_glue_client
1461 | 
1462 |     # Mock the region and account ID
1463 |     mock_get_region.return_value = 'us-east-1'
1464 |     mock_get_account_id.return_value = '123456789012'
1465 | 
1466 |     # Mock the is_resource_mcp_managed to return True
1467 |     mock_is_mcp_managed.return_value = True
1468 | 
1469 |     # Create a mock MCP server
1470 |     mock_mcp = MagicMock()
1471 | 
1472 |     # Initialize the Glue Workflow handler with the mock MCP server
1473 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1474 |     handler.glue_client = mock_glue_client
1475 | 
1476 |     # Create a mock context
1477 |     mock_ctx = MagicMock(spec=Context)
1478 | 
1479 |     # Mock the get_trigger response
1480 |     mock_glue_client.get_trigger.return_value = {
1481 |         'Trigger': {'Name': 'test-trigger', 'Tags': {'ManagedBy': 'MCP'}}
1482 |     }
1483 | 
1484 |     # Call the manage_aws_glue_triggers method with start-trigger operation
1485 |     result = await handler.manage_aws_glue_triggers(
1486 |         mock_ctx, operation='start-trigger', trigger_name='test-trigger'
1487 |     )
1488 | 
1489 |     # Verify the result
1490 |     assert not result.isError
1491 |     assert len(result.content) == 1
1492 |     assert result.content[0].type == 'text'
1493 |     assert 'Successfully started trigger test-trigger' in result.content[0].text
1494 |     assert result.trigger_name == 'test-trigger'
1495 | 
1496 |     # Verify that start_trigger was called with the correct parameters
1497 |     mock_glue_client.start_trigger.assert_called_once_with(Name='test-trigger')
1498 | 
1499 | 
1500 | @pytest.mark.asyncio
1501 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1502 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1503 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1504 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
1505 | async def test_stop_trigger_success(
1506 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
1507 | ):
1508 |     # Create a mock Glue client
1509 |     mock_glue_client = MagicMock()
1510 |     mock_create_client.return_value = mock_glue_client
1511 | 
1512 |     # Mock the region and account ID
1513 |     mock_get_region.return_value = 'us-east-1'
1514 |     mock_get_account_id.return_value = '123456789012'
1515 | 
1516 |     # Mock the is_resource_mcp_managed to return True
1517 |     mock_is_mcp_managed.return_value = True
1518 | 
1519 |     # Create a mock MCP server
1520 |     mock_mcp = MagicMock()
1521 | 
1522 |     # Initialize the Glue Workflow handler with the mock MCP server
1523 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1524 |     handler.glue_client = mock_glue_client
1525 | 
1526 |     # Create a mock context
1527 |     mock_ctx = MagicMock(spec=Context)
1528 | 
1529 |     # Mock the get_trigger response
1530 |     mock_glue_client.get_trigger.return_value = {
1531 |         'Trigger': {'Name': 'test-trigger', 'Tags': {'ManagedBy': 'MCP'}}
1532 |     }
1533 | 
1534 |     # Call the manage_aws_glue_triggers method with stop-trigger operation
1535 |     result = await handler.manage_aws_glue_triggers(
1536 |         mock_ctx, operation='stop-trigger', trigger_name='test-trigger'
1537 |     )
1538 | 
1539 |     # Verify the result
1540 |     assert not result.isError
1541 |     assert len(result.content) == 1
1542 |     assert result.content[0].type == 'text'
1543 |     assert 'Successfully stopped trigger test-trigger' in result.content[0].text
1544 |     assert result.trigger_name == 'test-trigger'
1545 | 
1546 |     # Verify that stop_trigger was called with the correct parameters
1547 |     mock_glue_client.stop_trigger.assert_called_once_with(Name='test-trigger')
1548 | 
1549 | 
1550 | @pytest.mark.asyncio
1551 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1552 | async def test_trigger_invalid_operation(mock_create_client):
1553 |     # Create a mock Glue client
1554 |     mock_glue_client = MagicMock()
1555 |     mock_create_client.return_value = mock_glue_client
1556 | 
1557 |     # Create a mock MCP server
1558 |     mock_mcp = MagicMock()
1559 | 
1560 |     # Initialize the Glue Workflow handler with the mock MCP server with write access
1561 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1562 |     handler.glue_client = mock_glue_client
1563 | 
1564 |     # Create a mock context
1565 |     mock_ctx = MagicMock(spec=Context)
1566 | 
1567 |     # Call the manage_aws_glue_triggers method with an invalid operation
1568 |     result = await handler.manage_aws_glue_triggers(
1569 |         mock_ctx, operation='invalid-operation', trigger_name='test-trigger'
1570 |     )
1571 | 
1572 |     # Verify the result indicates an error due to invalid operation
1573 |     assert result.isError
1574 |     assert len(result.content) == 1
1575 |     assert result.content[0].type == 'text'
1576 |     assert 'Invalid operation: invalid-operation' in result.content[0].text
1577 |     assert result.trigger_name == 'test-trigger'
1578 | 
1579 | 
1580 | @pytest.mark.asyncio
1581 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1582 | async def test_trigger_not_found(mock_create_client):
1583 |     # Create a mock Glue client
1584 |     mock_glue_client = MagicMock()
1585 |     mock_create_client.return_value = mock_glue_client
1586 | 
1587 |     # Create a mock MCP server
1588 |     mock_mcp = MagicMock()
1589 | 
1590 |     # Initialize the Glue Workflow handler with the mock MCP server
1591 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1592 |     handler.glue_client = mock_glue_client
1593 | 
1594 |     # Create a mock context
1595 |     mock_ctx = MagicMock(spec=Context)
1596 | 
1597 |     # Mock the get_trigger to raise EntityNotFoundException
1598 |     mock_glue_client.exceptions.EntityNotFoundException = ClientError(
1599 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Trigger not found'}},
1600 |         'get_trigger',
1601 |     )
1602 |     mock_glue_client.get_trigger.side_effect = mock_glue_client.exceptions.EntityNotFoundException
1603 | 
1604 |     # Call the manage_aws_glue_triggers method with delete-trigger operation
1605 |     result = await handler.manage_aws_glue_triggers(
1606 |         mock_ctx, operation='delete-trigger', trigger_name='test-trigger'
1607 |     )
1608 | 
1609 |     # Verify the result indicates an error because the trigger was not found
1610 |     assert result.isError
1611 |     assert len(result.content) == 1
1612 |     assert result.content[0].type == 'text'
1613 |     assert 'Trigger test-trigger not found' in result.content[0].text
1614 |     assert result.trigger_name == 'test-trigger'
1615 | 
1616 |     # Verify that delete_trigger was NOT called
1617 |     mock_glue_client.delete_trigger.assert_not_called()
1618 | 
1619 | 
1620 | @pytest.mark.asyncio
1621 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1622 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1623 | async def test_create_workflow_without_description(mock_prepare_tags, mock_create_client):
1624 |     """Test creating workflow without description parameter."""
1625 |     mock_glue_client = MagicMock()
1626 |     mock_create_client.return_value = mock_glue_client
1627 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1628 |     mock_mcp = MagicMock()
1629 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1630 |     handler.glue_client = mock_glue_client
1631 |     mock_ctx = MagicMock(spec=Context)
1632 | 
1633 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
1634 | 
1635 |     result = await handler.manage_aws_glue_workflows(
1636 |         mock_ctx,
1637 |         operation='create-workflow',
1638 |         workflow_name='test-workflow',
1639 |         workflow_definition={},
1640 |     )
1641 | 
1642 |     assert not result.isError
1643 |     args, kwargs = mock_glue_client.create_workflow.call_args
1644 |     assert 'Description' not in kwargs
1645 | 
1646 | 
1647 | @pytest.mark.asyncio
1648 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1649 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1650 | async def test_create_workflow_without_default_run_properties(
1651 |     mock_prepare_tags, mock_create_client
1652 | ):
1653 |     """Test creating workflow without DefaultRunProperties parameter."""
1654 |     mock_glue_client = MagicMock()
1655 |     mock_create_client.return_value = mock_glue_client
1656 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1657 |     mock_mcp = MagicMock()
1658 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1659 |     handler.glue_client = mock_glue_client
1660 |     mock_ctx = MagicMock(spec=Context)
1661 | 
1662 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
1663 | 
1664 |     result = await handler.manage_aws_glue_workflows(
1665 |         mock_ctx,
1666 |         operation='create-workflow',
1667 |         workflow_name='test-workflow',
1668 |         workflow_definition={'Description': 'Test'},
1669 |     )
1670 | 
1671 |     assert not result.isError
1672 |     args, kwargs = mock_glue_client.create_workflow.call_args
1673 |     assert 'DefaultRunProperties' not in kwargs
1674 | 
1675 | 
1676 | @pytest.mark.asyncio
1677 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1678 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1679 | async def test_create_workflow_without_max_concurrent_runs(mock_prepare_tags, mock_create_client):
1680 |     """Test creating workflow without MaxConcurrentRuns parameter."""
1681 |     mock_glue_client = MagicMock()
1682 |     mock_create_client.return_value = mock_glue_client
1683 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1684 |     mock_mcp = MagicMock()
1685 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1686 |     handler.glue_client = mock_glue_client
1687 |     mock_ctx = MagicMock(spec=Context)
1688 | 
1689 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
1690 | 
1691 |     result = await handler.manage_aws_glue_workflows(
1692 |         mock_ctx,
1693 |         operation='create-workflow',
1694 |         workflow_name='test-workflow',
1695 |         workflow_definition={'Description': 'Test'},
1696 |     )
1697 | 
1698 |     assert not result.isError
1699 |     args, kwargs = mock_glue_client.create_workflow.call_args
1700 |     assert 'MaxConcurrentRuns' not in kwargs
1701 | 
1702 | 
1703 | @pytest.mark.asyncio
1704 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1705 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1706 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1707 | async def test_delete_workflow_client_error(
1708 |     mock_get_account_id, mock_get_region, mock_create_client
1709 | ):
1710 |     """Test delete workflow with non-EntityNotFoundException ClientError."""
1711 |     mock_glue_client = MagicMock()
1712 |     mock_create_client.return_value = mock_glue_client
1713 |     mock_get_region.return_value = 'us-east-1'
1714 |     mock_get_account_id.return_value = '123456789012'
1715 |     mock_mcp = MagicMock()
1716 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1717 |     handler.glue_client = mock_glue_client
1718 |     mock_ctx = MagicMock(spec=Context)
1719 | 
1720 |     mock_glue_client.get_workflow.side_effect = ClientError(
1721 |         {'Error': {'Code': 'AccessDeniedException', 'Message': 'Access denied'}}, 'get_workflow'
1722 |     )
1723 | 
1724 |     result = await handler.manage_aws_glue_workflows(
1725 |         mock_ctx, operation='delete-workflow', workflow_name='test-workflow'
1726 |     )
1727 | 
1728 |     assert result.isError
1729 |     assert 'Error in manage_aws_glue_workflows' in result.content[0].text
1730 | 
1731 | 
1732 | @pytest.mark.asyncio
1733 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1734 | async def test_get_workflow_without_include_graph(mock_create_client):
1735 |     """Test get workflow without include_graph parameter."""
1736 |     mock_glue_client = MagicMock()
1737 |     mock_create_client.return_value = mock_glue_client
1738 |     mock_mcp = MagicMock()
1739 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
1740 |     handler.glue_client = mock_glue_client
1741 |     mock_ctx = MagicMock(spec=Context)
1742 | 
1743 |     mock_glue_client.get_workflow.return_value = {'Workflow': {'Name': 'test-workflow'}}
1744 | 
1745 |     result = await handler.manage_aws_glue_workflows(
1746 |         mock_ctx,
1747 |         operation='get-workflow',
1748 |         workflow_name='test-workflow',
1749 |         workflow_definition={},
1750 |     )
1751 | 
1752 |     assert not result.isError
1753 |     args, kwargs = mock_glue_client.get_workflow.call_args
1754 |     assert 'IncludeGraph' not in kwargs
1755 | 
1756 | 
1757 | @pytest.mark.asyncio
1758 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1759 | async def test_list_workflows_without_pagination(mock_create_client):
1760 |     """Test list workflows without pagination parameters."""
1761 |     mock_glue_client = MagicMock()
1762 |     mock_create_client.return_value = mock_glue_client
1763 |     mock_mcp = MagicMock()
1764 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
1765 |     handler.glue_client = mock_glue_client
1766 |     mock_ctx = MagicMock(spec=Context)
1767 | 
1768 |     mock_glue_client.list_workflows.return_value = {'Workflows': ['workflow1']}
1769 | 
1770 |     result = await handler.manage_aws_glue_workflows(mock_ctx, operation='list-workflows')
1771 | 
1772 |     assert not result.isError
1773 | 
1774 | 
1775 | @pytest.mark.asyncio
1776 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1777 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1778 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1779 | async def test_start_workflow_run_client_error(
1780 |     mock_get_account_id, mock_get_region, mock_create_client
1781 | ):
1782 |     """Test start workflow run with non-EntityNotFoundException ClientError."""
1783 |     mock_glue_client = MagicMock()
1784 |     mock_create_client.return_value = mock_glue_client
1785 |     mock_get_region.return_value = 'us-east-1'
1786 |     mock_get_account_id.return_value = '123456789012'
1787 |     mock_mcp = MagicMock()
1788 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1789 |     handler.glue_client = mock_glue_client
1790 |     mock_ctx = MagicMock(spec=Context)
1791 | 
1792 |     mock_glue_client.get_workflow.side_effect = ClientError(
1793 |         {'Error': {'Code': 'AccessDeniedException', 'Message': 'Access denied'}}, 'get_workflow'
1794 |     )
1795 | 
1796 |     result = await handler.manage_aws_glue_workflows(
1797 |         mock_ctx, operation='start-workflow-run', workflow_name='test-workflow'
1798 |     )
1799 | 
1800 |     assert result.isError
1801 |     assert 'Error in manage_aws_glue_workflows' in result.content[0].text
1802 | 
1803 | 
1804 | @pytest.mark.asyncio
1805 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1806 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1807 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1808 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
1809 | async def test_start_workflow_run_without_run_properties_mcp_managed(
1810 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
1811 | ):
1812 |     """Test start workflow run without run_properties when workflow is MCP managed."""
1813 |     mock_glue_client = MagicMock()
1814 |     mock_create_client.return_value = mock_glue_client
1815 |     mock_get_region.return_value = 'us-east-1'
1816 |     mock_get_account_id.return_value = '123456789012'
1817 |     mock_is_mcp_managed.return_value = True
1818 |     mock_mcp = MagicMock()
1819 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1820 |     handler.glue_client = mock_glue_client
1821 |     mock_ctx = MagicMock(spec=Context)
1822 | 
1823 |     mock_glue_client.get_workflow.return_value = {
1824 |         'Workflow': {'Name': 'test-workflow', 'Tags': {'ManagedBy': 'MCP'}}
1825 |     }
1826 |     mock_glue_client.start_workflow_run.return_value = {'RunId': 'run-123'}
1827 | 
1828 |     result = await handler.manage_aws_glue_workflows(
1829 |         mock_ctx,
1830 |         operation='start-workflow-run',
1831 |         workflow_name='test-workflow',
1832 |         workflow_definition={},
1833 |     )
1834 | 
1835 |     assert not result.isError
1836 |     args, kwargs = mock_glue_client.start_workflow_run.call_args
1837 |     assert 'RunProperties' not in kwargs
1838 | 
1839 | 
1840 | @pytest.mark.asyncio
1841 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1842 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1843 | async def test_create_trigger_individual_params(mock_prepare_tags, mock_create_client):
1844 |     """Test create trigger with individual optional parameters."""
1845 |     mock_glue_client = MagicMock()
1846 |     mock_create_client.return_value = mock_glue_client
1847 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1848 |     mock_mcp = MagicMock()
1849 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1850 |     handler.glue_client = mock_glue_client
1851 |     mock_ctx = MagicMock(spec=Context)
1852 | 
1853 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
1854 | 
1855 |     # Test with WorkflowName
1856 |     await handler.manage_aws_glue_triggers(
1857 |         mock_ctx,
1858 |         operation='create-trigger',
1859 |         trigger_name='test-trigger',
1860 |         trigger_definition={
1861 |             'Type': 'SCHEDULED',
1862 |             'Actions': [{'JobName': 'test-job'}],
1863 |             'WorkflowName': 'test-workflow',
1864 |         },
1865 |     )
1866 | 
1867 |     # Test with Schedule
1868 |     await handler.manage_aws_glue_triggers(
1869 |         mock_ctx,
1870 |         operation='create-trigger',
1871 |         trigger_name='test-trigger',
1872 |         trigger_definition={
1873 |             'Type': 'SCHEDULED',
1874 |             'Actions': [{'JobName': 'test-job'}],
1875 |             'Schedule': 'cron(0 12 * * ? *)',
1876 |         },
1877 |     )
1878 | 
1879 |     # Test with Predicate
1880 |     await handler.manage_aws_glue_triggers(
1881 |         mock_ctx,
1882 |         operation='create-trigger',
1883 |         trigger_name='test-trigger',
1884 |         trigger_definition={
1885 |             'Type': 'CONDITIONAL',
1886 |             'Actions': [{'JobName': 'test-job'}],
1887 |             'Predicate': {'Conditions': []},
1888 |         },
1889 |     )
1890 | 
1891 |     # Test with Description
1892 |     await handler.manage_aws_glue_triggers(
1893 |         mock_ctx,
1894 |         operation='create-trigger',
1895 |         trigger_name='test-trigger',
1896 |         trigger_definition={
1897 |             'Type': 'SCHEDULED',
1898 |             'Actions': [{'JobName': 'test-job'}],
1899 |             'Description': 'Test trigger',
1900 |         },
1901 |     )
1902 | 
1903 |     # Test with StartOnCreation
1904 |     await handler.manage_aws_glue_triggers(
1905 |         mock_ctx,
1906 |         operation='create-trigger',
1907 |         trigger_name='test-trigger',
1908 |         trigger_definition={
1909 |             'Type': 'SCHEDULED',
1910 |             'Actions': [{'JobName': 'test-job'}],
1911 |             'StartOnCreation': True,
1912 |         },
1913 |     )
1914 | 
1915 |     # Test with EventBatchingCondition
1916 |     await handler.manage_aws_glue_triggers(
1917 |         mock_ctx,
1918 |         operation='create-trigger',
1919 |         trigger_name='test-trigger',
1920 |         trigger_definition={
1921 |             'Type': 'EVENT',
1922 |             'Actions': [{'JobName': 'test-job'}],
1923 |             'EventBatchingCondition': {'BatchSize': 5},
1924 |         },
1925 |     )
1926 | 
1927 |     assert mock_glue_client.create_trigger.call_count == 6
1928 | 
1929 | 
1930 | @pytest.mark.asyncio
1931 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1932 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
1933 | async def test_create_trigger_without_user_tags(mock_prepare_tags, mock_create_client):
1934 |     """Test create trigger without user-provided tags."""
1935 |     mock_glue_client = MagicMock()
1936 |     mock_create_client.return_value = mock_glue_client
1937 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
1938 |     mock_mcp = MagicMock()
1939 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1940 |     handler.glue_client = mock_glue_client
1941 |     mock_ctx = MagicMock(spec=Context)
1942 | 
1943 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
1944 | 
1945 |     result = await handler.manage_aws_glue_triggers(
1946 |         mock_ctx,
1947 |         operation='create-trigger',
1948 |         trigger_name='test-trigger',
1949 |         trigger_definition={
1950 |             'Type': 'SCHEDULED',
1951 |             'Actions': [{'JobName': 'test-job'}],
1952 |         },
1953 |     )
1954 | 
1955 |     assert not result.isError
1956 |     args, kwargs = mock_glue_client.create_trigger.call_args
1957 |     assert kwargs['Tags'] == {'ManagedBy': 'MCP'}
1958 | 
1959 | 
1960 | @pytest.mark.asyncio
1961 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1962 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
1963 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
1964 | async def test_delete_trigger_client_error(
1965 |     mock_get_account_id, mock_get_region, mock_create_client
1966 | ):
1967 |     """Test delete trigger with non-EntityNotFoundException ClientError."""
1968 |     mock_glue_client = MagicMock()
1969 |     mock_create_client.return_value = mock_glue_client
1970 |     mock_get_region.return_value = 'us-east-1'
1971 |     mock_get_account_id.return_value = '123456789012'
1972 |     mock_mcp = MagicMock()
1973 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
1974 |     handler.glue_client = mock_glue_client
1975 |     mock_ctx = MagicMock(spec=Context)
1976 | 
1977 |     mock_glue_client.get_trigger.side_effect = ClientError(
1978 |         {'Error': {'Code': 'AccessDeniedException', 'Message': 'Access denied'}}, 'get_trigger'
1979 |     )
1980 | 
1981 |     result = await handler.manage_aws_glue_triggers(
1982 |         mock_ctx, operation='delete-trigger', trigger_name='test-trigger'
1983 |     )
1984 | 
1985 |     assert result.isError
1986 |     assert 'Error in manage_aws_glue_triggers' in result.content[0].text
1987 | 
1988 | 
1989 | @pytest.mark.asyncio
1990 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
1991 | async def test_get_triggers_without_pagination(mock_create_client):
1992 |     """Test get triggers without pagination parameters."""
1993 |     mock_glue_client = MagicMock()
1994 |     mock_create_client.return_value = mock_glue_client
1995 |     mock_mcp = MagicMock()
1996 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
1997 |     handler.glue_client = mock_glue_client
1998 |     mock_ctx = MagicMock(spec=Context)
1999 | 
2000 |     mock_glue_client.get_triggers.return_value = {'Triggers': []}
2001 | 
2002 |     result = await handler.manage_aws_glue_triggers(mock_ctx, operation='get-triggers')
2003 | 
2004 |     assert not result.isError
2005 | 
2006 | 
2007 | @pytest.mark.asyncio
2008 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2009 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2010 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2011 | async def test_start_trigger_client_error(
2012 |     mock_get_account_id, mock_get_region, mock_create_client
2013 | ):
2014 |     """Test start trigger with non-EntityNotFoundException ClientError."""
2015 |     mock_glue_client = MagicMock()
2016 |     mock_create_client.return_value = mock_glue_client
2017 |     mock_get_region.return_value = 'us-east-1'
2018 |     mock_get_account_id.return_value = '123456789012'
2019 |     mock_mcp = MagicMock()
2020 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2021 |     handler.glue_client = mock_glue_client
2022 |     mock_ctx = MagicMock(spec=Context)
2023 | 
2024 |     mock_glue_client.get_trigger.side_effect = ClientError(
2025 |         {'Error': {'Code': 'AccessDeniedException', 'Message': 'Access denied'}}, 'get_trigger'
2026 |     )
2027 | 
2028 |     result = await handler.manage_aws_glue_triggers(
2029 |         mock_ctx, operation='start-trigger', trigger_name='test-trigger'
2030 |     )
2031 | 
2032 |     assert result.isError
2033 |     assert 'Error in manage_aws_glue_triggers' in result.content[0].text
2034 | 
2035 | 
2036 | @pytest.mark.asyncio
2037 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2038 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2039 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2040 | async def test_stop_trigger_client_error(mock_get_account_id, mock_get_region, mock_create_client):
2041 |     """Test stop trigger with non-EntityNotFoundException ClientError."""
2042 |     mock_glue_client = MagicMock()
2043 |     mock_create_client.return_value = mock_glue_client
2044 |     mock_get_region.return_value = 'us-east-1'
2045 |     mock_get_account_id.return_value = '123456789012'
2046 |     mock_mcp = MagicMock()
2047 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2048 |     handler.glue_client = mock_glue_client
2049 |     mock_ctx = MagicMock(spec=Context)
2050 | 
2051 |     mock_glue_client.get_trigger.side_effect = ClientError(
2052 |         {'Error': {'Code': 'AccessDeniedException', 'Message': 'Access denied'}}, 'get_trigger'
2053 |     )
2054 | 
2055 |     result = await handler.manage_aws_glue_triggers(
2056 |         mock_ctx, operation='stop-trigger', trigger_name='test-trigger'
2057 |     )
2058 | 
2059 |     assert result.isError
2060 |     assert 'Error in manage_aws_glue_triggers' in result.content[0].text
2061 | 
2062 | 
2063 | @pytest.mark.asyncio
2064 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2065 | async def test_triggers_no_write_access_fallback(mock_create_client):
2066 |     """Test triggers no write access fallback response."""
2067 |     mock_glue_client = MagicMock()
2068 |     mock_create_client.return_value = mock_glue_client
2069 |     mock_mcp = MagicMock()
2070 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=False)
2071 |     handler.glue_client = mock_glue_client
2072 |     mock_ctx = MagicMock(spec=Context)
2073 | 
2074 |     result = await handler.manage_aws_glue_triggers(
2075 |         mock_ctx, operation='unknown-operation', trigger_name='test-trigger'
2076 |     )
2077 | 
2078 |     assert result.isError
2079 |     assert (
2080 |         'Operation unknown-operation is not allowed without write access' in result.content[0].text
2081 |     )
2082 | 
2083 | 
2084 | @pytest.mark.asyncio
2085 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2086 | async def test_triggers_general_exception(mock_create_client):
2087 |     """Test general exception handling in triggers."""
2088 |     mock_glue_client = MagicMock()
2089 |     mock_glue_client.get_trigger.side_effect = Exception('Test exception')
2090 |     mock_create_client.return_value = mock_glue_client
2091 |     mock_mcp = MagicMock()
2092 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2093 |     handler.glue_client = mock_glue_client
2094 |     mock_ctx = MagicMock(spec=Context)
2095 | 
2096 |     result = await handler.manage_aws_glue_triggers(
2097 |         mock_ctx, operation='get-trigger', trigger_name='test-trigger'
2098 |     )
2099 | 
2100 |     assert result.isError
2101 |     assert 'Error in manage_aws_glue_triggers: Test exception' in result.content[0].text
2102 | 
2103 | 
2104 | @pytest.mark.asyncio
2105 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2106 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
2107 | async def test_create_workflow_with_description_only(mock_prepare_tags, mock_create_client):
2108 |     """Test creating workflow with description parameter only."""
2109 |     mock_glue_client = MagicMock()
2110 |     mock_create_client.return_value = mock_glue_client
2111 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
2112 |     mock_mcp = MagicMock()
2113 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2114 |     handler.glue_client = mock_glue_client
2115 |     mock_ctx = MagicMock(spec=Context)
2116 | 
2117 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
2118 | 
2119 |     result = await handler.manage_aws_glue_workflows(
2120 |         mock_ctx,
2121 |         operation='create-workflow',
2122 |         workflow_name='test-workflow',
2123 |         workflow_definition={'Description': 'Test workflow'},
2124 |     )
2125 | 
2126 |     assert not result.isError
2127 |     args, kwargs = mock_glue_client.create_workflow.call_args
2128 |     assert kwargs['Description'] == 'Test workflow'
2129 |     assert 'DefaultRunProperties' not in kwargs
2130 | 
2131 | 
2132 | @pytest.mark.asyncio
2133 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2134 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
2135 | async def test_create_workflow_with_default_run_properties_only(
2136 |     mock_prepare_tags, mock_create_client
2137 | ):
2138 |     """Test creating workflow with DefaultRunProperties parameter only."""
2139 |     mock_glue_client = MagicMock()
2140 |     mock_create_client.return_value = mock_glue_client
2141 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
2142 |     mock_mcp = MagicMock()
2143 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2144 |     handler.glue_client = mock_glue_client
2145 |     mock_ctx = MagicMock(spec=Context)
2146 | 
2147 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
2148 | 
2149 |     result = await handler.manage_aws_glue_workflows(
2150 |         mock_ctx,
2151 |         operation='create-workflow',
2152 |         workflow_name='test-workflow',
2153 |         workflow_definition={'DefaultRunProperties': {'ENV': 'test'}},
2154 |     )
2155 | 
2156 |     assert not result.isError
2157 |     args, kwargs = mock_glue_client.create_workflow.call_args
2158 |     assert kwargs['DefaultRunProperties'] == {'ENV': 'test'}
2159 |     assert 'Description' not in kwargs
2160 | 
2161 | 
2162 | @pytest.mark.asyncio
2163 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2164 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
2165 | async def test_create_workflow_with_max_concurrent_runs_only(
2166 |     mock_prepare_tags, mock_create_client
2167 | ):
2168 |     """Test creating workflow with MaxConcurrentRuns parameter only."""
2169 |     mock_glue_client = MagicMock()
2170 |     mock_create_client.return_value = mock_glue_client
2171 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
2172 |     mock_mcp = MagicMock()
2173 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2174 |     handler.glue_client = mock_glue_client
2175 |     mock_ctx = MagicMock(spec=Context)
2176 | 
2177 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
2178 | 
2179 |     result = await handler.manage_aws_glue_workflows(
2180 |         mock_ctx,
2181 |         operation='create-workflow',
2182 |         workflow_name='test-workflow',
2183 |         workflow_definition={'MaxConcurrentRuns': 2},
2184 |     )
2185 | 
2186 |     assert not result.isError
2187 |     args, kwargs = mock_glue_client.create_workflow.call_args
2188 |     assert kwargs['MaxConcurrentRuns'] == 2
2189 | 
2190 | 
2191 | @pytest.mark.asyncio
2192 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2193 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2194 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2195 | async def test_delete_workflow_entity_not_found(
2196 |     mock_get_account_id, mock_get_region, mock_create_client
2197 | ):
2198 |     """Test delete workflow when workflow is not found."""
2199 |     mock_glue_client = MagicMock()
2200 |     mock_create_client.return_value = mock_glue_client
2201 |     mock_get_region.return_value = 'us-east-1'
2202 |     mock_get_account_id.return_value = '123456789012'
2203 |     mock_mcp = MagicMock()
2204 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2205 |     handler.glue_client = mock_glue_client
2206 |     mock_ctx = MagicMock(spec=Context)
2207 | 
2208 |     mock_glue_client.get_workflow.side_effect = ClientError(
2209 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Workflow not found'}},
2210 |         'get_workflow',
2211 |     )
2212 | 
2213 |     result = await handler.manage_aws_glue_workflows(
2214 |         mock_ctx, operation='delete-workflow', workflow_name='test-workflow'
2215 |     )
2216 | 
2217 |     assert result.isError
2218 |     assert 'Workflow test-workflow not found' in result.content[0].text
2219 | 
2220 | 
2221 | @pytest.mark.asyncio
2222 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2223 | async def test_get_workflow_with_include_graph_true(mock_create_client):
2224 |     """Test get workflow with include_graph parameter set to True."""
2225 |     mock_glue_client = MagicMock()
2226 |     mock_create_client.return_value = mock_glue_client
2227 |     mock_mcp = MagicMock()
2228 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2229 |     handler.glue_client = mock_glue_client
2230 |     mock_ctx = MagicMock(spec=Context)
2231 | 
2232 |     mock_glue_client.get_workflow.return_value = {'Workflow': {'Name': 'test-workflow'}}
2233 | 
2234 |     result = await handler.manage_aws_glue_workflows(
2235 |         mock_ctx,
2236 |         operation='get-workflow',
2237 |         workflow_name='test-workflow',
2238 |         workflow_definition={'include_graph': True},
2239 |     )
2240 | 
2241 |     assert not result.isError
2242 |     args, kwargs = mock_glue_client.get_workflow.call_args
2243 |     assert kwargs['IncludeGraph']
2244 | 
2245 | 
2246 | @pytest.mark.asyncio
2247 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2248 | async def test_list_workflows_with_max_results(mock_create_client):
2249 |     """Test list workflows with max_results parameter."""
2250 |     mock_glue_client = MagicMock()
2251 |     mock_create_client.return_value = mock_glue_client
2252 |     mock_mcp = MagicMock()
2253 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2254 |     handler.glue_client = mock_glue_client
2255 |     mock_ctx = MagicMock(spec=Context)
2256 | 
2257 |     mock_glue_client.list_workflows.return_value = {'Workflows': ['workflow1']}
2258 | 
2259 |     result = await handler.manage_aws_glue_workflows(
2260 |         mock_ctx, operation='list-workflows', max_results=10
2261 |     )
2262 | 
2263 |     assert not result.isError
2264 |     args, kwargs = mock_glue_client.list_workflows.call_args
2265 |     assert kwargs['MaxResults'] == 10
2266 | 
2267 | 
2268 | @pytest.mark.asyncio
2269 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2270 | async def test_list_workflows_with_next_token(mock_create_client):
2271 |     """Test list workflows with next_token parameter."""
2272 |     mock_glue_client = MagicMock()
2273 |     mock_create_client.return_value = mock_glue_client
2274 |     mock_mcp = MagicMock()
2275 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2276 |     handler.glue_client = mock_glue_client
2277 |     mock_ctx = MagicMock(spec=Context)
2278 | 
2279 |     mock_glue_client.list_workflows.return_value = {'Workflows': ['workflow1']}
2280 | 
2281 |     result = await handler.manage_aws_glue_workflows(
2282 |         mock_ctx, operation='list-workflows', next_token='token123'
2283 |     )
2284 | 
2285 |     assert not result.isError
2286 |     args, kwargs = mock_glue_client.list_workflows.call_args
2287 |     assert kwargs['NextToken'] == 'token123'
2288 | 
2289 | 
2290 | @pytest.mark.asyncio
2291 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2292 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2293 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2294 | async def test_start_workflow_run_entity_not_found(
2295 |     mock_get_account_id, mock_get_region, mock_create_client
2296 | ):
2297 |     """Test start workflow run when workflow is not found."""
2298 |     mock_glue_client = MagicMock()
2299 |     mock_create_client.return_value = mock_glue_client
2300 |     mock_get_region.return_value = 'us-east-1'
2301 |     mock_get_account_id.return_value = '123456789012'
2302 |     mock_mcp = MagicMock()
2303 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2304 |     handler.glue_client = mock_glue_client
2305 |     mock_ctx = MagicMock(spec=Context)
2306 | 
2307 |     mock_glue_client.get_workflow.side_effect = ClientError(
2308 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Workflow not found'}},
2309 |         'get_workflow',
2310 |     )
2311 | 
2312 |     result = await handler.manage_aws_glue_workflows(
2313 |         mock_ctx, operation='start-workflow-run', workflow_name='test-workflow'
2314 |     )
2315 | 
2316 |     assert result.isError
2317 |     assert 'Workflow test-workflow not found' in result.content[0].text
2318 | 
2319 | 
2320 | @pytest.mark.asyncio
2321 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2322 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2323 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2324 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.is_resource_mcp_managed')
2325 | async def test_start_workflow_run_with_run_properties(
2326 |     mock_is_mcp_managed, mock_get_account_id, mock_get_region, mock_create_client
2327 | ):
2328 |     """Test start workflow run with run_properties."""
2329 |     mock_glue_client = MagicMock()
2330 |     mock_create_client.return_value = mock_glue_client
2331 |     mock_get_region.return_value = 'us-east-1'
2332 |     mock_get_account_id.return_value = '123456789012'
2333 |     mock_is_mcp_managed.return_value = True
2334 |     mock_mcp = MagicMock()
2335 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2336 |     handler.glue_client = mock_glue_client
2337 |     mock_ctx = MagicMock(spec=Context)
2338 | 
2339 |     mock_glue_client.get_workflow.return_value = {
2340 |         'Workflow': {'Name': 'test-workflow', 'Tags': {'ManagedBy': 'MCP'}}
2341 |     }
2342 |     mock_glue_client.start_workflow_run.return_value = {'RunId': 'run-123'}
2343 | 
2344 |     result = await handler.manage_aws_glue_workflows(
2345 |         mock_ctx,
2346 |         operation='start-workflow-run',
2347 |         workflow_name='test-workflow',
2348 |         workflow_definition={'run_properties': {'ENV': 'test'}},
2349 |     )
2350 | 
2351 |     assert not result.isError
2352 |     args, kwargs = mock_glue_client.start_workflow_run.call_args
2353 |     assert kwargs['RunProperties'] == {'ENV': 'test'}
2354 | 
2355 | 
2356 | @pytest.mark.asyncio
2357 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2358 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2359 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2360 | async def test_delete_trigger_entity_not_found(
2361 |     mock_get_account_id, mock_get_region, mock_create_client
2362 | ):
2363 |     """Test delete trigger when trigger is not found."""
2364 |     mock_glue_client = MagicMock()
2365 |     mock_create_client.return_value = mock_glue_client
2366 |     mock_get_region.return_value = 'us-east-1'
2367 |     mock_get_account_id.return_value = '123456789012'
2368 |     mock_mcp = MagicMock()
2369 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2370 |     handler.glue_client = mock_glue_client
2371 |     mock_ctx = MagicMock(spec=Context)
2372 | 
2373 |     mock_glue_client.get_trigger.side_effect = ClientError(
2374 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Trigger not found'}},
2375 |         'get_trigger',
2376 |     )
2377 | 
2378 |     result = await handler.manage_aws_glue_triggers(
2379 |         mock_ctx, operation='delete-trigger', trigger_name='test-trigger'
2380 |     )
2381 | 
2382 |     assert result.isError
2383 |     assert 'Trigger test-trigger not found' in result.content[0].text
2384 | 
2385 | 
2386 | @pytest.mark.asyncio
2387 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2388 | async def test_get_triggers_with_max_results(mock_create_client):
2389 |     """Test get triggers with max_results parameter."""
2390 |     mock_glue_client = MagicMock()
2391 |     mock_create_client.return_value = mock_glue_client
2392 |     mock_mcp = MagicMock()
2393 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2394 |     handler.glue_client = mock_glue_client
2395 |     mock_ctx = MagicMock(spec=Context)
2396 | 
2397 |     mock_glue_client.get_triggers.return_value = {'Triggers': []}
2398 | 
2399 |     result = await handler.manage_aws_glue_triggers(
2400 |         mock_ctx, operation='get-triggers', max_results=10
2401 |     )
2402 | 
2403 |     assert not result.isError
2404 |     args, kwargs = mock_glue_client.get_triggers.call_args
2405 |     assert kwargs['MaxResults'] == 10
2406 | 
2407 | 
2408 | @pytest.mark.asyncio
2409 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2410 | async def test_get_triggers_with_next_token(mock_create_client):
2411 |     """Test get triggers with next_token parameter."""
2412 |     mock_glue_client = MagicMock()
2413 |     mock_create_client.return_value = mock_glue_client
2414 |     mock_mcp = MagicMock()
2415 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2416 |     handler.glue_client = mock_glue_client
2417 |     mock_ctx = MagicMock(spec=Context)
2418 | 
2419 |     mock_glue_client.get_triggers.return_value = {'Triggers': []}
2420 | 
2421 |     result = await handler.manage_aws_glue_triggers(
2422 |         mock_ctx, operation='get-triggers', next_token='token123'
2423 |     )
2424 | 
2425 |     assert not result.isError
2426 |     args, kwargs = mock_glue_client.get_triggers.call_args
2427 |     assert kwargs['NextToken'] == 'token123'
2428 | 
2429 | 
2430 | @pytest.mark.asyncio
2431 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2432 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2433 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2434 | async def test_start_trigger_entity_not_found(
2435 |     mock_get_account_id, mock_get_region, mock_create_client
2436 | ):
2437 |     """Test start trigger when trigger is not found."""
2438 |     mock_glue_client = MagicMock()
2439 |     mock_create_client.return_value = mock_glue_client
2440 |     mock_get_region.return_value = 'us-east-1'
2441 |     mock_get_account_id.return_value = '123456789012'
2442 |     mock_mcp = MagicMock()
2443 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2444 |     handler.glue_client = mock_glue_client
2445 |     mock_ctx = MagicMock(spec=Context)
2446 | 
2447 |     mock_glue_client.get_trigger.side_effect = ClientError(
2448 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Trigger not found'}},
2449 |         'get_trigger',
2450 |     )
2451 | 
2452 |     result = await handler.manage_aws_glue_triggers(
2453 |         mock_ctx, operation='start-trigger', trigger_name='test-trigger'
2454 |     )
2455 | 
2456 |     assert result.isError
2457 |     assert 'Trigger test-trigger not found' in result.content[0].text
2458 | 
2459 | 
2460 | @pytest.mark.asyncio
2461 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2462 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_region')
2463 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.get_aws_account_id')
2464 | async def test_stop_trigger_entity_not_found(
2465 |     mock_get_account_id, mock_get_region, mock_create_client
2466 | ):
2467 |     """Test stop trigger when trigger is not found."""
2468 |     mock_glue_client = MagicMock()
2469 |     mock_create_client.return_value = mock_glue_client
2470 |     mock_get_region.return_value = 'us-east-1'
2471 |     mock_get_account_id.return_value = '123456789012'
2472 |     mock_mcp = MagicMock()
2473 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2474 |     handler.glue_client = mock_glue_client
2475 |     mock_ctx = MagicMock(spec=Context)
2476 | 
2477 |     mock_glue_client.get_trigger.side_effect = ClientError(
2478 |         {'Error': {'Code': 'EntityNotFoundException', 'Message': 'Trigger not found'}},
2479 |         'get_trigger',
2480 |     )
2481 | 
2482 |     result = await handler.manage_aws_glue_triggers(
2483 |         mock_ctx, operation='stop-trigger', trigger_name='test-trigger'
2484 |     )
2485 | 
2486 |     assert result.isError
2487 |     assert 'Trigger test-trigger not found' in result.content[0].text
2488 | 
2489 | 
2490 | @pytest.mark.asyncio
2491 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2492 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
2493 | async def test_create_workflow_empty_definition(mock_prepare_tags, mock_create_client):
2494 |     """Test creating workflow with empty definition."""
2495 |     mock_glue_client = MagicMock()
2496 |     mock_create_client.return_value = mock_glue_client
2497 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
2498 |     mock_mcp = MagicMock()
2499 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2500 |     handler.glue_client = mock_glue_client
2501 |     mock_ctx = MagicMock(spec=Context)
2502 | 
2503 |     mock_glue_client.create_workflow.return_value = {'Name': 'test-workflow'}
2504 | 
2505 |     result = await handler.manage_aws_glue_workflows(
2506 |         mock_ctx,
2507 |         operation='create-workflow',
2508 |         workflow_name='test-workflow',
2509 |         workflow_definition={},
2510 |     )
2511 | 
2512 |     assert result.isError is False
2513 |     args, kwargs = mock_glue_client.create_workflow.call_args
2514 |     assert 'Description' not in kwargs
2515 |     assert 'DefaultRunProperties' not in kwargs
2516 |     assert 'MaxConcurrentRuns' not in kwargs
2517 |     assert kwargs['Tags'] == {'ManagedBy': 'MCP'}
2518 | 
2519 | 
2520 | @pytest.mark.asyncio
2521 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2522 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.prepare_resource_tags')
2523 | async def test_create_trigger_minimal_params(mock_prepare_tags, mock_create_client):
2524 |     """Test create trigger with minimal parameters."""
2525 |     mock_glue_client = MagicMock()
2526 |     mock_create_client.return_value = mock_glue_client
2527 |     mock_prepare_tags.return_value = {'ManagedBy': 'MCP'}
2528 |     mock_mcp = MagicMock()
2529 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2530 |     handler.glue_client = mock_glue_client
2531 |     mock_ctx = MagicMock(spec=Context)
2532 | 
2533 |     mock_glue_client.create_trigger.return_value = {'Name': 'test-trigger'}
2534 | 
2535 |     result = await handler.manage_aws_glue_triggers(
2536 |         mock_ctx,
2537 |         operation='create-trigger',
2538 |         trigger_name='test-trigger',
2539 |         trigger_definition={
2540 |             'Type': 'SCHEDULED',
2541 |             'Actions': [{'JobName': 'test-job'}],
2542 |         },
2543 |     )
2544 | 
2545 |     assert result.isError is False
2546 |     args, kwargs = mock_glue_client.create_trigger.call_args
2547 |     assert kwargs['Type'] == 'SCHEDULED'
2548 |     assert kwargs['Actions'] == [{'JobName': 'test-job'}]
2549 |     assert 'WorkflowName' not in kwargs
2550 |     assert 'Schedule' not in kwargs
2551 |     assert 'Predicate' not in kwargs
2552 |     assert 'Description' not in kwargs
2553 |     assert 'StartOnCreation' not in kwargs
2554 |     assert 'EventBatchingCondition' not in kwargs
2555 | 
2556 | 
2557 | @pytest.mark.asyncio
2558 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2559 | async def test_workflow_parameter_validation_errors(mock_create_client):
2560 |     """Test workflow parameter validation errors."""
2561 |     mock_glue_client = MagicMock()
2562 |     mock_create_client.return_value = mock_glue_client
2563 |     mock_mcp = MagicMock()
2564 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2565 |     handler.glue_client = mock_glue_client
2566 |     mock_ctx = MagicMock(spec=Context)
2567 | 
2568 |     # Test missing workflow_name for get-workflow
2569 |     with pytest.raises(ValueError) as excinfo:
2570 |         await handler.manage_aws_glue_workflows(
2571 |             mock_ctx, operation='get-workflow', workflow_name=None
2572 |         )
2573 |     assert 'workflow_name is required' in str(excinfo.value)
2574 | 
2575 |     # Test missing workflow_name for delete-workflow
2576 |     with pytest.raises(ValueError) as excinfo:
2577 |         await handler.manage_aws_glue_workflows(
2578 |             mock_ctx, operation='delete-workflow', workflow_name=None
2579 |         )
2580 |     assert 'workflow_name is required' in str(excinfo.value)
2581 | 
2582 |     # Test missing workflow_name for start-workflow-run
2583 |     with pytest.raises(ValueError) as excinfo:
2584 |         await handler.manage_aws_glue_workflows(
2585 |             mock_ctx, operation='start-workflow-run', workflow_name=None
2586 |         )
2587 |     assert 'workflow_name is required' in str(excinfo.value)
2588 | 
2589 | 
2590 | @pytest.mark.asyncio
2591 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2592 | async def test_trigger_parameter_validation_errors(mock_create_client):
2593 |     """Test trigger parameter validation errors."""
2594 |     mock_glue_client = MagicMock()
2595 |     mock_create_client.return_value = mock_glue_client
2596 |     mock_mcp = MagicMock()
2597 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=True)
2598 |     handler.glue_client = mock_glue_client
2599 |     mock_ctx = MagicMock(spec=Context)
2600 | 
2601 |     # Test missing trigger_name for get-trigger
2602 |     with pytest.raises(ValueError) as excinfo:
2603 |         await handler.manage_aws_glue_triggers(
2604 |             mock_ctx, operation='get-trigger', trigger_name=None
2605 |         )
2606 |     assert 'trigger_name is required' in str(excinfo.value)
2607 | 
2608 |     # Test missing trigger_name for delete-trigger
2609 |     with pytest.raises(ValueError) as excinfo:
2610 |         await handler.manage_aws_glue_triggers(
2611 |             mock_ctx, operation='delete-trigger', trigger_name=None
2612 |         )
2613 |     assert 'trigger_name is required' in str(excinfo.value)
2614 | 
2615 |     # Test missing trigger_name for start-trigger
2616 |     with pytest.raises(ValueError) as excinfo:
2617 |         await handler.manage_aws_glue_triggers(
2618 |             mock_ctx, operation='start-trigger', trigger_name=None
2619 |         )
2620 |     assert 'trigger_name is required' in str(excinfo.value)
2621 | 
2622 |     # Test missing trigger_name for stop-trigger
2623 |     with pytest.raises(ValueError) as excinfo:
2624 |         await handler.manage_aws_glue_triggers(
2625 |             mock_ctx, operation='stop-trigger', trigger_name=None
2626 |         )
2627 |     assert 'trigger_name is required' in str(excinfo.value)
2628 | 
2629 | 
2630 | @pytest.mark.asyncio
2631 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2632 | async def test_workflow_general_exception(mock_create_client):
2633 |     """Test general exception handling in workflows."""
2634 |     mock_glue_client = MagicMock()
2635 |     mock_glue_client.get_workflow.side_effect = Exception('Test exception')
2636 |     mock_create_client.return_value = mock_glue_client
2637 |     mock_mcp = MagicMock()
2638 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2639 |     handler.glue_client = mock_glue_client
2640 |     mock_ctx = MagicMock(spec=Context)
2641 | 
2642 |     result = await handler.manage_aws_glue_workflows(
2643 |         mock_ctx, operation='get-workflow', workflow_name='test-workflow'
2644 |     )
2645 | 
2646 |     assert result.isError is True
2647 |     assert 'Error in manage_aws_glue_workflows: Test exception' in result.content[0].text
2648 | 
2649 | 
2650 | @pytest.mark.asyncio
2651 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2652 | async def test_trigger_general_exception(mock_create_client):
2653 |     """Test general exception handling in triggers."""
2654 |     mock_glue_client = MagicMock()
2655 |     mock_glue_client.get_trigger.side_effect = Exception('Test exception')
2656 |     mock_create_client.return_value = mock_glue_client
2657 |     mock_mcp = MagicMock()
2658 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp)
2659 |     handler.glue_client = mock_glue_client
2660 |     mock_ctx = MagicMock(spec=Context)
2661 | 
2662 |     result = await handler.manage_aws_glue_triggers(
2663 |         mock_ctx, operation='get-trigger', trigger_name='test-trigger'
2664 |     )
2665 | 
2666 |     assert result.isError is True
2667 |     assert 'Error in manage_aws_glue_triggers: Test exception' in result.content[0].text
2668 | 
2669 | 
2670 | @pytest.mark.asyncio
2671 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2672 | async def test_workflow_no_write_access_fallback(mock_create_client):
2673 |     """Test workflow no write access fallback response."""
2674 |     mock_glue_client = MagicMock()
2675 |     mock_create_client.return_value = mock_glue_client
2676 |     mock_mcp = MagicMock()
2677 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=False)
2678 |     handler.glue_client = mock_glue_client
2679 |     mock_ctx = MagicMock(spec=Context)
2680 | 
2681 |     result = await handler.manage_aws_glue_workflows(
2682 |         mock_ctx, operation='unknown-operation', workflow_name='test-workflow'
2683 |     )
2684 | 
2685 |     assert result.isError is True
2686 |     assert 'Invalid operation: unknown-operation' in result.content[0].text
2687 | 
2688 | 
2689 | @pytest.mark.asyncio
2690 | @patch('awslabs.aws_dataprocessing_mcp_server.utils.aws_helper.AwsHelper.create_boto3_client')
2691 | async def test_trigger_no_write_access_fallback(mock_create_client):
2692 |     """Test trigger no write access fallback response."""
2693 |     mock_glue_client = MagicMock()
2694 |     mock_create_client.return_value = mock_glue_client
2695 |     mock_mcp = MagicMock()
2696 |     handler = GlueWorkflowAndTriggerHandler(mock_mcp, allow_write=False)
2697 |     handler.glue_client = mock_glue_client
2698 |     mock_ctx = MagicMock(spec=Context)
2699 | 
2700 |     result = await handler.manage_aws_glue_triggers(
2701 |         mock_ctx, operation='create-trigger', trigger_name='test-trigger'
2702 |     )
2703 | 
2704 |     assert result.isError is True
2705 |     assert 'Operation create-trigger is not allowed without write access' in result.content[0].text
2706 | 
```
Page 499/503FirstPrevNextLast