Skip to main content
Glama

docbridge

An MCP server that converts documents — PDF, DOCX, Markdown, plain text, images — and returns, with every conversion, a report of what was checked, what failed, what was never checked, and what the formats cannot carry. It also reads long documents cheaply without weakening them: outline, exact search and verbatim reads.

NOT_CHECKED is never treated as PASS. A check that could not run, or that met content docbridge cannot read, is reported as NOT_CHECKED or UNSUPPORTED and is never counted as a pass. Silent corruption is treated as worse than a refused conversion: a changed digit in an organisation number (923 456 781 → 923 456 718), an amount (€4,999 → €4,599) or a date (14/07/2024 → 14/07/2025) is a FAIL, reported with both values, their locations and their context.

docbridge went through four rounds of adversarial audit. Every confirmed finding — 21 across the four rounds — was fixed and is covered by regression tests. 282 tests pass.

Version 0.2.4 · schema 0.2.4 · Python ≥ 3.10 · licence AGPL-3.0

Tools

Tool

Does

docbridge_contract

the vocabulary: statuses, reasons, error codes, what each format can carry — call it first

document_outline

the map of a document in a few hundred characters: pages/lines/paragraphs, headings from the file itself, tables, unreadable pages

document_search

exact search with page/line, offsets, context and a match_id; says which pages it could not search

document_read

verbatim text of a page/line/paragraph range, capped; a cut is stated and a cursor continues it exactly

document_read_around

the pages (or paragraphs, lines) around a search match, verbatim

get_report

the full report behind a report_id

pdf_merge

PDFs → one PDF, every page proven identical to its source page

pdf_split

PDF → one file per range, or per page

images_to_pdf

images → PDF, JPEG bytes unchanged, rotation without re-encoding

pdf_to_markdown

PDF text layer → Markdown with page markers (no OCR)

docx_to_markdown

DOCX → Markdown (Pandoc, sandboxed)

markdown_to_docx

Markdown → DOCX (Pandoc, sandboxed)

txt_to_docx

plain text → DOCX, one paragraph per line

document_extract

a mechanical inventory: counts, then only the lists asked for (numbers, dates, URLs, identifiers, tables, ...), paged

document_compare

two documents compared through their canonical forms

validate_conversion

the full report for a conversion made by anything

Related MCP server: PDF MCP Flow

Supported conversions

From

To

Tool

Notes

PDF

Markdown

pdf_to_markdown

the PDF's text layer, with page markers; no OCR

DOCX

Markdown

docx_to_markdown

via Pandoc

Markdown

DOCX

markdown_to_docx

via Pandoc

plain text

DOCX

txt_to_docx

one paragraph per line

images

PDF

images_to_pdf

JPEG bytes embedded unchanged; rotation without re-encoding

several PDFs

one PDF

pdf_merge

every page proven identical to its source page

PDF

several PDFs

pdf_split

by ranges, or one file per page

A conversion made by any other tool can be checked with validate_conversion, and any two documents compared with document_compare, across PDF, DOCX, Markdown and plain text.

Reading a report

By default a tool returns report_summary and a report_id; detail="full" or get_report(report_id) gives the whole report. The summary never states a different verdict.

operation_completed          the file was written            (not a verdict)
status                       PASS | FAIL | NOT_CHECKED | UNSUPPORTED
required_axes                what a PASS covers for this operation
status_basis                 why, in one sentence
differences                  each change: axis, kind, before, after, location, context
unsupported_checks           everything that was not established

NOT_CHECKED and UNSUPPORTED are never passes. Full semantics: DOCUMENT_MCP_CONTRACT.md and VALIDATION_MODEL.md.

Evidence preservation and lossless reading

docbridge may reduce the volume of its own responses, but it never alters, summarizes, paraphrases, semantically filters, or silently truncates source evidence.

  • Reads are verbatim. Every excerpt carries the file's SHA-256, its offsets and the SHA-256 of the returned text.

  • A cut is always stated: truncated, remaining_chars, and a next_cursor that continues at exactly the next character. A cursor or match_id issued for another version of the file is refused with stale_reference.

  • Content docbridge cannot read — a page with no text layer, an equation, an embedded object — becomes an UNKNOWN sentinel that matches nothing, so no comparison can pass across it.

  • Sources are never overwritten; outputs are written atomically.

  • Every path must be absolute and inside the allowed roots (DOCBRIDGE_ROOTS).

  • A PDF's text means its text layer, not what the page shows. There is no OCR.

document_outline(path)                      the map: units, headings, tables, unreadable pages
document_search(path, "tax residence")      exact matches, each with a match_id and its page
document_read_around(path, match_id)        the surrounding pages, verbatim
document_read(path, start=12, end=16)       any range, verbatim; follow next_cursor if truncated

Install

Python ≥ 3.10. Pandoc ≥ 2.15 is needed only for markdown_to_docx and docx_to_markdown; docbridge finds it on PATH, or set DOCBRIDGE_PANDOC to the executable. Every other tool works without it.

git clone https://github.com/Mormolykos/docbridge.git
cd docbridge
python -m venv .venv
.venv/bin/pip install -e ".[dev]"      # Windows: .venv\Scripts\pip install -e ".[dev]"

