Skip to main content
Glama

@yawlabs/terraform-cwd-mcp

Add to Yaw MCP

One click adds this to your local Yaw MCP config so it's available in every Yaw Terminal session. Or install manually below.

What is actually true in THIS Terraform working directory: the exact provider schemas pinned in your .terraform.lock.hcl (so coding agents stop writing arguments that do not exist, were removed, or are read-only), plus your saved plans, your state (redacted), your local and installed modules, and what a provider upgrade would break. It complements HashiCorp's terraform-mcp-server rather than replacing it: that server answers from the Terraform Registry docs, which describe the latest provider release; this one answers from terraform providers schema -json in your root module, which describes the version you actually locked. Run both.

npm version License: MIT

Built and maintained by Yaw Labs.

Why this one?

Your lock file says hashicorp/aws 5.31.0; the registry docs (and the model's training data) say whatever came later or earlier. Agents then write 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.

  • Pinned, not latest -- the source of truth is terraform providers schema -json run in your root module, with versions read from .terraform.lock.hcl.

  • Read-only, never inits -- it never runs terraform init (no downloads, no backend contact, no lock-file rewrites). An uninitialized directory gets an actionable error telling you what to run.

  • Cached per lock file -- 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; you pay for that dump once per lock-file change, not per question.

  • Small answers -- tf_get_schema renders one type as a compact indented outline with required / optional / optional+computed / computed (read-only), [deprecated], [sensitive] and [write_only] flags, instead of handing the model raw JSON.

  • Cross-platform -- macOS, Linux and Windows. Terraform is spawned directly (no shell) and its output is streamed, so there is no buffer ceiling.

Related MCP server: Terraform Cloud MCP

Tools

Tool

What it does

tf_list_providers

Providers in the root module with their pinned versions and resource / data / ephemeral counts. Call this first.

tf_search_types

Find type names containing a substring (s3_bucket), per kind.

tf_get_schema

Every argument and nested block of one type at the pinned version, with mode and flags. Use before writing or editing a block.

tf_check_arguments

Validate dotted paths (["bucket", "versioning.enabled"]) and get ok, ok (block) (either with [deprecated]), READ-ONLY (computed), '<x>' is an attribute, not a block or UNKNOWN per path.

tf_summarize_plan

Summarize a saved plan (plan_file: binary from terraform plan -out, or plan JSON) or plan JSON text (plan_json, e.g. an HCP run's plan fetched by the official server). Deletes and replaces first, with the attribute that forces each replace; then updates (changed paths), creates, imports, moves, forgets, drift, deferred changes and outputs; Terraform's own Plan: counts; a destroy warning naming renames that need a moved block. Prints no values.

tf_module_interface

Variables (exact type expression, required/optional, default, [sensitive] / [not nullable] / [ephemeral], validation count), outputs and module calls of the root, a local module path, or an installed module by address (module.network, incl. downloaded registry/git modules). Flags module calls that are not installed or stale. No subprocess.

tf_state_addresses

Resource instance addresses in the current state (terraform state list), with a substring filter and id lookup.

tf_show_resource

One instance's attribute values from state (terraform show -json), with sensitive values redacted and a footer saying what was hidden and why.

tf_upgrade_impact

What breaks if a pinned provider moves to an exact version: the arguments, nested blocks, attribute reads and provider block arguments your configuration (root + installed modules) uses that are removed, read-only, retyped, newly required or deprecated in the target; version constraints that block it; confirmed by terraform validate on a temp copy.

Every tool takes an optional dir (the root module); kind is resource (default), data or ephemeral.

Division of authority with HashiCorp's official server. This server wins on argument validity for the version you pinned and on what this directory's plan, state and modules contain. The official server wins on usage docs, latest versions, public registry modules and HCP/TFE runs. For an HCP run's plan, get its plan id there (get_run_details), fetch the plan with get_plan_json_output(plan_id) and pass the JSON to tf_summarize_plan as plan_json (those tools need the official server's terraform toolset and TFE_TOKEN).

What is read-only, and what touches the network

  • Never written: your root module, its .terraform/, its lock file and its state. terraform init is never run in it.

  • State tools (tf_state_addresses, tf_show_resource) run terraform state list / terraform show -json, which never lock and never refresh. With a remote backend they read S3/GCS/HCP with the credentials the server inherited from its MCP client. Selecting a non-default workspace that does not exist would make Terraform create it (the s3 backend writes an empty state), so the server checks terraform workspace list first and refuses.

  • tf_upgrade_impact downloads the target provider version with terraform init in a throwaway temp dir into a plugin cache (TERRAFORM_CWD_MCP_PLUGIN_CACHE, else your TF_PLUGIN_CACHE_DIR, else <cache>/plugins), then runs terraform validate on a temp copy of your configuration whose .terraform/providers entries are links to the packages you already have. State and *.tfvars are never copied. Calls are serialized (the plugin cache is not safe for concurrent installs).

  • Redaction (tf_show_resource): Terraform's sensitive markers, plus any string equal to (or containing) a marked value anywhere in state, plus values under secret-like keys (password, api_token, client_secret, ... but not password_length or secret_arn), plus secret-shaped strings (private keys, JWTs, GitHub/GitLab/Slack/npm tokens; URL passwords are masked in place). There is deliberately no "show sensitive" switch. Unmarked derived values Terraform itself shows (e.g. content_md5 of a sensitive file) are printed.

  • Every terraform child gets CHECKPOINT_DISABLE=1, so no version check phones home.

Example tf_summarize_plan output (real plan, abridged):

plan (terraform 1.15.7, format 1.2): applyable, complete
totals: 1 delete, 5 replace, 1 update, 1 create, 0 read, 1 import, 1 move, 1 forget, 0 unchanged (terraform: 1 to import, 6 to add, 1 to change, 6 to destroy)
DELETE (1)
  - null_resource.gone (not in configuration)
REPLACE (5)
  -/+ local_sensitive_file.sf delete-then-create; forced by: content [sensitive]
  +/- random_string.cbd create-before-destroy; forced by: keepers
  ...
UPDATE (1)
  ~ terraform_data.cfg: input.version, output (known after apply)
WARNING: 6 object(s) will be destroyed (1 delete, 5 replace). 1 moved block(s) applied; none covers these.

Example tf_upgrade_impact output (real validate run):

upgrade hashicorp/random 2.3.1 -> 3.6.3 (major) for /work/infra
constraints: root pins 2.3.1 as local name rnd (change it to allow 3.6.3)
used types: resource random_password, random_id
affected arguments (2):
  random_password.p.number (main.tf:18): DEPRECATED in 3.6.3
  reads random_id.i.b64 (main.tf:36): REMOVED in 3.6.3
validate on a temp copy, 3.6.3 vs 2.3.1: 1 new error, 1 new warning, 1 warning resolved
  error main.tf:36: Unsupported attribute - This object has no argument, nested block, or exported attribute named "b64".
  warning main.tf:18 random_password.p: Attribute Deprecated - **NOTE**: This is deprecated, use `numeric` instead.
verdict: BREAKING (1 error after upgrade)

Example tf_get_schema output:

resource random_password (registry.terraform.io/hashicorp/random 3.9.1)
  bcrypt_hash: string computed (read-only) [sensitive] - A bcrypt hash of the generated random password. ...
  keepers: ["map","string"] optional - Arbitrary map of values that, when changed, will trigger recreation of resource. ...
  length: number required - The length of the password desired. ...
  number: bool optional+computed [deprecated] - Include numeric characters in the result. ...
  result: string computed (read-only) [sensitive] - The generated random password.

Quick start

1. Initialize the root module once (you, not the server):

terraform init -backend=false

-backend=false is enough: the schema only needs the providers, not state.

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 (or anywhere, and set TERRAFORM_CWD_MCP_DIR):

macOS / Linux / WSL:

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

Windows:

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

Why the extra step on Windows? Since Node 20, child_process.spawn cannot directly execute .cmd files (that's what npx is on Windows). Wrapping with cmd /c is the standard workaround.

3. Restart your MCP client and ask, for example: "Add a versioned S3 bucket -- check the arguments against our pinned AWS provider first."

Tell your agent to use it

Agents use the server reliably when the project tells them to. Paste this into the root module's CLAUDE.md (or AGENTS.md):

## Terraform provider schemas

This repo pins provider versions in `.terraform.lock.hcl`; registry docs and your
training data describe other versions. Use the terraform-cwd MCP server:

- Call `tf_list_providers` once per session to see the pinned versions.
- Before writing or editing any `resource`, `data` or `ephemeral` block, call
  `tf_get_schema` for that type.
- Call `tf_check_arguments` with every argument path you set (dotted for nested
  blocks, e.g. `versioning.enabled`). Never use an argument it reports as
  `UNKNOWN` or `READ-ONLY (computed)`; replace a `[deprecated]` one if the
  schema offers an alternative.
- Before calling a module, read its inputs with `tf_module_interface`.
- After `terraform plan -out=tfplan`, review it with `tf_summarize_plan`
  (plan_file: tfplan) and call out every DELETE and REPLACE.
- Before bumping a provider version, run `tf_upgrade_impact`.

Pairs well with

HashiCorp's terraform-mcp-server

hashicorp/terraform-mcp-server answers registry and HCP questions; this server answers what is true in your working directory. Run both -- they do not overlap, and when they disagree the table says who wins:

Question

Authority

Is argument X valid for the provider version I have pinned?

terraform-cwd-mcp

Which arguments I use break if I upgrade to vN?

terraform-cwd-mcp (tf_upgrade_impact)

What does this saved plan, this state, or this local / installed module contain?

terraform-cwd-mcp

How is resource X meant to be used? What do the docs and examples say?

terraform-mcp-server

What is the latest provider or module version?

terraform-mcp-server

Which public registry module should I use?

terraform-mcp-server

HCP Terraform / TFE workspaces and runs

terraform-mcp-server

An HCP run's plan

terraform-mcp-server fetches it (get_run_details -> plan id -> get_plan_json_output(plan_id)); tf_summarize_plan summarizes it (plan_json)

The official server starts with only its registry toolset. The HCP / TFE rows need it started with --toolsets=registry,terraform (or all) and TFE_TOKEN. Its docs search tool is search_provider_docs from v1.3.1 on (search_providers before; a BREAKING rename), which matters if you allowlist tools by name.

Yaw Mode skills

Yaw Terminal's Yaw Mode ships four skills that drive both servers, degrade gracefully when either is missing, and stop at terraform plan (they never apply or destroy):

  • /yaw-tf -- everyday write / edit / fix: check every argument against the pinned schema, then fmt, validate, plan and summarize; hands off to the three below.

  • /yaw-tf-refactor -- renames, module moves and imports with moved / import / removed blocks, done only when the plan shows zero destroys and replaces.

  • /yaw-tf-plan-review -- go / no-go punch list for a local saved plan or an HCP run: destroys first, then checkov / trivy and IAM, network and encryption hot spots.

  • /yaw-tf-upgrade -- provider bumps: latest version, tf_upgrade_impact against the arguments you actually use, the upgrade guide, then edits, re-pin, validate and plan.

Configuration

All optional.

Env var

Default

Purpose

TERRAFORM_CWD_MCP_DIR

the server's working directory

Root module used when a tool call passes no dir.

TERRAFORM_CWD_MCP_CACHE

~/.cache/terraform-cwd-mcp

Where schema dumps are cached (<key>.json). Safe to delete at any time.

TERRAFORM_CWD_MCP_BINARY

terraform

Binary to run, e.g. a full path, or tofu for OpenTofu (same providers schema -json output).

TERRAFORM_CWD_MCP_TIMEOUT_MS

300000

Kill any terraform command (schema dump, state read, target init, validate) after this long.

TERRAFORM_CWD_MCP_PLUGIN_CACHE

TF_PLUGIN_CACHE_DIR, else <cache>/plugins

Where tf_upgrade_impact keeps downloaded provider packages.

Runtime (oam or Node):

The terraform-cwd-mcp command prefers oam when it finds a usable one and otherwise runs on Node. It never serves on an oam older than 0.19.0.

Env var

Default

Purpose

TERRAFORM_CWD_MCP_RUNTIME

auto

auto: the newest oam at 0.19.0 or newer, else Node. oam: oam or exit with an error. node: always Node -- the escape hatch when a problem only shows up under oam.

OAM_BIN

(unset)

Path to the oam binary to use. Otherwise the launcher checks OAM_INSTALL_DIR, the installed locations (~/.oam/bin, and %LOCALAPPDATA%\oam\bin on Windows) and PATH, and takes the newest.

An outdated oam is fixed with oam self-update. Under Yaw MCP, which runs servers on oam by default, yaw-mcp set <namespace> runtime=node switches this server to Node. There is no --permission sandbox option: the server spawns terraform and reads whatever directory a call names, so there is nothing narrow to grant.

Requirements

  • Node.js 20+

  • Terraform (or OpenTofu) on PATH, recent enough to have terraform providers schema -json (0.12+; ephemeral resources need 1.10+)

  • An initialized root module (.terraform/ and .terraform.lock.hcl present) for every tool except tf_module_interface on the root or a local path, and tf_summarize_plan with plan JSON

  • State tools: the backend initialized (terraform init, not -backend=false) and its credentials in the server's environment

  • tf_upgrade_impact: registry access the first time a target version is requested (later runs for that version are offline)

  • .terraform/ at <dir>/.terraform: TF_DATA_DIR is not honoured

Contributing

git clone https://github.com/YawLabs/terraform-cwd-mcp.git
cd terraform-cwd-mcp
npm install
npm run lint       # Biome check
npm run lint:fix   # Auto-fix
npm run build      # tsup bundle + declarations
npm test           # Vitest (the integration test runs only when terraform is on PATH)
npm run typecheck  # oam check . when oam is installed, else tsc --noEmit
npm run check:oam-floor  # the oam floor agrees across the repo and matches the latest oam release

See CONTRIBUTING.md for the full workflow, including release process.

License

MIT

Follow @YawLabs on X

Available Tools

9 tools
tf_check_argumentsA
Read-onlyIdempotent

Validate argument / nested-block paths against the PINNED schema before writing them, e.g. ["bucket", "region", "versioning.enabled"]. Flags unknown, read-only and deprecated paths.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
kindNoresource | data | ephemeralresource
argumentsYesDotted paths; nested blocks are separated by '.'
type_nameYesFull type name, e.g. aws_s3_bucket

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/no-destructive/idempotent/closed-world, so the safety profile is covered. The description adds real behavioral value beyond that: validation happens against the PINNED schema, and the tool flags unknown, read-only and deprecated paths. It does not describe error handling or prerequisites, but the added disclosure is substantial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the verb and purpose, followed by one illustrating example and a short second sentence on detected conditions. No filler; every clause carries information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description usefully indicates what comes back (flags for unknown/read-only/deprecated paths) and when to invoke it. It leaves "PINNED schema" and result shape (list vs error) partly undefined, but remains usable for a 4-param, fully-documented read-only tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all four parameters (dir, kind, arguments, type_name) are already documented in the schema. The description's example path mainly restates the schema's "dotted paths; nested blocks separated by '.'" convention, adding only marginal meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (validate) on a specific resource (argument / nested-block paths) and gives a concrete example path, so the tool's role is unambiguous. It is clearly distinct from siblings like tf_get_schema or tf_search_types, which retrieve rather than check paths.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"before writing them" gives an explicit timing/context for when to call this tool, which is genuinely useful guidance. It stops short of naming alternatives or stating when-not to use it (e.g. vs tf_get_schema for a full schema dump).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_get_schemaA
Read-onlyIdempotent

Exact arguments and nested blocks for one type at the PINNED provider version. Use BEFORE writing or editing any resource/data/ephemeral block; only arguments listed here exist. 'computed (read-only)' attributes cannot be set. kind: resource | data | ephemeral.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
kindNoresource | data | ephemeralresource
max_depthNoNested block levels to expand (default 3)
type_nameYesFull type name, e.g. aws_s3_bucket
description_charsNoTruncate each description to this many characters; 0 = no limit (default 160)

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover readOnly/idempotent/non-destructive, but the description adds real behavioral value: attributes are pinned to the provider version, computed (read-only) attributes cannot be set, and unlisted arguments do not exist. That materially shapes how an agent writes config after calling this.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three dense sentences, front-loaded with the core action and the pre-write instruction. Every sentence carries information, with only the trailing kind enumeration being a partial restatement of the schema default.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only introspection tool with fully documented parameters, the description covers purpose, timing, and the key constraint about computed attributes and unlisted arguments. No output schema exists, yet the description gives no hint of the returned structure beyond 'arguments and nested blocks,' a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents dir, kind, max_depth, type_name and description_chars. The description only echoes the kind enum values, adding nothing new about the other four parameters. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource: returns exact arguments and nested blocks for one type at the pinned provider version, which is clearly distinct from tf_search_types (discovery) and tf_check_arguments (validation). It does not explicitly name those siblings, so the differentiation is inferable rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

'Use BEFORE writing or editing any resource/data/ephemeral block' gives an explicit timing and trigger condition. It also sets the hard constraint 'only arguments listed here exist.' It stops short of naming an alternative tool or a when-not-to-use condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_list_providersA
Read-onlyIdempotent

List providers and their PINNED versions for a Terraform root module (default: cwd). Call this first so code targets the versions actually locked in .terraform.lock.hcl, not the latest release. Lists only the providers locked in THIS directory; it does not search the registry. For registry search, provider docs or the latest version, use the official terraform MCP server (search_provider_docs / get_latest_provider_version).

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/idempotentHint/destructiveHint=false, so safety is covered. The description adds genuine behavioral context beyond that: the data source is .terraform.lock.hcl and it lists only providers locked in THIS directory, which is real scope information. It stops short of describing return format or handling of uninitialized directories.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, all front-loaded and purposeful: what it returns, when to call it, what it does not cover, and where to go instead. No filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter, read-only listing tool with no output schema, the description covers the return subject (providers and pinned versions), the scope limitation, and the routing to alternatives. Nothing needed to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%; the single dir parameter already documents its default precedence (TERRAFORM_CWD_MCP_DIR, else server working directory). The description's '(default: cwd)' restates this without adding syntax or edge-case detail, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (List) plus resource (providers and their PINNED versions) and scopes it to a Terraform root module defaulting to cwd. It also distinguishes itself from registry search, so an agent can separate it from tf_get_schema or a registry lookup without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Call this first' and gives the reason (code should target versions locked in .terraform.lock.hcl, not the latest release). It also states when NOT to use it ('does not search the registry') and names the alternative server and tools (search_provider_docs / get_latest_provider_version).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_module_interfaceA
Read-onlyIdempotent

Variables (exact type expression, required/optional, default, sensitive/nullable/ephemeral, validation count), outputs and module calls of a module in THIS working directory: the root, a local module directory, or an installed module by address (module.network, resolved through .terraform/modules/modules.json, so downloaded registry/git modules work). Module calls are checked against what is installed. For public registry modules you have not installed, use the official terraform MCP server.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (need not be initialized for the root or a local path). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
moduleNoModule to describe: omitted = the root; a module address like 'module.network' or 'module.a.module.b' (resolved through .terraform/modules/modules.json, so downloaded registry/git modules work); or a directory path relative to dir
description_charsNoTruncate each description to this many characters; 0 = no limit (default 160)

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnlyHint, idempotentHint, destructiveHint false, openWorldHint false), so the bar is lower. The description still adds useful mechanics: address resolution runs through .terraform/modules/modules.json (so downloaded registry/git modules resolve), and module calls are validated against what is installed. It does not describe failure behavior when a module is missing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the highest-value content (what gets returned), and the second sentence carries the exclusion. The first sentence is dense and parenthetical-heavy, but every clause adds a distinct piece of information rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description must convey return content, and it does: it lists the variable attributes surfaced and the presence of outputs and module calls. Combined with the read-only annotations and 100%-covered schema, an agent has enough to call it correctly; only error/missing-module behavior is left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all three parameters (dir, module, description_chars) are already documented in the schema. The description restates the module address forms that the schema already covers, adding essentially no syntax or default detail beyond it. Baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names the resource (a module) and enumerates exactly what it returns: variables (with type expression, required/optional, default, sensitive/nullable/ephemeral, validation count), outputs and module calls. The 'in THIS working directory' scope is a real differentiator, though no sibling tool (e.g. tf_get_schema or tf_check_arguments) is named to sharpen the boundary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It states the when (root, local module directory, or installed module address resolved via modules.json) and the when-not with an explicit alternative: 'For public registry modules you have not installed, use the official terraform MCP server.' That is a complete routing rule for an agent deciding between tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_search_typesA
Read-onlyIdempotent

Find resource / data source / ephemeral resource type names containing query (e.g. 's3_bucket') in the pinned providers. kind: resource | data | ephemeral.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
kindNoresource | data | ephemeralresource
limitNoMax names to return (default 50)
queryYesCase-insensitive substring of the type name

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare the full safety profile (readOnlyHint, idempotentHint, destructiveHint=false, openWorldHint=false), so the description is not the primary carrier of behavior. It adds the useful scoping fact that the search covers only the *pinned* providers, but says nothing about result ordering, caps, or what happens on no match beyond the schema's limit default.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the action and match semantics; the trailing 'kind: resource | data | ephemeral' is a compact enumeration with no filler. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple name-search tool with no output schema, the description covers the search semantics, scope (pinned providers), and result kind. The return value (a list of matching type names) is self-evident, and safety is fully covered by annotations, so nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all four parameters (dir, kind, limit, query) including defaults and bounds. The description restates only `query` and the `kind` enum, adding no syntax or format meaning beyond the structured fields. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Find'), the exact resource being searched (resource/data source/ephemeral type names), the matching semantics (substring of `query`), and the scope ('in the pinned providers'). This is distinguishable from siblings like tf_list_providers (lists providers, not type names) and tf_get_schema (fetches a schema for a known type).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when it is useful (locating a type name by substring), which is clear context, but it never states when not to use it or names the alternative for getting details once a name is found (e.g. tf_get_schema). Usage is inferable rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_show_resourceA
Read-onlyIdempotent

