# Reported issues for docgen-mcp-server

Pod holds 14 of 14 problems reported by people outside the maintainer team. Issues filed by the project's own owners, members and collaborators are excluded entirely — a maintainer's release checklist is not a warning to a prospective user.

Back to [docgen-mcp-server](/mcp/docgen-mcp-server).

## Most discussed

### docs(design.md): stale downloadUrl references in delivery model section

### Description

`docs/design.md` has 9+ references to `downloadUrl` as an active delivery mechanism — lines 141–142, 259–260, 308–309, 390, and 434 describe `downloadUrl` as populated from `MCP_PUBLIC_URL` in HTTP/hosted mode. This was suppressed in the 0.1.1 working tree (#2): `buildEnvelope` no longer sets the field, `initDocumentStore()` no longer takes an `AppConfig`, and the `buildDownloadUrl()` private method was removed entirely.

The design doc is now inconsistent with the implementatio

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/7) · 2026-06-28 · closed · 2 comments

### bug(docgen_render_pdf): reject data unless template is the active source

### Server version

0.1.1

### mcp-ts-core version

0.10.9

### Runtime

Node.js

### Runtime version

Node v26.3.1

### Transport

HTTP (Streamable HTTP)

### OS

macOS / Darwin 25.1.0 arm64

### Description

`docgen_render_pdf` says callers must provide exactly one source: `{ html }`, `{ markdown }`, or `{ template, data }`. The handler counts only `html`, `markdown`, and `template`, so `{ html, data }` or `{ markdown, data }` succeeds and silently ignores `data`.

### Steps to reproduce

1. S

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/6) · 2026-06-27 · closed · 2 comments

### bug(docgen_fill_form): accept line-wrapped base64 PDFs

### Server version

0.1.1

### mcp-ts-core version

0.10.9

### Runtime

Node.js

### Runtime version

Node v26.3.1

### Transport

stdio

### OS

macOS / Darwin 25.1.0 arm64

### Description

`docgen_fill_form` rejects a valid base64-encoded PDF when the base64 string contains line breaks. Base64 produced by CLIs, MIME encoders, or copy/paste workflows is often wrapped; the decoder currently trims only the ends and then applies a no-whitespace regex to the whole string.

### Steps to reproduce

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/5) · 2026-06-27 · closed · 2 comments

### bug(docgen_export_spreadsheet): validate worksheet names before calling ExcelJS

### Server version

0.1.1

### mcp-ts-core version

0.10.9

### Runtime

Node.js

### Runtime version

Node v26.3.1

### Transport

HTTP (Streamable HTTP)

### OS

macOS / Darwin 25.1.0 arm64

### Description

`docgen_export_spreadsheet` does not validate worksheet names against ExcelJS/Excel constraints before rendering. Invalid and duplicate names throw through as generic tool errors with no declared reason or recovery, while over-31-character names are silently truncated by ExcelJS and the re

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/4) · 2026-06-27 · closed · 2 comments

### bug(documentId): malformed ids surface storage validation internals

### Server version

0.1.1

### mcp-ts-core version

0.10.9

### Runtime

Node.js

### Runtime version

Node v26.3.1

### Transport

HTTP (Streamable HTTP)

### OS

macOS / Darwin 25.1.0 arm64

### Description

`docgen_get_document` and the `docgen://document/{documentId}` resource pass unvalidated document IDs into the tenant state key. IDs containing storage-invalid characters or `..` bypass the declared `document_expired` contract and return storage validation errors with internal storage key/

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/3) · 2026-06-27 · closed · 1 comment

### bug(downloadUrl): emitted document URLs return 404

### Server version

0.1.1

### mcp-ts-core version

0.10.9

### Runtime

Node.js

### Runtime version

Node v26.3.1

### Transport

HTTP (Streamable HTTP)

### OS

macOS / Darwin 25.1.0 arm64

### Description

When `MCP_PUBLIC_URL` is set, render/export/fill envelopes include `downloadUrl`, but the advertised `/documents/{documentId}` route is not served by the HTTP app. The same artifact is retrievable via `docgen_get_document` and `resources/read`, so the document exists; only the HTTP URL is 

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/2) · 2026-06-27 · closed · 1 comment

### bug(docgen_render_pdf): template_render_failed missing recovery hint from declared error contract

### Server version

0.1.0

### mcp-ts-core version

0.10.9

### Runtime

Bun

### Runtime version

Bun 1.3.11

### Transport

HTTP (Streamable HTTP)

### Description

`docgen_render_pdf` declares a `template_render_failed` error contract entry with recovery hint `"Check the template's {{referenced}} fields against the keys present in the data object."` — but the error response never includes `data.recovery.hint`, so the recovery text is silently dropped.

