Terraform
Integrate your private module registry with the Terraform MCP server
The Terraform Model Context Protocol (MCP) server enhances AI models with real-time access to current Terraform provider documentation, modules, and policies from the Terraform registry. This ensures AI-generated Terraform configurations use accurate, up-to-date information rather than potentially outdated training data.
MCP is an open standard that enables AI models to securely connect with external tools, applications, and data sources. MCP allows AI models to access information beyond their training data, providing more current and accurate responses.
In this tutorial you will add modules to your private module registry in HCP Terraform, deploy the Terraform MCP server, then use it to assist in writing your own Terraform module.
Prerequisites
This tutorial assumes that you are familiar with the Terraform workflow. If you are new to Terraform, complete the Get Started collection first.
To complete this tutorial, you will need the following:
- The Terraform CLI (v1.14.0+) installed locally.
- An HCP Terraform or Terraform Enterprise organization.
- A GitHub account.
- An AWS account and associated credentials.
- The AWS CLI installed locally.
- Visual Studio Code (v1.99+) installed locally with GitHub Copilot.
Publish a private module
Navigate to the template repository for this tutorial. Click the Use this template button and select Create a new repository. Choose a GitHub account to create the repository in and name the new repository terraform-aws-s3-static-website. Leave the rest of the settings at their default values.
Review module configuration
The module repository contains the following files:
.
├── main.tf
├── outputs.tf
├── README.md
├── terraform.tf
├── variables.tf
└── www
├── dot-pattern.png
├── hashicorp-logos.png
├── index.html
├── terramino.css
└── terramino.js
This module deploys and configures an AWS S3 bucket to host a static website, then uploads a collection of HTML, JavaScript, CSS, and images to the bucket. It also defines variables that let you customize the deployment, such as the path to the website files, so that you can use the module to deploy your own custom website.
Publish the module
Complete the following steps to publish the module to your HCP Terraform organization’s private module registry:
- Sign in to your HCP Terraform or Terraform Enterprise organization and click Registry in the sidebar.
- Click the Publish dropdown, then click Module.
- Choose your VCS provider.
- In the Repository dropdown, select the terraform-aws-static-website repository you created earlier in this tutorial.
- Under Module Publishing Type, chose Branch.
- Enter a Branch Name of
main. - Enter a Module Version of
1.0.0. - Click Next.
- Enter a Module Name of
terraform-aws-static-website. - Enter a Provider Name of
aws. - Click Publish module.
After a few moments, HCP Terraform displays your module overview.
Add public modules to your private registry
Next, add more modules to your private registry to give the MCP server more to search through. HCP Terraform lets you search for modules in the public module registry and add them to your private registry. The private registry stores a pointer to these public modules so that you can view their data from within HCP Terraform.
Navigate back to your organizations registry’s Private Library, then click Search public registry.
In the search box, enter terraform-aws-modules/vpc, hover over the terraform-aws-modules/vpc module, then click Add. HCP Terraform shows a prompt to confirm that you want to add the module to your registry. Click Add to finish adding the module.
Repeat these steps with the hashicorp/subnets module.
Create a team token
To connect the MCP server to HCP Terraform or Terraform Enterprise, you must create an API token for the server to present. Create a team to scope the access of your API token.
Complete the following steps to create a new team:
- Navigate to your organization’s Settings page.
- Click Teams in the left navigation panel, then click Create a team.
- Enter
mcpin the Team name field. - Click Create.
- Enable the following team permissions settings:
- Under Project permissions, select View all projects.
- Under Workspace permissions, select Manage all workspaces
- Under Settings permissions, select Manage policies**
- Under Private registry permissions, select Manage private registry and leave all of the related boxes checked.
- Click the Update team organization access button to save your team's permissions.
Next, create a team API token for this team. On your team’s configuration page, scroll down and click the Go to API tokens button.
On the API tokens page, make sure you are on the Team Tokens tab, then click Create a team token.
Select the mcp team under the Team dropdown, leave the default Expiration at 30 days, then click Create.
HCP Terraform only shows your API token once, so copy it and store it in a secure location. You will use this token when you deploy the MCP server.
Deploy the MCP server
In your terminal, clone the next example repository for this tutorial.
$ git clone https://github.com/hashicorp-education/terraform-aws-terraform-mcp-server.git
Change into the repository directory.
$ cd terraform-aws-terraform-mcp-server
Next, review the configuration. This configuration deploys the MCP server on AWS ECS using Fargate, and configures the required networking resources including a load balancer to add authentication in front of the MCP server.
Open the mcp.tf file. This configuration sets up an ECS cluster, deploys the Terraform MCP server container to it, and configures CloudWatch so that you can review the logs from the container.
mcp.tf
resource "aws_ecs_cluster" "compute" {
name = "terraform-mcp-${random_string.suffix.id}"
}
resource "aws_ecs_task_definition" "mcp" {
family = "terraform-mcp"
requires_compatibilities = ["FARGATE"]
network_mode = "awsvpc"
cpu = "256"
memory = "512"
execution_role_arn = aws_iam_role.ecs_execution.arn
container_definitions = jsonencode([
{
name = "terraform-mcp-${random_string.suffix.id}"
image = "hashicorp/terraform-mcp-server"
essential = true
environment = [
{
name = "TRANSPORT_MODE"
value = "streamable-http"
},
{
name = "TRANSPORT_HOST"
value = "0.0.0.0"
},
{
name = "TRANSPORT_PORT"
value = tostring(var.port)
},
{
name = "LOG_LEVEL"
value = var.log_level
},
{
name = "TFE_ADDRESS",
value = var.tfe_address
},
{
name = "TFE_TOKEN",
value = var.tfe_token
}
]
portMappings = [{
containerPort = var.port
protocol = "tcp"
}]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.mcp.name
"awslogs-region" = var.region
"awslogs-stream-prefix" = "ecs"
}
}
}
])
}
resource "aws_ecs_service" "mcp" {
name = "terraform-mcp-${random_string.suffix.id}"
cluster = aws_ecs_cluster.compute.id
task_definition = aws_ecs_task_definition.mcp.arn
desired_count = 1
launch_type = "FARGATE"
network_configuration {
subnets = module.vpc.private_subnets
security_groups = [aws_security_group.fargate_traffic.id]
assign_public_ip = false
}
load_balancer {
target_group_arn = aws_lb_target_group.mcp.arn
container_name = "terraform-mcp-${random_string.suffix.id}"
container_port = var.port
}
depends_on = [aws_lb.mcp]
}
resource "aws_cloudwatch_log_group" "mcp" {
name = "/ecs/terraform-mcp"
retention_in_days = 1
}
This tutorial does not store an API token with the MCP server, and instead configures the client to send it with every request. However, you can choose to set the TFE_TOKEN environment variable to configure the MCP server to use a set token with every request. If you configure the TFE_TOKEN on both the server and the client, the MCP server chooses to use the client's API token. This is useful if you want to support limited permissions by default, but allow users to authenticate with higher permissions.
Next, open the networking.tf file. This configuration sets up the network infrastructure required by the rest of the configuration. It uses a module to deploy a VPC, then sets up a load balancer between the user and the MCP server.
The configuration also generates a random password and configures the load balancer to reject all requests unless they are authenticated with the username admin and the generated password. The configuration also sets up CloudFront to encrypt all traffic between the client and AWS.
networking.tf
##...
resource "aws_lb_listener_rule" "auth" {
listener_arn = aws_lb_listener.mcp.arn
priority = 1
action {
type = "forward"
target_group_arn = aws_lb_target_group.mcp.arn
}
condition {
http_header {
http_header_name = "Authorization"
values = ["Basic ${base64encode("admin:${random_string.password.id}")}"]
}
}
}
Next, initialize your configuration.
$ terraform init
Initializing the backend...
Initializing modules...
Downloading registry.terraform.io/terraform-aws-modules/vpc/aws 6.6.1 for vpc...
- vpc in .terraform/modules/vpc
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Reusing previous version of hashicorp/random from the dependency lock file
- Installing hashicorp/aws v6.46.0...
- Installed hashicorp/aws v6.46.0 (signed by HashiCorp)
- Installing hashicorp/random v3.9.0...
- Installed hashicorp/random v3.9.0 (signed by HashiCorp)
Terraform has been successfully initialized!
Apply the configuration. When prompted, enter yes to confirm the apply operation. This will take several minutes to complete.
$ terraform apply
data.aws_availability_zones.available: Reading...
data.aws_availability_zones.available: Read complete after 1s [id=us-east-2]
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:
##...
Plan: 38 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ authorization = (sensitive value)
+ cluster_name = (known after apply)
+ hostname = (known after apply)
+ mcp_json = (sensitive value)
+ service_name = (known after apply)
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
random_string.suffix: Creating...
##...
Apply complete! Resources: 38 added, 0 changed, 0 destroyed.
Outputs:
authorization = <sensitive>
cluster_name = "terraform-mcp-abcd1234"
hostname = "terraform-mcp- abcd1234-1234567890.us-east-2.elb.amazonaws.com:8080"
mcp_json = <sensitive>
The MCP server may take a few minutes to start responding to requests. Use curl to send a request to the MCP server health endpoint to test if it is running and accepting requests.
$ curl -H "Authorization: Basic $(terraform output -raw authorization)" $(terraform output -raw hostname)/health
{"status":"ok","service":"terraform-mcp-server","transport":"streamable-http","endpoint":"/mcp"}
This configuration also configures AWS CloudWatch to gather logs from the MCP server. Open a new terminal and use the AWS CLI to watch the logs.
$ aws logs tail /ecs/terraform-mcp --follow
2026-05-22T14:59:23.222000+00:00 ecs/terraform-mcp-Zrs43Ea2/566635c5a9f3431392093f44e9ec4972 time="2026-05-22T14:59:23Z" level=info msg="Starting in Streamable HTTP mode based on environment configuration"
Configure Visual Studio Code
Visual Studio Code lets you add MCP server configurations to either your user or workspace configuration. For this tutorial, create a new Visual Studio Code workspace and add your MCP configuration to it.
First, copy your MCP server configuration from the Terraform output. In your original terminal, run the following command to show the configuration as JSON.
$ terraform output -raw mcp_json
Copy this output. Next, navigate out of the terraform-aws-terraform-mcp-server directory.
$ cd ..
Create a new directory to use as a new Visual Studio Code workspace.
$ mkdir learn-terraform-mcp
Change to the new directory.
$ cd learn-terraform-mcp
Next, create a .vscode directory with an empty mcp.json file.
$ mkdir .vscode && touch .vscode/mcp.json
Open the .vscode/mcp.json file and add your MCP server configuration from the Terraform output.
.vscode/mcp.json
{
"servers": {
"terraform-mcp-server": {
"url": "https://example1234.cloudfront.net/mcp",
"type": "http",
"headers": {
"Authorization": "Basic ExampleAuth123456789=",
"TFE_TOKEN": "TOKEN"
}
}
},
"inputs": []
}
Replace the TFE_TOKEN value with the team API token you created and save the file.
For more information on configuring VS Code to use the Terraform MCP server, refer to the Deploy the Terraform MCP server documentation.
Use the MCP server to explore the private registry
Use the MCP server to query information about your HCP Terraform or Terraform Enterprise organization and generate Terraform configuration.
Open the chat window in Visual Studio Code. To open the chat window, click View and choose Chat from the dropdown menu.
Next, enter the following prompt to discover the modules you have in your private registry.
#terraform-mcp-server What modules do I have in my HCP Terraform organization to manage AWS resources?
Visual Studio Code lets you use the # symbol to tell the AI model to specifically use files, MCP servers, and other tools in your prompts. In this example, the #terraform-mcp-server mention helps make sure the model uses the MCP server. Refer to the Manage context for AI Visual Studio Code documentation for more information.
If Visual Studio Code prompts you to approve the tool result, click Allow Without Review in this Session.
The AI model uses the Terraform MCP server to query the HCP Terraform or Terraform Enterprise API for your organization name. Next, it queries your organization for the modules in the private registry. Then, it uses the MCP server to gather more information about the modules it found and determine which modules meet your requirements. Because AI models are nondeterministic, you may need to supply follow-up prompts or answer questions to help guide the model.
When the model responds to your prompt, it lists the modules in your private registry that use the AWS provider, including the public modules you added to your private registry.
Next, continue chatting with the model to narrow down which module you should use to deploy the website. Enter the following prompt.
Which of these modules can I use to deploy a website to AWS?
The model uses the Terraform MCP server to gather details to determine which module is the best to use to deploy a website. The model checks the README, inputs, outputs, and the resources the modules deploy. Information such as variable and output descriptions help AI models and the MCP server more accurately determine what a module creates.
Likely, the model worked with the MCP server to determine that terraform-aws-static-website module you published earlier in this tutorial is the best fit. If not, continue to prompt the model to help narrow down your choice.
Generate Terraform configuration
Now that you have used the AI model and the MCP server to gather information about the modules in your registry, run the following prompt to generate a static website and the Terraform configuration to deploy it.
Generate a static website that contains a list of links to the Terraform MCP server documentation on developer.hashicorp.com. Then, generate Terraform configuration that uses the terraform-aws-static-website module to deploy it.
After a few moments, the model generates a static website as well as the Terraform configuration to deploy it. Click Keep to use this configuration.
Review the Terraform configuration, as well as the HTML the model generated. The MCP server uses the Terraform style guide to generate Terraform configuration, so it likely created a file named main.tf. If you do not see this file, explore the other files it generated. The following example includes configuration that the model and MCP server may generate.
main.tf
terraform {
required_version = ">= 1.2.0"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 6.46.0"
}
}
}
provider "aws" {
region = var.region
}
module "static_site" {
source = "app.terraform.io/YOUR_ORGANIZATION/terraform-aws-static-website/aws"
version = "1.0.0"
region = var.region
path = var.website_path
bucket_name = var.bucket_name
tags = var.tags
}
Depending on the configuration the model generated for you, your configuration may be different and may have additional files. In this example, the model may create a variables.tf file to define input variables and an outputs.tf file to define the output values.
Next, initialize your configuration.
$ terraform init
Initializing the backend...
Initializing modules...
Downloading app.terraform.io/YOUR_ORGANIZATION/terraform-aws-static-website/aws 1.0.0 for static_site...
- static_site in .terraform/modules/static_site
Initializing provider plugins...
- Reusing previous version of hashicorp/aws from the dependency lock file
- Installing hashicorp/aws v6.46.0...
- Installed hashicorp/aws v6.46.0 (signed by HashiCorp)
Terraform has been successfully initialized!
Next, run terraform plan and verify the resources that Terraform will deploy when you apply the plan.
$ terraform plan
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:
+ resource "aws_s3_bucket" "s3_bucket" {
##...
+ resource "aws_s3_bucket_acl" "s3_bucket" {
##...
+ resource "aws_s3_bucket_ownership_controls" "s3_bucket" {
##...
+ resource "aws_s3_bucket_policy" "s3_bucket" {
##...
+ resource "aws_s3_bucket_public_access_block" "s3_bucket" {
##...
+ resource "aws_s3_bucket_website_configuration" "s3_bucket" {
##...
+ resource "aws_s3_object" "files" {
##...
+ resource "aws_s3_object" "files" {
##...
Plan: 8 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ bucket_arn = (known after apply)
+ bucket_name = (known after apply)
+ error_endpoint = (known after apply)
+ website_endpoint = (known after apply)
After you confirm that the resources the configuration deploys match your expectations, run terraform apply to deploy them. When prompted, respond with yes to confirm the apply operation.
$ terraform apply
##...
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
##...
Apply complete! Resources: 8 added, 0 changed, 0 destroyed.
Outputs:
bucket_arn = "arn:aws:s3:::terraform-123456789123456789123456789"
bucket_name = "terraform-123456789123456789123456789"
error_endpoint = "http://terraform-123456789123456789123456789.s3-website.us-east-2.amazonaws.com/error.html"
website_endpoint = "http://terraform-123456789123456789123456789.s3-website.us-east-2.amazonaws.com/index.html"
Next, open the website. In this example, the website_endpoint output provides the URL to reach the static website, but this output may be different depending on the configuration you generated.

It may take a few moments for AWS to start responding to requests to this URL.
Continue to issue prompts to the model to explore your HCP Terraform or Terraform Enterprise organization and iterate on your Terraform configuration.
Clean up resources
Delete the resources you created in this tutorial to run the MCP server and the static website.
First, delete the static website you created with the MCP server. Run the terraform destroy command in the learn-terraform-mcp directory. When prompted, enter yes to confirm that you want to destroy the infrastructure.
$ terraform destroy
##...
Plan: 0 to add, 0 to change, 8 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
##...
Destroy complete! Resources: 8 destroyed.
In your terminal, navigate back to the terraform-aws-terraform-mcp-server directory.
$ cd ../terraform-aws-terraform-mcp-server
Next, run terraform destroy to delete the MCP server infrastructure. When prompted, respond with yes to confirm the deletion.
$ terraform destroy
##...
Plan: 0 to add, 0 to change, 38 to destroy.
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes
##...
Destroy complete! Resources: 38 destroyed.
Next, delete the mcp team token now that you no longer need it. Navigate to your HCP Terraform or Terraform Enterprise organization’s Settings page, choose API tokens in the left navigation panel, then choose the Team Tokens tab.
Click the ellipsis next to the mcp team token, then click Delete. Click Confirm to delete your team token.
Finally, delete the team you created for this tutorial. Click Teams in the left navigation panel, then click the mcp team. Scroll down to the bottom of the page and click the Delete mcp button. Click Yes, delete team to delete the team.
Next steps
In this tutorial, you learned how to deploy and configure the Terraform MCP server. Then, you learned how to connect VS Code to the MCP server and use it to query information about your HCP Terraform or Terraform Enterprise organization and generate Terraform configuration.
To learn more about the Terraform MCP server, refer to the following resources:
- Read the Terraform MCP server overview documentation.
- Learn the different methods to Deploy the Terraform MCP server
- Refer to the Terraform MCP server reference to learn about the specialized tools the Terraform MCP server provides to AI models.