snapotter-mcp
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@snapotter-mcpRun OCR on this scanned PDF and save the extracted text"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
snapotter-mcp
An MCP server for SnapOtter — 243 file-processing tools across image, video, audio, PDF, and general files.
AI Content Warning This was written almost entirely by Claude. Life is too short to write an MCP for a well-defined OpenAPI spec by hand.
Setup
Install however you like. With mise:
mise install && mise exec -- uv syncOr with nothing but Python 3.12+:
python3 -m venv .venv && . .venv/bin/activate
pip install -e ".[dev]"Either way you get a snapotter-mcp entry point. mise is a convenience,
not a requirement: nothing in the package imports it, and the helper scripts
fall back to any interpreter they can find.
Point it at your instance with two environment variables:
export SNAPOTTER_URL=https://snapotter.example.com
export SNAPOTTER_API_KEY=si_... # Settings UI, or POST /api/v1/api-keysThat is the whole required setup. No config file is needed.
Then fetch the OpenAPI spec your instance serves — the tool catalog is built from it, so it always matches the version you are talking to:
mise run fetch-specOptional: Cloudflare Access
If your instance sits behind Cloudflare Access, set a service token and the server adds the headers automatically:
export CF_ACCESS_CLIENT_ID=....access
export CF_ACCESS_CLIENT_SECRET=cfast_...Leave them unset and requests go out plain. Nothing else changes. The Access
policy must use the Service Auth action — Allow with only a service-token
selector still demands an interactive login.
Optional: 1Password instead of environment variables
Copy snapotter.example.toml to snapotter.toml and uncomment the [secrets]
block, naming the item that holds your credentials:
[secrets]
item = "<1password item uuid>" # or the item title
vault = "<vault uuid>" # required with a service account token
token_file = ".env" # holds OP_SERVICE_ACCOUNT_TOKENNaming an item is enough — the provider is inferred. Requires the op CLI.
With a service account token only that bootstrap token touches disk (keep it
chmod 600); the credentials it unlocks stay in memory. Omit token_file to
authenticate as a signed-in user through the desktop app instead.
Environment variables override any single resolved value under any provider,
so you can point at a different instance for one run without editing anything.
Other knobs: SNAPOTTER_CONFIG, SNAPOTTER_OUTPUT_DIR (default
./snapotter-output), SNAPOTTER_SPEC, SNAPOTTER_TIMEOUT (120s),
SNAPOTTER_ASYNC_TIMEOUT (900s).
mise tasks are thin wrappers; the plain equivalents work in any virtualenv:
mise | plain |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| all three of the above |
The two shell scripts pick an interpreter themselves — an active virtualenv,
then .venv/, then uv, then mise, then python3 — so they need no
particular toolchain.
Both checkers run clean with no per-line suppressions. mypy is strict = true
over the whole package; the only concession is ignore_missing_imports for
mcp.*, which ships no stubs. Ruff runs pycodestyle, pyflakes, isort,
pyupgrade, bugbear, simplify, comprehensions, pathlib, return, unused-args and
a pylint subset. max-args = 8 is raised from the default because an MCP
tool's signature is its public API.
Register with Claude Code via the included .mcp.json, or:
claude mcp add snapotter -- mise exec -- uv run snapotter-mcpRelated MCP server: ffmpeg-mcp
Design
SnapOtter's 243 tool routes share one request shape — POST /api/v1/tools/{section}/{toolId} with a multipart file plus an optional
settings JSON string. Rather than generate 243 near-identical MCP tools
(which would flood the model's context), this exposes eight generic ones and
indexes the OpenAPI spec for discovery:
Tool | Purpose |
| Browse/search the catalog by section or keyword |
| Show a tool's documented |
| Run one tool on a file; awaits async jobs |
| Chain steps server-side in one pass |
| One tool over many files |
| Add a local file to the library |
| List the SnapOtter library |
| One file's metadata and version history |
| Fetch a |
| Connectivity check |
snapotter_run_tool and snapotter_run_pipeline take
save_as_version_of=<library file id> to store their result in the library as
a new version, building a version chain with a cumulative toolChain:
v1 image/png 153115B 900x900 []
v2 image/png 33886B 500x500 ['resize']
v3 image/png 30412B 520x520 ['resize', 'border']
v4 image/webp 31942B 520x520 ['resize', 'border', 'convert']Pass the previous version's id to extend a chain; passing the same parent repeatedly creates siblings at the same version number instead.
Settings are discovered at call time. SnapOtter's validation errors name the missing field and enumerate valid enum values, so a wrong first call is self-correcting — no need to hand-model 243 settings schemas.
Things that bite
Cloudflare Access returns its sign-in page at HTTP 200. A status-code check
will cheerfully accept an HTML login form as a JPEG. The client sniffs every
response and raises AccessBlockedError instead. This is also why
check-access.sh parses the body rather than trusting %{http_code}.
Results are served through a CDN redirect. Downloads must follow redirects or you save the 302 body to disk.
54 of 243 tools are async (most video, some PDF): they return 202 {"async": true} with no downloadUrl, and complete over the SSE stream at
/api/v1/jobs/{jobId}/progress. snapotter_run_tool handles this
transparently.
Batch answers with application/zip, not JSON. POST /api/v1/tools/{section}/{toolId}/batch streams back an archive of results
with the job id in an X-Job-Id header. snapotter_batch saves it, extracts
the members (flattening names, so a hostile archive can't traverse out of the
output directory), and deletes the archive unless keep_zip=true.
Some tools return many outputs, not one. pdf/pdf-to-image,
image/image-to-pdf, and image/gif-tools answer with a pages[] array of
per-item URLs plus a zip of everything under the top-level downloadUrl.
Saving that downloadUrl writes a ZIP wearing whatever extension you asked
for. run_tool prefers pages[] whenever present: one page with a concrete
filename is honoured exactly, several pages go into a directory.
GET /api/v1/pipeline/tools over-advertises. It lists color-effects,
brightness-contrast, color-channels, and saturation, which have no
endpoint; color-effects hangs a pipeline rather than erroring.
snapotter_run_pipeline validates step ids against the spec first.
fileId is not a general mechanism. ToolResponse.savedFileId reads as
though any tool can auto-save to the library, but only pdf/sign-pdf
declares a fileId form field, and passing it to other tools is silently
ignored — no error, no savedFileId. The general path is
POST /api/v1/files/save-result with parentId + toolId, which is what
save_as_version_of uses; fileId is passed natively only where the tool
actually supports it.
Tool errors must be re-raised as ToolError. The MCP SDK replaces an
uncaught exception with a bare "Error executing tool ", discarding
SnapOtter's validation text. The @surfaced decorator converts our
exceptions so the model sees format: Invalid enum value. Expected 'jpg' | 'png' | ... and can correct itself.
Downloads have no app-level auth. /api/v1/download/{jobId}/{filename}
needs no SnapOtter API key — only Cloudflare Access protects it. Don't add an
Access bypass for /api/v1/* unless you accept that jobId URLs become public.
License
MIT — see LICENSE.
SnapOtter itself is AGPL-3.0. This is an independent client that talks to it over HTTP, so the two licenses are unrelated. The OpenAPI spec is fetched from your own instance at setup rather than vendored here.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides powerful video and audio editing capabilities through FFmpeg, enabling AI assistants to perform professional-grade operations including format conversion, trimming, overlays, transitions, and advanced audio processing.2784MIT
- AlicenseAqualityDmaintenanceProvides video and audio manipulation tools powered by FFmpeg, enabling AI assistants to perform media operations such as cutting, converting, and removing silence.61052MIT
- AlicenseNot gradedqualityBmaintenancePrivacy-first file tools for AI agents, enabling operations like PDF merge/split, image compression/convert, metadata stripping, and background removal without storing files.46MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to interact with your Iconik media asset management library, providing 143 MCP tools for search, metadata, collections, and more.
Related MCP Connectors
Upload, organize, search, and transform images, videos, and files with AI-powered tools.
OCR, transcription, file extraction, and image generation for AI agents via MCP.
Transform video, audio and images, and generate media from prompts. FFmpeg, captions, models.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/highb/mcp-snapotter'
If you have feedback or need assistance with the MCP directory API, please join our Discord server