Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/ecs-mcp-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ An MCP server for containerizing applications, deploying applications to Amazon
- **Security Best Practices**: Implement AWS security best practices for container deployments
- **Resource Management**: List and explore ECS resources such as task definitions, services, clusters, and tasks
- **ECR Integration**: View repositories and container images in Amazon ECR
- **AWS Knowledge Integration**: Access up-to-date AWS documentation through the integrated AWS Knowledge MCP Server proxy which includes knowledge on ECS and new features released that models may not be aware of

Customers can use the `containerize_app` tool to help them containerize their applications with best practices and deploy them to Amazon ECS. The `create_ecs_infrastructure` tool automates infrastructure deployment using CloudFormation, while `get_deployment_status` returns the status of deployments and provide the URL of the set up Application Load Balancer. When resources are no longer needed, the `delete_ecs_infrastructure` tool allows for easy cleanup and removal of all deployed components.

Expand Down Expand Up @@ -86,6 +87,9 @@ The following operations are read-only and relatively safe for production enviro
| `ecs_troubleshooting_tool` | `fetch_service_events` | ✅ Safe - Read-only |
| `ecs_troubleshooting_tool` | `get_ecs_troubleshooting_guidance` | ✅ Safe - Read-only |
| `get_deployment_status` | Status checking | ✅ Safe - Read-only |
| `aws_knowledge_aws___search_documentation` | AWS documentation search | ✅ Safe - Read-only |
| `aws_knowledge_aws___read_documentation` | AWS documentation reading | ✅ Safe - Read-only |
| `aws_knowledge_aws___recommend` | AWS documentation recommendations | ✅ Safe - Read-only |

The following operations modify resources and should be used with extreme caution in production:

Expand Down Expand Up @@ -298,6 +302,18 @@ This tool provides comprehensive access to Amazon ECS resources to help you moni

The resource management tool enforces permission checks for write operations. Operations that modify resources require the ALLOW_WRITE environment variable to be set to true.

### AWS Documentation Tools

