diff --git a/client-strands-agents-mcp/main.py b/client-strands-agents-mcp/main.py index 784299c..dd40b7d 100644 --- a/client-strands-agents-mcp/main.py +++ b/client-strands-agents-mcp/main.py @@ -4,8 +4,8 @@ from strands.tools.mcp import MCPClient # Add your API Gateway URL here as it outputs from the sam deploy command (include /mcp at the end): -api_gateway_url = "https://1234567890.execute-api.us-east-1.amazonaws.com/Prod/mcp" -auth_token = "1234567890" +api_gateway_url = "https://ma8rga14yj.execute-api.us-west-2.amazonaws.com/Prod/mcp" +auth_token = "juhui" # This uses the Nova Pro model from Amazon Bedrock, in a US region: bedrock_model = BedrockModel( diff --git a/server-http-python-lambda/server/app.py b/server-http-python-lambda/server/app.py index 941579f..22d7d19 100644 --- a/server-http-python-lambda/server/app.py +++ b/server-http-python-lambda/server/app.py @@ -3,6 +3,9 @@ import random import boto3 import os +import ipaddress +import json +import ast # Get session table name from environment variable session_table = os.environ.get('MCP_SESSION_TABLE', 'mcp_sessions') @@ -72,6 +75,132 @@ def update_last_time(s): # Catch-all for unexpected errors return f"Error: An unexpected error occurred: {str(e)}" +@mcp_server.tool() +def create_vpc(params: dict) -> dict: + """ + Generalized VPC and Subnet Creator for OSS contribution. + + Parameters expected in `params`: + - cidr_block: str + - az_list: list[str] + - public_subnets_per_az: int + - private_subnets_per_az: int + - name_tag: str + + e.g. + createVpc(params={"cidr_block":"10.20.0.0/16","az_list":["us-west-2a","us-west-2b"],"public_subnets_per_az":1,"private_subnets_per_az":1,"name_tag":"mcp"}) + """ + ec2 = boto3.client("ec2", region_name="us-west-2") + out = {} + + + if isinstance(params, str): + params = json.loads(params) + # Extract parameters with defaults + cidr_block = params.get("cidr_block", "10.0.0.0/16") + az_list = params.get("az_list", ["us-west-2a", "us-west-2b"]) + public_subnets_per_az = params.get("public_subnets_per_az", 1) + private_subnets_per_az = params.get("private_subnets_per_az", 1) + name_tag = params.get("name_tag", "mcp-server") + + total_subnets_needed = (public_subnets_per_az + private_subnets_per_az) * len(az_list) + subnet_blocks = list(ipaddress.ip_network(cidr_block).subnets(new_prefix=24)) + if len(subnet_blocks) < total_subnets_needed: + raise Exception("Not enough subnet blocks in CIDR for requested subnets.") + + # Check existing VPC + existing = ec2.describe_vpcs(Filters=[ + {"Name": "tag:Name", "Values": [f"{name_tag}-vpc"]} + ])["Vpcs"] + if existing: + vpc_id = existing[0]["VpcId"] + print(f"[INFO] Existing VPC found: {vpc_id}") + out["VpcId"] = vpc_id + return out + + # Create VPC + vpc_id = ec2.create_vpc(CidrBlock=cidr_block)["Vpc"]["VpcId"] + ec2.modify_vpc_attribute(VpcId=vpc_id, EnableDnsSupport={"Value": True}) + ec2.modify_vpc_attribute(VpcId=vpc_id, EnableDnsHostnames={"Value": True}) + ec2.create_tags(Resources=[vpc_id], + Tags=[{"Key": "Name", "Value": f"{name_tag}-vpc"}]) + out["VpcId"] = vpc_id + + # IGW and main route + igw_id = ec2.create_internet_gateway()["InternetGateway"]["InternetGatewayId"] + ec2.attach_internet_gateway(VpcId=vpc_id, InternetGatewayId=igw_id) + out["InternetGatewayId"] = igw_id + + main_rt_id = ec2.describe_route_tables( + Filters=[ + {"Name": "vpc-id", "Values": [vpc_id]}, + {"Name": "association.main", "Values": ["true"]} + ] + )["RouteTables"][0]["RouteTableId"] + ec2.create_route(RouteTableId=main_rt_id, + DestinationCidrBlock="0.0.0.0/0", + GatewayId=igw_id) + + out["PublicSubnets"] = [] + out["PrivateSubnets"] = [] + + idx = 0 + for az in az_list: + # Create public subnets + for i in range(public_subnets_per_az): + cidr_pub = str(subnet_blocks[idx]) + idx += 1 + pub_subnet = ec2.create_subnet( + VpcId=vpc_id, CidrBlock=cidr_pub, AvailabilityZone=az, + TagSpecifications=[{ + "ResourceType": "subnet", + "Tags": [{"Key": "Name", "Value": f"{name_tag}-pub-{az}-{i}"}] + }] + )["Subnet"] + pub_id = pub_subnet["SubnetId"] + ec2.modify_subnet_attribute(SubnetId=pub_id, MapPublicIpOnLaunch={"Value": True}) + out["PublicSubnets"].append(pub_id) + + # Create NAT Gateway for private subnets + eip = ec2.allocate_address(Domain="vpc")["AllocationId"] + nat = ec2.create_nat_gateway( + SubnetId=pub_id, AllocationId=eip, + TagSpecifications=[{ + "ResourceType": "natgateway", + "Tags": [{"Key": "Name", "Value": f"{name_tag}-nat-{az}"}] + }] + )["NatGateway"] + nat_id = nat["NatGatewayId"] + + waiter = ec2.get_waiter("nat_gateway_available") + print(f"Waiting for NAT Gateway {nat_id} in {az}...") + waiter.wait(NatGatewayIds=[nat_id]) + print(f"NAT Gateway {nat_id} is available.") + + # Create private subnets + for i in range(private_subnets_per_az): + cidr_pri = str(subnet_blocks[idx]) + idx += 1 + pri_subnet = ec2.create_subnet( + VpcId=vpc_id, CidrBlock=cidr_pri, AvailabilityZone=az, + TagSpecifications=[{ + "ResourceType": "subnet", + "Tags": [{"Key": "Name", "Value": f"{name_tag}-pri-{az}-{i}"}] + }] + )["Subnet"] + pri_id = pri_subnet["SubnetId"] + out["PrivateSubnets"].append(pri_id) + + rt_priv = ec2.create_route_table(VpcId=vpc_id)["RouteTable"]["RouteTableId"] + ec2.associate_route_table(RouteTableId=rt_priv, SubnetId=pri_id) + ec2.create_route(RouteTableId=rt_priv, + DestinationCidrBlock="0.0.0.0/0", + NatGatewayId=nat_id) + + return { + "Message": f"VPC {vpc_id} and related resources created successfully." + } + def lambda_handler(event, context): """AWS Lambda handler function.""" return mcp_server.handle_request(event, context) \ No newline at end of file diff --git a/server-http-python-lambda/template.yaml b/server-http-python-lambda/template.yaml index 60d9441..70bbfa9 100644 --- a/server-http-python-lambda/template.yaml +++ b/server-http-python-lambda/template.yaml @@ -10,7 +10,7 @@ Parameters: Globals: Function: - Timeout: 60 + Timeout: 900 Runtime: python3.12 Architectures: [x86_64] @@ -85,6 +85,26 @@ Resources: - dynamodb:UpdateItem - dynamodb:DescribeTable Resource: !GetAtt McpSessionsTable.Arn + - Effect: Allow + Action: + - ec2:CreateVpc + - ec2:ModifyVpcAttribute + - ec2:CreateTags + - ec2:DescribeVpcs + - ec2:CreateInternetGateway + - ec2:AttachInternetGateway + - ec2:DescribeInternetGateways + - ec2:DescribeRouteTables + - ec2:CreateRoute + - ec2:CreateRouteTable + - ec2:AssociateRouteTable + - ec2:CreateSubnet + - ec2:ModifySubnetAttribute + - ec2:DescribeSubnets + - ec2:AllocateAddress + - ec2:CreateNatGateway + - ec2:DescribeNatGateways + Resource: "*" Events: McpAPI: Type: Api