README.md•8.69 kB
# Isolator MCP Server
`isolator-mcp` is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server written in TypeScript. It acts as a wrapper around the embedded [`isolator` Go CLI tool](./isolator-cli), providing a secure code execution sandbox accessible via MCP.
LLM applications (MCP Hosts) can connect to this server and use its `execute_code` tool to safely run Python, Go, or JavaScript code snippets provided directly or loaded from predefined snippet files.
## Features
* Provides the `execute_code` MCP tool.
* Supports executing code provided directly (`language`, `entrypoint_code`) or via named snippets (`snippet_name`).
* Supports multiple languages (Python, Go, JavaScript, configurable).
* Uses the embedded `isolator` Go CLI (`isolator-cli/`) for secure Docker container execution.
* Configurable security defaults (timeout, resource limits, network) via `isolator_config.json`.
* Manages temporary directories on the host for code execution.
* Handles file copying into containers (by instructing the `isolator` CLI).
* Returns structured results (stdout, stderr, status) via MCP, setting `isError: true` on tool-level failures.
## Prerequisites
* **Docker:** Required for container creation and execution by the `isolator-cli`. Ensure the Docker daemon is running.
* **Go:** Required to build the embedded `isolator-cli` Go binary.
* **Node.js and npm:** Required to install dependencies, build, and run the `isolator-mcp` TypeScript server.
## Installation
1. **Build `isolator` Go CLI:** Navigate to the embedded Go CLI directory and build the binary:
```bash
cd isolator-cli
go build -o isolator main.go
cd ..
```
This creates the `./isolator-cli/isolator` executable needed by the server.
2. **Configure `isolator-mcp`:**
* Edit `isolator_config.json`: Update `isolatorPath` to point to the absolute path of the built binary (e.g., `/Users/ompragash/Documents/Cline/MCP/isolator-mcp/isolator-cli/isolator`). Adjust default limits, container workdir, language images, or the `promptsDir` (used for snippets) location if needed.
* Ensure the `prompts` directory exists (default: `./prompts`). Add code snippet files (e.g., `hello_world.py`). The filename base (e.g., `hello_world`) is used as the `snippet_name`.
3. **Install Server Dependencies:** Navigate to the main directory (`isolator-mcp`) and run:
```bash
npm install
```
4. **Build Server:** Compile the TypeScript code:
```bash
npm run build
```
This creates the executable script at `build/index.js`.
5. **Configure MCP Host:** Add the server to your MCP client's settings file (e.g., `cline_mcp_settings.json` for the VS Code extension):
```json
{
"mcpServers": {
"isolator": {
"command": "node",
"args": ["/Users/ompragash/Documents/Cline/MCP/isolator-mcp/build/index.js"],
"env": {},
"disabled": false,
"autoApprove": []
}
}
}
```
*(Adjust the path in `args` if necessary)*. The MCP Host should automatically detect and start the server.
**Important Note:** Ensure the Docker images specified in `isolator_config.json` (e.g., `python:3.11-alpine`, `golang:1.21-alpine`) are pulled onto your system beforehand using `docker pull <image_name>`. The `isolator` tool does not automatically download missing images.
## Local Development / Testing
To run the server locally for development or testing (without installing it via MCP Host settings):
1. **Build Go CLI:** Ensure the `isolator` Go CLI is built within its subdirectory:
```bash
cd isolator-cli
go build -o isolator main.go
cd ..
```
2. **Build TS Server:** In this main directory (`isolator-mcp`), run `npm install` and `npm run build`.
3. **Configure:** Make sure `isolator_config.json` correctly points to the built `./isolator-cli/isolator` binary via the `isolatorPath` key (use the absolute path).
4. **Run Server:** Execute the built server directly using Node:
```bash
node build/index.js
```
The server will start, connect via stdio, and print logs (including `console.error` messages from `index.ts`) to the console.
5. **Interact (Manual):** You can manually send JSON-RPC messages (e.g., `tools/list`, `tools/call`) to the server's standard input to test its responses. Tools like `@modelcontextprotocol/inspector` can also be helpful (`npm run inspector`).
*(Remember to stop this manually run server before relying on the MCP Host to start it via the settings file.)*
## Architecture & Flow
1. **MCP Host Request:** An LLM asks the MCP Host (e.g., VS Code Extension) to call the `isolator` server's `execute_code` tool with arguments.
2. **Server Processing (`index.ts`):**
* Receives the `tools/call` request via stdio.
* Validates arguments using Zod.
* Loads configuration from `isolator_config.json`.
* Determines the code source:
* If `snippet_name` is provided, reads the corresponding file from the configured `promptsDir` and determines the language from the file extension.
* If `entrypoint_code` and `language` are provided, uses them directly.
* Creates a temporary directory on the host.
* Writes the entrypoint code and any `additional_files` into the temporary directory.
* Constructs the command-line arguments for the embedded `isolator` Go CLI, including security flags from the config and the path to the temporary directory.
* Spawns the `isolator` process using Node.js `child_process.spawn`.
3. **Go CLI Execution (`isolator-cli/isolator run`):**
* Parses flags (including the new `--env` flag).
* Creates a tar stream of the temporary directory contents.
* Uses the Docker SDK to create a container with specified image, resource limits, environment variables (from `--env`), and security settings (NO bind mount).
* Uses `CopyToContainer` to copy the tar stream into the container's working directory.
* Starts the container, which executes the requested command (e.g., `python /workspace/hello_world.py`).
* Waits for completion, captures stdout/stderr.
* Removes the container.
* Prints the result (status, output, etc.) as JSON to its stdout.
4. **Server Result Handling (`index.ts`):**
* Reads the JSON output from the finished `isolator` process stdout.
* Parses the JSON result.
* Formats the `CallToolResult` for MCP, combining stdout/stderr and setting `isError` if the Go CLI reported a non-success status.
* Sends the result back to the MCP Host.
* Cleans up the temporary directory on the host.
5. **MCP Host Response:** Relays the result back to the LLM, which then formulates a response for the user.
## `execute_code` Tool
### Description
Executes code (Python, Go, JavaScript) in a secure, isolated container environment.
### Input Schema (`arguments`)
* `language` (string, optional): The programming language (e.g., "python", "go", "javascript"). Required if `snippet_name` is not provided.
* `entrypoint_code` (string, optional): The main code content to execute. Required if `snippet_name` is not provided.
* `entrypoint_filename` (string, optional): Filename for the main code (e.g., "main.py", "script.js"). Defaults based on language if not provided.
* `additional_files` (array, optional): Array of objects, each with:
* `filename` (string, required): Name of the additional file.
* `content` (string, required): Content of the additional file.
* `snippet_name` (string, optional): Name of a pre-defined code snippet file (without extension) located in the configured `promptsDir`. Mutually exclusive with `language` and `entrypoint_code`.
**Constraint:** Either `snippet_name` OR both `language` and `entrypoint_code` must be provided.
### Output (`CallToolResult`)
* `content`: An array containing a single `TextContent` object.
* `type`: "text"
* `text`: A string containing the combined stdout and stderr from the execution, formatted like:
```
--- stdout ---
[Actual stdout output]
--- stderr ---
[Actual stderr output]
```
If an error occurred *during* execution (non-zero exit code, timeout), the text will be prepended with `Execution Failed (status): [error message]\n\n`.
* `isError` (boolean): `true` if the execution status reported by the `isolator` CLI was "error" or "timeout", `false` otherwise.
*(Protocol-level errors, like invalid arguments or failure to start the process, will result in a standard MCP error response instead of a `CallToolResult`)*.