Introduction
Have you ever woken up after 10 years working on AWS to realise you have never built anything in CloudFormation? Well, that is exactly what happened to me. So I did.
Building it was the fun part. The part that made me nervous was the question that comes right after: how do I know it is any good? I did not want to rely on “it deployed, so it must be fine”, and I did not have a decade of CloudFormation scar tissue to lean on either. That is where the AWS IaC MCP server came in.
If you have not met MCP yet, it stands for Model Context Protocol. In plain terms, it lets an AI assistant call real tools instead of guessing. This particular server gives Claude Code access to cfn-lint and cfn-guard, so a template gets checked by the same linters you would run in CI, without leaving your editor.
This post covers how I set it up and what its checks cover.
What the server provides
The awslabs.aws-iac-mcp-server package exposes tools including:
validate_cloudformation_template– runs cfn-lint (syntax, schema, resource properties)check_cloudformation_template_compliance– runs cfn-guard against a bundled security rulesetsearch_cloudformation_documentation– searches the official CloudFormation docssearch_cdk_documentation– searches the CDK API reference, best practices guide and CDK Nag rulessearch_cdk_samples_and_constructs– finds code samples, patterns and community constructs, filterable by languagecdk_best_practices– returns CDK best practices and security guidelines
It is not just for CloudFormation. The server also covers CDK, with tools for documentation, sample code and best practices. The checking tools only read CloudFormation templates, so with CDK you would run cdk synth first and check the output.
It runs locally over stdio. Claude Code launches it as a child process and talks to it over standard input and output.
Setup
The official documentation for this server lives on the AWS Labs MCP site: AWS IaC MCP Server.
You need uv installed so that uvx is available. For a personal project, the quickest route is one command, run from your project folder:
claude mcp add aws-iac-mcp-server -e FASTMCP_LOG_LEVEL=ERROR -- uvx awslabs.aws-iac-mcp-server@latest
The .mcp.json alternative
You can write the same thing as a file called .mcp.json in your project root:
{
"mcpServers": {
"aws-iac-mcp-server": {
"type": "stdio",
"command": "uvx",
"args": ["awslabs.aws-iac-mcp-server@latest"],
"env": {
"FASTMCP_LOG_LEVEL": "ERROR"
}
}
}
}
The upside is that the config lives in your repo, so it is easy to read and reproduce. The downside is that it is committed with your code, so only put things in it that you are happy for anyone with the repo to see. Never put keys or secrets in it.
Prefer Docker?
You can run this server in Docker instead of uvx. You build the image locally and point your MCP config at docker run, rather than at uvx. The server’s docs walk through the exact steps.
Checking it connected
Run /mcp in Claude Code to see the status of each configured server. A connected server lists its tools, which you can then ask Claude to use by name or by describing the task, for example “validate template.yml and summarise the warnings”.
Using the tools well
cfn-lint
Syntax and schema validation. It returns an error, warning and info count plus line numbers. Errors block deployment. Warnings are worth reading but are often informational.
cfn-guard
Security rules. It returns a list of violations with remediation hints. Three things to keep in mind:
- Not every rule fits your workload. Rules such as Object Lock or replication suit compliance-heavy systems, and are overkill for a small project.
- Output can be coarse. Some results identify the resource only as “Unknown”, so you may need to work out which resource a rule applied to.
- Expect some noise. If you have used tfsec, you know the feeling: static analysis tools flag things that are technically correct but irrelevant to your workload, and sometimes things that are not correct at all. Treat a finding as a prompt to check, not a verdict.
What the bundled cfn-guard rules cover
| Area | Examples of what it checks |
|---|---|
| S3 | Public read and write access, public ACLs, wildcard principals and actions in bucket policies, SSL-only requests, default encryption, versioning, logging, Object Lock, replication |
| Security groups | Ingress open to the world, SSH open to the world, all-protocol rules, wide CIDR ranges, missing descriptions |
| Networking | Unrestricted routes to an internet gateway, subnets that auto-assign public IPs, network ACL port and protocol rules |
| IAM | Wildcard actions or resources, admin or full-access policies, inline policies, PassRole with wildcards, policies attached directly to users, plaintext passwords |
| EC2 | Public IPs, instance profile attached, EBS encryption, detailed monitoring |
| RDS | Storage encryption, public access, Multi-AZ, deletion protection, backups, logging, plaintext credentials |
Rules only fire on resource types that exist in your template.
Pre-deployment validation
The server also returns instructions for CloudFormation change set validation, which catches issues such as name conflicts and non-empty bucket deletions before provisioning starts. Run it before a real deploy.
Wrapping up
Ten years in, I finally have a CloudFormation template I wrote myself, and a quick, repeatable way to sanity check it before it goes anywhere near a deploy. You might be asking, would I write CloudFormation again? Probably not. I will most likely stick with Terraform going forward.
Getting started is a single command, and /mcp tells you whether it worked. After that it is a case of asking Claude to run the checks and reading the results with a bit of healthy scepticism. cfn-lint tells you the template is valid, cfn-guard tells you how it stacks up against a set of security rules, and you decide what to fix and what to leave alone.
Written by a human, made legible with AI.

