Documentation · Getting started
Quickstart: AWS
This page does one job: get the MCPDBWizard console running in an AWS account and sign you into it. Everything after that — loading a config, generating a server, issuing a token, connecting an agent — is the same wherever the container runs, and it is in the Quickstart.
Use AWS when you want managed capacity: the instance is replaceable, the state survives on EFS, and the template refuses to build network in your account. For a laptop or a server you already administer, Quickstart: Docker is fewer moving parts.
What the stack builds
One EC2 instance running one ECS task, into a VPC and subnets you already have.
- ECS cluster, capacity provider, ASG and launch template — one instance, IMDSv2 only, encrypted gp3 root volume, ECS-optimized AMI resolved from SSM at deploy time.
- An EFS filesystem, a mount target in each subnet, and an access point for
/data. - Two security groups — 8080 from
AllowedCidrto the instance, 2049 from the instance to EFS. - Two IAM roles — the instance role (ECS agent and SSM Session Manager) and a task execution role
scoped to
GetSecretValueon your one secret ARN, nothing wider. - A CloudWatch log group.
It does not create a VPC. A template that builds network in someone else’s account needs a
change-review of its own before anyone may run it, which is exactly the friction it was meant to
remove. You supply VpcId and SubnetIds; the only requirement on them is that they can reach
your Oracle listener.
One instance, one task, and that is not a limitation to fix later. This is a stateful authoring tool, not a horizontally-scalable service: it owns the configs, the accounts, the access matrix and the audit trail, and it launches a child MCP server per running config on loopback inside the container. Two tasks would be two independent products sharing nothing. Scale it by giving the instance more memory, not by adding tasks.
Before you start
- A VPC and at least two subnets in different availability zones — two so the ASG can replace the instance if an AZ fails, and because the template puts an EFS mount target in each.
- An Oracle listener reachable from those subnets. RDS for Oracle, or your own instance. 12c through 26ai are supported.
- The demo user and schema from Quickstart steps 1 and 2, if you are following the demo rather than pointing at your own schema.
- The AWS CLI, with credentials that may create IAM roles.
1. Put the Oracle password in Secrets Manager
It is passed to the container as a secret rather than an environment variable, so it never
appears in docker inspect, the ECS console, the change set or your shell history.
aws secretsmanager create-secret \
--name mcpdbwizard/oracle \
--secret-string 'the-password'
Keep the ARN it prints.
2. Get the template
curl -fsSLO https://mcpdbwizard.com/deploy/ecs-ec2.yaml
It is a single CloudFormation template with no dependencies, and it is worth reading before you run it — every decision in it carries a comment saying why.
3. Deploy
aws cloudformation deploy \
--stack-name mcpdbwizard \
--template-file ecs-ec2.yaml \
--capabilities CAPABILITY_IAM \
--parameter-overrides \
VpcId=vpc-0123456789abcdef0 \
SubnetIds=subnet-aaaa\,subnet-bbbb \
AllowedCidr=10.0.0.0/8 \
OracleHost=db.example.internal \
OracleSid=/FREEPDB1 \
OracleUser=MCPDEMO \
DbPasswordSecretArn=arn:aws:secretsmanager:eu-west-1:111122223333:secret:mcpdbwizard/oracle-AbCdEf
Two things bite here, both in the first minute:
Escape the comma in SubnetIds. --parameter-overrides uses Key=Value shorthand, in which a
bare comma starts the next parameter — so an unescaped list is read as a malformed second override
and the error names the wrong parameter.
OracleSid takes a leading / for the service-name form (/FREEPDB1), a bare name for a SID.
The stack takes a few minutes: the ASG has to bring an instance up, the ECS agent has to register it, and the task then pulls the image.
Which image it pulls
ImageSource chooses the registry, and both choices are the same build — one buildx
invocation, copied between registries without rebuilding, so they serve the identical manifest
digest.
ImageSource | Registry | Who can pull it |
|---|---|---|
Public (default) | GitHub Container Registry | anyone |
Marketplace | AWS Marketplace ECR | an account entitled to the product |
The Marketplace path needs no IAM change: the task execution role already carries
AmazonECSTaskExecutionRolePolicy, and AWS attaches the repository policy that lets an entitled
account pull. An account without an entitlement fails the pull, which is the point.
ImageTag names the version and defaults to the current release. Pin it — :latest moves
under you, and a task that pulls it when the instance is replaced can come back a different build
from the one you tested. ImageUri overrides both, for a private mirror or a build of your own.
4. Reach the console
The stack’s ConsoleHint output tells you where.
aws cloudformation describe-stacks --stack-name mcpdbwizard \
--query 'Stacks[0].Outputs' --output table
Port 8080 is published on the instance and governed by the security group. On a public subnet,
browse to the instance’s address on 8080 from within AllowedCidr.
On a private subnet, forward the port rather than opening one. The instance carries
AmazonSSMManagedInstanceCore and the template creates no inbound SSH rule even if you pass
KeyName:
aws ssm start-session --target i-0123456789abcdef0 \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["8080"],"localPortNumber":["8080"]}'
Then http://localhost:8080. Do not widen AllowedCidr to make this convenient — 8080 is the
admin console as well as the MCP proxy.
5. Sign in
There is no default password, and the stack carries no credential to leak. On first start the
container generates one for this deployment, writes it to /data/initial-admin-password on the EFS
volume, and the sign-in page names that path. So it has to be read off the instance — which is
the whole point of the design.
aws ssm start-session --target i-0123456789abcdef0
then, on the instance:
sudo docker exec "$(sudo docker ps -q --filter name=mcpdbwizard | head -1)" \
cat /data/initial-admin-password
Sign in as admin and choose your own password. You are made to before the console will do
anything else, and the file is deleted when you do.
Seeding happens only when the volume is empty. An existing installation keeps its own accounts, so re-deploying the stack changes nothing — which is the point, but it also means none of this can reset a forgotten password.
Deleting the stack does not delete your data
ConfigFileSystem carries DeletionPolicy: Retain, and it is the single most important line in the
template. Every config, every account, the access matrix and the audit trail live there, and none of
it exists anywhere else: it was authored by hand and is not reproducible.
So delete-stack leaves the filesystem behind, still accruing a small monthly charge. That is the
intended trade — a retained filesystem is a reversible mistake and a deleted one is not. Keep the
ConfigFileSystemId output: it is what you need to mount it again, or to delete it deliberately
once you are certain.
Four things to know before this faces anything real
Memory is load-bearing. TaskMemory is shared by the web app, the forked generator and one MCP
server per running config, each with its own heap. Budget
TaskMemory >= (web heap + ~300m) + servers * (server heap + ~200m); at the defaults 4 GB holds
the web app and about four concurrent servers, and 8 GB on the instance (t3.large) is the
sensible floor. An OOM-killed JVM gets no graceful shutdown, and the kill lands on the largest
process rather than the guilty one.
No load balancer, by default. Port 8080 is the admin console as well as the /mcp/<owner>/<config>
proxy, so the first version restricts it by security group rather than publishing it. For anything
real, put an ALB with an ACM certificate in front and narrow AllowedCidr to the load balancer’s
security group.
No rule for 8090–8109, ever. The generated MCP servers bind loopback inside the container and every agent reaches them through the proxy on 8080, which is the only component that knows which account is calling. Opening those ports would bypass the accounts and the access matrix entirely.
Every deployment is a short outage, by design. There is one instance and the task publishes a
fixed host port, so a second copy could not start alongside the first even if asked for. The old
task stops, then the new one starts. Update by changing ImageTag and deploying again.
Graviton
The image is published for linux/amd64 and linux/arm64, so t4g.large works and is cheaper — but
then EcsAmiSsmParameter must be the arm64 AMI:
/aws/service/ecs/optimized-ami/amazon-linux-2023/arm64/recommended/image_id
Changing the instance type alone gives you an instance that cannot run the AMI it was given.
Next
You have a console. Continue at Quickstart step 4 — load the demo config, generate the server, issue a token and point an agent at it.
Auditing, TLS and origin settings, and the licence-tiered retention are in Setting up auditing and Connecting to the MCP server.