Skip to main content
Glama

digibib5-mcp

A clone-in-progress of the Digitale Bibliothek 5 reader (Directmedia / Digitale Bibliothek), built on a from-scratch reverse-engineering of its .DKI volume format. It reads the original CD-ROM images - volume list, table of contents, and decoded text - and exposes them over MCP and REST, with a reader webapp.

The .DKI format was reversed from the real discs (see reversing-mcp docs/DIGIBIB5_DKI_FORMAT.md). Two format generations are supported: older single-table volumes (DB008) and newer ones (DB074, DB006) with magic-prefixed TEXT.DKI, direct TREE.DKA mapping, high-bit word lengths and .xml source markers. Digibib5 itself is the oracle: run it alongside to compare rendered output.

Documentation

Doc

What

INSTALL.md

setup, MCP config

docs/ONBOARDING.md

first-timer guide: discs, costs (none), sanity check

docs/CONFIGURATION.md

env vars, ports, per-volume file layout

docs/TOOLS.md

MCP ops, REST endpoints, Python library

docs/DEVELOPMENT.md

repo layout, gates, codec map, release

docs/TROUBLESHOOTING.md

symptoms and fixes

Related MCP server: hbls_mcp

Status

Early. What works today:

  • Volume discovery - scans the install root and lists every CD-ROM image.

  • Descriptor - reads DIGIBIB.TXT identity (title etc.).

  • TOC - parses TREE.DKI (indented-text tree) into a nested table of contents.

  • Text decode - decodes TEXT.DKI records (tokenized word-stream codec, v2: flowing paragraphs, heads dropped, de-hyphenated).

  • Search - FTS5 sidecar over decoded text with chapter snippets (search op, REST /api/.../search, reader search box).

  • Figures - IMAGES\ BMP scans served over REST with per-chapter figure strips in the reader (images op, /api/.../images, /api/.../image/...).

  • REST API + reader webapp - a Starlette backend serves the library as JSON, and a React/Vite/Tailwind reader renders the volume picker, TOC tree, and text.

Known v1 / approximate (tracked, to refine against the Digibib5 oracle):

  • The text codec's exact control-opcode grammar (heading levels, italics, links). Paragraph structure, running-head removal, de-hyphenation, spaced dashes, literal spans and reflowed line breaks are mapped (v2); output is flowing text but not yet byte-faithful.

  • Images (IMAGES\*.BMP / images.lib) and the search indexes (INDEX.* / LINKS.*) are not wired up yet.

Solved 2026-10-26: the TREE.DKA node -> record mapping. The table is a 1-based start-record run for every node but the volume root (root starts at record 0), located by monotonic-run scan. Clicking a TOC entry now renders the whole chapter (all records until the next non-descendant node, capped at 100); node_text reports record / record_end / records_total / truncated.

Format, in brief

A volume is a data\ folder:

File

Role

DIGIBIB.TXT

INI descriptor (identity shown in the CD picker)

TREE.DKI

TOC as indented CP1252 text (leading spaces = depth)

TREE.DKA

u32 node -> record table (1-based run for all nodes but the root; see CONFIGURATION)

TEXT.DKI

[u32 count][u32 offset table][records]; each record length-prefixed, content is a tokenized word stream

INDEX.*, LINKS.*

search / cross-reference indexes (later)

IMAGES\1..4\*.BMP

page images at 4 zoom levels (later)

MCP tool

One portmanteau, digibib:

digibib(operation="list_volumes")
digibib(operation="descriptor", volume_id="DB008")
digibib(operation="toc", volume_id="DB008", max_depth=3)
digibib(operation="node_text", volume_id="DB008", node_index=5)
digibib(operation="record_text", volume_id="DB008", record_index=0)
digibib(operation="search", volume_id="DB008", query="Nathanael", limit=10)
digibib(operation="images", volume_id="DB008", level=1)

node_text returns the node's full chapter extent (record..record_end, records_total, truncated when capped at 100 records) plus images (figure names referenced by the chapter) and image_levels; record_text reads one raw TEXT.DKI record; search returns FTS5 hits with the containing chapter and a «»-marked snippet per hit.

The install root defaults to K:\Digitale Bibliothek\Bibliothek (override with the DIGIBIB_ROOT env var or the root argument).

Library

from digibib5_mcp.dki import DigibibLibrary

lib = DigibibLibrary()
for ref in lib.list_volumes():
    print(ref.id, ref.title)

vol = lib.open("DB008")
print(vol.title)  # Digitale Bibliothek Band 8: Hoffmann
for root in vol.toc_tree():
    print(root.title)  # Hoffmann -> ...
print(vol.record_text(0))  # decoded record text

Run

uv run digibib5-mcp              # stdio MCP server
just api                         # REST backend only (Starlette on 14115)
just webapp                      # backend + Vite reader on http://127.0.0.1:14114

just webapp runs web_sota/start.ps1: it starts the backend, bun installs the frontend on first run, then launches the Vite dev server. The frontend proxies /api to the backend.

Reader webapp

web_sota/ - React 18 + Vite 6 + Tailwind 4 + react-router + Zustand (Bun). AppLayout shell (sidebar, topbar, health dot) with routed pages: Dashboard (library KPIs + onboarding), Reader (volume picker, TOC tree, content pane, search, figures), Tools (live op harness), Chat (local/cloud LLM, resident-first), Settings (backend + AI), Logs, Help. Ports: 14114 (frontend) / 14115 (backend REST).

Packaging

Fleet-standard: justfile (run / lint / test / release recipes), mcpb.json + manifest.json for MCPB bundling (just pack), and scripts/release.ps1 for the triple-play release (mcpb + NSIS installer + GitHub release).

Stack

