> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Creating a Resource in Terraform

> Guide demonstrating how to run Terraform via the tfmcp MCP bridge using JSON-RPC over stdio to plan and apply a simple local file resource, including setup and security notes

This guide shows how to run Terraform operations through an MCP (Message Control Plane) server using the Terraform MCP bridge (`tfmcp`). You will learn to initialize a Terraform workspace, plan and apply a simple configuration that creates a local file — all triggered by MCP-style JSON-RPC calls (stdio). This workflow is useful when you want programmatic, message-driven control of Terraform from agents, automation pipelines, or AI assistants that already speak MCP/JSON-RPC.

## Prerequisites (Ubuntu)

Install the required system packages, Rust toolchain, and the Terraform MCP bridge. The following table summarizes the key prerequisites and where to find them.

| Requirement          | Purpose                                         | Install / Reference                                     |
| -------------------- | ----------------------------------------------- | ------------------------------------------------------- |
| build tools          | Compile native dependencies                     | See the command below                                   |
| Rust (rustup)        | Build the `tfmcp` crate                         | See the command below                                   |
| Terraform MCP bridge | Runs the MCP server and handles Terraform calls | `cargo install tf-mcp` or `cargo install terraform-mcp` |

Install the build tools:

```bash theme={null}
sudo apt-get update
sudo apt-get install -y build-essential
```

Install Rust via rustup:

```bash theme={null}
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# follow the prompts and add Rust to your PATH (typically by sourcing ~/.cargo/env)
source "$HOME/.cargo/env"
```

Install the Terraform MCP bridge (the binary is commonly named `tfmcp`):

```bash theme={null}
# Either of these may be available depending on the crate name/version
cargo install tf-mcp
# or
cargo install terraform-mcp
```

Cargo will download and compile crates during installation; when complete the `tfmcp` binary should be on your PATH.

## Start the MCP bridge / server

Start the MCP server so it can accept MCP-style requests over stdio in this demo:

```bash theme={null}
tfmcp mcp
```

The server will run in the foreground and listen for JSON-RPC messages on stdin/stdout.

## Create a sample Terraform project

Create a working directory and a minimal Terraform configuration that writes a local file.

Create the directory and enter it:

```bash theme={null}
mkdir terraform-demo
cd terraform-demo
```

Create `main.tf` with the following content:

```hcl theme={null}
terraform {
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.0"
    }
  }
}

provider "local" {}

resource "local_file" "example" {
  filename = "${path.module}/example.txt"
  content  = "Hello from tfmcp!"
}
```

Initialize and validate the workspace, then create a plan:

```bash theme={null}
terraform init
terraform validate
terraform plan
```

Sample (cleaned) plan output:

```text theme={null}
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # local_file.example will be created
  + resource "local_file" "example" {
      + content               = "Hello from tfmcp!"
      + filename              = "./example.txt"
      + directory_permission  = "0777"
      + file_permission       = "0777"
      + id                    = (known after apply)
    }

Plan: 1 to add, 0 to change, 0 to destroy.
```

## Interact with the Terraform MCP server via JSON-RPC (stdio)

While `tfmcp mcp` is running in one terminal, send JSON-RPC messages from another terminal using a heredoc. The example sequence below performs:

1. An `initialize` request to the MCP server.
2. A `tools/call` request for `get_terraform_plan`.
3. A `tools/call` request for `apply_terraform` with `auto_approve=true`.

Send these requests via stdio:

```bash theme={null}
tfmcp mcp <<EOF
{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}
{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_terraform_plan", "arguments": {}}}
{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "apply_terraform", "arguments": {"auto_approve": true}}}
EOF
```

For quick reference, common MCP tool calls used in this demo:

