cloudformation-template.yaml•7.99 kB
AWSTemplateFormatVersion: '2010-09-09'
Description: 'Personal Resume MCP Server - Complete AWS Infrastructure'
Parameters:
ImageURI:
Type: String
Description: ECR image URI
Default: "YOUR_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/personal-resume-mcp:latest"
VpcCIDR:
Description: CIDR block for VPC
Type: String
Default: "10.0.0.0/16"
PublicSubnet1CIDR:
Description: CIDR block for public subnet 1
Type: String
Default: "10.0.1.0/24"
PublicSubnet2CIDR:
Description: CIDR block for public subnet 2
Type: String
Default: "10.0.2.0/24"
Resources:
# VPC and Networking
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: !Ref VpcCIDR
EnableDnsHostnames: true
EnableDnsSupport: true
Tags:
- Key: Name
Value: personal-resume-mcp-vpc
InternetGateway:
Type: AWS::EC2::InternetGateway
Properties:
Tags:
- Key: Name
Value: personal-resume-mcp-igw
InternetGatewayAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
InternetGatewayId: !Ref InternetGateway
VpcId: !Ref VPC
PublicSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [0, !GetAZs '']
CidrBlock: !Ref PublicSubnet1CIDR
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: personal-resume-mcp-public-subnet-1
PublicSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
AvailabilityZone: !Select [1, !GetAZs '']
CidrBlock: !Ref PublicSubnet2CIDR
MapPublicIpOnLaunch: true
Tags:
- Key: Name
Value: personal-resume-mcp-public-subnet-2
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
Tags:
- Key: Name
Value: personal-resume-mcp-public-routes
DefaultPublicRoute:
Type: AWS::EC2::Route
DependsOn: InternetGatewayAttachment
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref InternetGateway
PublicSubnet1RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet1
PublicSubnet2RouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
RouteTableId: !Ref PublicRouteTable
SubnetId: !Ref PublicSubnet2
# Security Groups
ALBSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: personal-resume-mcp-alb-sg
GroupDescription: Security group for ALB
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 80
ToPort: 80
CidrIp: 0.0.0.0/0
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: personal-resume-mcp-alb-sg
ECSSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupName: personal-resume-mcp-ecs-sg
GroupDescription: Security group for ECS tasks
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 8000
ToPort: 8000
SourceSecurityGroupId: !Ref ALBSecurityGroup
Tags:
- Key: Name
Value: personal-resume-mcp-ecs-sg
# Application Load Balancer
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: personal-resume-mcp-alb
Scheme: internet-facing
Type: application
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
SecurityGroups:
- !Ref ALBSecurityGroup
Tags:
- Key: Name
Value: personal-resume-mcp-alb
ALBTargetGroup:
Type: AWS::ElasticLoadBalancingV2::TargetGroup
Properties:
Name: personal-resume-mcp-tg
Port: 8000
Protocol: HTTP
VpcId: !Ref VPC
TargetType: ip
HealthCheckPath: /health
HealthCheckIntervalSeconds: 30
HealthCheckTimeoutSeconds: 5
HealthyThresholdCount: 2
UnhealthyThresholdCount: 3
ALBListener:
Type: AWS::ElasticLoadBalancingV2::Listener
Properties:
DefaultActions:
- Type: forward
TargetGroupArn: !Ref ALBTargetGroup
LoadBalancerArn: !Ref ApplicationLoadBalancer
Port: 80
Protocol: HTTP
# ECS Cluster and Service
ECSCluster:
Type: AWS::ECS::Cluster
Properties:
ClusterName: personal-resume-mcp-cluster
CapacityProviders:
- FARGATE
DefaultCapacityProviderStrategy:
- CapacityProvider: FARGATE
Weight: 1
ECSTaskDefinition:
Type: AWS::ECS::TaskDefinition
Properties:
Family: personal-resume-mcp-task
NetworkMode: awsvpc
RequiresCompatibilities:
- FARGATE
Cpu: 1024
Memory: 2048
ExecutionRoleArn: !Ref ECSTaskExecutionRole
TaskRoleArn: !Ref ECSTaskRole
ContainerDefinitions:
- Name: personal-resume-mcp-container
Image: !Ref ImageURI
Essential: true
PortMappings:
- ContainerPort: 8000
Protocol: tcp
Environment:
- Name: PORT
Value: "8000"
- Name: PYTHONPATH
Value: "/app/src"
LogConfiguration:
LogDriver: awslogs
Options:
awslogs-group: !Ref CloudWatchLogGroup
awslogs-region: !Ref AWS::Region
awslogs-stream-prefix: ecs
HealthCheck:
Command:
- CMD-SHELL
- "curl -f http://localhost:8000/health || exit 1"
Interval: 30
Timeout: 5
Retries: 3
StartPeriod: 60
ECSService:
Type: AWS::ECS::Service
DependsOn: ALBListener
Properties:
ServiceName: personal-resume-mcp-service
Cluster: !Ref ECSCluster
TaskDefinition: !Ref ECSTaskDefinition
LaunchType: FARGATE
DesiredCount: 1
NetworkConfiguration:
AwsvpcConfiguration:
SecurityGroups:
- !Ref ECSSecurityGroup
Subnets:
- !Ref PublicSubnet1
- !Ref PublicSubnet2
AssignPublicIp: ENABLED
LoadBalancers:
- ContainerName: personal-resume-mcp-container
ContainerPort: 8000
TargetGroupArn: !Ref ALBTargetGroup
# IAM Roles
ECSTaskExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: personal-resume-mcp-execution-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
ECSTaskRole:
Type: AWS::IAM::Role
Properties:
RoleName: personal-resume-mcp-task-role
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: ecs-tasks.amazonaws.com
Action: sts:AssumeRole
# CloudWatch Log Group
CloudWatchLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: /ecs/personal-resume-mcp-server
RetentionInDays: 30
Outputs:
LoadBalancerDNS:
Description: DNS name of the load balancer
Value: !GetAtt ApplicationLoadBalancer.DNSName
Export:
Name: !Sub "${AWS::StackName}-LoadBalancerDNS"
MCPEndpoint:
Description: MCP endpoint URL
Value: !Sub "http://${ApplicationLoadBalancer.DNSName}/mcp"
Export:
Name: !Sub "${AWS::StackName}-MCPEndpoint"
HealthCheckEndpoint:
Description: Health check endpoint URL
Value: !Sub "http://${ApplicationLoadBalancer.DNSName}/health"
Export:
Name: !Sub "${AWS::StackName}-HealthCheckEndpoint"