Lathe
Local image, PDF, audio and video processing and OCR for an AI assistant: convert, resize, crop, merge, split, trim and extract text. Files stay inside one working folder on your machine.
Documentation
Lathe
Made by Seaynic Labs. Need tools like this built around your own systems? We do that.
Lathe is an MCP bundle for anyone who handles files and media. It gives your AI assistant local tools for images, PDFs, audio and video, and OCR, plus batch runs and metadata removal. The files stay on your machine.
It is a bundle: one server made of modules, each switched on or off. Modules that arrive in an update and are off by default stay off until you turn them on.
| Security card | |
|---|---|
| Network | None. Lathe makes no network connections, and ffmpeg and ffprobe are restricted to local files (-protocol_whitelist file,pipe). --transport http listens on 127.0.0.1 only when you start it that way. |
| Files | Reads and writes files only inside the working folder (LATHE_WORKING_DIR). Reads its optional config file ( |
| Secrets | No keys, accounts or passwords. Nothing to store, and nothing that leaves the machine. |
| Read-only tools | 8: image_info, pdf_info, pdf_extract_text, audio_info, video_info, ocr_image, health, lathe_modules |
| Writes new files | audio_convert, batch_process, image_convert, image_crop, image_optimize, image_resize, image_thumbnail, pdf_compress, pdf_merge, pdf_split, pdf_to_images, scrub_metadata, video_thumbnail, video_to_gif, video_trim: each call writes new files in the working folder and never overwrites an existing one unless the call passes overwrite=true. batch_process asks the person once per run of two or more files, and nothing else asks. |
| Startup cost | about 7,600 tokens for a default install (21 tools, 4 skill prompts) |
| Changes | Tool descriptions are locked by hash (tool-manifest.lock.json); CI fails if they change silently. |
Modules
| Module | What it does | On by default | Needs |
|---|---|---|---|
images | Info, resize, convert, optimize, crop, thumbnail | yes | Pillow (always installed) |
pdf | Info, text (OCR for scanned pages), merge, render pages, split, compress | yes | pdf extra; ghostscript for rendering |
media | Audio and video info, audio convert, a frame, trim, GIF | yes | ffmpeg and ffprobe |
ocr | Text from an image | yes | ocr extra; tesseract |
batch | One operation over every file matching a glob, dry run first | no | per operation (see above) |
privacy | Inspect and remove GPS, camera and author metadata | no | pdf extra, for PDFs |
Lathe is free and MIT licensed. It has 21 tools by default and 23 with batch and privacy on.
Skills
Skills explain how to do a job well. Your AI assistant reads them as Agent Skills, or as MCP prompts in any MCP app.
| Skill | Use it for |
|---|---|
getting-started | Setup, the install command for each missing piece, --doctor, and the approval rules |
pdf | Turning a Markdown file into a PDF with Chrome or Chromium |
pdf-forms | Making a PDF with fillable text boxes and checkboxes |
web-image-prep | Removing location data and shrinking a folder of photos for a website |
First five minutes
- Install:
uvx --from "lathe-mcp[pdf,ocr]" lathe --versionprints the version. Needs Python 3.11 or newer and uv. - Add Lathe to your client (see Add it to your MCP client). Set
LATHE_WORKING_DIRto the folder with your files. - Run
lathe --doctor(uvx --from "lathe-mcp[pdf,ocr]" lathe --doctor). It printsokorFIXfor each piece and the command that fixes it. - Ask your assistant to call
lathe_modules. It lists every module, what is on, and what is missing.
Try these
Paste these into your assistant, after setting LATHE_WORKING_DIR:
Call lathe_modules and tell me which pieces are missing.Show me the metadata in photos/trip.jpg, then make a copy without it as photos/trip-clean.jpg.(needsLATHE_PRIVACY_ENABLED=true)Dry-run image_optimize on everything in photos/ into web/, then run it.(needsLATHE_BATCH_ENABLED=true)Split report.pdf into parts of 5 pages in parts/.Cut the first 10 seconds of clip.mp4 into clip-10s.mp4, then make a 5-second GIF from it.
Install
Lathe needs Python 3.11 or newer. With uv you don't install anything ahead of time. Choose the extras for the modules you use:
uvx --from lathe-mcp lathe --version # images, media and batch
uvx --from "lathe-mcp[pdf,ocr]" lathe --version # with PDF and OCR
Pinned to this release, for a repeatable setup:
uvx --from "lathe-mcp[pdf,ocr]==0.4.1" lathe --version
Or with pip:
pip install "lathe-mcp[pdf,ocr]"
Extras: pdf (pypdf), ocr (pytesseract), full (both). The images module needs nothing extra.
Claude Code plugin
The repository is also a Claude Code plugin. Its .mcp.json pins lathe-mcp[pdf,ocr]==0.4.1, and it ships the skills in skills/. The plugin is one way to install; the MCP config below works in any client.
System programs
Lathe starts without these. lathe --doctor and the lathe_modules tool list what is missing and the command for your platform.
| Program | Used by | macOS | Debian / Ubuntu |
|---|---|---|---|
| ffmpeg (includes ffprobe) | media, batch (audio) | brew install ffmpeg | sudo apt install ffmpeg |
| tesseract | ocr, and pdf_extract_text on scanned pages | brew install tesseract | sudo apt install tesseract-ocr |
| ghostscript | pdf_to_images, batch (PDF) | brew install ghostscript | sudo apt install ghostscript |
Settings
Set these as environment variables in your MCP client's config, or in a config file. Lathe starts without any of them.
| Variable | What it is |
|---|---|
LATHE_WORKING_DIR | The folder Lathe reads from and writes to. Default: the folder the server starts in. |
LATHE_MAX_FILE_MB | Largest input file, in MB. Default 500. |
LATHE_OCR_LANG | Tesseract language code(s), e.g. eng or eng+fra. Default eng. |
LATHE_<MODULE>_ENABLED | true or false. Default true for images, pdf, media and ocr; false for batch and privacy. |
LATHE_BATCH_PREAPPROVED | true lets a batch run of two or more files go ahead without the approval prompt. Default false. Set it only if your client cannot show approval prompts. |
LATHE_APPROVAL_LOG | Where the approval log is written. Default ~/.local/state/lathe/approvals.jsonl. |
Config file (optional). Lathe also reads ~/.config/lathe/config.toml, or the file named by LATHE_CONFIG. Environment variables win over the file.
[core]
working_dir = "/Users/you/Pictures"
[ocr]
lang = "eng"
[batch]
enabled = true
[privacy]
enabled = true
Add it to your MCP client
Every client below runs Lathe as a local process over stdio. Put the env values only where you need them.
Claude Desktop: claude_desktop_config.json (Settings, Developer, Edit Config)
{
"mcpServers": {
"lathe": {
"command": "uvx",
"args": ["--from", "lathe-mcp[pdf,ocr]", "lathe"],
"env": { "LATHE_WORKING_DIR": "/path/to/your/files", "LATHE_BATCH_ENABLED": "true", "LATHE_PRIVACY_ENABLED": "true" }
}
}
}
Claude Code
claude mcp add lathe -e LATHE_WORKING_DIR=/path/to/your/files -- uvx --from "lathe-mcp[pdf,ocr]" lathe
Cursor: ~/.cursor/mcp.json, or .cursor/mcp.json in a project
{
"mcpServers": {
"lathe": {
"command": "uvx",
"args": ["--from", "lathe-mcp[pdf,ocr]", "lathe"],
"env": { "LATHE_WORKING_DIR": "/path/to/your/files" }
}
}
}
VS Code: .vscode/mcp.json (note "servers", not "mcpServers")
{
"servers": {
"lathe": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "lathe-mcp[pdf,ocr]", "lathe"],
"env": { "LATHE_WORKING_DIR": "/path/to/your/files" }
}
}
}
Sonique, Hermes, OpenClaw, and other clients: any client that launches a stdio MCP server. Command uvx, arguments ["--from", "lathe-mcp[pdf,ocr]", "lathe"], plus the env values above.
Over HTTP. For clients that connect to a URL instead of starting a process:
lathe --transport http --port 8765
It serves streamable HTTP at http://127.0.0.1:8765/mcp. It listens only on your own machine by default. Put authentication in front of it before exposing it anywhere else.
Tools
| Tool | Module | What it does | Asks first |
|---|---|---|---|
health | core | Server version, working folder, and whether each external program is installed | no |
lathe_modules | core | Which modules are on, what is missing (with the install command), skills, and what each tool needs | no |
image_info | images | Width, height, format, mode, size, and EXIF tags | no |
image_resize | images | Resize by width, height or percentage, keeping the aspect ratio | no |
image_convert | images | Convert to png, jpeg, webp, avif or bmp | no |
image_optimize | images | Shrink for web delivery; metadata stripped unless strip_metadata=false | no |
image_crop | images | Crop a rectangle | no |
image_thumbnail | images | Fit inside a square | no |
pdf_info | Page count, size, encryption, title, author | no | |
pdf_extract_text | Text of the pages you name, or of the whole file; OCR for pages without a text layer; long text in parts | no | |
pdf_merge | Merge PDFs in order | no | |
pdf_to_images | Render pages to PNG or JPEG at a chosen DPI | no | |
pdf_split | Split into parts of N pages | no | |
pdf_compress | Lossless smaller copy: content streams and duplicate objects | no | |
audio_info | media | Duration, format, bitrate, sample rate, channels | no |
audio_convert | media | Convert to mp3, wav, flac, aac or ogg | no |
video_info | media | Duration, resolution, codec, frame rate, audio tracks | no |
video_thumbnail | media | Save one frame at a time in seconds | no |
video_trim | media | Cut a section (stream copy; cuts land on keyframes) | no |
video_to_gif | media | Animated GIF from up to 30 seconds of video | no |
ocr_image | ocr | Text from an image; long text in parts | no |
batch_process | batch | One operation over every matching file; dry run by default | yes, for runs of 2+ files |
scrub_metadata | privacy | Inspect (default), or write a copy without GPS, camera or author metadata | no |
Every tool returns structured data with a published schema. Long text comes in parts: pass next_offset back as offset. Errors always read lathe.<module>.<code>: <message> Fix: <hint>.
Approval
Only batch_process asks, and only for a run of two or more files. The client shows the person one plan: the operation, the output folder, whether existing outputs may be replaced, the file count and up to ten file names. The person approves or declines once for the whole run. The model cannot answer for the person. A client that cannot show prompts gets approval_unavailable, with the setting that fixes it (LATHE_BATCH_PREAPPROVED=true).
Every other writing tool writes one new file per call without asking. None of them overwrites an existing file unless the call passes overwrite=true.
Files and safety
- Working folder. Relative paths resolve against
LATHE_WORKING_DIR. Inputs and outputs must stay inside it. Symlinks that point outside are refused. - Nothing is overwritten by accident. An output that already exists is refused unless the call passes
overwrite=true. An output can never be the input file. - Batch runs never touch their inputs.
batch_processrefuses an output folder that is the input folder, and it skips any output that already exists. - Writes are atomic. A file is written under a temporary name and moved into place, so a failure never leaves a half-written file.
- Local only. Lathe makes no network connections, and ffmpeg and ffprobe only open local files.
- Size limit. Inputs over
LATHE_MAX_FILE_MB(500 MB by default) are refused.
Security
See SECURITY.md for how to report a problem and what Lathe does not do. The approval log at ~/.local/state/lathe/approvals.jsonl records each request, approval, decline and refusal. It never records file contents.
tool-manifest.lock.json records a hash of every tool description, prompt and the server instructions. python3 scripts/tool_lock.py --check shows whether anything has changed since the release.
Develop
uv venv -p 3.11 .venv && uv pip install -p .venv/bin/python -e '.[dev]'
.venv/bin/pytest -q
python3 scripts/check_skills.py
.venv/bin/python scripts/tool_lock.py --check
.venv/bin/python scripts/security_card.py --check
The tests generate their own fixtures. Tests that need ffmpeg, tesseract or ghostscript are skipped when the program is missing.
License
MIT. Made by Seaynic Labs. Third-party libraries and programs are listed in CREDITS.md.
Built by Seaynic Labs. We build tools like this around a business's own systems: local-first, with a person approving every change. See custom integrations.