requirements.lock pins the exact environment the test suite ran in.

MCP server setup

docbridge is a stdio MCP server: python -m docbridge.server, or the docbridge-mcp command the package installs. For clients that use the common mcpServers configuration:

{
  "mcpServers": {
    "docbridge": {
      "command": "/path/to/docbridge/.venv/bin/python",
      "args": ["-m", "docbridge.server"],
      "env": { "DOCBRIDGE_ROOTS": "/path/to/your/documents" }
    }
  }
}

On Windows, command is C:\\path\\to\\docbridge\\.venv\\Scripts\\python.exe. DOCBRIDGE_ROOTS lists the folders docbridge may read and write, separated by the system's path separator (: on macOS and Linux, ; on Windows); by default it is the user's home folder. Optional: DOCBRIDGE_PANDOC (the Pandoc executable) and DOCBRIDGE_SEARCH_TIMEOUT_S (the time bound on one search, default 2 s; a stopped search returns search_timeout, never a partial result).

Tests

.venv/bin/python -m pytest              # 282 tests, including the property fuzz
.venv/bin/python scripts/e2e_fresh.py   # a fresh end-to-end run over the real MCP protocol

DOCBRIDGE_FUZZ_N sets the property-fuzz iterations (default 300). Pandoc-dependent tests skip with a stated reason if Pandoc is absent — a skip is not a pass.

Documentation

  • DOCUMENT_MCP_CONTRACT.md — every tool, argument, status, reason and error code.

  • VALIDATION_MODEL.md — what each check compares, the declared domains, the known limits, and the four audit rounds with their findings and repairs.

Layout

src/docbridge/
  contract.py      statuses, reasons, error codes, required axes, format capabilities
  normalize.py     the declared domain: tokens, numbers, identifiers
  canonical.py     the one shape every format is read into
  reading.py       lossless reading: outline, search, verbatim reads, cursors
  _search_worker.py  one search in its own process, so it can be stopped (time bound)
  extract/         readers: text.py, markdown.py, html.py (raw HTML in Markdown), docx.py, pdf.py
  compare.py       token views, sequence alignment, structure checks
  validate.py      builds a report and the global verdict
  report.py        the report as typed models (the output schema)
  convert/         pandoc.py, pdf_md.py, txt_docx.py, pdf_ops.py, images.py
  paths.py         path policy, atomic writes
  tools.py         the sixteen tools as plain functions
  server.py        the MCP server
tests/             programmatic fixtures (builders.py) and 16 test files
scripts/e2e_fresh.py

Licence

AGPL-3.0 — see LICENSE. docbridge imports PyMuPDF, which is licensed under the AGPL-3.0.

Available Tools

16 tools
docbridge_contractA
Read-onlyIdempotent

The vocabulary every response uses: statuses, reasons, error codes, which axes a global PASS covers per operation, what each format can carry, the declared text normalization, what 'verbatim' means per format, and whether Pandoc is available. Call this before interpreting a report. [docbridge schema 0.2.4]

Inputs: no named parameters. Returns: tool, error, contract, disclaimer, +2 more

document_compareA
Read-onlyIdempotent

Compare two documents (any of PDF, DOCX, MD, TXT) through their canonical forms: missing, added and changed text, numbers and identifiers, structure and page-count differences, and what could not be compared. Read-only. [docbridge schema 0.2.4]

Inputs: left_path (required), right_path (required), detail, left_encoding, +2 more. Returns: tool, error, report, outputs, +7 more

document_extractA
Idempotent

A mechanical inventory of one PDF/DOCX/MD/TXT - not a substitute for reading it. Counts always; lists only for the kinds asked (numbers, identifiers, dates, urls, emails, headings, tables, links, emphasis, images, pages, blocks, warnings, unsupported, normalized_text), paged by offset/max_items with the rest stated. output_path writes everything to JSON. [docbridge schema 0.2.4]

Inputs: input_path (required), kinds, offset, encoding, +4 more. Returns: tool, error, document, disclaimer, +3 more

document_outlineA
Read-onlyIdempotent

The structural map of a PDF/DOCX/MD/TXT in a few hundred characters: unit kind and count (pages, lines or paragraphs), headings from the file's own markup or PDF bookmarks (never inferred), tables, per-page text-layer status, unreadable units. Use it to decide what to read. [docbridge schema 0.2.4]

Inputs: input_path (required), encoding, max_items. Returns: tool, error, source, outline, +3 more

document_readA
Read-onlyIdempotent

Verbatim text of units start..end (PDF pages, MD/TXT lines, DOCX paragraphs; end omitted = to the end), up to max_chars. Never summarized or filtered. The excerpt carries offsets and SHA-256; if cut, truncated=true, remaining_chars says how much is left and next_cursor continues exactly. [docbridge schema 0.2.4]

Inputs: input_path (required), end, start, cursor, +2 more. Returns: tool, error, match, source, +12 more

document_read_aroundA
Read-onlyIdempotent