Show one resource instance's attribute values from the current Terraform state (terraform show -json). Read-only: never locks, never refreshes. Sensitive values are redacted: Terraform's own markers, plus values equal to a marked one, secret-like names and secret-shaped strings; a footer says what was hidden and why.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
addressYesExact resource instance address from tf_state_addresses, e.g. aws_instance.web[0] or module.db.aws_db_instance.this["primary"]
include_nullNoAlso list attributes whose value is null
max_value_charsNoTruncate each value; 0 = no limit (default 200)

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/idempotent/non-destructive, so the safety profile is covered; the description still adds real value by specifying 'never locks, never refreshes' and detailing the redaction policy (Terraform markers, equal values, secret-like names/shapes) plus a footer explaining what was hidden. That is genuine behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tightly packed sentences: identity and source first, then safety, then redaction behavior. Every sentence carries information an agent needs, with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, so the description helps by explaining the read-only nature and the redaction footer that accompanies results. It could say a bit more about result shape (e.g., flattened attribute list, truncation), but it is largely complete for a single-resource read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all four parameters (dir, address, include_null, max_value_chars) are documented in the schema with defaults and constraints. The description adds no parameter-level syntax or format information beyond this, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Show one resource instance's attribute values') plus the exact source ('from the current Terraform state (terraform show -json)'). This clearly distinguishes it from siblings like tf_state_addresses, which would list addresses rather than dump an instance's attributes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: the address parameter description points to tf_state_addresses as the source of a valid address, suggesting a follow-on workflow. However, the description itself never says when to use this over alternatives or any when-not conditions. Adequate but with a clear gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_state_addressesA
Read-onlyIdempotent

