---
summary: "Adds a local SQLite+FTS5 catalog mirror for gutenberg_get_book/gutenberg_get_text, fixes a double-decoded HTML entity in the HTML-fallback text path, and adopts mcp-ts-core 0.13.6."
breaking: false
security: true
---

# 0.1.9 — 2026-09-20

## Added

- **Local SQLite+FTS5 catalog mirror** — `gutenberg_get_book` and `gutenberg_get_text` read from a local harvest of the bulk Gutenberg RDF archive when it holds the record, falling back to the live Gutendex API otherwise. Populate it with `bun run mirror:init`; `GUTENBERG_MIRROR_PATH` and `GUTENBERG_MIRROR_REFRESH_CRON` configure its location and an optional in-process refresh schedule.

## Changed

- **Nullable number fields in tool output schemas now render as `"type": ["number", "null"]`** instead of an `anyOf` of `number` and `null` (`birth_year`, `death_year`, `copyright`) — a semantically identical re-rendering from the `zod` bump below; no field, constraint, required key, or `additionalProperties` value changed.

## Fixed

- **`gutenberg_get_text`'s HTML fallback no longer double-decodes character references** — a sequential `&amp;` → `&lt;` → `<` replacement re-decoded output from its own earlier pass, so an escaped reference like `&amp;lt;` (meaning the literal text `&lt;`) collapsed to `<`. ([#16](https://github.com/cyanheads/gutenberg-mcp-server/issues/16))

## Security

- **Single-pass entity decoding resolves named references through a `Map`**, not an object literal, so a reference naming an `Object.prototype` member (e.g. `&constructor;`) can't resolve into the returned text. Also fixes CodeQL `js/double-escaping`. ([#16](https://github.com/cyanheads/gutenberg-mcp-server/issues/16))

## Dependencies

- `@cyanheads/mcp-ts-core` ^0.12.3 → ^0.13.6
- `zod` ^4.4.3 → ^4.6.5
