Skip to main content
Glama
document-mcp

document-mcp

by ExaDev

document-mcp

This repository has moved. document-mcp now lives at packages/document-mcp in the ExaDev/documents.js monorepo. This repository is archived and will receive no further commits, releases, issues, or pull requests — file issues and send pull requests against the monorepo instead. The npm package itself is unaffected: document-mcp keeps publishing from its new home under the same name.

GitHub npm Release CI

An MCP (Model Context Protocol) server exposing documents.js's document-conversion, .odb, metadata, and font tooling as MCP tools, so an MCP-speaking agent can convert, inspect, and edit docx/pptx/odt/odp/ods/odg/odf/pdf/odb/xlsx/markdown documents without writing TypeScript against documents.js directly.

document-mcp adds no conversion or editing logic of its own — it is a dispatch layer over documents.js's existing conversion functions, DocumentConverter port, and .odb/PDF readers, wired up as MCP tools served over stdio. document-cli is the sibling frontend over the identical documents.js library — a terminal CLI/TUI rather than an MCP server — so the two are independent consumers of one shared implementation and can expose different subsets of it. A convert_document call's fidelity — which (source, targetFormat) pairs round-trip losslessly, which are a best-effort reconstruction, and why — is exactly what documents.js's own Fidelity section documents, table included; it is not restated here.

graph TD
    schema("document-schema.js")
    ooxml("ooxml.js")
    odf("odf.js")
    pdfcodec("pdf-codec")
    mdcodec("markdown-codec")
    bytecodec("byte-codec")
    documents("documents.js")
    outline("document-outline.js")
    mcp("document-mcp")
    cli("document-cli")

    schema --> outline
    outline --> mcp
    schema --> ooxml
    schema --> odf
    schema --> pdfcodec
    schema --> mdcodec
    schema --> documents
    ooxml --> documents
    odf --> documents
    pdfcodec --> documents
    mdcodec --> documents
    bytecodec --> pdfcodec
    bytecodec --> documents
    documents --> mcp
    pdfcodec --> mcp
    documents --> cli
    odf --> cli
    pdfcodec --> cli

    click schema "https://github.com/ExaDev/document-schema.js" "document-schema.js"
    click ooxml "https://github.com/ExaDev/ooxml.js" "ooxml.js"
    click odf "https://github.com/ExaDev/odf.js" "odf.js"
    click pdfcodec "https://github.com/ExaDev/pdf-codec" "pdf-codec"
    click mdcodec "https://github.com/ExaDev/markdown-codec" "markdown-codec"
    click bytecodec "https://github.com/ExaDev/byte-codec" "byte-codec"
    click documents "https://github.com/ExaDev/documents.js" "documents.js"
    click outline "https://github.com/ExaDev/document-outline.js" "document-outline.js"
    click mcp "https://github.com/ExaDev/document-mcp" "document-mcp"
    click cli "https://github.com/ExaDev/document-cli" "document-cli"

    style mcp fill:#f9a825,stroke:#333,stroke-width:3px

Getting started

Run the server directly — no install step needed:

npx document-mcp

The server uses stdio transport (runs as a local process). This is supported by Claude Code, Claude Desktop, Codex CLI, Codex Desktop, and OpenCode directly. Claude Web (claude.ai), Claude Mobile, and ChatGPT require a remote HTTP MCP server — see Remote transport below.

Compatibility

Client

Transport

Direct support

Claude Code (CLI)

stdio

✅

Claude Code (plugin)

stdio

✅

Claude Desktop

stdio

✅

Codex CLI

stdio

✅

Codex Desktop

stdio

✅

OpenCode

stdio

✅

Claude Team/Enterprise (org)

stdio (per-machine)

✅ via managed settings

Claude Web (claude.ai)

HTTP/SSE only

❌ needs remote transport

Claude Mobile (iOS/Android)

HTTP/SSE only

❌ needs remote transport

ChatGPT (web/desktop)

HTTP only

❌ needs remote transport

Connecting from Claude Code

One-liner (adds the MCP server directly):

