DEV Community

Cover image for Building Secure Private MCP Connection with Amazon Quick

Building Secure Private MCP Connection with Amazon Quick

Scenario

Amazon Quick is an enterprise AI assistant platform that lets users search across company data, build custom AI agents, automate repetitive workflows, and generate deep research. Quick built-in MCP server connector feature helps Quick to access other resources that are currently not available as built-in connectors. However, the sensitive data of the organizations cannot be transferred from public MCP server endpoint to Amazon Quick in a public connection.

Taking the incident response as a use case, this blog guides how to setup a private Jaeger MCP server that Amazon Quick reaches directly inside a VPC through an Amazon Quick VPC connection. You may not care about the MCP server app, and focus on how to setup Quick to connect a private MCP server.

Prerequisites

  • Amazon Quick Enterprise subscription in the target account/region (in this blog is us-east-1).
  • A domain you control on a public DNS provider (here: pngha.io.vn on tenten.vn but you can buy Route 53 Domain).
  • 1 VPC that has 1 private subnet to host EC2 instance MCP server, 1 public subnet to host 1 Nat Gateway to install dependencies for MCP server
  • A bastion host in the public subnet that can connect to the EC2 instances in the private subnets (Just for demo. This is not recommended in best practices, you should use Instance Connect Endpoint or SSM port forwarding or other secure private EC2 connection methods).
  • 1 IAM user with sufficient privileges. For more information, please refer to https://docs.aws.amazon.com/quick/latest/userguide/permissions.html. In this case, I use an IAM AdminFullAccess user which is not recommended for best practices in security.

Architecture

Foundation (set up once, before any request)

A. Certificate trust (so TLS works on a private name)

  • tenten.vn is the third-party public DNS authoritative for pngha.io.vn. It holds a single DNS-validation CNAME that proves domain ownership to AWS Certificate Manager (ACM).
  • ACM issues a publicly-trusted certificate for mcp.apppayvn.pngha.io.vn and auto-renews it as long as that CNAME stays in place.
  • ACM installs this cert on the internal ALB, so the ALB can complete a valid TLS handshake even though the hostname itself is never published publicly.

B. Split-horizon DNS (so the name resolves only inside the VPC)

  • A Route 53 private hosted zone holds an A/alias record: mcp.apppayvn.pngha.io.vn → internal ALB. This record is only visible inside the VPC.

  • Because Amazon Quick does not use the default VPC resolver, two Route 53 Resolver inbound endpoints (172.31.107.179, 172.31.122.147) are created so an external caller (Quick) can resolve the private name from inside the VPC.

Runtime request flow

1a. Quick calls the MCP server. The user asks Amazon Quick a question (e.g., "I got a 500"). Quick initiates an MCP call to https://mcp.apppayvn.pngha.io.vn/mcp over its Quick VPC connection (its ENIs placed in the private subnets). The connection type in Quick is the named VPC connection private-mcp-vpc.

  1. (service mode only) — Get an OAuth token: If AUTH_MODE=service, Quick first calls the Cognito User Pool token endpoint (client_credentials grant) and receives a Bearer JWT, which it attaches to the MCP request. In the default AUTH_MODE=none, this step is skipped (No authentication). Note the Cognito token endpoint is public, which satisfies Quick's requirement that OAuth endpoints stay publicly reachable.

  2. Resolve the private hostname: The Quick ENIs query the Route 53 Resolver inbound endpoints to resolve mcp.apppayvn.pngha.io.vn. The resolver looks up the private hosted zone, follows the alias record, and returns the internal ALB's private IPs.

  3. TLS to the ALB: The Quick ENIs open an HTTPS connection on :443 to the internal ALB. TLS terminates at the ALB using the public ACM certificate, whose name matches the hostname, so the handshake succeeds.

  4. ALB forwards to the MCP server. The ALB forwards the request as plain HTTP on :8000 to the MCP server EC2 (in the private compute subnet). If AUTH_MODE=service, the MCP server validates the JWT here (RS256 signature via the Cognito JWKS, plus client_id and scope checks) and rejects anything invalid with 401/403.

  5. Query Jaeger. The MCP server runs the requested tool (one of 11), querying the Jaeger backend for traces, then returns a structured result back up the same path (ALB → Quick ENIs → Quick → user) as a root-cause answer.

