Upload README.md
This commit is contained in:
@@ -0,0 +1,97 @@
|
|||||||
|
# Turnstone MCP Server
|
||||||
|
|
||||||
|
A [Model Context Protocol](https://modelcontextprotocol.io/) 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
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
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 protection** — `extract_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.
|
||||||
Reference in New Issue
Block a user