tfplan-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| --dir | No | Sandbox directory; only files under this directory can be read. Defaults to the working directory. | |
| --max-mb | No | Maximum accepted plan file size in MB. Defaults to 256. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
Review a Terraform/OpenTofu plan without running terraform. The input is the JSON from terraform show -json tfplan > plan.json (pass its path as path). Start with plan_summary, then risky_changes for a ranked list of dangerous changes (destroyed databases/buckets/keys, forced replacements, IAM broadening, 0.0.0.0/0 on admin ports, public access, encryption or deletion-protection downgrades). Drill into one resource with diff_resource or explain_replace, browse with list_changes, compare two plans with compare_plans, and see output changes and drift with outputs_and_drift. Sensitive values are always shown as (sensitive). Everything is read-only; the server never contacts a cloud or provider.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| plan_summaryA | Overview of a plan: counts of create/update/delete/replace/read/forget/no-op by resource type and module, whether it is an empty or destroy plan, moved/imported resources, drift, output changes, failing checks, terraform version and warnings (errored, incomplete, deferred changes). Call this first. path: plan JSON from |
| risky_changesA | Ranked list of risky changes with reasons. Flags: destroy/replace of stateful resources (databases, buckets, disks, KMS keys, DNS zones, secrets; aws/azurerm/google/kubernetes plus generic name heuristics), which attribute forces a replacement, IAM wildcards and admin policies, security groups / firewalls opening 0.0.0.0/0 or ::/0 (admin and database ports rated highest), public access enabled, encryption disabled or key changed, deletion protection off, backup retention reduced. Tags-only updates are listed as low. min_severity: info | low | medium | high | critical. Only the findings are listed; resources not mentioned had nothing notable. Values of attributes are never printed here. |
| diff_resourceA | Attribute-level diff (before -> after) for one resource, with nested paths such as ingress[0].cidr_blocks[0]. Unknown values show as (known after apply). Sensitive values are ALWAYS shown as (sensitive): by Terraform's sensitivity masks and, as a second layer, by attribute names that look like credentials (password, secret, token, key...). address: exact address as in the plan, e.g. aws_instance.web["a b"] or module.net.aws_vpc.main[0]. Use list_changes to find addresses; unknown addresses return close matches. |
| list_changesB | List resource changes, filtered and capped. action: create | update | delete | replace | read | forget | no-op | import | move | other (default: everything except plain no-ops). type: glob such as aws_s3_*. module: 'root' or a module address prefix such as module.network (includes nested modules). address: glob where only * and ? are wild (brackets in addresses are literal). |
| explain_replaceB | Explain why a resource is being replaced: the action_reason, the forcing attribute(s) from replace_paths with their before -> after values, the order (destroy-then-create vs create_before_destroy), what that means (downtime, name collisions), the lifecycle hint from the plan's configuration when present, and the dependents that reference it. |
| compare_plansB | Compare two plans of the same configuration (for example before and after a code change, or two environments): resource changes new in B, gone in B, with a different action, or the same action but different planned values (shown as masked attribute diffs). |
| outputs_and_driftB | Output changes and resource_drift: what changed OUTSIDE Terraform (console edits, other tools) since the last apply, with masked attribute diffs. Sensitive outputs are masked. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 7 tools
Each tool targets a distinct facet of plan analysis: overview, risk ranking, single-resource diff, filtered listing, replacement explanation, plan-to-plan comparison, and outputs/drift. The main potential confusion is between list_changes, compare_plans, and plan_summary, since all surface resource changes, but the descriptions draw clear boundaries (filter/cap vs two-plan comparison vs counts).
Most names are verb_noun (diff_resource, list_changes, explain_replace, compare_plans), but plan_summary, risky_changes, and outputs_and_drift are noun-first, mixing conventions. Names remain readable and descriptive despite the inconsistency.
Seven tools is well-scoped for a Terraform plan analysis server, with each tool covering a clearly separate analytical need. Nothing feels redundant or missing at the count level.
The surface covers the plan lifecycle well: summary, change listing, attribute diffs, replacement reasoning, risk assessment, plan comparison, and outputs/drift. Minor gaps exist, such as no way to dump a full resource's planned configuration beyond a diff or to query state/configuration outside the plan.