pdf-mcp demonstrates solid naming conventions and clear descriptions for all 5 tools. All tools start with action verbs (get_, search_) which aids LLM tool selection. Tool descriptions are adequately detailed (ranging from 80-350 chars), providing context on what each tool does. Input parameters are well-documented with type information and usage guidance. However, critical gaps exist: (1) Output schemas are not explicitly documented in the source code, responses are inferred from return type hints alone, violating the pattern:tool requirement for documented output structure; (2) Error handling is minimal, no recovery guidance, categorization, or actionable error messages; (3) No pagination support for potentially large results (e.g., search_text could return hundreds of matches without limits); (4) Missing security considerations around file path handling (potential path traversal vulnerability); (5) No rate limiting or resource exhaustion safeguards.
Render a single PDF page as a PNG image.
Extract text content from one or more PDF pages.
Get metadata and basic info about a PDF file.
Get the table of contents (bookmarks/outline) from a PDF. When max_level is not specified and the TOC is very large, the depth is automatically reduced to keep the response manageable. The response will include an ``auto_trimmed_to_level`` field and a hint when this happens.
Search for text in a PDF file (case-insensitive). Returns a list of hits with page number and surrounding context.
Output schemas not explicitly documented. Tool descriptions reference returned fields (e.g., 'auto_trimmed_to_level', 'block/line/span detail') but no formal schema is provided. LLMs must infer structure from descriptions and return type hints, which is error-prone and wastes context tokens.
No pagination or result limits. search_text accepts query and context_chars but does not return total count, next_cursor, or page/limit parameters. A PDF with thousands of matching phrases could return an unbounded list, exhausting LLM context and failing silently.
Minimal error handling and recovery guidance. Tools open PDFs with fitz.open(filename) but do not catch exceptions (FileNotFoundError, PdfReadError, etc.). No recovery hints, if a PDF is corrupted or missing, the LLM receives a raw exception, not 'File not found. Check the path and try again.'
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 68 | 2026-07-28+ | v2 |
Path traversal vulnerability not mitigated. The filename parameter accepts any string and is passed directly to fitz.open(). An agent could be tricked into opening /etc/passwd or traversing parent directories. No input validation or sandboxing.
No rate limiting or resource exhaustion safeguards. Rendering PDFs with get_page_image at high DPI or extracting text from large page ranges (start_page=1, end_page=5000) can consume unbounded memory. No timeout, size limit, or concurrency control.
Parameter bounds not specified. get_page_text start_page and end_page accept integers but do not state valid ranges (1 to doc.page_count). search_text context_chars defaults to 100 but no min/max documented. LLMs may pass absurd values (negative pages, context_chars=999999).
Response field naming inconsistency. get_table_of_contents returns 'entries' but get_pdf_info returns metadata as part of a flat dict. Inconsistent response shape forces LLMs to remember tool-specific field names, increasing errors.