awslabs.terraform-mcp-server 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of awslabs.terraform-mcp-server might be problematic. Click here for more details.
- awslabs/__init__.py +2 -0
- awslabs/terraform_mcp_server/__init__.py +3 -0
- awslabs/terraform_mcp_server/impl/resources/__init__.py +11 -0
- awslabs/terraform_mcp_server/impl/resources/terraform_aws_provider_resources_listing.py +52 -0
- awslabs/terraform_mcp_server/impl/resources/terraform_awscc_provider_resources_listing.py +55 -0
- awslabs/terraform_mcp_server/impl/tools/__init__.py +15 -0
- awslabs/terraform_mcp_server/impl/tools/execute_terraform_command.py +206 -0
- awslabs/terraform_mcp_server/impl/tools/run_checkov_scan.py +359 -0
- awslabs/terraform_mcp_server/impl/tools/search_aws_provider_docs.py +677 -0
- awslabs/terraform_mcp_server/impl/tools/search_awscc_provider_docs.py +627 -0
- awslabs/terraform_mcp_server/impl/tools/search_specific_aws_ia_modules.py +444 -0
- awslabs/terraform_mcp_server/impl/tools/utils.py +558 -0
- awslabs/terraform_mcp_server/models/__init__.py +27 -0
- awslabs/terraform_mcp_server/models/models.py +260 -0
- awslabs/terraform_mcp_server/scripts/generate_aws_provider_resources.py +1224 -0
- awslabs/terraform_mcp_server/scripts/generate_awscc_provider_resources.py +1020 -0
- awslabs/terraform_mcp_server/scripts/scrape_aws_terraform_best_practices.py +129 -0
- awslabs/terraform_mcp_server/server.py +329 -0
- awslabs/terraform_mcp_server/static/AWSCC_PROVIDER_RESOURCES.md +3125 -0
- awslabs/terraform_mcp_server/static/AWS_PROVIDER_RESOURCES.md +3833 -0
- awslabs/terraform_mcp_server/static/AWS_TERRAFORM_BEST_PRACTICES.md +2523 -0
- awslabs/terraform_mcp_server/static/MCP_INSTRUCTIONS.md +126 -0
- awslabs/terraform_mcp_server/static/TERRAFORM_WORKFLOW_GUIDE.md +198 -0
- awslabs/terraform_mcp_server/static/__init__.py +22 -0
- awslabs/terraform_mcp_server/tests/__init__.py +1 -0
- awslabs/terraform_mcp_server/tests/run_tests.sh +35 -0
- awslabs/terraform_mcp_server/tests/test_parameter_annotations.py +207 -0
- awslabs/terraform_mcp_server/tests/test_tool_implementations.py +309 -0
- awslabs_terraform_mcp_server-0.0.1.dist-info/METADATA +97 -0
- awslabs_terraform_mcp_server-0.0.1.dist-info/RECORD +32 -0
- awslabs_terraform_mcp_server-0.0.1.dist-info/WHEEL +4 -0
- awslabs_terraform_mcp_server-0.0.1.dist-info/entry_points.txt +2 -0
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
"""Test script for Terraform MCP server implementation functions."""
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
import json
|
|
5
|
+
import sys
|
|
6
|
+
from awslabs.terraform_mcp_server.impl.tools.search_aws_provider_docs import (
|
|
7
|
+
search_aws_provider_docs_impl,
|
|
8
|
+
)
|
|
9
|
+
from awslabs.terraform_mcp_server.impl.tools.search_awscc_provider_docs import (
|
|
10
|
+
search_awscc_provider_docs_impl,
|
|
11
|
+
)
|
|
12
|
+
from awslabs.terraform_mcp_server.impl.tools.search_specific_aws_ia_modules import (
|
|
13
|
+
search_specific_aws_ia_modules_impl,
|
|
14
|
+
)
|
|
15
|
+
from loguru import logger
|
|
16
|
+
from typing import Any
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Configure logger for enhanced diagnostics with stacktraces
|
|
20
|
+
logger.configure(
|
|
21
|
+
handlers=[
|
|
22
|
+
{
|
|
23
|
+
'sink': sys.stderr,
|
|
24
|
+
'backtrace': True,
|
|
25
|
+
'diagnose': True,
|
|
26
|
+
'format': '<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan> - <level>{message}</level>',
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def print_aws_provider_results(results):
|
|
33
|
+
"""Print formatted results data using the provided logger.
|
|
34
|
+
|
|
35
|
+
Args:
|
|
36
|
+
results: List of result objects containing asset information
|
|
37
|
+
logger: Logger object to use for output
|
|
38
|
+
"""
|
|
39
|
+
logger.info(f'Found {len(results)} results')
|
|
40
|
+
|
|
41
|
+
for i, result in enumerate(results):
|
|
42
|
+
logger.info(f'\nResult {i + 1}:')
|
|
43
|
+
logger.info(f' Asset Name: {result.asset_name}')
|
|
44
|
+
logger.info(f' Asset Type: {result.asset_type}')
|
|
45
|
+
logger.info(f' URL: {result.url}')
|
|
46
|
+
|
|
47
|
+
# Handle description
|
|
48
|
+
if result.description:
|
|
49
|
+
description_preview = (
|
|
50
|
+
result.description[:50] + '...'
|
|
51
|
+
if len(result.description) > 50
|
|
52
|
+
else result.description
|
|
53
|
+
)
|
|
54
|
+
logger.info(f' Description: {description_preview}')
|
|
55
|
+
else:
|
|
56
|
+
logger.info(' No description')
|
|
57
|
+
|
|
58
|
+
# Handle example usage
|
|
59
|
+
if result.example_usage:
|
|
60
|
+
logger.info(f' Example Usage: {len(result.example_usage)} found')
|
|
61
|
+
|
|
62
|
+
# Handle arguments
|
|
63
|
+
if result.arguments:
|
|
64
|
+
logger.info(f' Arguments: {len(result.arguments)} found')
|
|
65
|
+
|
|
66
|
+
# Handle attributes
|
|
67
|
+
if result.attributes:
|
|
68
|
+
logger.info(f' Attributes: {len(result.attributes)} found')
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def print_awscc_provider_results(results):
|
|
72
|
+
"""Print formatted results data using the provided logger.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
results: List of result objects containing asset information
|
|
76
|
+
logger: Logger object to use for output
|
|
77
|
+
"""
|
|
78
|
+
logger.info(f'Found {len(results)} results')
|
|
79
|
+
|
|
80
|
+
for i, result in enumerate(results):
|
|
81
|
+
logger.info(f'\nResult {i + 1}:')
|
|
82
|
+
logger.info(f' Asset Name: {result.asset_name}')
|
|
83
|
+
logger.info(f' Asset Type: {result.asset_type}')
|
|
84
|
+
logger.info(f' URL: {result.url}')
|
|
85
|
+
|
|
86
|
+
# Handle description
|
|
87
|
+
if result.description:
|
|
88
|
+
description_preview = (
|
|
89
|
+
result.description[:50] + '...'
|
|
90
|
+
if len(result.description) > 50
|
|
91
|
+
else result.description
|
|
92
|
+
)
|
|
93
|
+
logger.info(f' Description: {description_preview}')
|
|
94
|
+
else:
|
|
95
|
+
logger.info(' No description')
|
|
96
|
+
|
|
97
|
+
# Handle example usage
|
|
98
|
+
if result.example_usage:
|
|
99
|
+
logger.info(f' Example Usage: {len(result.example_usage)} found')
|
|
100
|
+
|
|
101
|
+
# Handle schema arguments
|
|
102
|
+
if result.schema_arguments:
|
|
103
|
+
logger.info(f' Schema arguments: {len(result.schema_arguments)} found')
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
async def test_search_aws_provider_docs():
|
|
107
|
+
"""Test the AWS provider docs search function."""
|
|
108
|
+
logger.info('=== Testing search_aws_provider_docs_impl ===')
|
|
109
|
+
|
|
110
|
+
# Test case 1: Common resource with just 1 example snippet
|
|
111
|
+
logger.info('**********---Test case 1: Searching for aws_s3_bucket as a resource---**********')
|
|
112
|
+
results = await search_aws_provider_docs_impl('aws_s3_bucket', 'resource')
|
|
113
|
+
print_aws_provider_results(results)
|
|
114
|
+
|
|
115
|
+
# Test case 2: Common resource with multiple example snippets
|
|
116
|
+
logger.info(
|
|
117
|
+
'**********---Test case 2: Searching for aws_api_gateway_rest_api as a resource---**********'
|
|
118
|
+
)
|
|
119
|
+
results = await search_aws_provider_docs_impl('api_gateway_rest_api', 'resource')
|
|
120
|
+
print_aws_provider_results(results)
|
|
121
|
+
|
|
122
|
+
# Test case 3: Common resource with multiple example snippets and multiple arguments in subsections
|
|
123
|
+
logger.info(
|
|
124
|
+
'**********---Test case 3: Searching for aws_lambda_function as a resource---**********'
|
|
125
|
+
)
|
|
126
|
+
results = await search_aws_provider_docs_impl('aws_lambda_function', 'resource')
|
|
127
|
+
print_aws_provider_results(results)
|
|
128
|
+
|
|
129
|
+
# Test case 4: Specifying data source as asset type
|
|
130
|
+
logger.info(
|
|
131
|
+
'**********---Test case 4: Searching for aws_lambda_function as a data source ---**********'
|
|
132
|
+
)
|
|
133
|
+
results = await search_aws_provider_docs_impl('aws_lambda_function', 'data_source')
|
|
134
|
+
print_aws_provider_results(results)
|
|
135
|
+
|
|
136
|
+
# Test case 5: Searching for both kinds
|
|
137
|
+
logger.info('**********---Test case 5: Searching for aws_dynamodb_table as both ---**********')
|
|
138
|
+
results = await search_aws_provider_docs_impl('aws_dynamodb_table', 'both')
|
|
139
|
+
print_aws_provider_results(results)
|
|
140
|
+
|
|
141
|
+
# Test case 6: Non-existent resource
|
|
142
|
+
logger.info('**********---Test case 6: Searching for non-existent resource---**********')
|
|
143
|
+
results = await search_aws_provider_docs_impl('aws_nonexistent_resource')
|
|
144
|
+
print_aws_provider_results(results)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
async def test_search_awscc_provider_docs():
|
|
148
|
+
"""Test the AWSCC provider docs search function."""
|
|
149
|
+
logger.info('\n=== Testing search_awscc_provider_docs_impl ===')
|
|
150
|
+
|
|
151
|
+
# Test case 1: Common resource
|
|
152
|
+
logger.info(
|
|
153
|
+
'**********---Test case 1: Searching for awscc_apigateway_api_key as a resource---**********'
|
|
154
|
+
)
|
|
155
|
+
results = await search_awscc_provider_docs_impl('awscc_apigateway_api_key', 'resource')
|
|
156
|
+
print_awscc_provider_results(results)
|
|
157
|
+
|
|
158
|
+
# Test case 2: Resource with attribute
|
|
159
|
+
logger.info(
|
|
160
|
+
'**********---Test case 2: Searching for awscc_apigateway_api_key as a data source---**********'
|
|
161
|
+
)
|
|
162
|
+
results = await search_awscc_provider_docs_impl('awscc_apigateway_api_key', 'data_source')
|
|
163
|
+
print_awscc_provider_results(results)
|
|
164
|
+
|
|
165
|
+
# Test case 3: lambda_function resource
|
|
166
|
+
logger.info(
|
|
167
|
+
'**********---Test case 7: Searching for lambda_function as a resource---**********'
|
|
168
|
+
)
|
|
169
|
+
results = await search_awscc_provider_docs_impl('lambda_function', 'resource')
|
|
170
|
+
print_awscc_provider_results(results)
|
|
171
|
+
|
|
172
|
+
# Test case 4: Searching for both kinds
|
|
173
|
+
logger.info(
|
|
174
|
+
'**********---Test case 4: Searching for lambda_function as both kinds---**********'
|
|
175
|
+
)
|
|
176
|
+
results = await search_awscc_provider_docs_impl('awscc_lambda_function', 'both')
|
|
177
|
+
print_awscc_provider_results(results)
|
|
178
|
+
|
|
179
|
+
# Test case 5: Non-existent resource
|
|
180
|
+
logger.info('**********---Test case 5: Searching for non-existent resource---**********')
|
|
181
|
+
results = await search_awscc_provider_docs_impl('awscc_nonexistent_resource')
|
|
182
|
+
print_awscc_provider_results(results)
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
async def test_search_specific_aws_ia_modules():
|
|
186
|
+
"""Test the AWS IA modules search function."""
|
|
187
|
+
logger.info('\n=== Testing search_specific_aws_ia_modules_impl ===')
|
|
188
|
+
|
|
189
|
+
# Test case 1: Search all modules
|
|
190
|
+
logger.info('Test case 1: Searching all AWS IA modules')
|
|
191
|
+
results = await search_specific_aws_ia_modules_impl('')
|
|
192
|
+
|
|
193
|
+
logger.info(f'Found {len(results)} modules')
|
|
194
|
+
for i, result in enumerate(results):
|
|
195
|
+
logger.info(f'\nModule {i + 1}:')
|
|
196
|
+
logger.info(f' Name: {result.name}')
|
|
197
|
+
logger.info(f' Namespace: {result.namespace}')
|
|
198
|
+
logger.info(
|
|
199
|
+
f' Description: {result.description[:100]}...'
|
|
200
|
+
if result.description
|
|
201
|
+
else ' No description'
|
|
202
|
+
)
|
|
203
|
+
logger.info(f' URL: {result.url}')
|
|
204
|
+
|
|
205
|
+
# Test case 2: Search with query
|
|
206
|
+
logger.info("\nTest case 2: Searching for 'bedrock' modules")
|
|
207
|
+
results = await search_specific_aws_ia_modules_impl('bedrock')
|
|
208
|
+
|
|
209
|
+
logger.info(f'Found {len(results)} modules')
|
|
210
|
+
for i, result in enumerate(results):
|
|
211
|
+
logger.info(f'\nModule {i + 1}:')
|
|
212
|
+
logger.info(f' Name: {result.name}')
|
|
213
|
+
logger.info(f' Namespace: {result.namespace}')
|
|
214
|
+
logger.info(
|
|
215
|
+
f' Description: {result.description[:100]}...'
|
|
216
|
+
if result.description
|
|
217
|
+
else ' No description'
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
async def test_execute_terraform_command():
|
|
222
|
+
"""Test the Terraform command execution function.
|
|
223
|
+
|
|
224
|
+
Note: This test requires a valid Terraform configuration in a temporary directory.
|
|
225
|
+
Skip this test if you don't have a valid Terraform configuration to test with.
|
|
226
|
+
"""
|
|
227
|
+
logger.info('\n=== Testing execute_terraform_command_impl ===')
|
|
228
|
+
logger.info('Skipping actual execution as it requires a valid Terraform configuration.')
|
|
229
|
+
logger.info('To test this function, you would need to:')
|
|
230
|
+
logger.info('1. Create a temporary directory with valid Terraform files')
|
|
231
|
+
logger.info('2. Run terraform init, plan, etc. on those files')
|
|
232
|
+
|
|
233
|
+
# Example of how you would call it (commented out)
|
|
234
|
+
"""
|
|
235
|
+
request = TerraformExecutionRequest(
|
|
236
|
+
command="validate",
|
|
237
|
+
working_directory="/path/to/terraform/config",
|
|
238
|
+
variables={"environment": "test"},
|
|
239
|
+
aws_region="us-west-2",
|
|
240
|
+
strip_ansi=True
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
result = await execute_terraform_command_impl(request)
|
|
244
|
+
logger.info(f"Command: {result.command}")
|
|
245
|
+
logger.info(f"Status: {result.status}")
|
|
246
|
+
logger.info(f"Return Code: {result.return_code}")
|
|
247
|
+
if result.stdout:
|
|
248
|
+
logger.info(f"Stdout: {result.stdout[:100]}...")
|
|
249
|
+
if result.stderr:
|
|
250
|
+
logger.info(f"Stderr: {result.stderr[:100]}...")
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
async def test_run_checkov_scan():
|
|
255
|
+
"""Test the Checkov scan function.
|
|
256
|
+
|
|
257
|
+
Note: This test requires a valid Terraform configuration in a temporary directory.
|
|
258
|
+
Skip this test if you don't have a valid Terraform configuration to test with.
|
|
259
|
+
"""
|
|
260
|
+
logger.info('\n=== Testing run_checkov_scan_impl ===')
|
|
261
|
+
logger.info('Skipping actual execution as it requires a valid Terraform configuration.')
|
|
262
|
+
logger.info('To test this function, you would need to:')
|
|
263
|
+
logger.info('1. Create a temporary directory with valid Terraform files')
|
|
264
|
+
logger.info('2. Run Checkov on those files')
|
|
265
|
+
|
|
266
|
+
# Example of how you would call it (commented out)
|
|
267
|
+
"""
|
|
268
|
+
request = CheckovScanRequest(
|
|
269
|
+
working_directory="/path/to/terraform/config",
|
|
270
|
+
framework="terraform",
|
|
271
|
+
output_format="json"
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
result = await run_checkov_scan_impl(request)
|
|
275
|
+
logger.info(f"Status: {result.status}")
|
|
276
|
+
logger.info(f"Return Code: {result.return_code}")
|
|
277
|
+
logger.info(f"Found {len(result.vulnerabilities)} vulnerabilities")
|
|
278
|
+
for i, vuln in enumerate(result.vulnerabilities[:3]): # Show first 3 only
|
|
279
|
+
logger.info(f"\nVulnerability {i+1}:")
|
|
280
|
+
logger.info(f" ID: {vuln.id}")
|
|
281
|
+
logger.info(f" Resource: {vuln.resource}")
|
|
282
|
+
logger.info(f" Description: {vuln.description[:100]}..." if vuln.description else " No description")
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def format_json(obj: Any) -> str:
|
|
287
|
+
"""Format an object as pretty JSON."""
|
|
288
|
+
if hasattr(obj, 'model_dump'):
|
|
289
|
+
# For Pydantic v2
|
|
290
|
+
data = obj.model_dump()
|
|
291
|
+
elif hasattr(obj, 'dict'):
|
|
292
|
+
# For Pydantic v1
|
|
293
|
+
data = obj.dict()
|
|
294
|
+
else:
|
|
295
|
+
data = obj
|
|
296
|
+
return json.dumps(data, indent=2, default=str)
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
async def main():
|
|
300
|
+
"""Run all tests."""
|
|
301
|
+
try:
|
|
302
|
+
await test_search_aws_provider_docs()
|
|
303
|
+
await test_search_awscc_provider_docs()
|
|
304
|
+
except Exception as e:
|
|
305
|
+
logger.exception(f'Error running tests: {e}')
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
if __name__ == '__main__':
|
|
309
|
+
asyncio.run(main())
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: awslabs.terraform-mcp-server
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: An AWS Labs Model Context Protocol (MCP) server for terraform
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: beautifulsoup4>=4.12.0
|
|
7
|
+
Requires-Dist: checkov>=3.2.402
|
|
8
|
+
Requires-Dist: loguru>=0.7.0
|
|
9
|
+
Requires-Dist: mcp[cli]>=1.6.0
|
|
10
|
+
Requires-Dist: playwright>=1.40.0
|
|
11
|
+
Requires-Dist: pydantic>=2.10.6
|
|
12
|
+
Requires-Dist: pypdf2>=3.0.0
|
|
13
|
+
Requires-Dist: requests>=2.31.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# AWS Terraform MCP Server
|
|
17
|
+
|
|
18
|
+
MCP server for Terraform on AWS best practices, infrastructure as code patterns, and security compliance with Checkov.
|
|
19
|
+
|
|
20
|
+
## Features
|
|
21
|
+
|
|
22
|
+
- **Terraform Best Practices** - Get prescriptive Terraform advice for building applications on AWS
|
|
23
|
+
- AWS Well-Architected guidance for Terraform configurations
|
|
24
|
+
- Security and compliance recommendations
|
|
25
|
+
- AWSCC provider prioritization for consistent API behavior
|
|
26
|
+
|
|
27
|
+
- **Security-First Development Workflow** - Follow a structured process for creating secure code
|
|
28
|
+
- Step-by-step guidance for validation and security scanning
|
|
29
|
+
- Integration of Checkov at the right stages of development
|
|
30
|
+
- Clear handoff points between AI assistance and developer deployment
|
|
31
|
+
|
|
32
|
+
- **Checkov Integration** - Work with Checkov for security and compliance scanning
|
|
33
|
+
- Run security scans on Terraform code to identify vulnerabilities
|
|
34
|
+
- Automatically fix identified security issues when possible
|
|
35
|
+
- Get detailed remediation guidance for compliance issues
|
|
36
|
+
|
|
37
|
+
- **AWS Provider Documentation** - Search for AWS and AWSCC provider resources
|
|
38
|
+
- Find documentation for specific resources and attributes
|
|
39
|
+
- Get example snippets and implementation guidance
|
|
40
|
+
- Compare AWS and AWSCC provider capabilities
|
|
41
|
+
|
|
42
|
+
- **AWS-IA GenAI Modules** - Access specialized modules for AI/ML workloads
|
|
43
|
+
- Amazon Bedrock module for generative AI applications
|
|
44
|
+
- OpenSearch Serverless for vector search capabilities
|
|
45
|
+
- SageMaker endpoint deployment for ML model hosting
|
|
46
|
+
- Serverless Streamlit application deployment for AI interfaces
|
|
47
|
+
|
|
48
|
+
- **Terraform Workflow Execution** - Run Terraform commands directly
|
|
49
|
+
- Initialize, plan, validate, apply, and destroy operations
|
|
50
|
+
- Pass variables and specify AWS regions
|
|
51
|
+
- Get formatted command output for analysis
|
|
52
|
+
|
|
53
|
+
## Tools and Resources
|
|
54
|
+
|
|
55
|
+
- **Terraform Development Workflow**: Follow security-focused development process via `terraform://workflow_guide`
|
|
56
|
+
- **AWS Best Practices**: Access AWS-specific guidance via `terraform://aws_best_practices`
|
|
57
|
+
- **AWS Provider Resources**: Access resource listings via `terraform://aws_provider_resources_listing`
|
|
58
|
+
- **AWSCC Provider Resources**: Access resource listings via `terraform://awscc_provider_resources_listing`
|
|
59
|
+
|
|
60
|
+
## Prerequisites
|
|
61
|
+
|
|
62
|
+
1. Install `uv` from [Astral](https://docs.astral.sh/uv/getting-started/installation/) or the [GitHub README](https://github.com/astral-sh/uv#installation)
|
|
63
|
+
2. Install Python using `uv python install 3.10`
|
|
64
|
+
3. Install Terraform CLI for workflow execution
|
|
65
|
+
4. Install Checkov for security scanning
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
Here are some ways you can work with MCP across AWS, and we'll be adding support to more products including Amazon Q Developer CLI soon: (e.g. for Amazon Q Developer CLI MCP, `~/.aws/amazonq/mcp.json`):
|
|
70
|
+
|
|
71
|
+
```json
|
|
72
|
+
{
|
|
73
|
+
"mcpServers": {
|
|
74
|
+
"awslabs.terraform-mcp-server": {
|
|
75
|
+
"command": "uvx",
|
|
76
|
+
"args": ["awslabs.terraform-mcp-server@latest"],
|
|
77
|
+
"env": {
|
|
78
|
+
"FASTMCP_LOG_LEVEL": "ERROR"
|
|
79
|
+
},
|
|
80
|
+
"disabled": false,
|
|
81
|
+
"autoApprove": []
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Security Considerations
|
|
88
|
+
|
|
89
|
+
When using this MCP server, you should consider:
|
|
90
|
+
- **Following the structured development workflow** that integrates validation and security scanning
|
|
91
|
+
- Reviewing all Checkov warnings and errors manually
|
|
92
|
+
- Fixing security issues rather than ignoring them whenever possible
|
|
93
|
+
- Documenting clear justifications for any necessary exceptions
|
|
94
|
+
- Using the RunCheckovScan tool regularly to verify security compliance
|
|
95
|
+
- Preferring the AWSCC provider for its consistent API behavior and better security defaults
|
|
96
|
+
|
|
97
|
+
Before applying Terraform changes to production environments, you should conduct your own independent assessment to ensure that your infrastructure would comply with your own specific security and quality control practices and standards, as well as the local laws, rules, and regulations that govern you and your content.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
awslabs/__init__.py,sha256=4zfFn3N0BkvQmMTAIvV_QAbKp6GWzrwaUN17YeRoChM,115
|
|
2
|
+
awslabs/terraform_mcp_server/__init__.py,sha256=a-zIkwClerA84_XGykBggO4w5kf8f85EapnWnbAH01c,58
|
|
3
|
+
awslabs/terraform_mcp_server/server.py,sha256=3N5A5eP6YB0YqCw6nbekzpXctd724rgtu--6zqvFlfA,13626
|
|
4
|
+
awslabs/terraform_mcp_server/impl/resources/__init__.py,sha256=bxqHGDtuwWq8w-21lT5GzOuxBqkmnUvW6cnSA36ve3A,388
|
|
5
|
+
awslabs/terraform_mcp_server/impl/resources/terraform_aws_provider_resources_listing.py,sha256=t_guGQ44yvip9u2cONN2cWc3fXk6HyQGPu5DDP5YEkI,1973
|
|
6
|
+
awslabs/terraform_mcp_server/impl/resources/terraform_awscc_provider_resources_listing.py,sha256=RoBSe-p5OyLYWNYa7aGx2f4NWyjap1wNrj8F4o8_PSo,2060
|
|
7
|
+
awslabs/terraform_mcp_server/impl/tools/__init__.py,sha256=TRlf5cGGVKfofMGwX_T8YXvnq8Evcyl0AzabiwIZyFc,601
|
|
8
|
+
awslabs/terraform_mcp_server/impl/tools/execute_terraform_command.py,sha256=_fPxC2wT23oWa9XaAoUEV1j5lK7Xpi7MqBAq85fLNdU,8507
|
|
9
|
+
awslabs/terraform_mcp_server/impl/tools/run_checkov_scan.py,sha256=oS6qgUPPti7lpa2VNsUwPbswiq2hgpe49fggVUI_PfM,13435
|
|
10
|
+
awslabs/terraform_mcp_server/impl/tools/search_aws_provider_docs.py,sha256=w7NX4oQwsCeVQPj8YZzvXvXcox8drzZimW3mRL8Kd84,29049
|
|
11
|
+
awslabs/terraform_mcp_server/impl/tools/search_awscc_provider_docs.py,sha256=fY8eRQ1j6oB4XyfAoUC6mTUXNkoFaY0vsmMhV6w0NR8,27297
|
|
12
|
+
awslabs/terraform_mcp_server/impl/tools/search_specific_aws_ia_modules.py,sha256=Kny5iharA1Wj-9tnhoPHntu4qM9n-2mC2dB6TXwhqfk,20148
|
|
13
|
+
awslabs/terraform_mcp_server/impl/tools/utils.py,sha256=GB1OuhYgrg00AzKfhgaUpQwbVBK5D56GQLcm60NHd1c,20500
|
|
14
|
+
awslabs/terraform_mcp_server/models/__init__.py,sha256=L7nlJJ9g_J7tuYw_BD_XarEcwH3WonrIoOBZcD5FC7A,651
|
|
15
|
+
awslabs/terraform_mcp_server/models/models.py,sha256=ZVn0gFlqjYTD0mNvlvXTilNhk2o9Mse9oUEBbl38Cbo,10685
|
|
16
|
+
awslabs/terraform_mcp_server/scripts/generate_aws_provider_resources.py,sha256=v8t4UL8KwIoqVYz25Xd8wiJJ2cwKmHvxaF0_ZpUI0b4,56714
|
|
17
|
+
awslabs/terraform_mcp_server/scripts/generate_awscc_provider_resources.py,sha256=FN2QOYefeEcyy-JXl1v3hLEz2YSBNRJB_9i182DdWiA,48722
|
|
18
|
+
awslabs/terraform_mcp_server/scripts/scrape_aws_terraform_best_practices.py,sha256=t_eFbciBwZXdK6pNkkcp4X7VPR4vXyXkmE_YLhm6Xr4,3783
|
|
19
|
+
awslabs/terraform_mcp_server/static/AWSCC_PROVIDER_RESOURCES.md,sha256=I_vu3dWXzd9Pxcd7tkdxFQs97wtuunyoXdJCAkCUXnE,440270
|
|
20
|
+
awslabs/terraform_mcp_server/static/AWS_PROVIDER_RESOURCES.md,sha256=OMboscC0Ov6O3U3K1uqrzRzx18nq_5AsJzITc5-CA8Y,303030
|
|
21
|
+
awslabs/terraform_mcp_server/static/AWS_TERRAFORM_BEST_PRACTICES.md,sha256=cftJ9y2nZ0kMendoV6WBlQFsNw-QnGnmF6dR88eoYdA,87665
|
|
22
|
+
awslabs/terraform_mcp_server/static/MCP_INSTRUCTIONS.md,sha256=k6XQFgab3_W7_g0AZNXdyxyrzA2RjOzP9DbXS_9FiP4,6010
|
|
23
|
+
awslabs/terraform_mcp_server/static/TERRAFORM_WORKFLOW_GUIDE.md,sha256=qvqtaikyyQ_XHL-LyU_BDos1ym2kKBR7ljMZtLn3FAs,9322
|
|
24
|
+
awslabs/terraform_mcp_server/static/__init__.py,sha256=J5JGKYybg48XyBi2hepC101RDNFBxSXZS5YGvj0tql8,549
|
|
25
|
+
awslabs/terraform_mcp_server/tests/__init__.py,sha256=eWyaXCIPzCC8_4kXuKnK9s79gg6_J3XYoAtQzkNesWI,45
|
|
26
|
+
awslabs/terraform_mcp_server/tests/run_tests.sh,sha256=u6GUSQffYJyn0RkAd4qeqkczYc_cf-lL3kC4a1YYjB4,1068
|
|
27
|
+
awslabs/terraform_mcp_server/tests/test_parameter_annotations.py,sha256=7DrC-idSQmrSAAPLHQ09V3sU7a_8HkfCrOnqJn2SQeo,8361
|
|
28
|
+
awslabs/terraform_mcp_server/tests/test_tool_implementations.py,sha256=Uh8vyFJJ9ti14hkmQDkWJEtGUJvFR3IZ0P90ez0LiMY,11641
|
|
29
|
+
awslabs_terraform_mcp_server-0.0.1.dist-info/METADATA,sha256=nDWAkf29xw-lxh4eUuLBSW6QiFHd4f7hgkHwaw8xr8w,4344
|
|
30
|
+
awslabs_terraform_mcp_server-0.0.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
31
|
+
awslabs_terraform_mcp_server-0.0.1.dist-info/entry_points.txt,sha256=jCTPQeUJ74jpIDcYwVHQCk-y0n0ehRFFerh_Qm4ZU1c,90
|
|
32
|
+
awslabs_terraform_mcp_server-0.0.1.dist-info/RECORD,,
|