The throw site in `RenderService.renderT

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/1) · 2026-06-25 · closed · 1 comment

### feat(config): default MCP_SESSION_MODE to stateless across env, Docker, and src

`Dockerfile` sets `ENV MCP_SESSION_MODE="stateless"`, but `.env.example` carries a commented `# MCP_SESSION_MODE=stateful`, whose comment documents the value set as `stateful | stateless (default: stateful)`. The container and the same code run via `bunx`, `npm start`, or from source therefore resolve to different session modes — stateless in Docker, stateful everywhere else, since the framework schema defaults to `auto` and `auto` resolves to `stateful`.

Related: cyanheads/mcp-ts-core#376

## 

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/14) · 2026-08-22 · open · 0 comments

## Most recent

### feat(docgen): serve rendered documents over HTTP and populate downloadUrl

### Server version

0.2.1

### Description

`DocumentEnvelope` declares a `downloadUrl` field but never populates it — `src/services/document/types.ts` describes it as "Reserved for a future HTTP download route; not emitted in v1 (the field is always absent). Fetch the bytes via resourceUri or inlineBase64 instead."

That leaves two delivery paths, and both hand the caller base64:

- `inlineBase64`, present when the artifact is at or under `DOCGEN_INLINE_MAX_BYTES` (default 5 MB)
- `resourceUri`

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/13) · 2026-08-10 · open · 0 comments

### docs(docgen_export_spreadsheet): columns describe says "first row keys" but derives from all rows

### Server version

0.2.1

### mcp-ts-core version

0.10.9

### Runtime

Bun

### Runtime version

1.3.11

### Transport

stdio

### OS

macOS

### Description

In `render-types.ts`, `SheetSchema.columns` is described as: *"Optional ordered column spec. When omitted, columns derive from the first row keys."* But `RenderService.resolveColumns` derives them from the **union of all rows' keys** (`for (const row of sheet.rows) for (const k of Object.keys(row)) keys.add(k)`), not just the first row's

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/12) · 2026-06-30 · open · 0 comments

### security(docgen_fill_form): SSRF guard bypassable via DNS rebinding (resolve/fetch TOCTOU)

### Server version

0.2.1

### mcp-ts-core version

0.10.9

### Runtime

Bun

### Runtime version

1.3.11

### Transport

http

### OS

macOS

### Description

`fetch-guard.ts` validates the destination by resolving the hostname with `dns.lookup(host, { all: true })` and rejecting any private/loopback/link-local/metadata IP, then calls `fetch(url)`. Because `fetch` performs its **own** DNS resolution when it connects, the IP that was vetted and the IP actually connected to can differ — a time-of

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/11) · 2026-06-30 · open · 0 comments

### feat(docgen_fill_form): add docgen_list_form_fields to discover AcroForm field names

`docgen_fill_form` requires exact, case-sensitive AcroForm field names, but the server offers no way to discover them — the tool description itself says to "obtain them from whoever supplied the form, since docgen does not expose them." An agent that has the PDF but not a field list must guess names, read the misses back from `unmatchedFields[]`, and retry — and even then it learns only which guesses were wrong, never what the real names are.

## Proposal

Add a read-only `docgen_list_form_field

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/10) · 2026-06-30 · open · 0 comments

### bug(docgen_render_pdf): non-WinAnsi characters silently replaced with "?" and not flagged degraded

### Server version

0.2.1

### mcp-ts-core version

0.10.9

### Runtime

Bun

### Runtime version

1.3.11

### Transport

stdio

### OS

macOS

### Description

The lightweight PDF engine embeds the WinAnsi `StandardFonts` (Helvetica), which only encodes U+0020–U+00FF. `sanitizeForFont` (`src/services/document/render-service.ts`) maps any code point outside that range to `"?"` (with a few smart-punctuation exceptions) so `pdf-lib`'s `drawText` never throws. That keeps the engine robust, but it m

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/9) · 2026-06-30 · open · 0 comments

### bug(docgen_export_spreadsheet): boolean column coerces string "false"/"0"/"no" to true

### Server version

0.2.1

### mcp-ts-core version

0.10.9

### Runtime

Bun

### Runtime version

1.3.11

### Transport

stdio

### OS

macOS

### Description

`docgen_export_spreadsheet` coerces cell values per the column `type`, but the `boolean` branch uses `Boolean(value)` (`coerceCell` in `src/services/document/render-service.ts`). Every non-empty string is truthy in JS, so a string `"false"`, `"0"`, `"no"`, or `"off"` is written to the cell as **`true`** — silently inverting the data. Unl

[Read the thread](https://github.com/cyanheads/docgen-mcp-server/issues/8) · 2026-06-30 · open · 0 comments

The remaining reports are on [the project's issue tracker](https://github.com/cyanheads/docgen-mcp-server/issues).
