infra-guard
One-line summary: infra-guard is an MCP server that scans Terraform and Dockerfile content with Checkov and returns structured security findings (no guessing, no fixes) for the hosting LLM to explain.
scan_terraform_file(file_content, filename)— audits raw.tfcontent for misconfigurations (open security groups, public S3 buckets, wildcard IAM policies, hardcoded secrets, etc.).scan_dockerfile_file(file_content, filename)— audits raw Dockerfile content (unpinned base images,ADDinstead ofCOPY, exposed port 22, missingHEALTHCHECK, running as root, etc.).Takes file content as a string, not a path — you paste or pass raw code;
filenameis optional and only used as a friendlier output label (defaults:main.tf/Dockerfile).Returns identical structured shapes for both tools — summary counts (passed/failed/total) plus per-finding
check_id,title,resource,severity,start_line/end_line, andcode_snippet.No interpretation layer — it hands structured data straight back so the host assistant (Claude Code, Claude Desktop, Cursor, etc.) can explain or suggest fixes itself.
Severity values are locally approximated from a check-ID map, falling back to
"info"when unmapped.
Enables scanning Dockerfiles for security issues such as unpinned base images, ADD instead of COPY, exposed SSH ports, missing healthchecks, and running as root.
Enables scanning Terraform configuration files for security misconfigurations such as open security groups, public S3 buckets, wildcard IAM policies, and hardcoded secrets.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@infra-guardScan my Terraform for security misconfigurations and explain the findings"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
infra-guard
An MCP server that scans Terraform and Dockerfiles for real security misconfigurations — open security groups, public S3 buckets, wildcard IAM policies, hardcoded secrets, containers running as root — and hands back structured findings instead of a guess.
It plugs into Claude Code, Claude Desktop, or Cursor as a tool. Ask your AI assistant to review your infrastructure code, and it calls infra-guard, gets back real findings from Checkov, and explains them to you.
Try it in the browser: infra-guard-frontend-production.up.railway.app — paste Terraform, click Scan, see real findings. No install required.
MCP endpoint: https://infra-guard-production.up.railway.app/mcp
Why this exists
I did cloud infrastructure work at A.P. Moller–Maersk — Terraform, Docker, AWS provisioning at real scale. Most portfolio projects are generic web apps; this one is the tool I actually wished existed: something that turns "does my Terraform have any obvious security holes" into a real, structured answer instead of an AI assistant's best guess.
infra-guard doesn't guess. It runs your file through Checkov, a real static analysis engine with hundreds of built-in checks, and returns the actual findings — check ID, title, affected resource, line range, code snippet. The hosting LLM (Claude, or whatever's on the other end of the MCP connection) explains the findings in plain English. The tool's job is just to be correct.
Related MCP server: MCP Security Scanner
How it works
scanner.py → core engine: scan_terraform(...) / scan_dockerfile(...) -> structured dict
server.py → wraps both as MCP tools, served over stdio or Streamable HTTP
api.py → wraps both as a plain REST API (POST /api/scan, POST /api/scan-dockerfile),
plus POST /api/explain for optional local AI remediation
frontend/ → React + Vite playground: severity badges, sort/group findings,
click a finding to scroll/highlight its lines in a CodeMirror
editor, "Explain & Fix" for AI-generated remediation, calls api.pyscanner.py shells out to the Checkov CLI, parses its JSON output, and returns the same shape regardless of which framework ran:
{
"summary": { "passed": 14, "failed": 34, "total_checks": 48 },
"findings": [
{
"check_id": "CKV_AWS_24",
"title": "Ensure no security groups allow ingress from 0.0.0.0:0 to port 22",
"resource": "aws_security_group.app_sg",
"severity": "critical",
"start_line": 6,
"end_line": 24,
"code_snippet": "resource \"aws_security_group\" \"app_sg\" { ... }"
}
]
}server.py exposes two MCP tools, scan_terraform_file(file_content, filename) and scan_dockerfile_file(file_content, filename), with no interpretation layer of its own — the structured data goes straight to whatever LLM is hosting the session.
A note on severity: Checkov's open-source CLI always returns severity: null — real per-check severity only exists when a scan is connected to Bridgecrew/Prisma Cloud's paid platform (--bc-api-key), which means an account and sending scan content to that platform. This project doesn't do that, so scanner.py assigns severity locally from a small _SEVERITY_MAP keyed by check ID, falling back to "info" for anything unmapped. It's a deliberate, disclosed approximation, not a Checkov feature.
insecure_example.tf has four intentional Terraform issues (open SSH ingress, a public+unencrypted S3 bucket, a wildcard IAM policy, a hardcoded RDS password) — 14 passed / 34 failed checks. insecure_example.Dockerfile has five (unpinned base image, ADD instead of COPY, port 22 exposed, no HEALTHCHECK, runs as root) — 26 passed / 5 failed checks.
Running it locally
Requires uv.
git clone https://github.com/SanjanaJanardhan/infra-guard.git
cd infra-guard
uv syncRun the scanner directly:
uv run python3 scanner.pyRun the MCP server over stdio (for local clients like Claude Code/Desktop):
uv run python3 server.pyRun it over Streamable HTTP (for remote clients, or to reproduce the deployed setup):
uv run python3 server.py --transport streamable-http --port 8000Connecting it to an MCP client
Claude Code / Claude Desktop — add to .mcp.json (project-level) or your global MCP config:
{
"mcpServers": {
"infra-guard": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/infra-guard", "run", "python3", "server.py"]
}
}
}Any Streamable HTTP client (including the live deployment above) — point it at:
https://infra-guard-production.up.railway.app/mcpRunning the playground locally
# terminal 1 — API
uv run python3 api.py
# terminal 2 — frontend
cd frontend
npm install
npm run devThe frontend reads its API base URL from VITE_API_URL (see frontend/.env.local), defaulting to http://localhost:8001.
Enabling "Explain & Fix" (optional, local-only)
Clicking a finding shows an "Explain & Fix" button that calls Claude (Haiku) to generate a plain-English explanation and a suggested fixed code snippet, grounded in that finding's real check_id/resource/code_snippet.
This deliberately isn't enabled on the public deployment — the playground is public and unauthenticated, so wiring a paid API behind a button there means anyone's clicks spend your API credits. Instead, api.py looks for ANTHROPIC_API_KEY in the environment (via .env, loaded with python-dotenv) and returns {"configured": false} if it's missing, which the frontend renders as a plain "not enabled" message rather than a broken button.
To try it locally:
cp .env.example .env
# edit .env and add your own key from https://console.anthropic.com/
uv run python3 api.py.env is gitignored — never commit a real key, and never set ANTHROPIC_API_KEY on the Railway API service.
Deployment
Three services on Railway, all built from Docker/Nixpacks with no manual server config:
MCP server —
Dockerfile, Streamable HTTPREST API —
Dockerfile.api, samescanner.pycore, powers the playgroundFrontend — Railway's Nixpacks builder auto-detects the Vite app in
frontend/;VITE_API_URLis set at build time to the deployed API's URL
Both Python services read PORT from the environment, so they adapt to whatever port Railway assigns with no config changes.
Stack
Python · Checkov · MCP Python SDK · FastAPI · React · Vite · uv · Docker · Railway
Roadmap
Core Terraform scanning engine
MCP server over stdio
Streamable HTTP transport
Deployed to Railway
Web frontend with a live playground
Dockerfile scanning, including a Terraform/Dockerfile toggle in the playground
AI-generated remediation ("Explain & Fix"), local-only by design
Cost-impact estimate for findings
License
MIT
Available Tools
2 toolsscan_dockerfile_fileA
Scan Dockerfile content for security misconfigurations using Checkov and return structured findings, in the same shape as scan_terraform_file (check ID, title, resource, line range, code snippet). Use this whenever the user asks to review, audit, or check the security of a Dockerfile.
Args: file_content: the raw text of a Dockerfile filename: original filename, used only for a friendlier label in output
| Name | Required | Description | Default |
|---|---|---|---|
| filename | No | Dockerfile | |
| file_content | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Without annotations, the description carries the behavioral disclosure burden. It states it scanning the file and returns structured findings including check ID, title, resource, line range, and code snippet, which clearly implies non-mutating analysis and describes the output shape. It does not discuss error cases or external service dependencies, but the read-only nature is apparent enough.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured: a clear first sentence states the action, a second adds usage and format context, and an argument list adds parameter semantics. There is no filler or redundancy, and all content earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With two parameters, an output schema present, and a clear relationship to the sibling scan_terraform_file, the description is nearly complete. It covers purpose, usage, output format, and argument semantics. It could have noted potential limitations or invalid content behavior, but for this scope the core information for correct invoking is present.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must add meaning. It does so by explaining file_content is 'the raw text of a Dockerfile' and filename is 'used only for a friendlier label in output.' This adds useful semantic context beyond the schema's bare type/default information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('Scan'), the target resource ('Dockerfile content'), and the purpose ('for security misconfigurations'). It distinguishes from the sibling by naming the file type and explicitly noting the return shape is the same as scan_terraform_file, so an agent can tell them apart immediately.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description states 'Use this whenever the user asks to review, audit, or check the security of a Dockerfile.' This is explicit usage guidance. It doesn't explicitly say 'use scan_terraform_file for Terraform files,' though that is strongly implied by the sibling name and the shape reference, so it lacks an explicit when-not/exclusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_terraform_fileA
Scan Terraform (.tf) file content for security misconfigurations using Checkov and return structured findings.
Each finding includes the Checkov check ID, a human-readable title, the affected resource, its line range in the file, and the offending code snippet. Use this whenever the user asks to review, audit, or check the security of Terraform code.
Args: file_content: the raw text of a .tf file filename: original filename, used only for a friendlier label in output
| Name | Required | Description | Default |
|---|---|---|---|
| filename | No | main.tf | |
| file_content | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure, and it does well by outlining what the tool returns (Checkov check ID, title, resource, line range, code snippet). It does not mention limitations such as invalid Terraform or external dependencies, but it clearly communicates the main behavior and output shape.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and well-structured: a one-sentence definition, a use indicator, and an argument list that adds value beyond the schema. There is no redundant or filler content.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the small parameter count, output schema availability, and sibling context, the description covers the essential inputs and expected outputs. It could be slightly more explicit about behavior on invalid/nonexistent Terraform content, but for the average call it is complete enough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Input schema coverage is 0%, but the description fully compensates by documenting both arguments: file_content as the raw .tf text and filename as only a friendlier output label. This gives an agent everything needed to construct correct parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('scan') and resource type (Terraform .tf files) and states the goal ('security misconfigurations') and engine (Checkov). It is easily distinguished from sibling scan_dockerfile_file by mentioning Terraform explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says to use it whenever the user asks to review, audit, or check Terraform code. It does not explicitly mention excluding other file types or name the Dockerfile sibling as an alternative, so it slightly misses the top guidance bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v0.1.0- First observed
scan_dockerfile_file - First observed
scan_terraform_file
TDQS
Scored across 2 tools
The two tools are cleanly separated by file type: one handles Terraform files and the other handles Dockerfiles. There is no functional overlap or realistic risk of selecting the wrong tool.
Both tools follow the same scan_<format>_file pattern, and the descriptions mirror each other for symmetry. Naming is predictable and internally consistent.
Two tools is a thin set: they cover exactly Terraform and Dockerfile scanning, but the server named infra-guard feels narrow. The count is coherent but borderline for the apparent purpose.
For the supported file types, the scanning workflow is functional, but common IaC targets such as Kubernetes manifests or CloudFormation templates are absent. There is also no batch or exception-handling capability, leaving notable coverage gaps.
Maintenance
Related MCP Connectors
Zero-config MCP security scanner for AI-generated apps. 25K+ vulnerability patterns.
- mcpOAuthcom.vibgrate
Query your team's drift, vulnerability, and upgrade data from any AI assistant. OAuth 2.1, 51 tools.
CVE lookups (NVD) and dependency-manifest audits (OSV) for AI agents. No API keys.
CVE lookups (NVD) and dependency-manifest audits (OSV) for AI agents. No API keys.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to scan project dependencies and Infrastructure as Code files for security vulnerabilities and misconfigurations. It also provides automated fixing capabilities to remediate identified security issues.183MIT

MCP Security Scannerofficial
AlicenseAqualityDmaintenanceIntegrates Checkov, Semgrep, Bandit, and ASH to provide comprehensive code security analysis for AI coding assistants.1516MIT No Attribution
shieldly-mcpofficial
AlicenseAqualityCmaintenanceEnables AI assistants to analyze AWS IAM policies and CloudFormation templates for security risks.252MIT- AlicenseNot gradedqualityAmaintenanceEnables AI agents to scan code for security and quality issues and receive machine-readable reports with suggested fixes and verification criteria.722MIT