List resource instance addresses in the current Terraform state (terraform state list), optionally filtered. Read-only: never locks, never refreshes. With a remote backend this reads S3/GCS/HCP using the server's credentials; a non-default workspace that does not exist is refused (reading it would create it).

ParametersJSON Schema
NameRequiredDescriptionDefault
idNoOnly the instance whose id attribute equals this (terraform state list -id)
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
limitNoMax addresses to return (default 200)
filterNoCase-sensitive substring of the address, e.g. 'module.network' or 'aws_instance.'

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotency and non-destructiveness, yet the description still adds real value: it says it never locks or refreshes, reads S3/GCS/HCP with the server's credentials, and refuses a non-default workspace that does not exist to avoid creating it. These are non-obvious behavioral traits beyond the annotation set; the one gap is no note on pagination/truncation relative to the limit parameter.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three tight sentences with the core purpose front-loaded and no filler; the remote-backend and workspace caveats follow in decreasing order of importance. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, but the tool returns a simple address list, and the description plus annotations cover safety, backend access and the workspace-refusal edge case. A brief note on return shape or large-state truncation would complete it, but nothing essential for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all four parameters, including the filter substring syntax and id. The description only mirrors this ('optionally filtered') without adding format or edge-case detail, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('List resource instance addresses in the current Terraform state') and equates it to the known 'terraform state list' command. This is clearly distinguishable from every sibling (providers, types, schema, check_arguments, summarize_plan, module_interface, show_resource, upgrade_impact), which all address different resources.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description conveys context ('optionally filtered', remote-backend behavior) but never states when to choose this tool over an alternative such as tf_show_resource for inspecting state. There is no explicit when/when-not guidance, so usage is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_summarize_planA
Read-onlyIdempotent

