stayput-mcp
stayput-mcp is a local MCP server for privacy-preserving PDF and photo file operations.
Read PDF info: page count, page sizes, title, and encryption status.
Merge multiple PDFs into one file.
Extract, reorder, or delete PDF pages by page ranges.
Split a PDF into several files of N pages each.
Rotate PDF pages clockwise by 90, 180, or 270 degrees.
Add page numbers to PDFs with custom templates and placement.
Combine JPG/PNG images into a single PDF.
Inspect image metadata: GPS, camera info, capture time, software, EXIF/XMP/IPTC/comments.
Remove EXIF, GPS, XMP, IPTC, and comments from JPG/PNG/WebP images losslessly.
Work with local files only; no network access or uploads.
Stayput
Your files stay put.
Free, open-source tools for images, PDFs, video and audio that run entirely in your browser. Your files are not uploaded, there are no accounts or file size caps beyond what your device can hold, and it works offline after one visit (the AI-model tools need one online run to download their model).
Open stayput.dev · Tools · Verify the claim · How it works · MCP server · Privacy
Convert HEIC photos from an iPhone, merge, split, sign and compress PDFs, shrink images and strip GPS and EXIF data. Every tool is a static page and a bit of JavaScript and WebAssembly that does the work in your tab. There is no server that could receive your files.
Open the network tab. Your files never appear in it.
That is the whole pitch, and you can check it in three ways:
Watch the network. Open your browser's developer tools (F12, or Cmd-Option-I on a Mac), pick the Network tab, open any tool and drop a file. You will see requests for the page's own code, the site's own decoder files on the pages that need them, and one anonymous page count. You will never see a request carrying your file, because there is nowhere for it to go. Every tool page also counts its own requests after you add files and shows you the list.
Turn the network off. Load a tool, switch to airplane mode, and use it. It keeps working, because after one visit the site is cached by a service worker and the work happens in your tab.
Read the code. This repository is the site. It builds to static HTML, CSS and JavaScript with no backend; the deploy has no server-side code at all. The privacy page lists every request the site makes.
Related MCP server: mcp-pdf-utils
Tools
Images | PDFs |
HEIC to JPG or PNG (batch, keep or drop EXIF) | |
Convert images (PNG, JPG, WebP, AVIF, JPEG XL, HEIC, SVG in; JPG, PNG, WebP out) | |
Compress and resize images (plus Compress PNG, transparency kept, Compress GIF, Resize GIF and Crop GIF) | Compress PDF (lossless cleanup, image recompression, or flatten) |
Remove EXIF and GPS data (image data unchanged; sideways JPGs re-encoded only with Apply orientation on) | |
Crop image (ratios, exact pixels, circle) | |
EXIF viewer (location, camera, date and every field) | PDF to images (PNG, JPG or one multi-page TIFF) |
Video to GIF (MP4, MOV, WebM; trim, size, frame rate) | |
Blur or pixelate image (faces, plates, text; blur, pixelate or black box) | Sign PDF (draw or type, place on any page) |
Rotate or flip image (quarter turns, mirror, batch) | |
Video or audio to MP3 (MP4, MOV, M4A, WAV; or to WAV) | PDF to Word or text (paragraphs and headings, not layout) |
Image to text (OCR) (photos, screenshots, scans; copy or .txt) | Unlock PDF (remove a password you know, or print/copy restrictions) |
Color picker from image (HEX, RGB, HSL; main-colour palette) | Password protect PDF (AES-256) |
GIF to MP4 (animated GIF to video, up to 90% smaller) | Extract images from PDF (every picture at its stored size) |
Compress video (MP4, MOV, WebM; fit 10 MB for Discord or 25 MB for email) | |
Video to MP4 (MOV, MKV, WebM; H.264 copied with no quality loss) | |
Video to MOV (MP4, WebM, MKV; H.264 and AAC copied with no quality loss) | |
Trim video (cut a clip without re-encoding) | |
Video splitter (cut one video into parts at times, every N seconds or into equal parts, in one zip) | |
Mute video (remove the sound, picture copied untouched) | |
Resize video (1080p, 720p, custom size) | |
Rotate video (90°, 180°, flip) | |
Crop video (any box, 9:16, 1:1) | |
Change video speed (0.25× to 8×, pitch kept) | |
Merge videos (join clips into one MP4) | |
Side by side video (two clips left and right or top and bottom in one MP4, with the sound you choose) | |
Add audio to video (music or voice-over, picture copied untouched) | |
Reverse video (play a clip backwards) | |
Video to JPG (save frames as JPG or PNG) | |
Trim audio (cut MP3, WAV, M4A with a waveform) | |
Audio splitter (split an MP3 or WAV into parts at times or every N minutes) | |
Screen recorder (screen, window or tab, with sound and microphone) | |
Collage maker (grids, side by side, stitched screenshots) | |
Split image (Instagram grids and carousels) | |
Add text to image (captions, memes, watermarks) | Add text to GIF (a caption on every frame) |
AI image upscaler (2×, 3× or 4× with Real-ESRGAN, on the device) | |
Remove object from photo (paint over it, MI-GAN fills it in on the device) | |
Adjust photo (brightness, contrast, saturation, warmth, sharpen, invert) | |
Emote resizer (Twitch emotes and sub badges, Discord emoji and stickers, Slack emoji) | |
Image to ASCII art (width, character sets, invert, colour PNG, .txt) | |
Pixel art converter (auto or retro palettes, dithering, grid) | |
Photo to sketch (pencil, charcoal, coloured pencil) | |
Add border to image (border colour and width, rounded corners) | |
Compress audio (smaller MP3 or OGG, or fit a size limit) | |
Volume booster (louder, quieter or normalized audio and video) | |
Pitch and speed changer (change key by semitones, speed up or slow down) | |
BPM and key finder (tempo, key and Camelot code from an audio file) | |
Audio converter (MP3, WAV, FLAC, M4A, OGG) | |
QR code generator (link, Wi-Fi, contact, email, phone; PNG or SVG) | |
Barcode generator (Code 128, Code 39, UPC, EAN, ITF-14; PNG, SVG or PDF) | |
Signature maker (draw, type or photo; transparent PNG, SVG) | |
QR code scanner (image, paste, drop or camera; links are shown, never opened) | |
Voice recorder (microphone to MP3, WAV or M4A) | |
Merge audio (join MP3, WAV, M4A with silence or crossfades) | |
Metronome (any time signature, subdivisions, tap tempo) | |
GIF maker (animated GIF from photos or screenshots; timing, size, loop, there-and-back) | |
Merge GIFs (join animated GIFs end to end, fitted to the first one's size) | |
Image to SVG (trace PNG or JPG into vector shapes; black and white, logo or detailed) | |
Transcribe audio to text (Whisper on your device; text, SRT or WebVTT; 16+ languages) | |
Add subtitles to video (captions from the speech or your SRT, burned into the picture) | |
Vocal remover (karaoke instrumental or acapella, AI model on your device) | |
Video background remover (blur, colour or a picture behind the person) | |
OCR PDF (make a scanned PDF searchable) | |
Document scanner (phone photos of paper to a clean PDF) | |
EPUB to PDF (DRM-free ebooks to a paginated PDF) | |
Text to PDF (type, paste or drop .txt files; A4 or Letter) | |
PDF to EPUB (reflowable ebook from a PDF's text) | |
Open ZIP, RAR and 7z (extract archives; password-protected ZIPs open with the password) | |
Create ZIP (files or folders, optional AES-256 password) | |
Remove silence (shorten pauses, trim quiet ends) | |
Remove background noise (hiss, hum, fans and traffic out of voice recordings and videos) | |
Add watermark to video (text or logo, corner or centre, size and opacity; sound kept) | |
Blur faces in video (automatic, frame by frame; blur, pixelate, box or emoji) | |
Resize PDF pages (A4, Letter, Legal, A3, A5, Tabloid; content scaled to fit, text stays text) | |
Flatten PDF (form fields, comments, stamps and signatures into the page; text stays selectable) | |
Fill PDF form (type into fillable fields, tick boxes, optional flatten) | |
Online tuner (guitar, bass, ukulele, violin, chromatic; reference notes) | |
Mic test (level meter, verdict, record and play back) | |
Webcam test (preview, real resolution and frame rate, snapshot) | |
Keyboard test (on-screen ANSI or ISO keyboard, key and code log) | |
Speaker test (left, right or both channels, tones, sweep, pink noise) | |
Dead pixel test (full-screen black, white, red, green and blue; click or arrow keys, cycle mode) | |
Audio to video (MP3 plus a cover picture to MP4; 16:9, square, 9:16) |
Plus dedicated pages for the jobs people search for: image conversions such as HEIC to PNG, PNG to JPG, WebP to PNG, AVIF to JPG and JXL to PNG; tool presets such as JPG to PDF, PDF to JPG, Combine PDF, Resize image, Crop to circle and Remove location from photos; and guides that answer the question behind the tool ("is it safe to merge PDFs online?", "how do I remove location data from photos?").
MCP server
Stayput also ships as a local Model Context Protocol server, stayput-mcp, so an LLM client can call the same PDF and photo tools as tool calls, still with no network access and no uploads:
{ "mcpServers": { "stayput": { "command": "npx", "args": ["-y", "stayput-mcp"] } } }See mcp/README.md for the full tool list, or stayput.dev/mcp.
How it works
The site is a static Astro build: one page per tool, a shared tool shell, and a TypeScript module per tool that does the work in the tab. The MCP server (above) is the one part of this repo that does run as a local process; everything else described below is the browser-only website.
HEIC decoding: heic-to, a WebAssembly build of libheif, served by the site itself from
/vendor/(copied out of node_modules at build time byscripts/vendor.mjs). The request fetches only the decoder; no image data is sent.PDF editing: pdf-lib for merge, split, rotate, reorder, page numbers (standard fonts, nothing embedded), signature stamps, image embedding and rewriting image streams.
PDF to Word: pdf.js reads the positioned text runs;
src/lib/pdftext.tsrebuilds lines, paragraphs and headings andsrc/lib/docx.tswrites a minimal Office Open XML document with fflate. Text and structure only, no layout.PDF rendering: pdf.js (legacy build for wide browser support) on a dedicated web worker.
Image resize and encode: the canvas API, with stepped downscaling for sharp results.
Encrypted PDFs: many PDFs carry "owner" encryption with an empty user password (statements, forms with printing restrictions). pdf-lib cannot read those streams, so every PDF tool first checks the trailer for
/Encryptand, when found, runs qpdf compiled to WebAssembly (@neslinesli93/qpdf-wasm, served from/vendor/and loaded only when needed) to strip the encryption in the tab. Files with a user password prompt for it once; outputs are written without encryption. Seesrc/lib/unlock.ts.AVI decoding: most video runs on your browser's WebCodecs through Mediabunny. For old formats the browser cannot read, the page loads a decoder built from FFmpeg's libraries (LGPL) only when you convert such a file. Today that is AVI (Xvid and DivX 4+, Motion JPEG; MP3, MP2, AC-3, PCM sound) and 3GP (H.263 and MPEG-4 picture, AMR sound; builds in
vendor-builds/libav-3gp/, workersrc/lib/threegp-decode.worker.ts). The decoder is libav.js 6.10.9.0 with a short component list; the build script, the list and the patent-expiry evidence for each codec are invendor-builds/libav-avi/anddocs/research/avi-decoder-codec-patents-2026-10.md. The built files are committed andscripts/vendor.mjscopies them to/vendor/libav.js@6.10.9.0/; the conversion runs in a module worker (src/lib/avi-decode.worker.ts), and the file never leaves the tab.WMA decoding: a second, smaller build of the same FFmpeg libraries (LGPL) with only the ASF demuxer and the Windows Media Audio 1 and 2 decoders, loaded only when you convert a WMA to MP3. WMA Pro, WMA Lossless and WMA Voice are left out on purpose and refused by name. The build script, the component list and the reasoning are in
vendor-builds/libav-wma/anddocs/research/wma-decoder-codec-patents-2026-10.md; the conversion runs in a module worker (src/lib/wma-decode.worker.ts), and the file never leaves the tab.FLV reading: FLV is a container no browser opens, so the page loads a second, smaller libav.js build (the FLV demuxer and the MP3 decoder, nothing else) only when you convert an FLV. The H.264 picture and AAC sound are copied into the MP4 packet by packet and not decoded; MP3 is decoded and written as AAC. VP6, Sorenson Spark and other codecs have no decoder in the build and are refused by name. The build script, config and patent reasoning are in
vendor-builds/libav-flv/anddocs/research/flv-reader-codec-patents-2026-10.md; the worker issrc/lib/flv-decode.worker.ts.JPEG XL and AVIF decoding: the browser's own decoder when it has one (AVIF everywhere, JXL in Safari); otherwise the jSquash WebAssembly builds of libjxl and libavif, served from
/vendor/like the HEIC decoder. Tool pages that accept these formats ask the service worker to cache the decoders they may need (only JXL/AVIF decoders the browser lacks) and mark<html data-decoders="cached">when they are in, so they work offline after one visit; the service worker does not precache them for every visitor because together they are about 6 MB. Seesrc/lib/vendor.ts.Signatures: drawn on a canvas with pointer events (pressure-aware for pens) or typed in the self-hosted Caveat font, cropped to a transparent PNG and placed at preview coordinates mapped into PDF user space, page rotation included.
EXIF removal: a hand-written, lossless segment and chunk editor for JPEG, PNG and WebP in
src/lib/exif.ts. It deletes only the metadata segments and writes the image data back unchanged, so the pixels are identical and the file only gets smaller. The one exception is the tool's "Apply orientation" option (on by default), which re-encodes a JPEG stored sideways at quality 95 so it displays upright; the MCP server never does this. It also extracts EXIF from HEIC containers so "keep metadata" works on HEIC conversions.TIFF input: UTIF.js (
src/lib/tiff.ts), bundled and loaded only when a TIFF is dropped, since only Safari decodes TIFF natively. Images to PDF turns every page of a multi-page TIFF into a PDF page.Zip downloads: fflate in the tab when there is more than one output.
Offline: a service worker generated at build time (
src/pages/sw.js.ts) caches every tool page, andscripts/postbuild.mjswrites the list of hashed assets and fonts into it so all tool code (including the on-demand pdf-lib and pdf.js chunks) is cached on the first visit. Pages are network-first so deploys show up immediately; assets are cache-first because their names are content-hashed, and assets from earlier deploys are pruned on activation.Security headers: the site ships a strict Content-Security-Policy. Scripts may load only from the site itself and the self-hosted analytics host; no third-party CDN is involved.
connect-srcis limited the same way, so even a bug could not send a file elsewhere.Analytics: a self-hosted, cookie-free Umami counter records page views and a handful of anonymous events, such as a visit starting, files being added, a tool running and a search being used, each with coarse ranges rather than exact values. It never records file names, file types, exact sizes or file contents, and nothing is recorded when the browser sends a Do Not Track or Global Privacy Control signal. stayput.dev/privacy is the source of truth for exactly what is sent and what the stats server can see. In the code, every event and property is listed in
src/lib/analytics.ts, andtests/analytics.spec.tsfails if an event gains a property that is not listed or names a file.
There is no backend and no cookies. See /privacy for the full statement.
Development
Requirements: Node 22+.
npm install
npm run dev # http://localhost:4321
npm run build # static output in dist/
npm run check-links # fail on any broken internal link in dist/ (--external also checks outbound links)
node scripts/serve.mjs # serve dist/ locally with clean URLs and the production headers
npm run check # Astro and TypeScript checksTests
End-to-end tests drive every tool in headless Chromium with generated fixtures (JPEG with EXIF and GPS, PNG, WebP, HEIC, multi-page PDFs, plus static encrypted and offset-box PDFs under tests/fixtures/static), then check the downloaded outputs. One test also asserts the privacy claim directly: after files are added, no request leaves the page except the stubbed analytics call. The local server (scripts/serve.mjs) applies the site's production headers, so tests run under the production Content-Security-Policy and a violation shows up as a console error.
pip install pillow pillow-heif # once, for fixture generation
python3 tests/fixtures/make-fixtures.py && node tests/fixtures/make-pdf.mjs
npx playwright install chromium # once
npm run build && npm testSet PLAYWRIGHT_CHROMIUM_PATH=/path/to/chrome to use a preinstalled browser.
Social images
public/og.png and public/og/<slug>.png are rendered from the page copy by node scripts/make-og.mjs (headless Chromium). Re-run it after changing a tool's heading or tagline and commit the result.
Sitemap dates
Every sitemap URL has a real <lastmod>, and tool and guide structured data carries the same dateModified. The dates live in src/data/lastmod/, one small file per page (path, date and a content hash), so two branches that add pages never touch the same file, so builds never depend on git history, which Vercel and CI clones don't have. After you change a tool, pair, preset, guide or static page, run node scripts/lastmod.mjs: pages whose content hash changed get today's date and new pages are added. Commit the result. tests/lastmod.spec.ts runs node scripts/lastmod.mjs --check, so CI fails if you forget. Guides use their own updated field as the date, and the check also fails when a guide changes without it moving forward.
After each production deploy, scripts/indexnow.mjs pings IndexNow with only the pages whose lastmod entry differs from the previous commit. node scripts/indexnow.mjs --all resubmits every page (the workflow's manual run does this); --dry-run lists what would be sent.
Adding a tool
Add an entry to
src/data/tools.ts(slug, SEO copy, steps, FAQ) and a paragraph tosrc/data/engine.tssaying what actually runs in the tab. These feed the home page, footer, sitemap, service worker, structured data and social image.Create
src/pages/tools/<slug>.astrousingToolLayoutand put the option controls in theoptionsslot.Create
src/tools/<slug>.ts, callcreateShell({ process })fromsrc/lib/shell.ts, and return the output files.Add a test to
tests/tools.spec.ts, then runnode scripts/make-og.mjs.
A format-pair landing page ("WebP to PNG") is just an entry in src/data/pairs.ts; the page, its social image and its sitemap entry are generated. A preset landing page for any other tool ("JPG to PDF", "Combine PDF") is an entry in src/data/presets.ts naming the base tool and its option defaults; the base tool's option controls live in src/components/options/ so the tool page and its presets share one copy. A guide is an entry in src/data/guides.ts (sections, FAQ, the tools it points to); copy supports [text](/path) links and **bold**. Run node scripts/make-og.mjs after adding any of these.
See CONTRIBUTING.md for the ground rules, the main one being that no change may make a file leave the browser.
Support
Stayput is free and needs no account, no ads. If it saved you a subscription and you want to say thanks, the repository has a GitHub Sponsors link; sponsorship helps cover running costs (domain, hosting and the stats server).
License
MIT. See LICENSE. Third-party libraries keep their own licenses: heic-to (LGPL-3.0, loaded as a separate module at runtime), FFmpeg's libraries via libav.js (LGPL-2.1-or-later, loaded as a separate module at runtime), qpdf (Apache-2.0, loaded as a separate module at runtime), @jsquash/jxl and @jsquash/avif (Apache-2.0, loaded as separate modules at runtime), pdf-lib (MIT), pdf.js (Apache-2.0), fflate (MIT), UTIF.js and pako (MIT), Astro (MIT). The Caveat font in public/fonts is under the SIL Open Font License 1.1 (see public/fonts/OFL-Caveat.txt).
Available Tools
9 toolsextract_pdf_pagesExtract, reorder or delete PDF pagesA
Write a new PDF containing only the listed pages, in the listed order. Use it to pull out a range, reorder pages ("3,1,2") or drop pages (list the ones to keep). Pages are 1-based; ranges like "1-3, 7" and reversed ranges like "5-1" work. Writes a new PDF and returns its path; the input is not modified and an existing file is never overwritten. To cut a PDF into equal parts use split_pdf instead.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes | Path to the PDF. | |
| pages | Yes | Pages to keep, for example "1-3, 7" or "3,1,2". | |
| output | No | Where to write the result. Defaults to a new file beside the input. Existing files are never overwritten; a free name like file-1.pdf is used instead. | |
| password | No | Password for a PDF that asks for one when opened. Used only on this machine. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare a write operation that is not destructive (readOnlyHint=false, destructiveHint=false), and the description explains why: a new file is written, the input is untouched, and existing files are never overwritten. It also states what is returned (the new path). It stops short of describing error behavior, e.g. what happens with an encrypted PDF when no password is supplied.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with the core action, then semantics, then side effects, then the sibling routing note. No filler and nothing repeated from the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description supplies the return value (a path) and the non-destructive write contract. Combined with 100% parameter coverage, an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds genuine meaning beyond the schema: pages are 1-based, and reversed ranges like "5-1" are supported — neither of which appears in the schema's page description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a precise verb+resource+scope: 'Write a new PDF containing only the listed pages, in the listed order.' It names the three concrete use cases (range extraction, reordering, dropping pages) and explicitly distinguishes itself from the sibling split_pdf.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use cases ('pull out a range, reorder pages, drop pages') and an explicit when-not with the named alternative: 'To cut a PDF into equal parts use split_pdf instead.' The routing decision is fully resolved without opening any schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
images_to_pdfImages to PDFA
Put JPG and PNG images into one PDF, one image per page, in the order given. Images are embedded as they are, without re-compression. HEIC and WebP are rejected with an error that says how to convert them. Writes a new PDF and returns its path; an existing file is never overwritten.
| Name | Required | Description | Default |
|---|---|---|---|
| inputs | Yes | JPG or PNG paths, in page order. | |
| margin | No | Margin in points (72 = 1 inch). | |
| output | No | Where to write the result. Defaults to a new file beside the input. Existing files are never overwritten; a free name like file-1.pdf is used instead. | |
| page_size | No | "fit" makes each page the size of its image; "a4" and "letter" centre the image on a standard page. | fit |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With annotations only covering the safety profile, the description adds substantial behavior: images are embedded without re-compression, unsupported formats fail with an actionable error, the tool writes a new file and returns its path, and existing files are never overwritten. This is consistent with destructiveHint=false and gives the agent real operational context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with no filler, front-loading what the tool does before constraints and return behavior. Every clause carries information (formats, embedding policy, error behavior, return value, overwrite policy).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, and the description compensates by explaining the return value (a new PDF path) and the no-overwrite naming policy. Combined with format limits and page ordering, an agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented, including ordering for 'inputs' and the 72-points-per-inch margin convention. The description's 'in the order given' largely restates what the schema already says, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Put JPG and PNG images into one PDF') plus the output structure ('one image per page, in the order given'). This clearly distinguishes it from merge_pdfs and the other PDF siblings, which operate on PDFs rather than images.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear applicability conditions: accepted formats (JPG/PNG), rejected formats (HEIC/WebP) with a helpful error, and ordering expectations. It never names an alternative sibling (e.g. use merge_pdfs for PDFs, or a converter for HEIC), so the when-not guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
inspect_image_metadataInspect photo metadataARead-only
Report the metadata hidden in a JPG, PNG or WebP photo: GPS location, camera make and model, capture time, editing software, and which blocks (EXIF, XMP, IPTC, comments) are present. HEIC files report EXIF only. Read-only: nothing is written. Use before strip_image_metadata to see what would be removed.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the image. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered and the description's 'Read-only: nothing is written' is largely redundant. However, it adds genuine behavioral context beyond the annotations: format-specific degradation (HEIC reports EXIF only) and the set of metadata blocks it surfaces.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with what is reported, then format edge case, then read-only guarantee and routing advice. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
No output schema exists, so the description compensates by enumerating the returned fields and block types. Combined with the explicit read-only statement and the sibling routing note, an agent has everything needed to select and call it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
A single required 'path' parameter at 100% schema description coverage, so the schema already documents the input fully. The description adds no syntax, format, or constraint detail about the path (e.g., relative vs absolute, remote URLs), which matches the baseline 3 when the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Report') and resource (photo metadata) and enumerates exactly what is reported: GPS, camera make/model, capture time, editing software, and present blocks. It also scopes supported formats (JPG/PNG/WebP, with HEIC limited to EXIF), which cleanly separates it from the write-side sibling strip_image_metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative workflow: 'Use before strip_image_metadata to see what would be removed.' The condition that selects this tool over its sibling is stated outright rather than left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
merge_pdfsMerge PDFsA
Combine several PDFs on this machine into one, in the order given. The same file may appear more than once. Writes a new PDF and returns its path; the inputs are never modified and an existing file is never overwritten. To combine only some pages, run extract_pdf_pages first. Needs the optional password if an input is encrypted.
| Name | Required | Description | Default |
|---|---|---|---|
| inputs | Yes | PDF paths, in the order their pages should appear. | |
| output | No | Where to write the result. Defaults to a new file beside the input. Existing files are never overwritten; a free name like file-1.pdf is used instead. | |
| password | No | Password for a PDF that asks for one when opened. Used only on this machine. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only give coarse hints (readOnlyHint=false, destructiveHint=false); the description adds real behavioral detail beyond them: inputs are never modified, an existing output file is never overwritten (a free name is chosen instead), and a password is required for encrypted inputs. It also discloses the return value (the new PDF's path).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four short sentences, front-loaded with what the tool does and the ordering rule, followed by output/return behavior and the encrypted-input caveat. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly supplies the return value (a path), the non-destructive guarantee, the overwrite policy, and the password prerequisite — everything needed to invoke this tool safely and correctly. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents all three parameters including ordering and the no-overwrite default. The description restates ordering and adds a usage condition for the password ('if an input is encrypted'), but adds no syntax or format detail beyond the schema, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Combine several PDFs ... into one') plus the ordering constraint, and names the sibling tool (extract_pdf_pages) relevant to a related-but-different need. An agent can distinguish it from split_pdf or images_to_pdf without opening any schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly routes the page-subset case to extract_pdf_pages ('To combine only some pages, run extract_pdf_pages first'), which is a concrete alternative with a selecting condition. It does not spell out when-not to use merge_pdfs itself (e.g. vs. split_pdf), but the primary ambiguity is resolved.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
number_pdf_pagesAdd page numbersA
Stamp page numbers on a PDF. The template may use {n} for the page number and {total} for the last number, e.g. "Page {n} of {total}". Writes a new PDF and returns its path; the input is not modified and an existing file is never overwritten. Text only, in Helvetica.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes | Path to the PDF. | |
| start | No | Number printed on the first numbered page. | |
| output | No | Where to write the result. Defaults to a new file beside the input. Existing files are never overwritten; a free name like file-1.pdf is used instead. | |
| password | No | Password for a PDF that asks for one when opened. Used only on this machine. | |
| position | No | Where on each page the number goes: bottom or top, then left, center or right. The text sits 28 points (about 0.4 inch) in from the page edges. Default "bottom-center". | bottom-center |
| template | No | Text to print. Default "{n}". | {n} |
| font_size | No | Font size in points, from 4 to 72. Default 11. | |
| first_page | No | First page (1-based) that gets a number; earlier pages, such as a cover, are left blank. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (readOnlyHint=false, destructiveHint=false), and the description usefully adds that a new PDF is written, its path is returned, the input is untouched, and existing files are never overwritten. The 'Text only, in Helvetica' constraint is a valuable behavioral detail, though return-format specifics beyond 'path' remain thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action, then template syntax, then write semantics. No sentence is wasted and the most important constraint (non-destructive output) is clearly stated.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description correctly notes the return value (the new file path) and the non-overwrite guarantee. For an 8-parameter stamping tool this is nearly complete, though edge cases like password-protected inputs are only covered by the schema field itself.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is already 100%, so the baseline is 3, but the description adds real value by explaining the {n} and {total} placeholders in template, which the schema only labels as 'Text to print'. It does not expand on start, first_page, or position beyond what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Stamp page numbers on a PDF'), making the operation unambiguous. However, it never names or contrasts with siblings like split_pdf, merge_pdfs, or rotate_pdf, so there is no explicit differentiation for an agent choosing among PDF tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied by the purpose; there is no statement of when to prefer this over alternatives or any prerequisite context. An agent can infer intent from the verb, but the description offers no routing guidance or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pdf_infoPDF infoARead-only
Read a PDF on this machine and report its page count, page sizes, title and whether it was encrypted. Read-only: nothing is written. Use before split_pdf, extract_pdf_pages or rotate_pdf to learn the page count. Fails with a readable error if the file is not a PDF or needs a password.
| Name | Required | Description | Default |
|---|---|---|---|
| path | Yes | Path to the PDF. | |
| password | No | Password for a PDF that asks for one when opened. Used only on this machine. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so 'nothing is written' is largely redundant. The description does add genuine value beyond the annotations: the readable-error failure mode for non-PDFs/password-locked files and the assurance that a supplied password is used only locally.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences with the primary action and return fields front-loaded, followed by usage routing and failure behavior. No filler or repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema available, the description compensates by listing the returned fields (page count, page sizes, title, encryption) and the error behavior. It covers everything an agent needs to select and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, with both parameters documented in the schema itself. The description only implies the password parameter's purpose ('needs a password') without adding format, source, or handling detail beyond what the schema states, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (read/report) and resource (PDF) and enumerates exactly what is reported: page count, page sizes, title, encryption status. This clearly separates it from mutation siblings like split_pdf and rotate_pdf.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly tells the agent when to use it ('before split_pdf, extract_pdf_pages or rotate_pdf to learn the page count') and names the concrete downstream tools that depend on this information. The failure conditions (non-PDF, password-protected) further define its operating envelope.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rotate_pdfRotate PDF pagesA
Rotate all pages, or only the listed ones, clockwise by 90, 180 or 270 degrees, and save the rotation permanently in a new PDF. The input is not modified and an existing file is never overwritten; returns the new path.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes | Path to the PDF. | |
| pages | No | Pages to rotate, for example "1, 3-4". Default: every page. | |
| output | No | Where to write the result. Defaults to a new file beside the input. Existing files are never overwritten; a free name like file-1.pdf is used instead. | |
| degrees | Yes | Clockwise rotation to add. | |
| password | No | Password for a PDF that asks for one when opened. Used only on this machine. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds valuable context beyond annotations: states input is not modified, existing files are never overwritten, and returns a new path. Annotations declare non-destructive and non-readOnly, but the description clarifies safety and output behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, front-loaded with core action and constraints, no wasted words. Efficiently communicates scope, limits, and output behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers key behavioral aspects like input preservation and output path creation. Lacks details on error handling or password usage, but with no output schema and full schema coverage, it is nearly complete for an agent's needs.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameters are fully documented in schema. Description adds no new parameter details beyond what schema provides, such as defaults or format examples. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (rotate) plus resource (PDF pages) with details on scope (all pages or listed ones), rotation values, and permanent save. Clear enough to distinguish from siblings like split_pdf or merge_pdfs.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies use for permanent page rotation, but doesn't explicitly name alternatives or when not to use it. Sibling tools handle different operations, so context is clear, but no exclusions are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
split_pdfSplit PDFA
Split a PDF into several files of N pages each (1 = one file per page), written into a folder. Returns the list of files. The input is not modified and existing files are never overwritten. To keep a custom page range as one file use extract_pdf_pages instead.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes | Path to the PDF. | |
| password | No | Password for a PDF that asks for one when opened. Used only on this machine. | |
| output_dir | No | Folder for the parts. Defaults to a new folder beside the input named <file>-split. | |
| pages_per_file | No | Pages in each output file. Default 1. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false and openWorldHint=false, so safety is partly covered. The description adds genuinely useful context beyond that: the input is not modified, existing files are never overwritten, and the return value is a list of files (important since there is no output schema). No auth or size-limit caveats, but the important destructive-behavior questions are answered.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with what the tool does, then safety behavior, then the sibling alternative. No filler and no redundancy with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers the operation, the chunking control, the output location and format, the non-destructive/no-overwrite guarantee, and the competing tool. With only 4 simple parameters and no output schema, nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3, and the description earns above that by interpreting pages_per_file ('N pages each, 1 = one file per page') and describing the output folder destination. It does not add format detail for input/password, which the schema already handles.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource (split a PDF), the exact chunking semantics (N pages each, 1 = one file per page), and where output lands. It also differentiates itself from the sibling extract_pdf_pages, so an agent can route between them without reading other schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the alternative tool and the condition that selects it: 'To keep a custom page range as one file use extract_pdf_pages instead.' That is a concrete when-not-to-use rule, not implied guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
strip_image_metadataRemove photo metadataA
Write a copy of a JPG, PNG or WebP photo with EXIF (including GPS location), XMP, IPTC and comments removed. Lossless: the image data is not re-encoded. The original file is left untouched and an existing file is never overwritten; returns the new path and what was removed. HEIC is rejected with an error. Use inspect_image_metadata first to see what is there.
| Name | Required | Description | Default |
|---|---|---|---|
| input | Yes | Path to the image. | |
| output | No | Where to write the cleaned copy. Defaults to <name>-clean.<ext> beside the input. Existing files are never overwritten. | |
| keep_color_profile | No | Keep the ICC colour profile so colours look the same. Default true. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare the safety profile (readOnlyHint=false, destructiveHint=false, openWorldHint=false); the description goes well beyond that by disclosing that a copy is written, the original is untouched, existing files are never overwritten, the operation is lossless (no re-encode), HEIC fails, and what the call returns. That is exactly the extra behavioral context the annotations cannot carry.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with what the tool does and what it preserves, then side effects, then return value, then the routing hint. No filler and nothing repeated from structured fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description carries the burden of explaining the return ('the new path and what was removed') and does so, plus covers failure mode, overwrite behavior, and format limits. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all three parameters (input, output, keep_color_profile) are already documented including the default naming pattern and default true for keep_color_profile. The description adds only the supported-format constraint relevant to input, which the schema does not state; otherwise it does not extend parameter meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Names a precise verb+resource (remove metadata from a photo copy) and immediately scopes the supported formats and the lossless behavior. It also names the sibling inspect_image_metadata, so an agent can distinguish this from the read-only inspector without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit prerequisite ('Use inspect_image_metadata first to see what is there') and a clear when-not (HEIC is rejected with an error). This routes the agent to the right sibling and prevents a doomed call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v0.1.1- First observed
extract_pdf_pages - First observed
images_to_pdf - First observed
inspect_image_metadata - First observed
merge_pdfs - First observed
number_pdf_pages - First observed
pdf_info - First observed
rotate_pdf - First observed
split_pdf - First observed
strip_image_metadata
TDQS
Scored across 9 tools
Each tool targets a distinct file operation, and overlapping cases like split_pdf vs. extract_pdf_pages are explicitly differentiated in their descriptions. Read-only and modifying variants (pdf_info, inspect_image_metadata vs. strip_image_metadata) are clearly separated.
Most names follow a consistent snake_case verb_noun pattern (split_pdf, merge_pdfs, rotate_pdf, extract_pdf_pages). Minor deviations like pdf_info (noun-first) and images_to_pdf (noun_to_noun) are still readable and predictable.
9 tools is well within the ideal range for a PDF/image utility server. Each tool covers a unique operation, and none feels redundant or trivial.
The set covers core PDF operations (info, split, merge, extract, rotate, number) and image metadata handling. However, it lacks PDF encryption/decryption, PDF-to-image conversion, or text extraction, leaving minor gaps that agents would need to work around.
Maintenance
Related MCP Connectors
Privacy-first PDF tools over MCP: merge, split, rotate, delete, compress, protect, inspect.
Split, merge and compress PDF files locally - private by design, no uploads.
HTML and CSS to PDF MCP server with page headers, footers and page numbers. No headless browser.
Document conversion MCP server: PDF to Markdown, image OCR, spreadsheet parsing.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol (MCP) server for converting files between different formats5MIT
- AlicenseAqualityDmaintenanceAn MCP server for local PDF manipulation including merging, splitting, rotating, watermarking, and text extraction. It works with various MCP-compatible clients and processes PDFs entirely on-device without cloud services.1113 npmMIT
- AlicenseAqualityDmaintenanceEnables PDF processing and analysis including text extraction, metadata retrieval, search, page manipulation, splitting/merging, conversion to images, and form handling.10MIT
- AlicenseNot gradedqualityAmaintenanceA local MCP server that lets Claude, Cursor, Codex, or any MCP client work with Office documents on your Mac: evaluate spreadsheet formulas, read/write XLSX and PPTX, extract structured DOCX content, and merge/split/protect PDFs. 100% local, no network calls, no account. 14 tools.MIT