claude mcp add --transport stdio document-mcp -- npx -y document-mcp

Or install as a Claude Code plugin (this repo is a plugin marketplace — includes auto-update on new releases):

From the terminal:

claude plugin marketplace add ExaDev/document-mcp
claude plugin install document-mcp@exadev

Or from within a running Claude Code session:

/plugin marketplace add ExaDev/document-mcp
/plugin install document-mcp@exadev

Run /reload-plugins to activate in an already-running session. In Claude Desktop or on claude.ai: Customize → Plugins → Browse plugins, search for document-mcp, and install.

Connecting from Codex CLI

codex mcp add document-mcp -- npx -y document-mcp

Or via the Codex Desktop app: Settings → MCP Servers → + Add.

Or add to ~/.codex/config.toml manually:

[mcp_servers.document-mcp]
command = "npx"
args = ["-y", "document-mcp"]

Connecting from OpenCode

Add to opencode.json:

{
  "mcp": {
    "document-mcp": {
      "type": "local",
      "command": ["npx", "-y", "document-mcp"]
    }
  }
}

Connecting from Claude Desktop

Add to the mcpServers block in Claude Desktop's config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "document-mcp": {
      "command": "npx",
      "args": ["-y", "document-mcp"]
    }
  }
}

Or, for local development against a checkout of this repository rather than the published package, point command at the built binary directly:

{
  "mcpServers": {
    "document-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/document-mcp/dist/bin.js"]
    }
  }
}

Connecting from Claude Team/Enterprise (organization)

Organization admins can deploy MCP server configurations centrally via server-managed settings (Admin Settings → Claude Code → Managed settings in the claude.ai console). A managed-settings.json entry for document-mcp enforces the connection across all Claude Code users in the org — no per-user setup needed. Admins can also allow/block specific MCP servers via allowedMcpServers/blockedMcpServers in the same file.

Remote transport (HTTP)

Claude Web, Claude Mobile, and ChatGPT only accept remote (HTTP/SSE) MCP servers — a local stdio process is not reachable from a browser or phone. To use document-mcp on those platforms, run it behind an HTTP transport:

npx document-mcp --transport http --port 3000