Implementation

Shared variables used throughout:

VPC=vpc-00a0bb566f620d017            # default VPC, 172.31.0.0/16
SUBNET_A=subnet-0c4dc17fc2ba6d7a0    # private us-east-1a (172.31.96.0/20)
SUBNET_B=subnet-05b7cb71fd61f42a9    # private us-east-1b (172.31.112.0/20)
PUB_SUBNET=subnet-03338c6339631cd1f  # public us-east-1a (NAT + bastion)
HOSTNAME=mcp.apppayvn.pngha.io.vn
Enter fullscreen mode Exit fullscreen mode

Step 1 — NAT gateway (private-subnet outbound for setup)

The MCP box lives in a private subnet but needs outbound internet to install Docker, Python packages, and to pull the Jaeger image during setup.

EIP=$(aws ec2 allocate-address --domain vpc --query AllocationId --output text)
NAT=$(aws ec2 create-nat-gateway --subnet-id $PUB_SUBNET --allocation-id $EIP \
        --query NatGateway.NatGatewayId --output text)
aws ec2 wait nat-gateway-available --nat-gateway-ids $NAT
echo $NAT
# nat-0a1b2c3d4e5f6a7b8

# point the private route table's default route at the NAT
aws ec2 create-route --route-table-id rtb-0607dbb757c4ecb17 \
  --destination-cidr-block 0.0.0.0/0 --nat-gateway-id $NAT
# { "Return": true }
Enter fullscreen mode Exit fullscreen mode

Step 2 — Security groups