| Method                                 | Purpose                      | Example                                                                                                                |
| -------------------------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------- |
| `initialize`                           | Prepare the MCP tool session | `{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}`                                                           |
| `tools/call` with `get_terraform_plan` | Request a Terraform plan     | `{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"get_terraform_plan","arguments":{}}}`                 |
| `tools/call` with `apply_terraform`    | Apply the Terraform plan     | `{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"apply_terraform","arguments":{"auto_approve":true}}}` |

Wrap any JSON examples containing curly braces in code blocks to avoid parsing issues (as done above).

## Security policy and auto-approve

By default the MCP bridge may block automated apply operations for safety. If auto-approve is blocked, you will see an error such as:

```json theme={null}
{
  "jsonrpc":"2.0",
  "id":3,
  "error":{
    "code":-32603,
    "message":"Failed to apply Terraform configuration: Auto-approve for apply operation blocked by security policy. Set TFMCP_ALLOW_AUTO_APPROVE=true to enable."
  }
}
```

<Callout icon="lightbulb" color="#1CB2FE">
  Setting `TFMCP_ALLOW_AUTO_APPROVE=true` allows automated apply operations. Only enable this when you trust the Terraform configuration and understand the security implications.
</Callout>

If you decide to allow auto-approve, export the environment variable and re-run the JSON-RPC sequence:

```bash theme={null}
export TFMCP_ALLOW_AUTO_APPROVE=true

# Re-send the JSON-RPC sequence (initialize, plan, apply)
tfmcp mcp <<EOF
{"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {}}
{"jsonrpc": "2.0", "id": 2, "method": "tools/call", "params": {"name": "get_terraform_plan", "arguments": {}}}
{"jsonrpc": "2.0", "id": 3, "method": "tools/call", "params": {"name": "apply_terraform", "arguments": {"auto_approve": true}}}
EOF
```

## Successful apply and verification

When the apply completes, the MCP server will return the standard Terraform apply summary, for example:

```text theme={null}
local_file.example: Creation complete after 0s [id=<resource-id>]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
```

Verify the created file:

```bash theme={null}
cat example.txt
# Output:
# Hello from tfmcp!
```

## Why use Terraform with MCP?

* Consistent control channel: If your orchestration or automation stack already uses MCP/JSON-RPC, adding Terraform as an MCP tool keeps infrastructure control within the same messaging paradigm.
* Programmatic integration: Enables other agents, CI/CD pipelines, or AI assistants to request Terraform operations programmatically without shelling out or managing separate APIs.
* Auditability & policy: An MCP gateway can centralize security checks, logging, and policy enforcement around Terraform operations.

## Troubleshooting tips

* Ensure `tfmcp` is on your PATH after `cargo install` (check `~/.cargo/bin`).
* If `terraform init` fails, review provider version constraints and network access to provider registries.
* If JSON-RPC messages are not being processed, confirm `tfmcp mcp` is running in the terminal where you expect it and that your heredoc is directed at the same `tfmcp` instance.

## Summary

* Installed the Terraform MCP bridge (`tfmcp`) and required toolchain.
* Created a simple Terraform configuration that writes a local file.
* Executed Terraform init/plan/apply through MCP JSON-RPC calls (stdio).
* Addressed auto-approve security via the `TFMCP_ALLOW_AUTO_APPROVE` environment variable.
* Verified the resulting resource and discussed reasons to use Terraform via MCP in automated systems.

## Links and references

* [Terraform](https://www.terraform.io)
* [JSON-RPC specification](https://www.jsonrpc.org/specification)
* [Rustup (install Rust)](https://rustup.rs)
* Terraform local provider: [https://registry.terraform.io/providers/hashicorp/local](https://registry.terraform.io/providers/hashicorp/local)

If you need an example for integrating this into a CI pipeline or automating the JSON-RPC calls programmatically (Python, Node, etc.), I can provide sample clients that interact with `tfmcp` via stdio.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/mcp-for-beginners/module/910a0b7a-ac6e-43f1-956e-203a70c3d455/lesson/ebcb2c5e-7537-4c08-a561-8f09c05276c8" />
</CardGroup>
