@yawlabs/terraform-cwd-mcp answers from your working directory, not the registry. The source of truth is terraform providers schema -json run in your root module, with versions read from .terraform.lock.hcl - so the schema an agent checks against is the one you actually pinned, not the one the latest docs describe. It also reads your saved plans, your state (redacted), and your local and installed modules, and it computes what a provider upgrade would break. Built and maintained by Yaw Labs, MIT licensed, published on npm.

npx -y @yawlabs/terraform-cwd-mcp@latest

GitHub · npm · Add to Yaw MCP

Who it is for

Anyone who has watched an agent write Terraform against the wrong provider version. Your lock file says hashicorp/aws 5.31.0; the registry docs and the model's training data say whatever came later or earlier. The agent then writes arguments that were added after your pin, removed before it, or are computed-only and cannot be set at all. terraform validate catches it - after the code is written. This server lets the agent check before it writes:

Install

1. Initialize the directory once. The schema tools read the provider packages Terraform has already downloaded, so the root module must have been initialized. The backend does not need to be reachable:

terraform init -backend=false

The server itself never runs terraform init in your working directory. An uninitialized directory gets an actionable error telling you what to run.

2. Add the server. Claude Code, from the root module:

# macOS / Linux / WSL claude mcp add terraform-cwd -- npx -y @yawlabs/terraform-cwd-mcp@latest # Windows claude mcp add terraform-cwd -- cmd /c npx -y @yawlabs/terraform-cwd-mcp@latest

Or add it to .mcp.json in the root module. On macOS, Linux and WSL:

{ "mcpServers": { "terraform-cwd": { "command": "npx", "args": ["-y", "@yawlabs/terraform-cwd-mcp@latest"] } } }

On Windows, wrap the call in cmd /c: since Node 20, child_process.spawn cannot directly execute .cmd files, and that is what npx is on Windows.

{ "mcpServers": { "terraform-cwd": { "command": "cmd", "args": ["/c", "npx", "-y", "@yawlabs/terraform-cwd-mcp@latest"] } } }

Point it at a module other than your current directory with TERRAFORM_CWD_MCP_DIR, or per call with the dir argument every tool takes. On Windows, env vars set in a bash or PowerShell profile are not inherited by MCP servers launched via cmd, so put them in the env block.

3. Tell your agent to use it. Agents reach for the server reliably when the project tells them to. Add this to the root module's CLAUDE.md or AGENTS.md:

## Terraform provider schemas Call tf_list_providers once per session. Before writing any resource, data or ephemeral block, call tf_get_schema for that type. Call tf_check_arguments with every argument path you set, and never use one it reports as UNKNOWN or READ-ONLY (computed).

Running Yaw MCP? One click adds it to your local config, and it is then available in every Yaw Terminal session.

What it covers

ToolWhat it does
tf_list_providersProviders in the root module with their pinned versions and resource, data and ephemeral counts. Call this first.
tf_search_typesFind type names containing a substring (for example s3_bucket), per kind.
tf_get_schemaEvery argument and nested block of one type at the pinned version, with mode and flags. Use before writing or editing a block.
tf_check_argumentsValidate dotted argument paths and get a per-path verdict: ok, ok (block), READ-ONLY (computed), '<x>' is an attribute, not a block or UNKNOWN.
tf_summarize_planSummarize a saved plan (binary or JSON): deletes and replaces first, with the forcing attribute; then updates, creates, imports, moves, drift, deferred changes and outputs. Prints no values.
tf_module_interfaceVariables (exact type, required/optional, default, flags), outputs and module calls of the root, a local module path, or an installed module by address. No subprocess.
tf_state_addressesResource instance addresses in the current state, with a substring filter and id lookup.
tf_show_resourceOne instance's attribute values from state, with sensitive values redacted and a footer saying what was hidden and why.
tf_upgrade_impactWhat breaks if a pinned provider moves to an exact version: arguments, nested blocks, attribute reads and provider-block arguments that are removed, read-only, retyped, newly required or deprecated in the target - confirmed by terraform validate on a temp copy.

Every tool takes an optional dir (the root module), and kind is resource (default), data or ephemeral. Dumps are cached in memory and on disk keyed on the root path plus the lock file's bytes, so a provider upgrade invalidates the cache automatically - the AWS provider's schema is tens of MB, and you pay for that dump once per lock-file change, not per question.

Safety and control

Frequently asked questions

What does the Terraform CWD MCP server do?

It answers what is true in the Terraform working directory you point it at, not in the public registry. The source of truth is terraform providers schema -json run in your root module, with versions read from .terraform.lock.hcl, so the tool surface describes the provider version you actually pinned. On top of that it reads your saved plans, your state (with sensitive values redacted), your local and installed modules, and it computes what a provider version bump would break.

How is this different from HashiCorp's terraform-mcp-server?

They answer different questions. HashiCorp's server answers from the Terraform Registry docs, which describe the latest provider release, and from HCP Terraform / Terraform Enterprise. This server answers from terraform providers schema in your root module, which describes the version you locked. Run both: this one wins on argument validity for your pin and on what this directory's plan, state and modules contain, and the official one wins on usage docs, latest versions, public registry modules and HCP runs.

Does it modify my configuration or run terraform init?

No. It never runs terraform init in your root module, never writes your configuration, your state or your lock file, and there is no apply path. The schema tools read from the provider packages you already downloaded, so the directory must have been initialized with terraform init -backend=false first; an uninitialized directory gets an actionable error telling you what to run. The provider-upgrade tool downloads a target version with terraform init inside a throwaway temp directory, never in yours.

Is my state safe to show an agent?

The state tools redact sensitive values before returning anything. That includes Terraform's own sensitive markers, any string equal to or containing a marked value, values under secret-like keys such as password or client_secret, and secret-shaped strings like private keys and API tokens. There is deliberately no show-sensitive switch. Unmarked derived values that Terraform itself displays, such as a content hash of a sensitive file, are printed.

What does the provider-upgrade tool actually do?

Given a pinned provider and an exact target version, it reports the arguments, nested blocks, attribute reads and provider-block arguments that your configuration uses and that are removed, read-only, retyped, newly required or deprecated in the target, along with version constraints that block the move. It confirms the result by running terraform validate on a temp copy whose provider entries link to packages you already have. State and *.tfvars are never copied, and calls are serialized because the plugin cache is not safe for concurrent installs.

Related MCP servers

Further reading

Published by Yaw Labs.