2026-07-15 19:39:00 +01:00
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 19:39:00 +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, production-ready tools for LLM-driven workflows. Built with FastMCP and Playwright, it exposes code execution, headless browser automation, and file-to-Markdown conversion over HTTP.

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

# Install dependencies
pip install fastmcp playwright markitdown
playwright install chromium

# Run the server
python server.py

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

Configuration

All limits are configurable via environment variables with sensible defaults:

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_ROOT /workspace Base directory for file-relative operations

Example with custom limits:

PYTHON_EXEC_TIMEOUT=60 PYTHON_MAX_MEMORY_MB=512 python server.py

Architecture

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

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.

Endpoints

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

Project Structure

server.py          # Complete MCP server — all logic in a single module

This repository is intentionally minimal: one file, zero dependencies beyond the pip requirements.

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%