document-mcp
document-mcp
This repository has moved.
document-mcpnow lives atpackages/document-mcpin theExaDev/documents.jsmonorepo. 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-mcpkeeps publishing from its new home under the same name.
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 againstdocuments.jsdirectly.
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:3pxGetting started
Run the server directly — no install step needed:
npx document-mcpThe 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-mcpOr 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@exadevOr from within a running Claude Code session:
/plugin marketplace add ExaDev/document-mcp
/plugin install document-mcp@exadevRun /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-mcpOr 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 3000Then 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 httpflag 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 stdioDocument 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 |
| Converts a document from one supported format to another via |
| Lists every |
| Reads a document's title/author/subject/keywords/creator/producer/created-and-modified timestamps. Works across every supported format, including xlsx and odf. |
| Patches a document's title/author/subject/keywords in place. Does not convert format — source and target format must match (or both be |
| Lists every source-embedded font face a docx/pptx/odt/odp/ods/odg document carries (family, weight/style, byte length). |
| Reads a standalone |
| Reads a docx's own comments, footnotes, headers, footers, and numbering definitions — data the |
| Parses a PDF and reports a summary (page count, per-page size and item-kind histogram, metadata, embedded image formats), or the entire parsed |
| Converts a |
| Rebuilds real document bytes in a target format from a |
| Projects a document's own table of contents as structured JSON: groups ( |
| Lists every table an embedded |
| Lists every form an |
| Lists every report an |
| Runs a bounded single-table |
| Extracts exactly one named table from an embedded |
| Extracts every table an embedded |
| Resolves one of an |
References
documents.js — the library this server exposes.
document-outline.js — the artefact-utilities package over document-schema.js's tree-form
DocumentPackagewhosebuildOutlinepowersoutline_document.document-cli — the sibling CLI/TUI over the same library, whose toolchain this repository's scaffold mirrors.
Model Context Protocol — the protocol this server implements, via
@modelcontextprotocol/server.
Gotchas
Runtime dependencies are
documents.js+document-outline.js+@modelcontextprotocol/server+zodonly;pdf-codecandodf.jsare devDependencies (test-support only).document-outline.jsis the one dependency beyond the server stack itself:outline_documentimportsbuildOutline/outlineLeafTextfrom it, and documents.js deliberately does not re-export them (the outline projection lives in the family's artefact-utilities package, which depends only ondocument-schema.js— already a transitive dependency via documents.js — so it adds no second copy of anything). Every runtime reach intopdf-codec/odf.js—ProvidedFont/FontSubstitution/describeFontFace/theWinAnsisubstitution shape — goes throughdocuments.js's own re-exports, so a published install pulls in no directpdf-codec/odf.jsdependency.odf.jssurvives indevDependenciessolely becausesrc/test-support/odm-fixture.tsandsrc/test-support/embedded-font-fixture.tsbuild real ODF package fixtures from its low-level XML primitives (zipPackage/el/rootElement), andsrc/test-support/is excluded from thetsdownbuild — onlysrc/index.tsandsrc/bin.tsare entry points — so neither fixture module ever ships indist/.
License
MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ExaDev/document-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server