Skip to content

Commit b9bdd99

Browse files
committed
Initial release: local sandbox MCP server for Apple Containers
0 parents  commit b9bdd99

13 files changed

Lines changed: 4907 additions & 0 deletions

.github/workflows/ci.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
jobs:
8+
test:
9+
runs-on: ubuntu-latest
10+
strategy:
11+
fail-fast: false
12+
matrix:
13+
python-version: ["3.11", "3.12"]
14+
15+
steps:
16+
- name: Checkout
17+
uses: actions/checkout@v4
18+
19+
- name: Setup Python
20+
uses: actions/setup-python@v5
21+
with:
22+
python-version: ${{ matrix.python-version }}
23+
24+
- name: Setup uv
25+
uses: astral-sh/setup-uv@v5
26+
27+
- name: Install dependencies
28+
run: uv sync --group dev
29+
30+
- name: Run tests
31+
run: uv run pytest tests/ -q
32+
33+
- name: Compile check
34+
run: python -m compileall sandbox_mcp_server.py tests
35+
36+
package:
37+
runs-on: ubuntu-latest
38+
39+
steps:
40+
- name: Checkout
41+
uses: actions/checkout@v4
42+
43+
- name: Setup Python
44+
uses: actions/setup-python@v5
45+
with:
46+
python-version: "3.11"
47+
48+
- name: Install build backend
49+
run: python -m pip install --upgrade pip build hatchling
50+
51+
- name: Build package
52+
run: python -m build

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
__pycache__/
2+
*.pyc
3+
.venv/
4+
*.egg-info/
5+
.pytest_cache/
6+
dist/
7+
PLAN.md

CLAUDE.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# sandbox-mcp
2+
3+
MCP server for Apple Container sandboxes. Single-file Python server (`sandbox_mcp_server.py`, ~2850 lines) using FastMCP.
4+
5+
## Project structure
6+
7+
```
8+
sandbox_mcp_server.py # Everything: Sandbox class, SandboxManager, 32 MCP tools
9+
pyproject.toml # uv/hatchling packaging, entry point: sandbox-mcp
10+
Containerfile.mcp-dev # Alpine 3.23 image with Python/Node/Go/Rust
11+
tests/ # pytest test suite
12+
```
13+
14+
## Key patterns
15+
16+
- **Shell quoting**: Always use `_sq(value)` for any user-provided string interpolated into shell commands. Never use f-string quotes.
17+
- **Env key validation**: Use `_validate_env_key(key)` before any env var operations.
18+
- **Audit logging**: Pass `audit=False` for internal/diagnostic commands to keep the audit log clean.
19+
- **Port forwarding**: Uses `container exec -i <name> nc` proxy, NOT `-p` flag (broken in Apple Containers v0.9.0).
20+
- **Profile tuple**: `_get_profile()` returns `(cpus, memory, virtualization)` — 3-tuple, unpack accordingly.
21+
22+
## Running
23+
24+
```bash
25+
uv run sandbox-mcp # stdio mode (for MCP clients)
26+
python3 sandbox_mcp_server.py # also works
27+
```
28+
29+
## Testing
30+
31+
```bash
32+
uv run pytest tests/ -v
33+
```
34+
35+
## Adding a new tool
36+
37+
1. Add manager method to `SandboxManager` class
38+
2. Add `@mcp_server.tool()` function that calls the manager method
39+
3. Update the docstring tool list at the top of the file
40+
4. Add to permissions in `~/.claude/settings.local.json`
41+
5. Run tests

Containerfile.mcp-dev

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
FROM alpine:3.23
2+
3+
# Core build tools
4+
RUN apk add --no-cache \
5+
build-base \
6+
cmake \
7+
git \
8+
curl \
9+
wget \
10+
jq \
11+
tar \
12+
gzip \
13+
unzip \
14+
openssh-client \
15+
ca-certificates
16+
17+
# Python
18+
RUN apk add --no-cache \
19+
python3 \
20+
py3-pip \
21+
py3-setuptools \
22+
py3-wheel \
23+
py3-virtualenv
24+
25+
# Node.js
26+
RUN apk add --no-cache \
27+
nodejs \
28+
npm
29+
30+
# Go
31+
RUN apk add --no-cache go
32+
33+
# Rust
34+
RUN apk add --no-cache \
35+
rust \
36+
cargo
37+
38+
# Create workspace
39+
RUN mkdir -p /workspace
40+
WORKDIR /workspace

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 bird
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)