From 095436f0667b49daa4f6d05d701d0e307c3c0abb Mon Sep 17 00:00:00 2001 From: Anubhav Goel Date: Tue, 7 Oct 2025 12:47:09 +0530 Subject: [PATCH 1/4] feat(mcp-server-integration): TF-28514: Added configurable container runtime for MCP server integration --- README.md | 17 ++++++++++++-- package.json | 7 ++++++ src/features/mcpServer.ts | 49 ++++----------------------------------- 3 files changed, 27 insertions(+), 46 deletions(-) diff --git a/README.md b/README.md index 3621b582c..aeb063696 100644 --- a/README.md +++ b/README.md @@ -185,9 +185,22 @@ You can enable or disable this feature via: - The Command Palette: `HashiCorp Terraform: Enable MCP Server` or `HashiCorp Terraform: Disable MCP Server` - Settings: `terraform.mcp.server.enable` -Note that enabling this feature requires Docker to be installed and running on your system. +#### Container Runtime Configuration -When enabled, the MCP server runs as a Docker container (`hashicorp/terraform-mcp-server`), providing your AI assistant with contextual knowledge about Terraform providers, modules, and best practices. The extension automatically manages the server lifecycle, starting it when needed for AI interactions. +By default, the extension uses Docker to run the MCP server container. However, you can configure it to use alternative container runtimes such as Podman: + +```json +"terraform.mcp.server.containerRuntime": "podman" +``` + +**Supported container runtimes:** +- `docker` (default) - Requires Docker to be installed and running +- `podman` - Requires Podman to be installed and running +- Any other container runtime that supports the same command-line interface as Docker + +**Note:** The specified container runtime must be installed and running on your system before enabling the MCP server integration. + +When enabled, the MCP server runs as a container (`hashicorp/terraform-mcp-server`), providing your AI assistant with contextual knowledge about Terraform providers, modules, and best practices. The extension automatically manages the server lifecycle, starting it when needed for AI interactions. ![](/docs/hashicorp-terraform-mcp-server.gif) diff --git a/package.json b/package.json index 6cfce9713..b3d5e6290 100644 --- a/package.json +++ b/package.json @@ -506,6 +506,13 @@ "type": "boolean", "default": false, "description": "Enable HashiCorp Terraform MCP Server integration" + }, + "terraform.mcp.server.containerRuntime": { + "order": 4, + "scope": "window", + "type": "string", + "default": "docker", + "description": "Container runtime command to use for running the HashiCorp Terraform MCP Server (e.g., 'docker', 'podman')" } } }, diff --git a/src/features/mcpServer.ts b/src/features/mcpServer.ts index 7b063164b..33505b686 100644 --- a/src/features/mcpServer.ts +++ b/src/features/mcpServer.ts @@ -4,13 +4,9 @@ */ import TelemetryReporter from '@vscode/extension-telemetry'; -import { exec } from 'child_process'; -import { promisify } from 'util'; import * as vscode from 'vscode'; import { config } from '../utils/vscode'; -const execAsync = promisify(exec); - interface McpServerDefinition { label: string; command: string; @@ -98,10 +94,12 @@ export class McpServerFeature { return []; } + const containerRuntime = config('terraform').get('mcp.server.containerRuntime', 'docker'); + const server: McpServerDefinition = { label: 'HashiCorp Terraform MCP Server', - command: 'docker', - args: ['run', '-i', '--rm', 'hashicorp/terraform-mcp-server'], + command: containerRuntime, + args: ['run', '-i', '--rm', 'hashicorp/terraform-mcp-server:0.2.3'], env: {}, }; @@ -114,53 +112,16 @@ export class McpServerFeature { // All user interactions should happen here // Should return resolved server definition if server should be started - private async resolveMcpServerDefinition(definition: McpServerDefinition): Promise { + private resolveMcpServerDefinition(definition: McpServerDefinition): McpServerDefinition { if (definition.label !== 'HashiCorp Terraform MCP Server') { // Not our definition, return as is return definition; } - const dockerAvailable = await this.dockerValidations(); - if (!dockerAvailable) { - throw new Error('Docker is required but not available or running'); - } - this.reporter.sendTelemetryEvent('terraform-mcp-server-start'); return definition; } - private async dockerValidations(): Promise { - try { - if (!(await this.checkDockerRunning())) { - return false; - } - - return true; - } catch (error) { - this.logError('Docker validation error', error); - return false; - } - } - - // Check if container runtime is available and running - // The 'docker info' command validates both installation and daemon status - private async checkDockerRunning(): Promise { - try { - await execAsync('docker info', { timeout: 5000 }); - return true; - } catch (error) { - this.logError('Docker daemon check failed', error); - void vscode.window - .showWarningMessage('Please install and start a Docker compatible runtime to use this feature.', 'Learn More') - .then((selection) => { - if (selection === 'Learn More') { - void vscode.env.openExternal(vscode.Uri.parse('https://docs.docker.com/get-started/')); - } - }); - return false; - } - } - dispose(): void { // context.subscriptions will be disposed by the extension, so any explicit code should not be required. } From cf33dd1b2b73c958c04a4c12eb2ed46638abd083 Mon Sep 17 00:00:00 2001 From: Anubhav Goel Date: Tue, 7 Oct 2025 12:50:01 +0530 Subject: [PATCH 2/4] feat(mcp-server-integration): TF-28514: Added changelog --- .changes/unreleased/ENHANCEMENTS-20251007-124945.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changes/unreleased/ENHANCEMENTS-20251007-124945.yaml diff --git a/.changes/unreleased/ENHANCEMENTS-20251007-124945.yaml b/.changes/unreleased/ENHANCEMENTS-20251007-124945.yaml new file mode 100644 index 000000000..e4737099a --- /dev/null +++ b/.changes/unreleased/ENHANCEMENTS-20251007-124945.yaml @@ -0,0 +1,6 @@ +kind: ENHANCEMENTS +body: Added configurable container runtime for MCP server integration +time: 2025-10-07T12:49:45.840468+05:30 +custom: + Issue: "2139" + Repository: vscode-terraform From be1d966b90176463e4d3f976426e8697a6f049b2 Mon Sep 17 00:00:00 2001 From: Anubhav Goel Date: Tue, 7 Oct 2025 13:04:05 +0530 Subject: [PATCH 3/4] feat(mcp-server-integration): TF-28514: Modified: image version --- src/features/mcpServer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/features/mcpServer.ts b/src/features/mcpServer.ts index 33505b686..e09e5df66 100644 --- a/src/features/mcpServer.ts +++ b/src/features/mcpServer.ts @@ -99,7 +99,7 @@ export class McpServerFeature { const server: McpServerDefinition = { label: 'HashiCorp Terraform MCP Server', command: containerRuntime, - args: ['run', '-i', '--rm', 'hashicorp/terraform-mcp-server:0.2.3'], + args: ['run', '-i', '--rm', 'hashicorp/terraform-mcp-server:0.2'], env: {}, }; From 3d4172a0fae33a23ac001fb2f5727e50f2a1f175 Mon Sep 17 00:00:00 2001 From: Anubhav Goel Date: Wed, 8 Oct 2025 16:05:19 +0530 Subject: [PATCH 4/4] feat(mcp-server-integration): TF-28514: Added: automatic container runtime detection for MCP server integration with Docker and Podman support --- .../ENHANCEMENTS-20251007-124945.yaml | 2 +- README.md | 12 ++-- package.json | 7 -- src/features/mcpServer.ts | 71 +++++++++++++++++-- 4 files changed, 71 insertions(+), 21 deletions(-) diff --git a/.changes/unreleased/ENHANCEMENTS-20251007-124945.yaml b/.changes/unreleased/ENHANCEMENTS-20251007-124945.yaml index e4737099a..1b562f463 100644 --- a/.changes/unreleased/ENHANCEMENTS-20251007-124945.yaml +++ b/.changes/unreleased/ENHANCEMENTS-20251007-124945.yaml @@ -1,5 +1,5 @@ kind: ENHANCEMENTS -body: Added configurable container runtime for MCP server integration +body: Added automatic container runtime detection for MCP server integration with Docker and Podman support time: 2025-10-07T12:49:45.840468+05:30 custom: Issue: "2139" diff --git a/README.md b/README.md index aeb063696..653c0cd7c 100644 --- a/README.md +++ b/README.md @@ -187,18 +187,16 @@ You can enable or disable this feature via: #### Container Runtime Configuration -By default, the extension uses Docker to run the MCP server container. However, you can configure it to use alternative container runtimes such as Podman: +The extension automatically detects available container runtimes on your system and uses them in the following priority order: -```json -"terraform.mcp.server.containerRuntime": "podman" -``` +1. **Docker** (preferred) - If Docker is installed and running +2. **Podman** (fallback) - If Docker is not available but Podman is installed and running **Supported container runtimes:** -- `docker` (default) - Requires Docker to be installed and running +- `docker` - Requires Docker to be installed and running - `podman` - Requires Podman to be installed and running -- Any other container runtime that supports the same command-line interface as Docker -**Note:** The specified container runtime must be installed and running on your system before enabling the MCP server integration. +**Note:** At least one supported container runtime (Docker or Podman) must be installed and running on your system before enabling the MCP server integration. If neither is available, the extension will show an error message with links to installation guides for both runtimes. When enabled, the MCP server runs as a container (`hashicorp/terraform-mcp-server`), providing your AI assistant with contextual knowledge about Terraform providers, modules, and best practices. The extension automatically manages the server lifecycle, starting it when needed for AI interactions. diff --git a/package.json b/package.json index b3d5e6290..6cfce9713 100644 --- a/package.json +++ b/package.json @@ -506,13 +506,6 @@ "type": "boolean", "default": false, "description": "Enable HashiCorp Terraform MCP Server integration" - }, - "terraform.mcp.server.containerRuntime": { - "order": 4, - "scope": "window", - "type": "string", - "default": "docker", - "description": "Container runtime command to use for running the HashiCorp Terraform MCP Server (e.g., 'docker', 'podman')" } } }, diff --git a/src/features/mcpServer.ts b/src/features/mcpServer.ts index e09e5df66..6ef07721f 100644 --- a/src/features/mcpServer.ts +++ b/src/features/mcpServer.ts @@ -4,9 +4,15 @@ */ import TelemetryReporter from '@vscode/extension-telemetry'; +import { exec } from 'child_process'; +import { promisify } from 'util'; import * as vscode from 'vscode'; import { config } from '../utils/vscode'; +const execAsync = promisify(exec); + +type ContainerRuntime = 'docker' | 'podman'; + interface McpServerDefinition { label: string; command: string; @@ -94,11 +100,10 @@ export class McpServerFeature { return []; } - const containerRuntime = config('terraform').get('mcp.server.containerRuntime', 'docker'); - + // Use Docker as default command, runtime detection happens in resolveMcpServerDefinition const server: McpServerDefinition = { label: 'HashiCorp Terraform MCP Server', - command: containerRuntime, + command: 'docker', // Default to docker, will be resolved later args: ['run', '-i', '--rm', 'hashicorp/terraform-mcp-server:0.2'], env: {}, }; @@ -112,14 +117,68 @@ export class McpServerFeature { // All user interactions should happen here // Should return resolved server definition if server should be started - private resolveMcpServerDefinition(definition: McpServerDefinition): McpServerDefinition { + private async resolveMcpServerDefinition(definition: McpServerDefinition): Promise { if (definition.label !== 'HashiCorp Terraform MCP Server') { // Not our definition, return as is return definition; } - this.reporter.sendTelemetryEvent('terraform-mcp-server-start'); - return definition; + const availableRuntime = await this.getAvailableContainerRuntime(); + if (!availableRuntime) { + const errorMessage = + 'Please install and start a Docker compatible runtime (docker or podman) to use this feature.'; + void vscode.window.showErrorMessage(errorMessage, 'Docker', 'Podman').then((selection) => { + if (selection === 'Docker') { + void vscode.env.openExternal(vscode.Uri.parse('https://docs.docker.com/get-started/')); + } else if (selection === 'Podman') { + void vscode.env.openExternal(vscode.Uri.parse('https://podman.io/get-started')); + } + }); + throw new Error(errorMessage); + } + + this.outputChannel.appendLine( + `Container runtime command to use for running the HashiCorp Terraform MCP Server ${availableRuntime}`, + ); + + // Update the definition to use the available container runtime + const resolvedDefinition: McpServerDefinition = { + ...definition, + command: availableRuntime, + }; + + this.reporter.sendTelemetryEvent('terraform-mcp-server-start', { + containerRuntime: availableRuntime, + }); + + return resolvedDefinition; + } + + // Check which container runtime is available, preferring Docker over Podman + private async getAvailableContainerRuntime(): Promise { + // Check Docker first (preferred) + if (await this.checkContainerRuntimeAvailable('docker')) { + return 'docker'; + } + + // Fall back to Podman + if (await this.checkContainerRuntimeAvailable('podman')) { + return 'podman'; + } + + return null; + } + + // Check if a specific container runtime is available and running + // The 'info' command validates both installation and daemon status + private async checkContainerRuntimeAvailable(runtime: ContainerRuntime): Promise { + try { + await execAsync(`${runtime} info`, { timeout: 5000 }); + return true; + } catch (error) { + this.logError(`${runtime} daemon check failed`, error); + return false; + } } dispose(): void {