Skip to main content
Glama
main.tf15.7 kB
################################################################################ # Terraform Configuration for KYC MCP Server on AWS EC2 # This configuration provisions all necessary AWS resources ################################################################################ terraform { required_version = ">= 1.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } # Uncomment to use S3 backend for state management # backend "s3" { # bucket = "your-terraform-state-bucket" # key = "kyc-mcp-server/terraform.tfstate" # region = "us-east-1" # encrypt = true # dynamodb_table = "terraform-state-lock" # } } provider "aws" { region = var.aws_region default_tags { tags = { Project = "KYC-MCP-Server" Environment = var.environment ManagedBy = "Terraform" } } } ################################################################################ # Data Sources ################################################################################ # Get latest Amazon Linux 2 AMI data "aws_ami" "amazon_linux_2" { most_recent = true owners = ["amazon"] filter { name = "name" values = ["amzn2-ami-hvm-*-x86_64-gp2"] } filter { name = "virtualization-type" values = ["hvm"] } } # Get latest Ubuntu 22.04 AMI data "aws_ami" "ubuntu_22_04" { most_recent = true owners = ["099720109477"] # Canonical filter { name = "name" values = ["ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"] } filter { name = "virtualization-type" values = ["hvm"] } } # Get current AWS account ID data "aws_caller_identity" "current" {} # Get current AWS region data "aws_region" "current" {} ################################################################################ # VPC and Networking ################################################################################ resource "aws_vpc" "main" { count = var.create_vpc ? 1 : 0 cidr_block = var.vpc_cidr enable_dns_hostnames = true enable_dns_support = true tags = { Name = "${var.project_name}-vpc" } } resource "aws_internet_gateway" "main" { count = var.create_vpc ? 1 : 0 vpc_id = aws_vpc.main[0].id tags = { Name = "${var.project_name}-igw" } } resource "aws_subnet" "public" { count = var.create_vpc ? length(var.availability_zones) : 0 vpc_id = aws_vpc.main[0].id cidr_block = cidrsubnet(var.vpc_cidr, 8, count.index) availability_zone = var.availability_zones[count.index] map_public_ip_on_launch = true tags = { Name = "${var.project_name}-public-subnet-${count.index + 1}" } } resource "aws_route_table" "public" { count = var.create_vpc ? 1 : 0 vpc_id = aws_vpc.main[0].id route { cidr_block = "0.0.0.0/0" gateway_id = aws_internet_gateway.main[0].id } tags = { Name = "${var.project_name}-public-rt" } } resource "aws_route_table_association" "public" { count = var.create_vpc ? length(var.availability_zones) : 0 subnet_id = aws_subnet.public[count.index].id route_table_id = aws_route_table.public[0].id } ################################################################################ # Security Groups ################################################################################ resource "aws_security_group" "kyc_mcp_server" { name_prefix = "${var.project_name}-sg-" description = "Security group for KYC MCP Server" vpc_id = var.create_vpc ? aws_vpc.main[0].id : var.existing_vpc_id # SSH access ingress { description = "SSH from allowed IPs" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = var.allowed_ssh_cidrs } # HTTP access ingress { description = "HTTP" from_port = 80 to_port = 80 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } # HTTPS access ingress { description = "HTTPS" from_port = 443 to_port = 443 protocol = "tcp" cidr_blocks = ["0.0.0.0/0"] } # Metrics port (restrict to monitoring IPs in production) ingress { description = "Prometheus metrics" from_port = 9090 to_port = 9091 protocol = "tcp" cidr_blocks = var.allowed_monitoring_cidrs } # Node exporter ingress { description = "Node exporter" from_port = 9100 to_port = 9100 protocol = "tcp" cidr_blocks = var.allowed_monitoring_cidrs } # Outbound traffic egress { description = "All outbound traffic" from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "${var.project_name}-sg" } lifecycle { create_before_destroy = true } } ################################################################################ # IAM Role and Instance Profile ################################################################################ resource "aws_iam_role" "kyc_mcp_server" { name_prefix = "${var.project_name}-role-" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [ { Action = "sts:AssumeRole" Effect = "Allow" Principal = { Service = "ec2.amazonaws.com" } } ] }) tags = { Name = "${var.project_name}-role" } } # CloudWatch Logs policy resource "aws_iam_role_policy" "cloudwatch_logs" { name_prefix = "cloudwatch-logs-" role = aws_iam_role.kyc_mcp_server.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents", "logs:DescribeLogStreams" ] Resource = "arn:aws:logs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:log-group:/aws/ec2/${var.project_name}*" } ] }) } # CloudWatch Metrics policy resource "aws_iam_role_policy" "cloudwatch_metrics" { name_prefix = "cloudwatch-metrics-" role = aws_iam_role.kyc_mcp_server.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "cloudwatch:PutMetricData" ] Resource = "*" } ] }) } # S3 backup policy resource "aws_iam_role_policy" "s3_backup" { count = var.enable_s3_backup ? 1 : 0 name_prefix = "s3-backup-" role = aws_iam_role.kyc_mcp_server.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "s3:PutObject", "s3:GetObject", "s3:ListBucket", "s3:DeleteObject" ] Resource = [ "arn:aws:s3:::${var.backup_bucket_name}", "arn:aws:s3:::${var.backup_bucket_name}/*" ] } ] }) } # SSM policy for parameter store resource "aws_iam_role_policy" "ssm_parameters" { name_prefix = "ssm-parameters-" role = aws_iam_role.kyc_mcp_server.id policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "ssm:GetParameter", "ssm:GetParameters", "ssm:GetParametersByPath" ] Resource = "arn:aws:ssm:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:parameter/${var.project_name}/*" } ] }) } # Attach CloudWatch agent policy resource "aws_iam_role_policy_attachment" "cloudwatch_agent" { role = aws_iam_role.kyc_mcp_server.name policy_arn = "arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy" } # Attach SSM managed instance policy resource "aws_iam_role_policy_attachment" "ssm_managed_instance" { role = aws_iam_role.kyc_mcp_server.name policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore" } resource "aws_iam_instance_profile" "kyc_mcp_server" { name_prefix = "${var.project_name}-profile-" role = aws_iam_role.kyc_mcp_server.name tags = { Name = "${var.project_name}-instance-profile" } } ################################################################################ # Key Pair ################################################################################ resource "aws_key_pair" "deployer" { count = var.create_key_pair ? 1 : 0 key_name = "${var.project_name}-key" public_key = var.ssh_public_key tags = { Name = "${var.project_name}-key" } } ################################################################################ # Elastic IP ################################################################################ resource "aws_eip" "kyc_mcp_server" { count = var.use_elastic_ip ? 1 : 0 domain = "vpc" tags = { Name = "${var.project_name}-eip" } } resource "aws_eip_association" "kyc_mcp_server" { count = var.use_elastic_ip ? 1 : 0 instance_id = aws_instance.kyc_mcp_server.id allocation_id = aws_eip.kyc_mcp_server[0].id } ################################################################################ # EC2 Instance ################################################################################ resource "aws_instance" "kyc_mcp_server" { ami = var.ami_id != "" ? var.ami_id : (var.os_type == "ubuntu" ? data.aws_ami.ubuntu_22_04.id : data.aws_ami.amazon_linux_2.id) instance_type = var.instance_type subnet_id = var.create_vpc ? aws_subnet.public[0].id : var.existing_subnet_id vpc_security_group_ids = [aws_security_group.kyc_mcp_server.id] iam_instance_profile = aws_iam_instance_profile.kyc_mcp_server.name key_name = var.create_key_pair ? aws_key_pair.deployer[0].key_name : var.existing_key_name associate_public_ip_address = !var.use_elastic_ip root_block_device { volume_type = var.root_volume_type volume_size = var.root_volume_size delete_on_termination = true encrypted = true } user_data = templatefile("${path.module}/user-data.sh", { project_name = var.project_name environment = var.environment }) metadata_options { http_endpoint = "enabled" http_tokens = "required" http_put_response_hop_limit = 1 } monitoring = var.enable_detailed_monitoring tags = { Name = "${var.project_name}-instance" } lifecycle { ignore_changes = [ami] } } ################################################################################ # CloudWatch Log Group ################################################################################ resource "aws_cloudwatch_log_group" "kyc_mcp_server" { name = "/aws/ec2/${var.project_name}" retention_in_days = var.log_retention_days tags = { Name = "${var.project_name}-logs" } } ################################################################################ # CloudWatch Alarms ################################################################################ # CPU Utilization Alarm resource "aws_cloudwatch_metric_alarm" "cpu_utilization" { alarm_name = "${var.project_name}-high-cpu" comparison_operator = "GreaterThanThreshold" evaluation_periods = "2" metric_name = "CPUUtilization" namespace = "AWS/EC2" period = "300" statistic = "Average" threshold = var.cpu_alarm_threshold alarm_description = "This metric monitors EC2 CPU utilization" alarm_actions = var.alarm_sns_topic_arn != "" ? [var.alarm_sns_topic_arn] : [] dimensions = { InstanceId = aws_instance.kyc_mcp_server.id } tags = { Name = "${var.project_name}-cpu-alarm" } } # Memory Utilization Alarm (requires CloudWatch agent) resource "aws_cloudwatch_metric_alarm" "memory_utilization" { alarm_name = "${var.project_name}-high-memory" comparison_operator = "GreaterThanThreshold" evaluation_periods = "2" metric_name = "mem_used_percent" namespace = "CWAgent" period = "300" statistic = "Average" threshold = var.memory_alarm_threshold alarm_description = "This metric monitors EC2 memory utilization" alarm_actions = var.alarm_sns_topic_arn != "" ? [var.alarm_sns_topic_arn] : [] dimensions = { InstanceId = aws_instance.kyc_mcp_server.id } tags = { Name = "${var.project_name}-memory-alarm" } } # Disk Utilization Alarm resource "aws_cloudwatch_metric_alarm" "disk_utilization" { alarm_name = "${var.project_name}-high-disk" comparison_operator = "GreaterThanThreshold" evaluation_periods = "2" metric_name = "disk_used_percent" namespace = "CWAgent" period = "300" statistic = "Average" threshold = var.disk_alarm_threshold alarm_description = "This metric monitors EC2 disk utilization" alarm_actions = var.alarm_sns_topic_arn != "" ? [var.alarm_sns_topic_arn] : [] dimensions = { InstanceId = aws_instance.kyc_mcp_server.id path = "/" fstype = "ext4" } tags = { Name = "${var.project_name}-disk-alarm" } } # Status Check Failed Alarm resource "aws_cloudwatch_metric_alarm" "status_check_failed" { alarm_name = "${var.project_name}-status-check-failed" comparison_operator = "GreaterThanThreshold" evaluation_periods = "2" metric_name = "StatusCheckFailed" namespace = "AWS/EC2" period = "60" statistic = "Maximum" threshold = "0" alarm_description = "This metric monitors EC2 status checks" alarm_actions = var.alarm_sns_topic_arn != "" ? [var.alarm_sns_topic_arn] : [] dimensions = { InstanceId = aws_instance.kyc_mcp_server.id } tags = { Name = "${var.project_name}-status-alarm" } } ################################################################################ # S3 Bucket for Backups (Optional) ################################################################################ resource "aws_s3_bucket" "backups" { count = var.enable_s3_backup && var.create_backup_bucket ? 1 : 0 bucket_prefix = "${var.project_name}-backups-" tags = { Name = "${var.project_name}-backups" } } resource "aws_s3_bucket_versioning" "backups" { count = var.enable_s3_backup && var.create_backup_bucket ? 1 : 0 bucket = aws_s3_bucket.backups[0].id versioning_configuration { status = "Enabled" } } resource "aws_s3_bucket_server_side_encryption_configuration" "backups" { count = var.enable_s3_backup && var.create_backup_bucket ? 1 : 0 bucket = aws_s3_bucket.backups[0].id rule { apply_server_side_encryption_by_default { sse_algorithm = "AES256" } } } resource "aws_s3_bucket_lifecycle_configuration" "backups" { count = var.enable_s3_backup && var.create_backup_bucket ? 1 : 0 bucket = aws_s3_bucket.backups[0].id rule { id = "delete-old-backups" status = "Enabled" expiration { days = var.backup_retention_days } noncurrent_version_expiration { noncurrent_days = 30 } } } resource "aws_s3_bucket_public_access_block" "backups" { count = var.enable_s3_backup && var.create_backup_bucket ? 1 : 0 bucket = aws_s3_bucket.backups[0].id block_public_acls = true block_public_policy = true ignore_public_acls = true restrict_public_buckets = true }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/CTD-Techs/CTD-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server