Then add the server URL (e.g., https://your-host:3000/mcp) as a connector in Claude Web (claude.ai/customize/connectors) or ChatGPT (Settings → Connectors → Advanced → Enable Developer Mode → Create). Use a tunnel (Cloudflare Tunnel, ngrok) or deploy to a server with TLS — both platforms require HTTPS.

Note: the --transport http flag is not yet implemented. The server currently only supports stdio. Track this as a future capability — the MCP SDK supports SSE/streamable-http transports, so adding it is a matter of wiring the existing server to an HTTP listener.

Development

Requires Node.js >=20 and pnpm 11.6.0 (pinned via packageManager in package.json).

pnpm install
pnpm build         # turbo -> tsdown -> dist/ (ESM + CJS + .d.ts)
pnpm typecheck     # turbo -> tsc --noEmit
pnpm lint          # turbo -> eslint . --fix --cache --max-warnings 0
pnpm test          # turbo -> vitest run --project unit
pnpm test:workers  # turbo -> vitest under the real Cloudflare Workers runtime (workerd) via @cloudflare/vitest-pool-workers, driving createServer() through an in-memory JSON-RPC pair
pnpm test:smoke    # turbo -> tsdown then vitest --project smoke -- spawns dist/bin.js as a real subprocess driven over genuine MCP stdio

Related MCP server: docs-mcp

Document I/O

Every tool that takes or produces document bytes goes through the same two hybrid shapes, documented once here rather than repeated per tool below.

Input (DocumentInput) is a union: either a filesystem path (the format is inferred from the file extension — docx, pptx, xlsx, odt, odp, ods, odg, odf, md/markdown, pdf), or inline bytesBase64 plus an explicit format (required, since inline bytes carry no filename to infer one from). Each ODF/OOXML template and macro-enabled variant also reads as its base format: .ott/.ots/.otp/.otg/.otf as odt/ods/odp/odg/odf, and .dotx/.potx/.xltx (templates) or .docm/.xlsm/.pptm (macro-enabled) as their OOXML base — a template is the same package with a -template mimetype, and a macro-enabled file carries a vbaProject part this library reads past without executing or re-emitting. .odb tools are the one exception: a .odb has no single DocumentFormat of its own (it is a database front end, not a document — tables, saved queries, and reports are three unrelated output shapes), so their source.path/source.bytesBase64 bytes are read directly with no format inference at all.

Output (DocumentOutput), on every tool that produces a document, is a single optional outputPath: supply it to have the tool write the result to that filesystem path (the response then reports { path, byteLength }); omit it to receive the bytes inline instead ({ bytesBase64, byteLength }, flagged large: true above 5 MB — advisory only, the bytes are never truncated or refused).

Tools

Tool

Description

convert_document

Converts a document from one supported format to another via documents.js's DocumentConverter port — docx, pptx, xlsx, odt, odp, ods, odg, odf, markdown, and pdf. Not every (source, targetFormat) pair is direct; call list_document_conversions first.

list_document_conversions

Lists every (source, target) format pair convert_document actually supports.

metadata_read

Reads a document's title/author/subject/keywords/creator/producer/created-and-modified timestamps. Works across every supported format, including xlsx and odf.

metadata_write

Patches a document's title/author/subject/keywords in place. Does not convert format — source and target format must match (or both be pdf); odf (a standalone formula document) is rejected as either, since it has no write path back out at all.

fonts

Lists every source-embedded font face a docx/pptx/odt/odp/ods/odg document carries (family, weight/style, byte length).

describe_font_file

Reads a standalone .ttf/.otf font file and reports the family/bold/italic triple it declares about itself.

docx_extras

Reads a docx's own comments, footnotes, headers, footers, and numbering definitions — data the ContentDocument pivot cannot carry, so no other tool sees it.

pdf_inspect

Parses a PDF and reports a summary (page count, per-page size and item-kind histogram, metadata, embedded image formats), or the entire parsed LayoutDocument with full: true.

odm_to_pdf

Converts a .odm (ODF master document) to PDF. A .odm never carries its chapters' content inline, so each chapter resolves via a caller-supplied chapters href-to-document map and/or a chaptersDir searched by basename.

from_package

Rebuilds real document bytes in a target format from a DocumentPackage previously serialised to JSON (e.g. by a conversion tool's own onDocument/package-dump step).

outline_document

Projects a document's own table of contents as structured JSON: groups ({ text, level, children }) for headings, list items, slides, sheets, and draw pages, leaves ({ kind, text }) for the content between them. The outline is over the source's own content — read through documents.js's DocumentConverter port and built by document-outline.js's buildOutline.

odb_tables

Lists every table an embedded .odb database declares — column names, types, and row data — across every storage tier documents.js supports (HSQLDB TEXT/CACHED/BINARY, Firebird gbak backups).

odb_forms

Lists every form an .odb database declares, with each form's own data source and field-bound controls.

odb_reports

Lists every report an .odb database declares, with each report's own data-source command, band/group structure, and rpt: formula expressions.

odb_query

Runs a bounded single-table SELECT over an embedded .odb database's extracted tables — given directly as SQL or by naming a saved query. No database engine involved; an unsupported construct is reported as a tool error naming it, never silently ignored.

odb_to_csv

Extracts exactly one named table from an embedded .odb database as CSV bytes. The table name is required whenever the database declares more than one table.

odb_to_xlsx

Extracts every table an embedded .odb database declares into one xlsx workbook, one sheet per table.

odb_render_report

Resolves one of an .odb database's own reports — its data-bound command run through the bounded SQL engine, its rpt: formulas evaluated, its bands laid out — and renders the result to docx, odt, or pdf.

References

Gotchas

  • Runtime dependencies are documents.js + document-outline.js + @modelcontextprotocol/server + zod only; pdf-codec and odf.js are devDependencies (test-support only). document-outline.js is the one dependency beyond the server stack itself: outline_document imports buildOutline/outlineLeafText from it, and documents.js deliberately does not re-export them (the outline projection lives in the family's artefact-utilities package, which depends only on document-schema.js — already a transitive dependency via documents.js — so it adds no second copy of anything). Every runtime reach into pdf-codec/odf.js — ProvidedFont/FontSubstitution/describeFontFace/the WinAnsi substitution shape — goes through documents.js's own re-exports, so a published install pulls in no direct pdf-codec/odf.js dependency. odf.js survives in devDependencies solely because src/test-support/odm-fixture.ts and src/test-support/embedded-font-fixture.ts build real ODF package fixtures from its low-level XML primitives (zipPackage/el/rootElement), and src/test-support/ is excluded from the tsdown build — only src/index.ts and src/bin.ts are entry points — so neither fixture module ever ships in dist/.

License

MIT

Available Tools

18 tools
convert_documentConvert documentA

Converts a document from one supported format to another via documents.js's DocumentConverter port -- docx, pptx, xlsx, odt, odp, ods, odg, odf, markdown, and pdf. Not every (source, targetFormat) pair is supported directly (odf, for instance, only ever converts to pdf); call list_document_conversions first to see which pairs actually are.

Inputs: source (required), targetFormat (required), fonts, images, +2 more. Returns: output, diagnostics, targetFormat, fontSubstitutions

describe_font_fileDescribe font fileA

Reads a standalone TrueType/OpenType font file (.ttf/.otf) and reports the family/bold/italic triple it declares about itself.

Inputs: source (required).

docx_extrasDocx extrasA

Reads a docx's own comments, footnotes, headers, footers, and numbering definitions -- data documents.js's ContentDocument pivot cannot carry, so ordinary document-reading tools never see it. Returns the real DocxExtras object (comments/footnotes/headers/footers/numbering) as structured data.

Inputs: source (required).

fontsList document fontsA

Lists every source-embedded font face a docx/pptx/odt/odp/ods/odg document carries (family, weight/style, byte length).

Inputs: source (required).

from_packageBuild document from packageB

Rebuilds real document bytes in a target format from a DocumentPackage previously serialised to JSON (e.g. by a caller's own --dump-package-equivalent step) -- the read side of the DocumentPackage round trip a conversion's onDocument callback produces.

Inputs: source (required), targetFormat (required), output.

list_document_conversionsList document conversionsA

Lists every (source, target) format pair convert_document actually supports, straight from documents.js's own DocumentConverter port -- the definitive source of truth for what convert_document will and will not accept as a (source, targetFormat) combination.

Inputs: no named parameters. Returns: conversions

metadata_readRead document metadataA

Reads a document's own title/author/subject/keywords/creator/producer/created-and-modified-timestamp metadata. Works across every supported format, including xlsx (read via a throwaway xlsx-to-pdf preview, since documents.js has no dedicated xlsx metadata reader of its own) and odf (a standalone formula document).

Inputs: source (required).

metadata_writeWrite document metadataA

Patches a document's own title/author/subject/keywords, leaving every other field and every other flag as-is. Does not convert format -- the source document's own format and targetFormat must match (or both be 'pdf'); odf (a standalone formula document) is rejected outright as either a source or a target, since it has no write path back out at all. Convert the document to a different format first (e.g. with a documents.js conversion tool) if metadata needs to be set on the result of a format change.

Inputs: source (required), targetFormat (required), output, setTitle, +3 more.

odb_formsList .odb formsA

Lists every form an .odb database declares, with each form's own data source and field-bound controls.

Inputs: source (required).

odb_queryQuery an .odb databaseA

Runs a bounded single-table SELECT over an embedded .odb database's own extracted tables, given directly as SQL or by naming one of the database's saved queries. No database engine is involved -- the query runs in memory over the same tables odb_tables would return, against a closed grammar (SELECT/WHERE/GROUP BY/ORDER BY, no joins or subqueries); an unsupported construct is reported as a tool error naming it, never silently ignored.

Inputs: source (required), sql, query.

odb_render_reportRender .odb reportA

Resolves one of an .odb database's own reports -- its data-bound command run through the bounded SQL engine, its rpt: formulas evaluated, its bands laid out -- and renders the result to docx, odt, or pdf.

Inputs: source (required), targetFormat (required), fonts, output, +1 more. Returns: object

odb_reportsList .odb reportsA

Lists every report an .odb database declares, with each report's own data-source command, band/group structure, and rpt: formula expressions.

Inputs: source (required).

odb_tablesList .odb tablesA

Lists every table an embedded .odb database declares -- column names, types, and row data -- across every storage tier documents.js supports (HSQLDB TEXT/CACHED/BINARY script formats, Firebird gbak backups).

Inputs: source (required).

odb_to_csvExport one .odb table to CSVA

Extracts exactly one named table from an embedded .odb database as CSV bytes. The table name is required whenever the database declares more than one table.

Inputs: source (required), table, output.

odb_to_xlsxExport .odb tables to xlsxA

Extracts every table an embedded .odb database declares into one xlsx workbook, one sheet per table.

Inputs: source (required), output.

odm_to_pdfConvert ODM master document to PDFA

Converts a .odm (ODF master document) to PDF. A .odm never carries its own chapters' content inline -- every text:section is a bare external reference to a standalone .odt file -- so each chapter the master document declares must resolve through chapters (an explicit href -> document override) and/or chaptersDir (a directory searched by the href's own basename), checked in that order. A chapter left unresolved by both fails the whole conversion, naming every unresolved href.

Inputs: source (required), output, chapters, chaptersDir. Returns: object

outline_documentOutline documentA

Projects a document's table of contents as a structured outline: reads the source through documents.js's DocumentConverter port, takes the tree-form DocumentPackage the conversion reports, and runs document-outline.js's buildOutline over it. Groups carry { text, level, children } (a heading's, list item's, slide's, sheet's, or page's own label plus nested children); leaves carry { kind, text }. The outline is over the source's own content -- the internal conversion target preserves it and is pdf only for odf (the one format that only converts to pdf) and odg (whose alternative, svg, cannot represent more than one page).

Inputs: source (required).

pdf_inspectInspect PDFA

Parses a PDF (documents.js's readPdf) and reports a summary: page count, each page's own size and item-kind histogram, document metadata, and embedded image formats. Pass full: true to return the entire parsed LayoutDocument instead of a summary.

Inputs: source (required), full.

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 18 tools

    Disambiguation5/5

    Each tool targets a distinct resource or operation: conversion, metadata, outline, PDF inspection, fonts (embedded vs standalone), and the seven odb_* tools are separated by action (list/query/extract/render). The only close pair, fonts and describe_font_file, is disambiguated by document-embedded vs standalone file.

    Naming Consistency3/5

    Many tools follow verb_noun (convert_document, outline_document, describe_font_file) or noun_verb (metadata_read, metadata_write, pdf_inspect), but several are bare nouns (fonts, docx_extras, odb_tables, odb_forms, odb_reports) and one is a preposition phrase (from_package). The names are consistently snake_case and readable, but the verb-first convention is not applied throughout.

    Tool Count4/5

    18 tools is on the upper end of a typical server scope, but the breadth is justified by the mix of general document operations and format-specific utilities (ODB, ODM, PDF, docx extras). Each tool earns a place; the count feels slightly heavy rather than bloated.

    Completeness4/5

    The set covers conversion (with capability listing), metadata read/write, outline extraction, PDF inspection, font handling, and a full ODB sub-toolkit (tables, forms, reports, query, export, render). Notable gaps include document creation and content editing beyond metadata, and generic text extraction is only implicit through conversion to markdown.

    Maintenance

    ActivityInactive
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • F
      license
      A
      quality
      D
      maintenance
      MCP server for reading and writing .docx files. Exposes four paginated tools so agents can batch-read document content and styles, write content, and union style definitions.
      4
      -
    • F
      license
      A
      quality
      B
      maintenance
      Document-engineering MCP tool server providing tools for PDF, Office, Images, and Archives extraction and conversion. It never mutates source files and requires local tesseract for OCR.
      12
      -