Summarize a saved Terraform plan: deletes and replaces first (with the attribute that forces each replace), updates with changed paths, creates, imports, moves, forgets, drift and output changes, plus a destroy warning that names renames needing a moved block. Pass plan_file (binary from terraform plan -out, rendered with terraform show -json in dir, or a plan JSON file) or plan_json (e.g. from the official terraform MCP server's get_plan_json_output(plan_id) for an HCP run; get the plan id from its get_run_details). Prints no values: sensitive paths are truncated, import IDs omitted.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
max_pathsNoChanged attribute paths listed per updated resource (default 8)
plan_fileNoSaved plan (binary from `terraform plan -out`, rendered here with `terraform show -json` in `dir`) or a plan JSON file; relative paths resolve against dir
plan_jsonNoPlan JSON text, e.g. from the official terraform MCP server's get_plan_json_output
max_per_sectionNoMax entries listed per section (default 50)

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent, non-destructive, and closed-world, so the safety profile is covered. The description adds substantive behavior beyond that: it prints no values, truncates sensitive paths, and omits import IDs, plus it flags that destroy output names renames requiring a moved block. It stops short of describing error behavior when neither plan_file nor plan_json is supplied.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, purpose front-loaded before the input discussion, and nearly every clause carries distinct information (section inventory, input provenance, output redaction). It is dense to the point of being clause-heavy, but there is little that could be cut without losing signal.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description carries the return-value burden and does: it lists the report sections and states that sensitive values are truncated and import IDs omitted. With zero required parameters it still tells the agent which input to pass and where that input comes from, so an agent has enough to call it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning for the two plan inputs: plan_file is a binary from `terraform plan -out` rendered with `terraform show -json` in `dir`, or a plan JSON file, while plan_json is JSON text typically sourced from a specific sibling HCP server call. dir, max_paths, and max_per_section are left to the schema, which documents them adequately.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ("Summarize a saved Terraform plan") and then enumerates exactly what the summary contains: deletes/replaces with the forcing attribute, updates with changed paths, creates, imports, moves, forgets, drift, output changes, and a destroy warning about renames needing a moved block. That level of detail makes it unmistakable versus siblings like tf_state_addresses, tf_show_resource, or tf_upgrade_impact, which all cover different resources or phases.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly states the invocation context: supply plan_file or plan_json, and it names the concrete upstream source of plan_json (the official terraform MCP server's get_plan_json_output(plan_id), with plan_id from get_run_details), which is genuine routing guidance. It does not state when this tool should *not* be used (e.g. for planning an unsaved change, or for examining a single resource, where tf_show_resource would be the pick), so it stops short of explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tf_upgrade_impactA
Read-onlyIdempotent

What breaks if a pinned provider is upgraded (or downgraded) to an exact version: compares the pinned schema with the target's for the arguments, nested blocks and attribute reads this configuration uses (root and installed modules), checks version constraints, and confirms with terraform validate on a temp copy. Downloads the target provider from the registry into a cache (temp dirs only; never touches dir). For the latest version number or upgrade guides, use the official terraform MCP server.

ParametersJSON Schema
NameRequiredDescriptionDefault
dirNoTerraform root module directory (must already be initialized). Default: TERRAFORM_CWD_MCP_DIR, else the server's working directory.
versionYesExact target version, e.g. 6.0.0 (not a constraint)
providerYesProvider address as pinned, e.g. hashicorp/aws or registry.terraform.io/hashicorp/aws
validateNoConfirm with terraform validate on a temp copy (offline once the target is downloaded)
include_unusedNoAlso list target-version changes to types/arguments this configuration does not use

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations: it discloses a registry download into a cache, that only temp dirs are written and 'never touches dir', that validation runs on a temp copy, and that the operation becomes offline once the target is downloaded. That is exactly the network/disk side-effect context an agent needs and would not infer from the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The impact question is front-loaded, the mechanism follows, and the external-tool routing is last. Three dense sentences with no repetition of schema text and no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description must carry the return-value burden and it does not describe what the impact report contains (format, severity, per-module grouping). Everything else an agent needs — scope, side effects, prerequisites (initialized dir), routing — is present, so the gap is narrow.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning: 'this configuration uses' clarifies the default include_unused=false scope, and 'confirms with terraform validate on a temp copy' ties to the validate flag. The 'exact version, not a constraint' intent is also reinforced in prose. It does not, however, explain the dir fallback behavior in the body.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+outcome ('what breaks if a pinned provider is upgraded/downgraded to an exact version'), then names the exact comparison scope (arguments, nested blocks, attribute reads, root and installed modules). An agent can tell it apart from tf_get_schema or tf_check_arguments without opening any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States the trigger context (impact of a version change) and explicitly routes one adjacent need elsewhere: 'For the latest version number or upgrade guides, use the official terraform MCP server.' It does not distinguish itself from the sibling tools (tf_get_schema, tf_check_arguments), so no siblings-specific exclusions are given.

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.

  1. 9 tool updatesv0.1.0
    • First observedtf_check_arguments
    • First observedtf_get_schema
    • First observedtf_list_providers
    • First observedtf_module_interface
    • First observedtf_search_types
    • First observedtf_show_resource
    • First observedtf_state_addresses
    • First observedtf_summarize_plan
    • First observedtf_upgrade_impact

TDQS

A4.2/5.0

Scored across 9 tools

Disambiguation5/5

Each tool targets a distinct action on a clearly bounded resource: listing state addresses vs. showing a resource's attributes, listing pinned providers vs. searching type names vs. fetching a schema vs. validating argument paths, plus plan summary, module interface, and upgrade impact. Descriptions make the boundaries explicit, so an agent should not misselect.

Naming Consistency4/5

All names share the tf_ prefix and snake_case, giving a predictable namespace. Most follow verb_noun (tf_list_providers, tf_get_schema), but a few use noun-oriented phrasing (tf_state_addresses, tf_module_interface, tf_upgrade_impact), a minor deviation rather than a real inconsistency.

Tool Count5/5

Nine tools is well-scoped for a read-only, cwd-focused Terraform analysis server. Every tool has a clear niche, with no redundant wrappers or filler.

Completeness4/5

Coverage is strong for a read-only analysis surface: state inspection, pinned provider/type schema, argument validation, plan summarization, module interfaces, and upgrade impact. Minor gaps exist (e.g. no standalone workspace listing or outputs-only view), but the design intentionally defers mutation/execution and registry lookups to the official terraform MCP server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    A read-only MCP server for inspecting and diagnosing HCP Terraform workspaces, runs, and plan summaries from ChatGPT and other MCP clients. It provides tools to list workspaces, inspect runs, and summarize plans without exposing sensitive data.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Provides agents with read-only access to local code architecture graphs (structure from tree-sitter, semantic summaries from LLMs), including per-workspace graph/config/status/rebuild tools, while enforcing that topology comes only from static analysis.
    2 npm
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables safe, local DevOps inspection through a JSON-lines server with schema validation, path isolation, and redaction, supporting read-only Git operations, Kubernetes YAML validation, Terraform plan summaries, and sanitized log analysis.
    MIT