Python 3.12+, FastMCP 3.2+, Pydantic v2, Starlette, uv. Frontend: React 18, Vite 6, Tailwind 4, Bun.

For reading Digitale Bibliothek volumes you own. Intended for interoperability, preservation, and access on modern systems.

Interoperability note (not legal advice). This project contains no copy-protection circumvention and redistributes no content from the discs: no texts, no images, no audio, no keys - only code that reads CD-ROMs you own. The .DKI container is an undocumented but unprotected format; nothing here defeats an effective technical protection measure. Reverse-engineering a file format to make lawfully acquired data usable on current systems is the interoperability case the EU Software Directive (Art. 6) expressly permits. "Digitale Bibliothek" is named only to describe compatibility. If you are unsure in your jurisdiction, ask a lawyer before redistributing anything beyond the code.

Available Tools

1 tool
digibibA

DIGIBIB - read Digitale Bibliothek 5 volumes.

Operations:

  • list_volumes -> every installed CD-ROM volume: {id, title}.

  • descriptor -> the volume's DIGIBIB.TXT identity keys.

  • toc -> the table of contents as a nested tree (node index + record index per node). Use max_depth to trim.

  • node_text -> decoded text for a TOC node: the full chapter extent (record..record_end, records_total, truncated flag).

  • record_text -> decoded text for a raw TEXT.DKI record index.

  • search -> full-text search over decoded text (needs query): [{record, node_index, chapter, snippet}]. First search per volume builds an FTS cache (~10 s), then instant.

  • images -> figures at a zoom level (needs level or takes the highest): {levels, level, images: [{name, width, height, bpp, bytes, url}]}. Binary via the REST image endpoint (see url per figure).

NOTE: text decode is v2 (flowing paragraphs, heads dropped); output is readable but not yet byte-faithful.

NameRequiredDescriptionDefault
rootNoOverride the install root (default DIGIBIB_ROOT or K:\...).
levelNoimages: zoom level (default: highest).
limitNosearch: max hits (default 20, max 100).
queryNosearch: FTS5 query (words, AND/OR/NOT, "phrase", prefix*).
max_depthNotoc: limit nesting depth.
operationNolist_volumes | descriptor | toc | node_text | record_text | search | imageslist_volumes
volume_idNoVolume folder id, e.g. 'DB008' (all ops except list_volumes).
node_indexNotoc node index (node_text).
record_indexNorecord index (record_text).

Output Schema

NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden, and it discloses important behavior: the first search per volume builds an FTS cache (~10 s), images are served via a REST endpoint, and text decoding is v2 but not byte-faithful. It stops short of permissions or error behavior, but the disclosed traits are substantial.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the core purpose and then organized as a compact operation list. Every bullet adds information needed to select an operation or set a parameter, and the closing note about decode fidelity is relevant.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given seven operations and nine optional parameters, the description explains operation roles, parameter applicability, and workflow-adjacent details such as how toc exposes node indexes used by node_text. An output schema exists, so return-value explanation is not required, and the description is complete enough to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents parameters at a baseline level. The description adds operation-specific meaning: which parameters apply to toc, node_text, record_text, search, images, and volume_id. This is useful beyond the schema, though not exhaustive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'read Digitale Bibliothek 5 volumes.' It then enumerates all seven operations with concrete outputs, so an agent understands the tool's scope without consulting another tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is clear for each operation: search requires query, images uses level or defaults to the highest, and volume_id applies to all operations except list_volumes. It does not explicitly say when to avoid the tool, but no alternatives exist and the operation-level guidance is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 1 tool updatev0.5.0
    • First observeddigibib

TDQS

A4.3/5.0

Scored across 1 tool

Disambiguation4/5

The single dispatcher tool exposes clearly separated operations (list_volumes, descriptor, toc, node_text, record_text, search, images) with distinct inputs and outputs. The only real overlap is node_text vs record_text, which both return decoded text and differ only by addressing scheme (TOC node vs raw TEXT.DKI record index) — the descriptions clarify this, but an agent could still pick the wrong one.

Naming Consistency4/5

The operations inside the tool consistently follow a snake_case verb_noun pattern (list_volumes, node_text, record_text). The tool itself is a single server-named dispatcher ('digibib') rather than a verb_noun action, which is a minor deviation but acceptable for a multi-operation facade.

Tool Count3/5

A single exposed tool would normally feel thin, but it packs seven substantive operations covering the whole read lifecycle, so the surface is larger than the count suggests. Still, the single-tool dispatch pattern makes discovery and selection harder than a small set of explicit tools would.

Completeness4/5

For a read-only CD-ROM library reader the coverage is strong: volume listing, metadata, TOC navigation, chapter/record extraction, full-text search, and figure retrieval. Gaps are minor — no cross-volume aggregated search and no export/citation output, but agents can work around both by iterating volumes.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    A
    maintenance
    An MCP server for Christian scholarship and research, providing read-only access to a SQLite corpus of 66-book BSB and 83-book WEB Bibles, original-language Greek/Hebrew word studies with Strong's and morphology, cross-references, patristic citations (Irenaeus, Justin Martyr, Apostolic Fathers), verse alignments, semantic and hybrid search over ~55,800 embeddings, and multi-work passage retrieval, interlinear lookup, and research-brief synthesis prompts.
    3
    -
  • F
    license
    Not graded
    quality
    B
    maintenance
    MCP server providing full-text search and structured access to the Historisches Biographisches Lexikon der Schweiz, including biographies, articles, and volume listings.
    -
  • A
    license
    A
    quality
    A
    maintenance
    This MCP server enables AI agents to search and retrieve exact, cited passages from a large corpus of public-domain books, including full-text search, book metadata, chapters, quotes, and 'ask book' Q&A. Payments are handled via x402 micropayments on Base.
    8
    54 npm
    MIT