Verbatim text around a search match: the match's units plus before/after units (defaults: 1 page, 3 paragraphs, 15 lines). The match is always inside the excerpt; anything left out on either side is stated with a cursor. [docbridge schema 0.2.4]

Inputs: match_id (required), input_path (required), after, before, +2 more. Returns: tool, error, match, source, +12 more

docx_to_markdownA
Idempotent

Markdown (CommonMark + pipe tables + strikethrough) from a DOCX, via sandboxed Pandoc. The report checks text, numbers, identifiers, links, headings, lists, tables and bold/italic, and lists what Markdown cannot carry (headers/footers, comments, equations, images). [docbridge schema 0.2.4]

Inputs: input_path (required), detail, overwrite, output_path, +2 more. Returns: tool, error, report, outputs, +7 more

get_reportA
Read-onlyIdempotent

The full validation report behind a report_id (held for the last 200 operations of this server session), or one section of it: axes, structure_checks, differences, warnings, unsupported_checks. [docbridge schema 0.2.4]

Inputs: report_id (required), section. Returns: tool, error, report, section, +3 more

images_to_pdfA
Idempotent

One PDF page per image (JPEG, PNG, TIFF, BMP, GIF, WEBP). JPEGs are embedded byte-for-byte; EXIF orientation and the optional clockwise rotations are applied by page placement, never by re-encoding. The report checks bytes or pixels (colour and alpha separately) and orientation. [docbridge schema 0.2.4]

Inputs: inputs (required), output_path (required), detail, overwrite, +5 more. Returns: tool, error, report, outputs, +7 more

markdown_to_docxA
Idempotent

DOCX from Markdown (CommonMark + pipe tables + strikethrough) via sandboxed Pandoc: headings, paragraphs, bold/italic, lists, tables, links, code blocks. Images are never fetched (alt text is kept). The report checks text, numbers, identifiers and structure. [docbridge schema 0.2.4]

Inputs: input_path (required), detail, encoding, overwrite, +3 more. Returns: tool, error, report, outputs, +7 more

pdf_mergeA
Idempotent

Merge PDFs, in the order given, into one PDF. Bookmarks, links, annotations and form fields are carried. The report checks page count, and that every output page is pixel-identical (rendered), text-identical and rotation-identical to the source page it came from. [docbridge schema 0.2.4]

Inputs: inputs (required), output_path (required), detail, overwrite, +3 more. Returns: tool, error, report, outputs, +7 more

pdf_splitA
Idempotent

Split a PDF into one file per page range ('1-3', '5', '7-' to the end) or one file per page (each_page=true). Files are named _p-.pdf. The report checks each output's page count and that every page is identical to its source page. [docbridge schema 0.2.4]

Inputs: input_path (required), detail, ranges, each_page, +5 more. Returns: tool, error, report, outputs, +7 more

pdf_to_markdownA
Idempotent

Markdown from a PDF's text layer, with page markers. Headings, lists and tables are INFERRED (reported NOT_CHECKED); the text, numbers and identifiers are validated against the PDF. Pages with no text layer are marked, never guessed (no OCR). [docbridge schema 0.2.4]

Inputs: input_path (required), detail, overwrite, output_path, +4 more. Returns: tool, error, report, outputs, +7 more

txt_to_docxA
Idempotent

DOCX from plain text: one paragraph per line, tabs kept, form feeds as page breaks. Characters DOCX cannot store are refused with their positions, never dropped. The report checks text and numbers. [docbridge schema 0.2.4]

Inputs: input_path (required), detail, encoding, overwrite, +3 more. Returns: tool, error, report, outputs, +7 more

validate_conversionA
Idempotent

Given a source document and a converted one (made by anything), run every check that is possible for the format pair and return the validation report: text, numeric and identifier fidelity, structure, and every property NOT_CHECKED or UNSUPPORTED. Writes nothing unless report_path is set. [docbridge schema 0.2.4]

Inputs: source_path (required), target_path (required), detail, overwrite, +4 more. Returns: tool, error, report, outputs, +7 more

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.8/5.0

    Scored across 16 tools

    Disambiguation4/5

    Most tools target clearly distinct operations: read, read_around, outline, search, extract each occupy a different slice of document inspection, and merge/split/convert tools are format-specific. Minor overlap exists between document_compare and validate_conversion (both diff documents) and between document_read and document_read_around, but descriptions clarify boundaries well.

    Naming Consistency4/5

    Names follow readable, domain-specific patterns: document_* for inspection, <format>_to_<format> for conversions, and verb_noun for get_report/validate_conversion. It is not one single verb_noun convention throughout, but each family is internally consistent and predictable.

    Tool Count4/5

    16 tools is slightly on the heavy side but justified by the broad domain (inspection, extraction, four conversion routes, merge/split, compare, validate). Each tool addresses a distinct format or operation, so few feel redundant.

    Completeness4/5

    The surface covers a full read-search-extract-convert-validate lifecycle across PDF/DOCX/MD/TXT plus merge/split and image input. Minor gaps remain: no direct pdf_to_docx or markdown_to_pdf route (only via markdown), but core workflows and validation are well covered.

    Maintenance

    ActivitySlowing
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers