Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# CodeRunner Configuration Example
# Copy this file to .env and modify as needed

# Jupyter Settings
CODERUNNER_JUPYTER_HOST=127.0.0.1
CODERUNNER_JUPYTER_PORT=8888
CODERUNNER_JUPYTER_WS_URL=ws://127.0.0.1:8888

# Directory Settings
CODERUNNER_SHARED_DIR=/app/uploads

# Execution Settings
CODERUNNER_EXECUTION_TIMEOUT=300.0
CODERUNNER_WEBSOCKET_TIMEOUT=1.0
CODERUNNER_MAX_WAIT_JUPYTER=30

# FastMCP Settings
CODERUNNER_FASTMCP_HOST=0.0.0.0
CODERUNNER_FASTMCP_PORT=8222

# Logging Settings
CODERUNNER_LOG_LEVEL=INFO
CODERUNNER_LOG_FORMAT=%(asctime)s - %(levelname)s - %(message)s

# Resource Settings (optional)
# CODERUNNER_MAX_KERNEL_MEMORY=1G
# CODERUNNER_MAX_KERNEL_CPU=1.0
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ jupyter_runtime/

# Node modules (if any)
node_modules/
.aider*
94 changes: 43 additions & 51 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,74 +1,66 @@
# Use the specified standard Python 3.13.3 base image (Debian-based)
FROM python:3.13.3
# Multi-stage build for optimized image size
FROM python:3.13.3 as builder

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE 1
ENV PYTHONUNBUFFERED 1
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DEBIAN_FRONTEND=noninteractive

# Set working directory
WORKDIR /app

# Install system dependencies INCLUDING systemd
# Install build dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
systemd \
sudo \
curl \
iproute2 \
ffmpeg \
bash \
build-essential \
procps \
openssh-client \
openssh-server \
jq \
kmod \
&& apt-get clean && rm -rf /var/lib/apt/lists/*

&& rm -rf /var/lib/apt/lists/*

# Upgrade pip
RUN python -m pip install --no-cache-dir --upgrade pip

# Copy requirements file
COPY ./requirements.txt /app/requirements.txt
# Copy requirements and install Python dependencies
COPY requirements.txt /tmp/requirements.txt
RUN pip install --no-cache-dir --user -r /tmp/requirements.txt

# Install Python dependencies
RUN pip install --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.13.3-slim

# Set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV DEBIAN_FRONTEND=noninteractive
ENV PATH="/root/.local/bin:$PATH"

# Install the bash kernel spec for Jupyter (not working with uv)
RUN python -m bash_kernel.install
# Install runtime dependencies and tini for proper signal handling
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
jq \
tini \
&& rm -rf /var/lib/apt/lists/*

# Set working directory
WORKDIR /app

# Copy the application code (server.py)
COPY ./server.py /app/server.py
# Copy Python packages from builder stage
COPY --from=builder /root/.local /root/.local

# Create application/jupyter directories
RUN mkdir -p /app/uploads /app/jupyter_runtime
# Install the bash kernel spec for Jupyter
RUN python -m bash_kernel.install

# # Generate SSH host keys
# RUN ssh-keygen -A
# Copy application code
COPY server.py config.py jupyter_client.py /app/

# Clean systemd machine-id
RUN rm -f /etc/machine-id && touch /etc/machine-id
# Create application directories
RUN mkdir -p /app/uploads /app/jupyter_runtime

# --- Set environment variables for the application ---
ENV FASTMCP_HOST="0.0.0.0"
ENV FASTMCP_PORT="8222"
# Copy the entrypoint script
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

# Set environment variables for the application
ENV CODERUNNER_FASTMCP_HOST="0.0.0.0"
ENV CODERUNNER_FASTMCP_PORT="8222"
ENV CODERUNNER_JUPYTER_HOST="0.0.0.0"
ENV CODERUNNER_JUPYTER_PORT="8888"

# Expose the FastAPI port
EXPOSE 8222

# Start the FastAPI application
# CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8002", "--workers", "1", "--no-access-log"]


# Copy the entrypoint script into the image
COPY entrypoint.sh /entrypoint.sh

# Make the entrypoint script executable
RUN chmod +x /entrypoint.sh
EXPOSE 8222 8888

# Use the entrypoint script
ENTRYPOINT ["/entrypoint.sh"]
# Use tini for proper signal handling
ENTRYPOINT ["tini", "--", "/entrypoint.sh"]
175 changes: 173 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

CodeRunner is an MCP (Model Context Protocol) server that executes AI-generated code in a sandboxed environment on your Mac using Apple's native [containers](https://github.com/apple/container).

**Key use case:** Process your local files (videos, images, documents, data) with remote LLMs like Claude or ChatGPT without uploading your files to the cloud. The LLM generates code that runs locally on your machine to analyze, transform, or process your files.
**Key use case:** Process your local files (videos, images, documents, data) with remote LLMs like Claude or ChatGPT without uploading your files to the cloud. The LLM generates Python code or bash scripts that run locally on your machine to analyze, transform, or process your files.

## What CodeRunner Enables

Expand All @@ -21,6 +21,7 @@ CodeRunner is an MCP (Model Context Protocol) server that executes AI-generated
| Copy/paste scripts to run elsewhere | Code runs immediately, shows output/files |
| LLM analyzes text descriptions of files | LLM directly processes your actual files |
| Manage Python environments and packages | Pre-configured environment ready to use |
| Limited to one programming language | Supports both Python and Bash execution |

## Quick Start

Expand Down Expand Up @@ -140,15 +141,185 @@ From [@apple/container](https://github.com/apple/container/blob/main/docs/techni
## Architecture

CodeRunner consists of:
- **Sandbox Container:** Isolated execution environment with Jupyter kernel
- **Sandbox Container:** Isolated execution environment with Python and Bash Jupyter kernels
- **MCP Server:** Handles communication between AI models and the sandbox
- **Multi-Kernel Support:** Automatically routes Python and Bash code to appropriate kernels

## Examples

The `examples/` directory contains:
- `openai-agents` - Example OpenAI agents integration
- `claude-desktop` - Example Claude Desktop integration

## Development

### Running Locally

1. **Install dependencies:**
```bash
pip install -r requirements.txt
```

2. **Set up configuration:**
```bash
cp .env.example .env
# Edit .env with your preferred settings
```

3. **Run tests:**
```bash
python -m pytest tests/ -v
```

4. **Run the server:**
```bash
python server.py
```

### Available MCP Tools

CodeRunner provides the following MCP tools for AI models:

1. **`execute_python_code`** - Execute Python code in a persistent Jupyter kernel
```
execute_python_code(command="print('Hello, World!')")
```

2. **`execute_bash_code`** - Execute Bash commands in a persistent Jupyter bash kernel
```
execute_bash_code(command="ls -la && echo 'Directory listing complete'")
```

3. **`get_kernel_status`** - Check the status of available kernels
```
get_kernel_status()
```

### Usage Examples

**Python Code Execution:**
```python
# Data analysis
execute_python_code("""
import pandas as pd
import matplotlib.pyplot as plt

# Create sample data
data = {'x': [1, 2, 3, 4, 5], 'y': [2, 4, 6, 8, 10]}
df = pd.DataFrame(data)
print(df.describe())
""")
```

**Bash Script Execution:**
```bash
# File operations
execute_bash_code("""
# Create directory structure
mkdir -p /tmp/test_dir
cd /tmp/test_dir

# Create files
echo "Hello World" > hello.txt
echo "Goodbye World" > goodbye.txt

# List files with details
ls -la
""")
```

**Combined Usage:**
```python
# Use bash to prepare data, then Python to analyze
execute_bash_code("curl -o data.csv https://example.com/data.csv")
execute_python_code("""
import pandas as pd
df = pd.read_csv('data.csv')
print(df.head())
""")
```

### Configuration

CodeRunner can be configured via environment variables with the `CODERUNNER_` prefix for consistency across all components (Python application, Docker container, and entrypoint script). See `.env.example` for available options:

- `CODERUNNER_JUPYTER_HOST`: Jupyter server host (default: 127.0.0.1)
- `CODERUNNER_JUPYTER_PORT`: Jupyter server port (default: 8888)
- `CODERUNNER_FASTMCP_HOST`: FastMCP server host (default: 0.0.0.0)
- `CODERUNNER_FASTMCP_PORT`: FastMCP server port (default: 8222)
- `CODERUNNER_EXECUTION_TIMEOUT`: Code execution timeout in seconds (default: 300)
- `CODERUNNER_LOG_LEVEL`: Logging level (default: INFO)

### Testing

Run the test suite:
```bash
# Run all tests
python -m pytest tests/

# Run specific test files
python -m pytest tests/test_config.py -v

# Run tests with coverage (if installed)
python -m pytest tests/ --cov=. --cov-report=html
```

## Recent Changes (Refactor Branch)

### Major Refactoring Improvements

1. **Modularized Architecture**
- Extracted Jupyter client logic into `jupyter_client.py`
- Created centralized configuration system in `config.py`
- Improved separation of concerns

2. **Enhanced Configuration Management**
- Environment variable support with `CODERUNNER_` prefix
- Centralized configuration with sensible defaults
- Better local development support

3. **Improved Error Handling**
- Custom exception classes for better error categorization
- More robust WebSocket connection handling
- Comprehensive logging and error reporting

4. **Container Optimizations**
- Multi-stage Docker build for smaller images
- Proper signal handling with `tini`
- Better entrypoint script with error handling
- Unified configuration with `CODERUNNER_` prefix across all components

5. **Multi-Kernel Support**
- Added Bash kernel support alongside Python
- New `execute_bash_code` MCP tool for shell commands
- Kernel status monitoring with `get_kernel_status` tool

6. **Testing Framework**
- Comprehensive test suite with pytest
- Unit tests for configuration and Jupyter client
- Mock-based testing for isolated components

7. **Code Quality Improvements**
- Pinned dependency versions for reproducible builds
- Cleaner, more maintainable code structure
- Better documentation and type hints

### File Structure
```
coderunner/
β”œβ”€β”€ config.py # Configuration management
β”œβ”€β”€ jupyter_client.py # Jupyter WebSocket client
β”œβ”€β”€ server.py # Main FastMCP server
β”œβ”€β”€ requirements.txt # Pinned dependencies
β”œβ”€β”€ Dockerfile # Optimized multi-stage build
β”œβ”€β”€ entrypoint.sh # Improved container entrypoint
β”œβ”€β”€ .env.example # Configuration template
β”œβ”€β”€ pytest.ini # Test configuration
└── tests/ # Test suite
β”œβ”€β”€ test_config.py
└── test_jupyter_client.py
```

## Contributing

We welcome contributions! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
Expand Down
Loading