MCP server for managing markdown documentation and generating PDFs with customizable branding and layout
Server has 7 well-named tools with clear descriptions and complete input schemas. Naming follows verb_noun convention (list_docs, read_doc, write_doc, generate_pdf). Descriptions are substantive (100-250 chars) and explain WHAT and WHEN. However, parameter descriptions are sparse or missing for several tools (write_doc lacks 'content' description; generate_pdf lacks 'path' description detail). Output schemas are not documented, LLMs cannot infer what fields to expect from responses. Error handling is present but minimal (safePath validation, basic ENOENT handling). No tool annotations (readOnlyHint, destructiveHint) despite clear risk profiles (write_doc, generate_pdf are destructive). Missing pagination/limits guidance for list_docs. Overall: solid foundation, but incomplete for production LLM agents.
Returns a textual guide describing how this MCP works, where DOCS_ROOT is, how PDF rendering works, and how to change branding (colors, footer, logo, page breaks). Read this once per session before making changes.
Renders a markdown file to PDF and writes it next to the source MD (same folder, same basename, .pdf extension) inside DOCS_ROOT. Uses the onexip-branded pandoc + weasyprint pipeline of the pdf-builder repo (build.sh). Call explain() first to learn how to change branding/layout.
Lists markdown docs and folders inside DOCS_ROOT as a JSON tree. Hidden entries and the .history folder are filtered out.
Lists ISO timestamps of all snapshots for a given doc path. Returns an empty array if the file has no history yet.
Reads a markdown file inside DOCS_ROOT.
Returns the content of one historical snapshot of a doc.
Output schemas not documented. LLMs cannot infer response structure (e.g., does list_docs return TreeNode[] or {tree: TreeNode[]}? Does generate_pdf return string or {path: string, stdout: string}?). Forces agents to guess field names for downstream operations.
Parameter descriptions incomplete. write_doc 'content' param has no description. generate_pdf 'path' param lacks detail on expected format (.md suffix requirement). read_history 'version' param description is minimal.
No tool annotations despite clear risk profiles. write_doc and generate_pdf are destructive (WRITE risk) but lack destructiveHint annotation. list_docs, read_doc, list_history, read_history are read-only but lack readOnlyHint. Agents cannot distinguish safe from unsafe tools without annotations.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 61 | 2026-07-28+ | v2 |
Writes markdown to a path inside DOCS_ROOT. Snapshots the previous version (if any) into <DOCS_ROOT>/.history/<path>/<ISO>.md before overwriting. Creates parent folders automatically.
Error handling lacks recovery guidance. safePath() throws generic 'Path outside DOCS_ROOT' error. readHistory() validates version with regex but error message is terse. Per pattern:recovery-guide, errors should tell LLM what to do next (e.g., 'Invalid version format. Call list_history() to see available versions.').
list_docs lacks pagination/limit guidance. No mention of max result size or whether large doc trees are truncated. Per pattern:paginated-result, discovery tools should document result limits and offer pagination to prevent context window exhaustion.