2026-07-15 14:42:24 +01:00
2026-07-15 14:42:24 +01:00
2026-07-15 19:00:59 +01:00
2026-07-15 14:42:24 +01:00

Turnstone MCP Server

A Model Context Protocol server providing four sandboxed tools for LLM-driven workflows. Built with FastMCP and Playwright, it exposes code execution, headless browser automation, and file-to-Markdown conversion over HTTP.

Designed to run as a Docker container alongside the Turnstone platform, sharing the turnstone_workspace volume so tools can read and write files that other services in the ecosystem use.

Tools

Tool Description
execute_python_code Runs Python source in a subprocess with timeout, memory, and output-size limits
playwright_navigate Navigates a persistent headless Chromium session to a URL
playwright_get_page_text Extracts rendered text from the current browser page
extract_to_markdown Converts supported files (PDF, DOCX, images, CSV, etc.) to Markdown via markitdown

Quick Start

Run the server with Docker Compose:

docker compose up --build

The server starts on port 8000. The MCP health endpoint is available at http://localhost:8000/health.

Running in the background

docker compose up -d --build

Configuration

All limits are configurable via environment variables with sensible defaults. Set them in your .env file or pass them through docker compose:

Variable Default Description
PYTHON_EXEC_TIMEOUT 30 Python execution timeout (seconds)
PYTHON_MAX_OUTPUT 65536 Maximum stdout/stderr capture (bytes)
PYTHON_MAX_MEMORY_MB 256 Address-space memory limit per subprocess (MB)
PLAYWRIGHT_NAV_TIMEOUT 30000 Browser navigation timeout (ms)
PLAYWRIGHT_TEXT_TIMEOUT 15000 Page text extraction timeout (ms)
EXTRACT_MAX_FILE_SIZE 10485760 Maximum file size for extraction (10 MB)
WORKSPACE_MOUNT workspace Docker volume name for the shared workspace

Example with custom limits:

PYTHON_EXEC_TIMEOUT=60 PYTHON_MAX_MEMORY_MB=512 docker compose up --build

Architecture

┌──────────────┐     HTTP/MCP      ┌──────────────────┐
│   LLM Client │ ────────────────► │  Turnstone MCP    │
│              │                   │  Container :8000  │
└──────────────┘                   └────────┬─────────┘
                                            │
                    ┌───────────────────────┼───────────────────────┐
                    │                       │                       │
              ┌─────▼─────┐          ┌──────▼──────┐       ┌───────▼───────┐
              │ subprocess │          │ Playwright  │       │ markitdown    │
              │ (Python)   │          │ Chromium    │       │ (file → MD)   │
              └───────────┘          └─────────────┘       └───────────────┘
                    │                       │                       │
                    └───────────┬───────────┴───────────────────────┘
                                │
                      ┌─────────▼──────────┐
                      │  turnstone_workspace│
                      │  (shared volume)    │
                      └────────────────────┘

Key design decisions

  • Persistent browser session — A singleton PlaywrightBrowserManager holds the Chromium process alive across tool calls, preventing garbage-collection teardowns.
  • Sandboxed execution — Python code runs in a separate process with a per-subprocess memory limit (resource.setrlimit) and a wall-clock timeout enforced by subprocess.run.
  • Path traversal protectionextract_to_markdown resolves all paths against WORKSPACE_ROOT and rejects anything that escapes it.
  • Structured JSON logging — All tool invocations and responses are logged as structured JSON for observability.
  • CORS enabled — The server accepts requests from any origin with standard MCP headers.
  • Shared workspace volume — The container mounts the turnstone_workspace Docker volume at /workspace, giving the MCP tools read/write access to files used by other Turnstone services.

Docker Configuration

The service is defined in compose.yaml:

Setting Value
Port mapping 8000:8000
User 1000:1000
Restart policy unless-stopped
Health check HTTP GET /health every 30 s (timeout 10 s, 3 retries)
Workspace mount ${WORKSPACE_MOUNT:-workspace}:/workspace

Endpoints

Method Path Description
POST / MCP protocol endpoint (default)
GET /health Returns {"status": "healthy", "service": "turnstone-mcp"}

Project Structure

compose.yaml       # Docker Compose service definition
Dockerfile         # Container build instructions
server.py          # Complete MCP server — all logic in a single module

Development

No test framework or build step is required. To add a new tool, follow the existing pattern:

  1. Define the function with @mcp.tool()
  2. Add docstring with Parameters and Returns sections
  3. Implement input validation and error handling
  4. Return a string result (success or error message)

License

See the repository root for licensing information.

S
Description
No description provided
Readme
58 KiB
Languages
Python 97.8%
Dockerfile 2.2%