mcp-server-terraform 0.1.0
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.
- package/README.md +47 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/terraform.d.ts +12 -0
- package/dist/terraform.d.ts.map +1 -0
- package/dist/terraform.js +37 -0
- package/dist/terraform.js.map +1 -0
- package/dist/tools/apply.d.ts +3 -0
- package/dist/tools/apply.d.ts.map +1 -0
- package/dist/tools/apply.js +30 -0
- package/dist/tools/apply.js.map +1 -0
- package/dist/tools/destroy.d.ts +3 -0
- package/dist/tools/destroy.d.ts.map +1 -0
- package/dist/tools/destroy.js +30 -0
- package/dist/tools/destroy.js.map +1 -0
- package/dist/tools/fmt.d.ts +3 -0
- package/dist/tools/fmt.d.ts.map +1 -0
- package/dist/tools/fmt.js +21 -0
- package/dist/tools/fmt.js.map +1 -0
- package/dist/tools/import.d.ts +3 -0
- package/dist/tools/import.d.ts.map +1 -0
- package/dist/tools/import.js +16 -0
- package/dist/tools/import.js.map +1 -0
- package/dist/tools/init.d.ts +3 -0
- package/dist/tools/init.d.ts.map +1 -0
- package/dist/tools/init.js +27 -0
- package/dist/tools/init.js.map +1 -0
- package/dist/tools/output.d.ts +3 -0
- package/dist/tools/output.d.ts.map +1 -0
- package/dist/tools/output.js +21 -0
- package/dist/tools/output.js.map +1 -0
- package/dist/tools/plan.d.ts +3 -0
- package/dist/tools/plan.d.ts.map +1 -0
- package/dist/tools/plan.js +30 -0
- package/dist/tools/plan.js.map +1 -0
- package/dist/tools/state-list.d.ts +3 -0
- package/dist/tools/state-list.d.ts.map +1 -0
- package/dist/tools/state-list.js +18 -0
- package/dist/tools/state-list.js.map +1 -0
- package/dist/tools/state-show.d.ts +3 -0
- package/dist/tools/state-show.d.ts.map +1 -0
- package/dist/tools/state-show.js +15 -0
- package/dist/tools/state-show.js.map +1 -0
- package/dist/tools/validate.d.ts +3 -0
- package/dist/tools/validate.d.ts.map +1 -0
- package/dist/tools/validate.js +14 -0
- package/dist/tools/validate.js.map +1 -0
- package/package.json +67 -0
- package/src/index.ts +40 -0
- package/src/terraform.ts +49 -0
- package/src/tools/apply.ts +33 -0
- package/src/tools/destroy.ts +33 -0
- package/src/tools/fmt.ts +25 -0
- package/src/tools/import.ts +25 -0
- package/src/tools/init.ts +31 -0
- package/src/tools/output.ts +25 -0
- package/src/tools/plan.ts +33 -0
- package/src/tools/state-list.ts +23 -0
- package/src/tools/state-show.ts +21 -0
- package/src/tools/validate.ts +20 -0
- package/tests/terraform.test.ts +68 -0
- package/tests/tools.test.ts +160 -0
- package/tsconfig.json +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# mcp-server-terraform
|
|
2
|
+
|
|
3
|
+
MCP server for Terraform infrastructure-as-code operations. Lets AI assistants manage Terraform workflows — plan, apply, destroy, and inspect infrastructure state.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
| Tool | Description |
|
|
8
|
+
|------|-------------|
|
|
9
|
+
| `terraform_plan` | Preview changes without applying |
|
|
10
|
+
| `terraform_apply` | Apply infrastructure changes |
|
|
11
|
+
| `terraform_destroy` | Destroy managed infrastructure |
|
|
12
|
+
| `terraform_init` | Initialize working directory, download providers |
|
|
13
|
+
| `terraform_validate` | Validate configuration syntax |
|
|
14
|
+
| `terraform_state_list` | List resources in state |
|
|
15
|
+
| `terraform_state_show` | Show resource attributes from state |
|
|
16
|
+
| `terraform_fmt` | Format HCL files to canonical style |
|
|
17
|
+
| `terraform_output` | Show output values from state |
|
|
18
|
+
| `terraform_import` | Import existing resources into state |
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install -g mcp-server-terraform
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Usage
|
|
27
|
+
|
|
28
|
+
Add to your MCP client configuration:
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"mcpServers": {
|
|
33
|
+
"terraform": {
|
|
34
|
+
"command": "mcp-server-terraform"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Requirements
|
|
41
|
+
|
|
42
|
+
- Terraform CLI installed and in PATH
|
|
43
|
+
- Working directory with `.tf` files for the target infrastructure
|
|
44
|
+
|
|
45
|
+
## License
|
|
46
|
+
|
|
47
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { registerPlanTool } from "./tools/plan.js";
|
|
5
|
+
import { registerApplyTool } from "./tools/apply.js";
|
|
6
|
+
import { registerDestroyTool } from "./tools/destroy.js";
|
|
7
|
+
import { registerInitTool } from "./tools/init.js";
|
|
8
|
+
import { registerValidateTool } from "./tools/validate.js";
|
|
9
|
+
import { registerStateListTool } from "./tools/state-list.js";
|
|
10
|
+
import { registerStateShowTool } from "./tools/state-show.js";
|
|
11
|
+
import { registerFmtTool } from "./tools/fmt.js";
|
|
12
|
+
import { registerOutputTool } from "./tools/output.js";
|
|
13
|
+
import { registerImportTool } from "./tools/import.js";
|
|
14
|
+
const server = new McpServer({
|
|
15
|
+
name: "terraform-mcp-server",
|
|
16
|
+
version: "0.1.0",
|
|
17
|
+
});
|
|
18
|
+
registerPlanTool(server);
|
|
19
|
+
registerApplyTool(server);
|
|
20
|
+
registerDestroyTool(server);
|
|
21
|
+
registerInitTool(server);
|
|
22
|
+
registerValidateTool(server);
|
|
23
|
+
registerStateListTool(server);
|
|
24
|
+
registerStateShowTool(server);
|
|
25
|
+
registerFmtTool(server);
|
|
26
|
+
registerOutputTool(server);
|
|
27
|
+
registerImportTool(server);
|
|
28
|
+
async function main() {
|
|
29
|
+
const transport = new StdioServerTransport();
|
|
30
|
+
await server.connect(transport);
|
|
31
|
+
console.error("Terraform MCP Server running on stdio");
|
|
32
|
+
}
|
|
33
|
+
main().catch((error) => {
|
|
34
|
+
console.error("Fatal error:", error);
|
|
35
|
+
process.exit(1);
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,sBAAsB;IAC5B,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,iBAAiB,CAAC,MAAM,CAAC,CAAC;AAC1B,mBAAmB,CAAC,MAAM,CAAC,CAAC;AAC5B,gBAAgB,CAAC,MAAM,CAAC,CAAC;AACzB,oBAAoB,CAAC,MAAM,CAAC,CAAC;AAC7B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAC9B,eAAe,CAAC,MAAM,CAAC,CAAC;AACxB,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAC3B,kBAAkB,CAAC,MAAM,CAAC,CAAC;AAE3B,KAAK,UAAU,IAAI;IACjB,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;AACzD,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface TerraformResult {
|
|
2
|
+
stdout: string;
|
|
3
|
+
stderr: string;
|
|
4
|
+
exitCode: number | null;
|
|
5
|
+
}
|
|
6
|
+
export declare function runTerraform(args: string[], options?: {
|
|
7
|
+
cwd?: string;
|
|
8
|
+
env?: Record<string, string>;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
}): Promise<TerraformResult>;
|
|
11
|
+
export declare function formatResult(result: TerraformResult): string;
|
|
12
|
+
//# sourceMappingURL=terraform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terraform.d.ts","sourceRoot":"","sources":["../src/terraform.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,wBAAsB,YAAY,CAChC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,GAAE;IACP,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CACb,GACL,OAAO,CAAC,eAAe,CAAC,CAsB1B;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAM5D"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { promisify } from "node:util";
|
|
3
|
+
const execFileAsync = promisify(execFile);
|
|
4
|
+
export async function runTerraform(args, options = {}) {
|
|
5
|
+
const { cwd = process.cwd(), env, timeout = 120000 } = options;
|
|
6
|
+
try {
|
|
7
|
+
const result = await execFileAsync("terraform", args, {
|
|
8
|
+
cwd,
|
|
9
|
+
timeout,
|
|
10
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
11
|
+
env: env ? { ...process.env, ...env } : undefined,
|
|
12
|
+
});
|
|
13
|
+
return {
|
|
14
|
+
stdout: result.stdout,
|
|
15
|
+
stderr: result.stderr,
|
|
16
|
+
exitCode: 0,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
catch (error) {
|
|
20
|
+
return {
|
|
21
|
+
stdout: error.stdout || "",
|
|
22
|
+
stderr: error.stderr || error.message,
|
|
23
|
+
exitCode: error.code ?? 1,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function formatResult(result) {
|
|
28
|
+
const parts = [];
|
|
29
|
+
if (result.stdout.trim())
|
|
30
|
+
parts.push(result.stdout.trim());
|
|
31
|
+
if (result.stderr.trim())
|
|
32
|
+
parts.push(`STDERR:\n${result.stderr.trim()}`);
|
|
33
|
+
if (result.exitCode !== 0)
|
|
34
|
+
parts.push(`Exit code: ${result.exitCode}`);
|
|
35
|
+
return parts.join("\n\n") || "No output.";
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=terraform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terraform.js","sourceRoot":"","sources":["../src/terraform.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAmB,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAQ1C,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAc,EACd,UAII,EAAE;IAEN,MAAM,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,IAAI,EAAE;YACpD,GAAG;YACH,OAAO;YACP,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,OAAO;YACpC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS;SAClD,CAAC,CAAC;QACH,OAAO;YACL,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,QAAQ,EAAE,CAAC;SACZ,CAAC;IACJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO;YACL,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE;YAC1B,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO;YACrC,QAAQ,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC;SAC1B,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAuB;IAClD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IAC3D,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAAE,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACzE,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,YAAY,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.d.ts","sourceRoot":"","sources":["../../src/tools/apply.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,SAAS,QA4BlD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerApplyTool(server) {
|
|
4
|
+
server.tool("terraform_apply", "Apply Terraform changes to create, update, or destroy infrastructure resources.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
auto_approve: z.boolean().optional().describe("Skip interactive approval (default: false — requires confirmation)"),
|
|
7
|
+
target: z.string().optional().describe("Target specific resource"),
|
|
8
|
+
var_file: z.string().optional().describe("Path to variables file"),
|
|
9
|
+
vars: z.record(z.string()).optional().describe("Variable values to pass"),
|
|
10
|
+
}, async ({ directory, auto_approve, target, var_file, vars }) => {
|
|
11
|
+
const args = ["apply", "-no-color"];
|
|
12
|
+
if (auto_approve)
|
|
13
|
+
args.push("-auto-approve");
|
|
14
|
+
if (target)
|
|
15
|
+
args.push("-target", target);
|
|
16
|
+
if (var_file)
|
|
17
|
+
args.push("-var-file", var_file);
|
|
18
|
+
if (vars) {
|
|
19
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
20
|
+
args.push("-var", `${key}=${value}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const result = await runTerraform(args, { cwd: directory });
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
26
|
+
isError: result.exitCode !== 0,
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../src/tools/apply.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,iBAAiB,CAAC,MAAiB;IACjD,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,iFAAiF,EACjF;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,oEAAoE,CAAC;QACnH,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;QAClE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAClE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;KAC1E,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACpC,IAAI,YAAY;YAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7C,IAAI,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"destroy.d.ts","sourceRoot":"","sources":["../../src/tools/destroy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,SAAS,QA4BpD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerDestroyTool(server) {
|
|
4
|
+
server.tool("terraform_destroy", "Destroy all Terraform-managed infrastructure. Use with caution — this removes real resources.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
auto_approve: z.boolean().optional().describe("Skip interactive approval (default: false)"),
|
|
7
|
+
target: z.string().optional().describe("Target specific resource to destroy"),
|
|
8
|
+
var_file: z.string().optional().describe("Path to variables file"),
|
|
9
|
+
vars: z.record(z.string()).optional().describe("Variable values to pass"),
|
|
10
|
+
}, async ({ directory, auto_approve, target, var_file, vars }) => {
|
|
11
|
+
const args = ["destroy", "-no-color"];
|
|
12
|
+
if (auto_approve)
|
|
13
|
+
args.push("-auto-approve");
|
|
14
|
+
if (target)
|
|
15
|
+
args.push("-target", target);
|
|
16
|
+
if (var_file)
|
|
17
|
+
args.push("-var-file", var_file);
|
|
18
|
+
if (vars) {
|
|
19
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
20
|
+
args.push("-var", `${key}=${value}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const result = await runTerraform(args, { cwd: directory });
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
26
|
+
isError: result.exitCode !== 0,
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=destroy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"destroy.js","sourceRoot":"","sources":["../../src/tools/destroy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,mBAAmB,CAAC,MAAiB;IACnD,MAAM,CAAC,IAAI,CACT,mBAAmB,EACnB,+FAA+F,EAC/F;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,YAAY,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,4CAA4C,CAAC;QAC3F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,qCAAqC,CAAC;QAC7E,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAClE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,yBAAyB,CAAC;KAC1E,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QACtC,IAAI,YAAY;YAAE,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC7C,IAAI,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fmt.d.ts","sourceRoot":"","sources":["../../src/tools/fmt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,QAoBhD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerFmtTool(server) {
|
|
4
|
+
server.tool("terraform_fmt", "Reformat Terraform configuration files to canonical style (consistent indentation and alignment).", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
check: z.boolean().optional().describe("Check if files are formatted (don't modify, just report)"),
|
|
7
|
+
recursive: z.boolean().optional().describe("Process files in subdirectories"),
|
|
8
|
+
}, async ({ directory, check, recursive }) => {
|
|
9
|
+
const args = ["fmt", "-no-color"];
|
|
10
|
+
if (check)
|
|
11
|
+
args.push("-check");
|
|
12
|
+
if (recursive)
|
|
13
|
+
args.push("-recursive");
|
|
14
|
+
const result = await runTerraform(args, { cwd: directory });
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
17
|
+
isError: result.exitCode !== 0,
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=fmt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fmt.js","sourceRoot":"","sources":["../../src/tools/fmt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,eAAe,CAAC,MAAiB;IAC/C,MAAM,CAAC,IAAI,CACT,eAAe,EACf,mGAAmG,EACnG;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0DAA0D,CAAC;QAClG,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,iCAAiC,CAAC;KAC9E,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE;QACxC,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAClC,IAAI,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,SAAS;YAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../src/tools/import.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QAoBnD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerImportTool(server) {
|
|
4
|
+
server.tool("terraform_import", "Import an existing infrastructure resource into Terraform state. Maps a real-world resource to a Terraform resource address.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
resource_address: z.string().describe("Terraform resource address (e.g., aws_instance.web)"),
|
|
7
|
+
resource_id: z.string().describe("ID of the existing resource to import (e.g., i-1234567890abcdef0)"),
|
|
8
|
+
}, async ({ directory, resource_address, resource_id }) => {
|
|
9
|
+
const result = await runTerraform(["import", "-no-color", resource_address, resource_id], { cwd: directory });
|
|
10
|
+
return {
|
|
11
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
12
|
+
isError: result.exitCode !== 0,
|
|
13
|
+
};
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=import.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/tools/import.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,8HAA8H,EAC9H;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,gBAAgB,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,qDAAqD,CAAC;QAC5F,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mEAAmE,CAAC;KACtG,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,gBAAgB,EAAE,WAAW,EAAE,EAAE,EAAE;QACrD,MAAM,MAAM,GAAG,MAAM,YAAY,CAC/B,CAAC,QAAQ,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,CAAC,EACtD,EAAE,GAAG,EAAE,SAAS,EAAE,CACnB,CAAC;QACF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/tools/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,QA0BjD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerInitTool(server) {
|
|
4
|
+
server.tool("terraform_init", "Initialize a Terraform working directory. Downloads providers, modules, and configures the backend.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
upgrade: z.boolean().optional().describe("Upgrade providers and modules to latest compatible versions"),
|
|
7
|
+
reconfigure: z.boolean().optional().describe("Reconfigure the backend (discard previous state)"),
|
|
8
|
+
backend_config: z.record(z.string()).optional().describe("Backend configuration values"),
|
|
9
|
+
}, async ({ directory, upgrade, reconfigure, backend_config }) => {
|
|
10
|
+
const args = ["init", "-no-color"];
|
|
11
|
+
if (upgrade)
|
|
12
|
+
args.push("-upgrade");
|
|
13
|
+
if (reconfigure)
|
|
14
|
+
args.push("-reconfigure");
|
|
15
|
+
if (backend_config) {
|
|
16
|
+
for (const [key, value] of Object.entries(backend_config)) {
|
|
17
|
+
args.push("-backend-config", `${key}=${value}`);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const result = await runTerraform(args, { cwd: directory });
|
|
21
|
+
return {
|
|
22
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
23
|
+
isError: result.exitCode !== 0,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/tools/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,qGAAqG,EACrG;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,6DAA6D,CAAC;QACvG,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;QAChG,cAAc,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8BAA8B,CAAC;KACzF,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACnC,IAAI,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnC,IAAI,WAAW;YAAE,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3C,IAAI,cAAc,EAAE,CAAC;YACnB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;gBAC1D,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;YAClD,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/tools/output.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,QAoBnD"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerOutputTool(server) {
|
|
4
|
+
server.tool("terraform_output", "Show output values from the Terraform state. Outputs are defined in output blocks and often contain important resource attributes.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
name: z.string().optional().describe("Show a specific output by name"),
|
|
7
|
+
json: z.boolean().optional().describe("Output in JSON format"),
|
|
8
|
+
}, async ({ directory, name, json }) => {
|
|
9
|
+
const args = ["output", "-no-color"];
|
|
10
|
+
if (json)
|
|
11
|
+
args.push("-json");
|
|
12
|
+
if (name)
|
|
13
|
+
args.push(name);
|
|
14
|
+
const result = await runTerraform(args, { cwd: directory });
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
17
|
+
isError: result.exitCode !== 0,
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.js","sourceRoot":"","sources":["../../src/tools/output.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,kBAAkB,CAAC,MAAiB;IAClD,MAAM,CAAC,IAAI,CACT,kBAAkB,EAClB,oIAAoI,EACpI;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gCAAgC,CAAC;QACtE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;KAC/D,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACrC,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC7B,IAAI,IAAI;YAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,QA4BjD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerPlanTool(server) {
|
|
4
|
+
server.tool("terraform_plan", "Preview changes Terraform will make to infrastructure without applying them. Shows added, changed, and destroyed resources.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
destroy: z.boolean().optional().describe("If true, show destroy plan instead of normal plan"),
|
|
7
|
+
target: z.string().optional().describe("Target specific resource (e.g., aws_instance.web)"),
|
|
8
|
+
var_file: z.string().optional().describe("Path to variables file"),
|
|
9
|
+
vars: z.record(z.string()).optional().describe("Variable values to pass (e.g., region=us-east-1)"),
|
|
10
|
+
}, async ({ directory, destroy, target, var_file, vars }) => {
|
|
11
|
+
const args = ["plan", "-no-color"];
|
|
12
|
+
if (destroy)
|
|
13
|
+
args.push("-destroy");
|
|
14
|
+
if (target)
|
|
15
|
+
args.push("-target", target);
|
|
16
|
+
if (var_file)
|
|
17
|
+
args.push("-var-file", var_file);
|
|
18
|
+
if (vars) {
|
|
19
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
20
|
+
args.push("-var", `${key}=${value}`);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const result = await runTerraform(args, { cwd: directory });
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
26
|
+
isError: result.exitCode !== 0,
|
|
27
|
+
};
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/tools/plan.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,gBAAgB,CAAC,MAAiB;IAChD,MAAM,CAAC,IAAI,CACT,gBAAgB,EAChB,6HAA6H,EAC7H;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;QAC7F,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,mDAAmD,CAAC;QAC3F,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAClE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,kDAAkD,CAAC;KACnG,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;QACvD,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACnC,IAAI,OAAO;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnC,IAAI,MAAM;YAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;QACzC,IAAI,QAAQ;YAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC;QAC/C,IAAI,IAAI,EAAE,CAAC;YACT,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI,KAAK,EAAE,CAAC,CAAC;YACvC,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-list.d.ts","sourceRoot":"","sources":["../../src/tools/state-list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,QAkBtD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerStateListTool(server) {
|
|
4
|
+
server.tool("terraform_state_list", "List all resources tracked in the Terraform state file.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
id_pattern: z.string().optional().describe("Filter resources by ID pattern (supports glob)"),
|
|
7
|
+
}, async ({ directory, id_pattern }) => {
|
|
8
|
+
const args = ["state", "list", "-no-color"];
|
|
9
|
+
if (id_pattern)
|
|
10
|
+
args.push(id_pattern);
|
|
11
|
+
const result = await runTerraform(args, { cwd: directory });
|
|
12
|
+
return {
|
|
13
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
14
|
+
isError: result.exitCode !== 0,
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=state-list.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-list.js","sourceRoot":"","sources":["../../src/tools/state-list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,yDAAyD,EACzD;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gDAAgD,CAAC;KAC7F,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,UAAU,EAAE,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;QAC5C,IAAI,UAAU;YAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QAC5D,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-show.d.ts","sourceRoot":"","sources":["../../src/tools/state-show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,QAgBtD"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerStateShowTool(server) {
|
|
4
|
+
server.tool("terraform_state_show", "Show detailed attributes of a specific resource in the Terraform state.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
resource_id: z.string().describe("Resource ID in state (e.g., aws_instance.web)"),
|
|
7
|
+
}, async ({ directory, resource_id }) => {
|
|
8
|
+
const result = await runTerraform(["state", "show", "-no-color", resource_id], { cwd: directory });
|
|
9
|
+
return {
|
|
10
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
11
|
+
isError: result.exitCode !== 0,
|
|
12
|
+
};
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=state-show.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state-show.js","sourceRoot":"","sources":["../../src/tools/state-show.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,MAAM,CAAC,IAAI,CACT,sBAAsB,EACtB,yEAAyE,EACzE;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;QAC9E,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,+CAA+C,CAAC;KAClF,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,EAAE;QACnC,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QACnG,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAIpE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,QAerD"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { runTerraform, formatResult } from "../terraform.js";
|
|
3
|
+
export function registerValidateTool(server) {
|
|
4
|
+
server.tool("terraform_validate", "Validate Terraform configuration files for syntax and internal consistency without contacting any remote services.", {
|
|
5
|
+
directory: z.string().describe("Working directory containing Terraform files"),
|
|
6
|
+
}, async ({ directory }) => {
|
|
7
|
+
const result = await runTerraform(["validate", "-no-color"], { cwd: directory });
|
|
8
|
+
return {
|
|
9
|
+
content: [{ type: "text", text: formatResult(result) }],
|
|
10
|
+
isError: result.exitCode !== 0,
|
|
11
|
+
};
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/tools/validate.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,MAAM,UAAU,oBAAoB,CAAC,MAAiB;IACpD,MAAM,CAAC,IAAI,CACT,oBAAoB,EACpB,oHAAoH,EACpH;QACE,SAAS,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;KAC/E,EACD,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QACjF,OAAO;YACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;YACvD,OAAO,EAAE,MAAM,CAAC,QAAQ,KAAK,CAAC;SAC/B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-server-terraform",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Terraform infrastructure-as-code operations",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"mcp-server-terraform": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"mcp",
|
|
16
|
+
"mcp-server",
|
|
17
|
+
"terraform",
|
|
18
|
+
"infrastructure-as-code",
|
|
19
|
+
"iac",
|
|
20
|
+
"devops",
|
|
21
|
+
"cloud",
|
|
22
|
+
"aws",
|
|
23
|
+
"gcp",
|
|
24
|
+
"azure",
|
|
25
|
+
"hcl",
|
|
26
|
+
"terraform-plan",
|
|
27
|
+
"terraform-apply",
|
|
28
|
+
"terraform-state",
|
|
29
|
+
"claude-desktop",
|
|
30
|
+
"cursor",
|
|
31
|
+
"windsurf",
|
|
32
|
+
"infrastructure",
|
|
33
|
+
"provisioning",
|
|
34
|
+
"deployment",
|
|
35
|
+
"cloud-management",
|
|
36
|
+
"terraform-cli",
|
|
37
|
+
"hashicorp",
|
|
38
|
+
"kubernetes",
|
|
39
|
+
"docker",
|
|
40
|
+
"ci-cd",
|
|
41
|
+
"gitops",
|
|
42
|
+
"idempotent",
|
|
43
|
+
"drift-detection",
|
|
44
|
+
"remote-state",
|
|
45
|
+
"workspaces",
|
|
46
|
+
"modules",
|
|
47
|
+
"providers",
|
|
48
|
+
"backends",
|
|
49
|
+
"lifecycle",
|
|
50
|
+
"import",
|
|
51
|
+
"destroy",
|
|
52
|
+
"output",
|
|
53
|
+
"variables",
|
|
54
|
+
"terraform-cloud"
|
|
55
|
+
],
|
|
56
|
+
"author": "Nova",
|
|
57
|
+
"license": "MIT",
|
|
58
|
+
"dependencies": {
|
|
59
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
60
|
+
"zod": "^3.22.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/node": "^20.0.0",
|
|
64
|
+
"typescript": "^5.3.0",
|
|
65
|
+
"vitest": "^4.1.9"
|
|
66
|
+
}
|
|
67
|
+
}
|