dart_pdf_cli
Pure-Dart command line and Model Context Protocol tools for inspecting PDFs
with the dart-pdf engine. The
dartpdf executable runs on the Dart VM and does not import Flutter or
dart:ui.
The CLI and MCP adapter call the same transport-independent
DartPdfService handlers. The MCP layer contains no duplicate PDF logic.
Installation
From a checkout:
dart run packages/dart_pdf_cli/bin/dartpdf.dart --help
Once published, install the executable globally:
dart pub global activate dart_pdf_cli
dartpdf --help
Sidecar-enabled DartPDF desktop releases ship the same self-contained native executable (older package-manager releases naturally do not gain it retroactively):
| Desktop build | CLI/MCP executable |
|---|---|
| macOS app | /Applications/DartPDF.app/Contents/MacOS/dartpdf-cli |
| Windows installer | %LOCALAPPDATA%\Programs\DartPDF\dartpdf.exe |
| Windows portable | dartpdf.exe beside dart_pdf_editor_app.exe |
| Linux tarball / AppImage payload | dartpdf-cli beside dart_pdf_editor_app |
Arch dartpdf-bin |
/usr/bin/dartpdf-cli |
| Flatpak | flatpak run --command=dartpdf-cli dev.milanko.dartpdf |
| Snap | dartpdf.cli |
The macOS and Windows app installers do not modify the user's shell PATH;
use the explicit path above when registering their copy with an MCP host.
Commands
Successful PDF operations write JSON to stdout (--help and --version are
human-readable). Diagnostics go to stderr and failures use non-zero exit codes.
Output is indented by default; --json selects compact JSON for scripts and
agents.
dartpdf inspect input.pdf --json
dartpdf text input.pdf --pages 1-5,8 --json
dartpdf forms list input.pdf --json
dartpdf annotations list input.pdf --pages 1-5 --json
Page numbers are one-based. A missing page range reads at most the configured page limit. An explicit range over that limit is rejected rather than silently changed.
inspect returns the PDF version, information-dictionary metadata, page
count, encryption state, form and annotation counts, and compact signature
state. It does not perform trust-store validation.
Every operation has hard limits for variable strings and collections. The JSON
reports truncated: true when a metadata, signature, subtype, page, character,
field, widget, option, annotation, or annotation-text limit was reached.
Password-form values are never returned.
Passwords
Passwords are deliberately not accepted as process arguments, where they can appear in shell history and process listings. Select at most one protected source:
printf '%s\n' "$PDF_PASSWORD" | dartpdf inspect secured.pdf --password-stdin --json
dartpdf inspect secured.pdf --password-env PDF_PASSWORD --json
dartpdf inspect secured.pdf --password-file /secure/password.txt --json
Only one trailing line ending is removed from stdin or password-file input; other whitespace remains part of the password. Protected password inputs are limited to 4096 bytes and rejected rather than silently truncated.
JSON compatibility
Every result carries schemaVersion. Version 1 has these compatibility rules:
- existing keys keep their meaning and type within the major schema version;
- new optional keys may be added;
- array order is deterministic and follows document/page order unless the requested page range specifies another order;
- consumers must check
truncatedbefore assuming a result is complete.
MCP server
Run the stdio adapter with one or more allowed filesystem roots:
dartpdf mcp --root /work/pdfs --root /work/contracts
With no --root, only the current directory is accessible. Input PDF and
password-file paths are resolved through symlinks and rejected unless the
resolved file is inside an allowed root. Relative paths are tried against the
configured roots in command-line order. The server exposes four read-only,
idempotent tools:
inspect_pdfextract_pdf_textlist_pdf_formslist_pdf_annotations
Tools return structured JSON plus the MCP text fallback. They return paths and metadata only; complete PDFs are never base64-encoded into responses.
Register a globally activated executable with Codex:
codex mcp add dartpdf -- dartpdf mcp --root "$PWD"
Or register the copy bundled with the macOS desktop app:
codex mcp add dartpdf -- \
/Applications/DartPDF.app/Contents/MacOS/dartpdf-cli mcp --root "$PWD"
For a source checkout, register the Dart invocation instead:
codex mcp add dartpdf -- \
dart run packages/dart_pdf_cli/bin/dartpdf.dart mcp --root "$PWD"
MCP password sources are passwordEnv or passwordFile; raw password tool
arguments are not accepted. Hosts can therefore apply their own approval and
secret policies without exposing the password in the server command. Tool
schemas also cap path, page-range, and environment-name strings, and MCP error
text is bounded independently of parser diagnostics.
Scope
This first contract is read-only and VM-only. Editing commands can be added on top of the same service boundary after the JSON contract settles. Page raster export is intentionally outside this package until the pure-Dart software renderer work in #684 lands (the broader conversion roadmap is #369).
Libraries
- dart_pdf_cli
- Transport-independent PDF inspection services used by the
dartpdfcommand line executable and its MCP adapter.