
Docgen Mcp Server
io.github.cyanheadsPublished by GitHub account cyanheadsv0.3.0Updated Oct 27, 2026
Render HTML/markdown to PDF, export rows to xlsx, and fill AcroForm PDFs.
Overview
Local MCP server that renders HTML, markdown or templates to PDF, exports rows to xlsx, and fills AcroForm PDF forms for an assistant.
- What you can do
- Render HTML, markdown or {{key}} templates with page options into downloadable PDFs
- Export one or more named worksheets of row objects into an xlsx workbook
- Inspect AcroForm field names, types, required flags and choice options without changing the PDF
- Fill AcroForm fields from base64 or an https URL, optionally flattening the result
- Re-fetch a previously rendered document by its id, as a tool or as a document resource
- When to use it
- Useful when an assistant needs to produce deliverable files — reports, invoices, filled government or business forms, or spreadsheet exports — from data it already has, without calling an external rendering API.
- Requirements
- Runs locally over stdio (or Streamable HTTP) via npx, bunx or Docker; Bun v1.4.0+ or Node.js v24+. No API keys are required and all configuration variables are optional. Default storage is in-memory, so documents are lost on restart.
Installation
In SourceWeft
- Open Docgen Mcp Server in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
@cyanheads/docgen-mcp-server
Render HTML/markdown to PDF, export rows to xlsx, and fill AcroForm PDFs via MCP. STDIO or Streamable HTTP.
Overview
Generate documents from an agent: render HTML, markdown, or template data to PDF, export rows to Excel, and fill PDF forms. Everything renders locally on a bundled stack (pdf-lib, exceljs, marked).
Tools
Resources
All document data is also reachable via the tool surface — docgen_get_document is the tool-only twin of this resource.
Capability reference
docgen_render_pdf tool
- Provide exactly one
source:{ html },{ markdown }, or{ template, data }for{{key}}interpolation.pageOptionscontrols page size/orientation, CSS-length margins, headers/footers ({{page}},{{total}},{{date}}) and page numbers. - Returns a
DocumentEnvelopewithpageCount;degraded: truemeans CSS, images or scripts were dropped, or characters were replaced with?. The lightweight engine renders headings, paragraphs, lists and tables. - Typed failures:
invalid_source,template_render_failed,document_too_large,render_timeout.
docgen_export_spreadsheet tool
- Supply at least one sheet with a unique
name(1–31 characters) and scalarrows[]; empty rows yield a header-only sheet. Optionalcolumns[]sets headers, type (string/number/date/boolean), width and Excel format. - Omitted columns use all row keys in first-seen order. Boolean columns accept
true/1/yes/onandfalse/0/no/off, case-insensitive; other strings stay text. - Returns a
DocumentEnvelopewithsheetCount. Typed failures:empty_workbook,invalid_sheet_name,document_too_large,render_timeout.
docgen_fill_form tool
- Provide exactly one
sourcePdf:{ base64 }or{ url }(public https servingapplication/pdf), plusfieldsmapping exact, case-sensitive AcroForm field names to values. Flat or XFA-only PDFs returnnot_a_form. - Obtain exact names and choice options with
docgen_list_form_fieldsbefore filling an unfamiliar PDF. - Returns a
DocumentEnvelopewithpageCountandunmatchedFields[]for names with no matching field. flatten: truemakes the filled values non-editable (defaultfalse).
docgen_list_form_fields tool
- Accepts the same
sourcePdfbase64-or-URL source asdocgen_fill_form. Returns{ fields: [{ name, type, required, options? }] }without modifying the PDF or storing a document. - Types:
text,checkbox,dropdown,optionList,radioGroup,signature,button. Only dropdown, optionList and radioGroup entries includeoptions; signatures and buttons are discovery only. - Nested names retain their exact paths. PDFs without AcroForm fields return
not_a_form.
docgen_get_document tool
- Supply the
documentIdan earlier render/export/fill returned (doc_plus 24 url-safe characters). - Re-fetches its
DocumentEnvelopewithout rendering again; an expired or unknown id returnsdocument_expired.
docgen://document/{documentId} resource
- Use the
documentIdfrom a render/export/fill result (doc_plus 24 url-safe characters). - Returns a base64
blobwith the document's MIME type and JSON metadata (documentId,byteSize,pageCount/sheetCount,createdAt,ttlSecondsRemaining). Reads the same store asdocgen_get_document; expired or unknown ids returndocument_expired.
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
docgen-specific:
- No external API — a bundled rendering stack (
pdf-lib,exceljs,marked), so renders are local and deterministic with no upstream to fail - One shared
DocumentEnvelopeacross the four document delivery tools; field inspection returns its inventory directly - Bounded renders — a byte ceiling (
DOCGEN_MAX_DOCUMENT_BYTES) and a timeout (DOCGEN_RENDER_TIMEOUT_MS) turn a runaway render into a typed error instead of a hang - Tenant-scoped, expiring storage — a document id resolves only for the tenant that created it, and documents expire rather than accumulate
- SSRF-guarded form fetch — both form tools check every address, including each redirect hop, and block private, loopback and link-local destinations
Agent-friendly output:
- Dual-surface delivery — every envelope field appears in both
structuredContentand the markdown output, including thedocumentId, resource URI, size, and TTL - Inline by size —
inlineBase64is populated only at or underDOCGEN_INLINE_MAX_BYTES; larger documents are delivered through the resource URI - Partial-fill reporting —
docgen_fill_formreturnsunmatchedFields[]so the agent sees which field names didn't match - Typed errors with recovery hints (
invalid_source,template_render_failed,document_too_large,render_timeout,not_a_form,source_unfetchable,document_expired, …); semantic validation usesValidationError(-32007) and malformed argumentsInvalidParams(-32602)
Getting started
Add the following to your MCP client configuration file. No API keys are required.
Or with npx (no Bun required):
Or with Docker:
For Streamable HTTP, set the transport and start the server:
Documents are delivered by the docgen://document/{id} resource (and inline base64 when small enough) over every transport. The envelope's downloadUrl field is reserved for a future HTTP download route and is not emitted in this version.
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+); development uses Bun v1.4.3.
Installation
- Clone the repository:
- Navigate into the directory:
- Install dependencies:
- Configure environment:
Configuration
All configuration is optional — docgen runs with no required environment variables.
See .env.example for the full list of optional overrides.
The default in-memory storage drops every document on restart, and earlier ids then return
document_expired. To keep documents across restarts, pointSTORAGE_PROVIDER_TYPEat a persistent backend.
Running the server
Local development
-
Build and run:
-
Run checks and tests:
Docker
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/docgen-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Development guide
See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - Register new tools and resources in
src/index.ts'screateApp()arrays - One shared
DocumentEnvelopeacross all delivery tools — keep the writers and reader interchangeable
Contributing
Issues are welcome. Run checks and tests before submitting:
License
Apache-2.0 — see LICENSE for details.
Source: README.md at commit 702ad4a
Tools
0Version history
4- v0.3.0LatestOct 13, 2026
- v0.2.4Oct 7, 2026
- v0.2.3Sep 22, 2026
- v0.2.2Sep 16, 2026
Score
50% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 days25 pts
Keep the endpoint answering the MCP handshake; SourceWeft probes it every 30 days.
- Auth declared10 pts
Declare the credential headers in the registry entry, or keep the endpoint answering the probe so its auth can be classified.
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts