mcp-python-repl 0.1.1
A production-grade MCP server providing a persistent Python REPL with multi-session support, sandboxing, and timeout protection.
Requires Python: >=3.10
Keywords: agent, interpreter, llm, mcp, model-context-protocol, python, repl

# 🐍 mcp-python-repl

A **production-grade** MCP server providing a persistent Python REPL with multi-session support, sandboxing, and timeout protection.

Built for LLM agents that need to execute Python code across multiple turns with **variables that persist between calls**.

## ✨ Features

| Feature | Description |
|---|---|
| **Multi-session** | Isolated sessions with unique IDs — run parallel workflows |
| **Persistent namespace** | Variables survive across calls within a session |
| **Timeout protection** | Configurable execution timeout (SIGALRM on Unix) |
| **Sandboxing** | Optional mode blocks dangerous modules (`subprocess`, `socket`, etc.) |
| **Package install** | Install pip packages on-the-fly (prefers `uv` for speed) |
| **File execution** | Run `.py` files inside the persistent session |
| **Dual transport** | stdio (local) and streamable-http (remote) |
| **Full introspection** | List variables, get history, check server status |
| **Env-based config** | All settings via `REPL_*` environment variables |

## 🚀 Quick Start

### With Claude Desktop / Cursor (stdio)

Add to your MCP config:

```json
{
  "mcpServers": {
    "python-repl": {
      "command": "uvx",
      "args": ["mcp-python-repl"]
    }
  }
}
```

### With uv (local dev)

```bash
# Clone and run
git clone https://github.com/soufiane-aazizi/mcp-python-repl.git
cd mcp-python-repl
uv run mcp-python-repl
```

### HTTP transport (remote / multi-client)

```bash
REPL_TRANSPORT=streamable-http REPL_PORT=8000 uv run mcp-python-repl
```

## 🛠️ Tools

### Code Execution

| Tool | Description |
|---|---|
| `repl_run_code` | Execute Python code with persistent namespace |
| `repl_run_file` | Execute a `.py` file in the session |
| `repl_install_package` | Install a pip package (uses `uv` if available) |

### Namespace Management

| Tool | Description |
|---|---|
| `repl_list_namespace` | List all variables in a session |
| `repl_get_variable` | Get the full value of a variable |
| `repl_set_variable` | Inject a variable from JSON |
| `repl_delete_variable` | Delete a specific variable |
| `repl_clear_namespace` | Clear all variables in a session |

### Session Management

| Tool | Description |
|---|---|
| `repl_list_sessions` | List all active sessions |
| `repl_delete_session` | Delete a session and its data |

### Debugging

| Tool | Description |
|---|---|
| `repl_get_history` | Get execution history for a session |
| `repl_server_status` | Server config, Python version, session count |

## 🔄 How Persistence Works

```
Call 1:  repl_run_code(code="data = [1,2,3]; total = sum(data); result = total")
         → returns: {"result": 6, "session_id": "a1b2c3d4e5f6", "new_variables": ["data", "total"]}

Call 2:  repl_run_code(code="doubled = [x*2 for x in data]; result = doubled", session_id="a1b2c3d4e5f6")
         → returns: {"result": [2,4,6], "new_variables": ["doubled"]}
```

> **Important:** The `result` variable is for returning output to the caller. It does **NOT** persist. Use named variables instead.

## ⚙️ Configuration

All settings are configurable via environment variables:

| Variable | Default | Description |
|---|---|---|
| `REPL_TIMEOUT` | `30` | Max execution time in seconds |
| `REPL_MAX_SESSIONS` | `50` | Maximum concurrent sessions |
| `REPL_SESSION_TTL` | `120` | Session expiry in minutes |
| `REPL_MAX_OUTPUT` | `1048576` | Max stdout/stderr capture (bytes) |
| `REPL_SANDBOX` | `false` | Enable sandboxing (`true`/`false`) |
| `REPL_TRANSPORT` | `stdio` | Transport: `stdio` or `streamable-http` |
| `REPL_HOST` | `127.0.0.1` | HTTP host (when using HTTP transport) |
| `REPL_PORT` | `8000` | HTTP port (when using HTTP transport) |
| `REPL_WORKDIR` | `cwd` | Working directory for executions |

### Sandbox Mode

When `REPL_SANDBOX=true`, the following modules are blocked:

`subprocess`, `shutil`, `ctypes`, `socket`, `http.server`, `xmlrpc`, `ftplib`, `smtplib`, `telnetlib`, `webbrowser`

And the following builtins are removed: `exec`, `eval`, `compile`, `__import__` (replaced with a restricted version).

## 🧪 Development

```bash
# Install dev dependencies
uv sync --extra dev

# Run tests
uv run pytest -v

# Lint
uv run ruff check src/ tests/

# Test with MCP Inspector
npx @modelcontextprotocol/inspector uv run mcp-python-repl
```

## 📦 Project Structure

```
mcp-python-repl/
├── src/mcp_python_repl/
│   ├── __init__.py       # Package metadata
│   ├── config.py         # Env-based configuration
│   ├── session.py        # Multi-session manager with TTL
│   ├── executor.py       # Python code executor (timeout + sandbox)
│   └── server.py         # MCP server with all tools
├── tests/
│   └── test_core.py      # Unit + integration tests
├── pyproject.toml        # uv/hatch project config
├── LICENSE               # MIT
└── README.md
```

## 📄 License

MIT — See [LICENSE](LICENSE).