# Bastion SG (SSH from the internet)
BASTION_SG=$(aws ec2 create-security-group --group-name jaeger-mcp-prod-bastion-sg \
  --description "Bastion SSH" --vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $BASTION_SG \
  --protocol tcp --port 22 --cidr 0.0.0.0/0 >/dev/null

# ALB SG (HTTPS 443 from within the VPC)
ALB_SG=$(aws ec2 create-security-group --group-name jaeger-mcp-prod-alb-sg \
  --description "Internal ALB" --vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $ALB_SG \
  --protocol tcp --port 443 --cidr 172.31.0.0/16 >/dev/null

# MCP SG (8000 only from the ALB SG; SSH only from the bastion SG)
MCP_SG=$(aws ec2 create-security-group --group-name jaeger-mcp-prod-sg \
  --description "Private MCP server" --vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $MCP_SG \
  --protocol tcp --port 8000 --source-group $ALB_SG >/dev/null
aws ec2 authorize-security-group-ingress --group-id $MCP_SG \
  --protocol tcp --port 22 --source-group $BASTION_SG >/dev/null

echo "$ALB_SG  $MCP_SG  $BASTION_SG"
# sg-068049618d442344e  sg-0a...  sg-0b...
Enter fullscreen mode Exit fullscreen mode

Step 3 — MCP server EC2 (Jaeger + Python MCP)

Launch an Arm instance in the private subnet. The user-data installs Docker, runs Jaeger all-in-one, and starts the Python MCP server (11 tools) on :8000 as a systemd service. A small bastion in the public subnet gives SSH access.

MCP_ID=$(aws ec2 run-instances --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64 \
  --instance-type t4g.medium --subnet-id $SUBNET_A \
  --security-group-ids $MCP_SG --key-name jaeger-mcp-prod-key \
  --block-device-mappings 'DeviceName=/dev/xvda,Ebs={VolumeSize=30,VolumeType=gp3}' \
  --user-data file://mcp-userdata.sh \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=jaeger-mcp-prod-server}]' \
  --query 'Instances[0].InstanceId' --output text)

BASTION_ID=$(aws ec2 run-instances --image-id resolve:ssm:/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-arm64 \
  --instance-type t4g.nano --subnet-id $PUB_SUBNET --associate-public-ip-address \
  --security-group-ids $BASTION_SG --key-name jaeger-mcp-prod-key \
  --tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=jaeger-mcp-prod-bastion}]' \
  --query 'Instances[0].InstanceId' --output text)

aws ec2 wait instance-running --instance-ids $MCP_ID $BASTION_ID
aws ec2 describe-instances --instance-ids $MCP_ID \
  --query 'Reservations[0].Instances[0].{Id:InstanceId,Priv:PrivateIpAddress,State:State.Name}'
Enter fullscreen mode Exit fullscreen mode
{ "Id": "i-0a29191ca10faba0b", "Priv": "172.31.99.24", "State": "running" }
Enter fullscreen mode Exit fullscreen mode

The Jaeger + MCP server portion of mcp-userdata.sh (abbreviated):

#!/bin/bash
dnf install -y docker python3.11 git
systemctl enable --now docker
docker run -d --name jaeger --restart=always \
  -p 16686:16686 -p 4317:4317 -p 4318:4318 -p 9411:9411 \
  jaegertracing/all-in-one:latest

# MCP server (FastAPI/uvicorn) serving 11 Jaeger tools on :8000
cd /home/ec2-user && git clone <repo> mcp-server && cd mcp-server
python3.11 -m venv venv && ./venv/bin/pip install -r requirements.txt
cat >/etc/systemd/system/jaeger-mcp.service <<'UNIT'
[Unit]
Description=Jaeger MCP Server
After=network.target docker.service
[Service]
ExecStart=/home/ec2-user/mcp-server/venv/bin/python main.py
WorkingDirectory=/home/ec2-user/mcp-server
User=ec2-user
Restart=always
[Install]
WantedBy=multi-user.target
UNIT
systemctl daemon-reload && systemctl enable --now jaeger-mcp
Enter fullscreen mode Exit fullscreen mode

Confirm the service is up (via the bastion as an SSH jump host):

ssh -J ec2-user@<bastion-public-ip> ec2-user@172.31.99.24 \
  'systemctl is-active jaeger-mcp; curl -s http://localhost:8000/health'
Enter fullscreen mode Exit fullscreen mode
active
{"status":"ok","server":"jaeger-mcp","version":"1.0.0"}
Enter fullscreen mode Exit fullscreen mode

Step 4 — Public ACM certificate (DNS validation on tenten.vn)

The ALB needs a publicly trusted TLS cert whose name matches the hostname. Request it from ACM with DNS validation.

CERT_ARN=$(aws acm request-certificate --domain-name $HOSTNAME \
  --validation-method DNS --query CertificateArn --output text)
echo $CERT_ARN
# arn:aws:acm:us-east-1:**********:certificate/***-df3e-491a-b9f7-****

# read the CNAME you must add at the DNS provider
aws acm describe-certificate --certificate-arn $CERT_ARN \
  --query 'Certificate.DomainValidationOptions[0].ResourceRecord'
Enter fullscreen mode Exit fullscreen mode
{
    "Name": "_a1b2c3....mcp.apppayvn.pngha.io.vn.",
    "Type": "CNAME",
    "Value": "_x9y8z7....acm-validations.aws."
}
Enter fullscreen mode Exit fullscreen mode

Add that CNAME record in the tenten.vn control panel. ACM polls public DNS and flips to ISSUED (a few minutes after the record propagates). Because the CNAME is permanent, ACM auto-renews forever with no further action.

aws acm wait certificate-validated --certificate-arn $CERT_ARN
aws acm describe-certificate --certificate-arn $CERT_ARN \
  --query 'Certificate.{Status:Status,Domain:DomainName}'
Enter fullscreen mode Exit fullscreen mode
{ "Status": "ISSUED", "Domain": "mcp.apppayvn.pngha.io.vn" }
Enter fullscreen mode Exit fullscreen mode

Step 5 — Internal ALB + target group + HTTPS listener

ALB_ARN=$(aws elbv2 create-load-balancer --name jaeger-mcp-prod-alb \
  --scheme internal --type application \
  --subnets $SUBNET_A $SUBNET_B --security-groups $ALB_SG \
  --query 'LoadBalancers[0].LoadBalancerArn' --output text)

TG_ARN=$(aws elbv2 create-target-group --name jaeger-mcp-prod-tg \
  --protocol HTTP --port 8000 --target-type ip --vpc-id $VPC \
  --health-check-path /health --matcher HttpCode=200 \
  --query 'TargetGroups[0].TargetGroupArn' --output text)

# register the MCP server's private IP
aws elbv2 register-targets --target-group-arn $TG_ARN \
  --targets Id=172.31.99.24,Port=8000

# HTTPS:443 listener using the ACM cert → forwards to the MCP target group
aws elbv2 create-listener --load-balancer-arn $ALB_ARN \
  --protocol HTTPS --port 443 \
  --ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06 \
  --certificates CertificateArn=$CERT_ARN \
  --default-actions Type=forward,TargetGroupArn=$TG_ARN >/dev/null

aws elbv2 describe-load-balancers --load-balancer-arns $ALB_ARN \
  --query 'LoadBalancers[0].DNSName' --output text
Enter fullscreen mode Exit fullscreen mode
internal-jaeger-mcp-prod-alb-***.us-east-1.elb.amazonaws.com
Enter fullscreen mode Exit fullscreen mode

Wait until the target is healthy:

aws elbv2 describe-target-health --target-group-arn $TG_ARN \
  --query 'TargetHealthDescriptions[].TargetHealth.State'
Enter fullscreen mode Exit fullscreen mode
[ "healthy" ]
Enter fullscreen mode Exit fullscreen mode

Step 6 — Route 53 private hosted zone + alias record

Create (or reuse) a private hosted zone associated with the VPC, and point the hostname at the ALB. This is what makes mcp.apppayvn.pngha.io.vn resolve inside the VPC only.

ZONE_ID=$(aws route53 create-hosted-zone --name apppayvn.pngha.io.vn \
  --vpc VPCRegion=us-east-1,VPCId=$VPC \
  --hosted-zone-config PrivateZone=true \
  --caller-reference $(date +%s) --query 'HostedZone.Id' --output text)
echo $ZONE_ID   # /hostedzone/Z042766428HJLUMHK1M5M

cat > r53.json <<JSON
{ "Changes": [{ "Action": "UPSERT", "ResourceRecordSet": {
  "Name": "mcp.apppayvn.pngha.io.vn", "Type": "A",
  "AliasTarget": { "HostedZoneId": "Z35SXDOTRQ7X7K",
    "DNSName": "internal-jaeger-mcp-prod-alb-****.us-east-1.elb.amazonaws.com",
    "EvaluateTargetHealth": false } } }] }
JSON
aws route53 change-resource-record-sets --hosted-zone-id $ZONE_ID --change-batch file://r53.json \
  --query 'ChangeInfo.Status'
Enter fullscreen mode Exit fullscreen mode
"PENDING"
Enter fullscreen mode Exit fullscreen mode

Z35SXDOTRQ7X7K is the ALB's canonical hosted-zone ID for ALBs in us-east-1.

Step 7 — Route 53 Resolver inbound endpoint

Amazon Quick does not use the default VPC DNS resolver for MCP integrations, so it needs explicit resolver IPs that can answer the private hostname. Create an inbound resolver endpoint in the VPC; its ENIs get private IPs that Quick will query.

RESOLVER_SG=$(aws ec2 create-security-group --group-name private-mcp-resolver-inbound \
  --description "DNS inbound for Quick MCP resolver" --vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-ingress --group-id $RESOLVER_SG --protocol tcp --port 53 --cidr 172.31.0.0/16 >/dev/null
aws ec2 authorize-security-group-ingress --group-id $RESOLVER_SG --protocol udp --port 53 --cidr 172.31.0.0/16 >/dev/null

RESOLVER=$(aws route53resolver create-resolver-endpoint \
  --name private-mcp-resolver-inbound --direction INBOUND \
  --security-group-ids $RESOLVER_SG \
  --ip-addresses SubnetId=$SUBNET_A SubnetId=$SUBNET_B \
  --query 'ResolverEndpoint.Id' --output text)

aws route53resolver list-resolver-endpoint-ip-addresses --resolver-endpoint-id $RESOLVER \
  --query 'IpAddresses[].Ip'
Enter fullscreen mode Exit fullscreen mode
[ "172.31.107.179", "172.31.122.147" ]
Enter fullscreen mode Exit fullscreen mode

Keep these two IPs — they go into the Quick VPC connection next.

Step 8 — Amazon Quick VPC connection

This is the piece that lets Quick send traffic into your private subnets. It creates ENIs in the subnets you choose, using a security group you control, and you populate the DNS resolver endpoints with the two inbound-resolver IPs from Step 7.

# SG for the Quick connection ENIs: egress 443 to the ALB SG, DNS 53 to the resolver SG
QUICK_SG=$(aws ec2 create-security-group --group-name private-mcp-quick-eni \
  --description "Quick VPC connection ENIs" --vpc-id $VPC --query GroupId --output text)
aws ec2 authorize-security-group-egress --group-id $QUICK_SG \
  --ip-permissions IpProtocol=tcp,FromPort=443,ToPort=443,UserIdGroupPairs="[{GroupId=$ALB_SG,Description=HTTPS to ALB}]" >/dev/null
aws ec2 authorize-security-group-egress --group-id $QUICK_SG \
  --ip-permissions IpProtocol=tcp,FromPort=53,ToPort=53,UserIdGroupPairs="[{GroupId=$RESOLVER_SG}]" \
                   IpProtocol=udp,FromPort=53,ToPort=53,UserIdGroupPairs="[{GroupId=$RESOLVER_SG}]" >/dev/null
# allow the ALB SG to accept 443 from the Quick ENI SG (in addition to the VPC CIDR rule)
aws ec2 authorize-security-group-ingress --group-id $ALB_SG \
  --ip-permissions IpProtocol=tcp,FromPort=443,ToPort=443,UserIdGroupPairs="[{GroupId=$QUICK_SG,Description=HTTPS from Quick}]" >/dev/null

# IAM role Quick assumes to manage the ENIs (trust = quicksight.amazonaws.com)
# (role private-mcp-quick-vpc-connection created with the AWS-documented policy)

aws quicksight create-vpc-connection \
  --aws-account-id **********\
  --vpc-connection-id private-mcp-vpc \
  --name "Private MCP VPC" \
  --subnet-ids $SUBNET_A $SUBNET_B \
  --security-group-ids $QUICK_SG \
  --dns-resolvers 172.31.107.179 172.31.122.147 \
  --role-arn arn:aws:iam::**********:role/private-mcp-quick-vpc-connection \
  --query 'Status'
Enter fullscreen mode Exit fullscreen mode
"CREATION_IN_PROGRESS"
Enter fullscreen mode Exit fullscreen mode

Wait until it is AVAILABLE:

aws quicksight describe-vpc-connection --aws-account-id ********** \
  --vpc-connection-id private-mcp-vpc \
  --query 'VPCConnection.{Status:Status,Avail:AvailabilityStatus,DnsResolvers:DnsResolvers}'
Enter fullscreen mode Exit fullscreen mode
{
    "Status": "UPDATE_SUCCESSFUL",
    "Avail": "AVAILABLE",
    "DnsResolvers": [ "172.31.107.179", "172.31.122.147" ]
}
Enter fullscreen mode Exit fullscreen mode

Step 9 — End-to-end verification (from inside the VPC)

The bastion is in the same VPC, so it resolves and reaches the endpoint exactly like the Quick VPC connection will.

ssh -J ec2-user@<bastion-public-ip> ec2-user@172.31.99.24 \
  'getent hosts mcp.apppayvn.pngha.io.vn; curl -s -k https://mcp.apppayvn.pngha.io.vn/health'
Enter fullscreen mode Exit fullscreen mode
172.31.110.61   mcp.apppayvn.pngha.io.vn
172.31.123.248  mcp.apppayvn.pngha.io.vn
{"status":"ok","server":"jaeger-mcp","version":"1.0.0"}
Enter fullscreen mode Exit fullscreen mode

List the tools over the full HTTPS path:

curl -s -k https://mcp.apppayvn.pngha.io.vn/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' | python3 -m json.tool
Enter fullscreen mode Exit fullscreen mode
{
  "jsonrpc": "2.0", "id": 1,
  "result": { "tools": [
    {"name": "get-services", ...},
    {"name": "get-operations", ...},
    {"name": "get-trace", ...},
    {"name": "find-traces", ...},
    {"name": "get-dependencies", ...},
    {"name": "analyze-trace", ...},
    {"name": "find-error-traces", ...},
    {"name": "compare-traces", ...},
    {"name": "get-service-latency-stats", ...},
    {"name": "get-system-health", ...},
    {"name": "investigate-user-issue", ...}
  ] }
}
Enter fullscreen mode Exit fullscreen mode

11 tools resolved over TLS → the private path works.

Step 10 — Create the MCP integration in Amazon Quick

In the Amazon Quick console:

  1. Connectors → Create for your team → Model Context Protocol (MCP).
  2. Fill the integration:
    • MCP server endpoint: https://mcp.apppayvn.pngha.io.vn/mcp
    • Connection type: A named VPC connectionprivate-mcp-vpc
    • Authentication: No authentication
  3. Create and continue. Quick connects through the VPC connection, discovers the 11 tools, and registers each as an action.

You can now ask the assistant things like "I got a 500 error on checkout" and it will call investigate-user-issue against Jaeger and return a root-cause report.

Demo: https://1drv.ms/v/c/bc7d1506056ce750/IQAsopJEP1czR7aOCHBXftOwARLyUG4yS8WBQf0yIGtilts?e=Iz4om3

Troubleshooting

  • "hostname cannot be resolved" when creating the integration — the VPC connection's DNS resolver endpoints field must hold the Route 53 Resolver inbound IPs (Step 7). Quick does not use the default VPC resolver.
  • Connector passes discovery but fails at publish — a tool inputSchema is using JSON Schema Draft 3 ("required": true inside a property). Quick requires Draft 7: required must be a root-level array. Fix the tool schema and recreate the connector.
  • TLS errors — the ALB cert's domain must match the hostname in the endpoint URL (mcp.apppayvn.pngha.io.vn). ACM handles this once validated.
  • Target unhealthy — check the MCP SG allows :8000 from the ALB SG and that jaeger-mcp is active on the instance.

Next steps — hardening the network (reference, not applied here)

Once the path works, you can lock it down so only the Quick VPC connection reaches the MCP, and the Quick ENIs reach nothing else. With an ALB in the middle, the trust boundary is enforced by chained security-group references (Quick ENI → ALB → MCP).

SG Inbound Outbound
Quick ENI SG none needed (stateful) only 443 → ALB SG, 53 → Resolver SG
ALB SG only 443 from Quick ENI SG (remove the VPC-CIDR rule) 8000 → MCP SG
MCP SG only 8000 from ALB SG (+ 22 from bastion if kept) minimal
Resolver inbound SG only 53 from Quick ENI SG
  • The MCP is a server; it never initiates to Quick. Jaeger is local, so the box needs no runtime egress — drop the 0.0.0.0/0 egress after setup.
  • Manage via SSM Session Manager (VPC endpoints) instead of a bastion → no inbound SSH and no internet path for the MCP box.
  • Optional: private subnet with no NAT, plus subnet Network ACLs as a second layer.
  • Note: this is security-group / NACL work, not IAM — the VPC-connection IAM role only lets Quick manage its ENIs, it does not gate runtime traffic.

Cleanup

aws quicksight delete-vpc-connection --aws-account-id ********** --vpc-connection-id private-mcp-vpc
aws route53resolver delete-resolver-endpoint --resolver-endpoint-id $RESOLVER
aws elbv2 delete-load-balancer --load-balancer-arn $ALB_ARN
aws elbv2 delete-target-group --target-group-arn $TG_ARN
aws ec2 terminate-instances --instance-ids $MCP_ID $BASTION_ID
aws ec2 delete-nat-gateway --nat-gateway-id $NAT
# then release the EIP, delete SGs, the private hosted zone, and the ACM cert
Enter fullscreen mode Exit fullscreen mode

Why this design (vs AgentCore Gateway + managed VPC Lattice)

A private MCP target on AgentCore Gateway also works, but:

  • AgentCore Gateway ingress endpoint is public, so it needs PrivateLink added to achieve the same.
  • It adds another managed hop (Gateway → VPC Lattice resource gateway → ALB → EC2) and Lattice data-processing charges.

The native Quick VPC connection is the documented, first-class path for a single private MCP server connection to Quick: fewer moving parts, optional No-auth, and standard VPC networking the team already understands.

Top comments (0)