The ECS MCP Server integrates with the [AWS Knowledge MCP Server](https://github.com/awslabs/mcp/tree/main/src/aws-knowledge-mcp-server) to provide access to up-to-date AWS documentation, including ECS-specific knowledge about new features recently launched that models may not be aware of.

Note: these tools are duplicative if you have the AWS Knowledge MCP Server already configured in your MCP client. For the below knowledge tools, the ECS MCP Server adds extra guidance to the tool descriptions to help LLMs use the tools for ECS contexts.

- **aws_knowledge_aws___search_documentation**: Search across all AWS documentation including the latest AWS docs, API references, Blogs posts, Architectural references, and Well-Architected best practices.

- **aws_knowledge_aws___read_documentation**: Fetch and convert AWS documentation pages to markdown format.

- **aws_knowledge_aws___recommend**: Get content recommendations for AWS documentation pages.

## Example Prompts

### Containerization and Deployment
Expand Down Expand Up @@ -330,6 +346,12 @@ The resource management tool enforces permission checks for write operations. Op
- "Run a task in my cluster"
- "Stop a running task"

### AWS Documentation and Knowledge

- "What are the best practices for ECS deployments?"
- "How do I set up blue-green deployments in ECS?"
- "Get recommendations for ECS security best practices"

## Requirements

- Python 3.10+
Expand Down
121 changes: 74 additions & 47 deletions src/ecs-mcp-server/awslabs/ecs_mcp_server/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,13 @@
import logging
import os
import sys
from contextlib import asynccontextmanager
from typing import Any, Dict, Tuple

from fastmcp import FastMCP

from awslabs.ecs_mcp_server.modules import (
aws_knowledge_proxy,
containerize,
delete,
deployment_status,
Expand All @@ -36,42 +39,58 @@
secure_tool,
)

# Configure logging
log_level = os.environ.get("FASTMCP_LOG_LEVEL", "INFO")
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
log_file = os.environ.get("FASTMCP_LOG_FILE")

# Set up basic configuration
logging.basicConfig(
level=log_level,
format=log_format,
)
def _setup_logging() -> logging.Logger:
"""Configure logging for the server."""
log_level = os.environ.get("FASTMCP_LOG_LEVEL", "INFO")
log_format = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
log_file = os.environ.get("FASTMCP_LOG_FILE")

# Add file handler if log file path is specified
if log_file:
try:
# Create directory for log file if it doesn't exist
log_dir = os.path.dirname(log_file)
if log_dir and not os.path.exists(log_dir):
os.makedirs(log_dir, exist_ok=True)

# Add file handler
file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(logging.Formatter(log_format))
logging.getLogger().addHandler(file_handler)
logging.info(f"Logging to file: {log_file}")
except Exception as e:
logging.error(f"Failed to set up log file {log_file}: {e}")
logging.basicConfig(level=log_level, format=log_format)

if log_file:
try:
log_dir = os.path.dirname(log_file)
if log_dir and not os.path.exists(log_dir):
os.makedirs(log_dir, exist_ok=True)

file_handler = logging.FileHandler(log_file)
file_handler.setFormatter(logging.Formatter(log_format))
logging.getLogger().addHandler(file_handler)
logging.info(f"Logging to file: {log_file}")
except Exception as e:
logging.error(f"Failed to set up log file {log_file}: {e}")

return logging.getLogger("ecs-mcp-server")


@asynccontextmanager
async def server_lifespan(server):
"""
Server lifespan context manager for initialization and cleanup.

logger = logging.getLogger("ecs-mcp-server")
Provides safe access to async server methods during startup for
operations like tool transformations.
"""
logger = logging.getLogger("ecs-mcp-server")
logger.info("Server initializing")

# Load configuration
config = get_config()
# Safe async operations can be performed here
await aws_knowledge_proxy.apply_tool_transformations(server)

# Create the MCP server
mcp = FastMCP(
name="AWS ECS MCP Server",
instructions="""Use this server to containerize and deploy web applications to AWS ECS.
logger.info("Server ready")
yield
logger.info("Server shutting down")


def _create_ecs_mcp_server() -> Tuple[FastMCP, Dict[str, Any]]:
"""Create and configure the MCP server."""
config = get_config()

mcp = FastMCP(
name="AWS ECS MCP Server",
lifespan=server_lifespan,
instructions="""Use this server to containerize and deploy web applications to AWS ECS.

WORKFLOW:
1. containerize_app:
Expand All @@ -97,30 +116,38 @@
- Set ALLOW_WRITE=true to enable infrastructure creation and deletion
- Set ALLOW_SENSITIVE_DATA=true to enable access to logs and detailed resource information
""",
)
)

# Apply security wrappers to API functions
# Write operations
infrastructure.create_infrastructure = secure_tool(
config, PERMISSION_WRITE, "create_ecs_infrastructure"
)(infrastructure.create_infrastructure)
delete.delete_infrastructure = secure_tool(config, PERMISSION_WRITE, "delete_ecs_infrastructure")(
delete.delete_infrastructure
)
# Apply security wrappers to API functions
# Write operations
infrastructure.create_infrastructure = secure_tool(
config, PERMISSION_WRITE, "create_ecs_infrastructure"
)(infrastructure.create_infrastructure)
delete.delete_infrastructure = secure_tool(
config, PERMISSION_WRITE, "delete_ecs_infrastructure"
)(delete.delete_infrastructure)

# Register all modules
containerize.register_module(mcp)
infrastructure.register_module(mcp)
deployment_status.register_module(mcp)
resource_management.register_module(mcp)
troubleshooting.register_module(mcp)
delete.register_module(mcp)

# Register all modules
containerize.register_module(mcp)
infrastructure.register_module(mcp)
deployment_status.register_module(mcp)
resource_management.register_module(mcp)
troubleshooting.register_module(mcp)
delete.register_module(mcp)
# Register all proxies
aws_knowledge_proxy.register_proxy(mcp)

return mcp, config


def main() -> None:
"""Main entry point for the ECS MCP Server."""
try:
# Start the server
mcp, config = _create_ecs_mcp_server()
logger = _setup_logging()

logger.info("Server started")
logger.info(f"Write operations enabled: {config.get('allow-write', False)}")
logger.info(f"Sensitive data access enabled: {config.get('allow-sensitive-data', False)}")
Expand Down
Loading