An MCP server that edits Office documents and refuses to write one where an edit went unrecorded.
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Documented (README)
claude mcp add mcp-ooxml-ledger -- uvx mcp-ooxml-ledger{
"mcpServers": {
"mcp-ooxml-ledger": {
"command": "uvx",
"args": ["mcp-ooxml-ledger"]
}
}
}MCP Servers overview
# mcp-ooxml-ledger
<!-- The MCP registry proves package ownership by fetching this README (served via PyPI,
per pyproject.toml's `readme = "README.md"`) and grepping for the marker below.
Do not delete it as "stray" — removing it fails registry publication validation. -->
<!-- mcp-name: io.github.Anselmoo/mcp-ooxml-ledger -->
[](https://github.com/Anselmoo/mcp-ooxml-ledger/actions/workflows/cicd.yml)
[](https://codecov.io/gh/Anselmoo/mcp-ooxml-ledger)
[](https://pypi.org/project/mcp-ooxml-ledger/)
[](https://test.pypi.org/project/mcp-ooxml-ledger/)
[](https://pypi.org/project/mcp-ooxml-ledger/)
[](LICENSE)
[](https://modelcontextprotocol.io)
**An MCP server that edits Office documents and refuses to write one where an edit went unrecorded.**
Before sealing a session it replays every recorded operation against the document's baseline
and compares the result to what is actually on disk. A change no operation explains means the
commit is **refused**. Of ~18 competing MCP document-editing projects, none gates the write on
that check. The refusal is the product.
## Setup
```bash
uv add mcp-ooxml-ledger
```
Add to `.mcp.json` (project) or `claude_desktop_config.json` (desktop — use an absolute path,
`${CLAUDE_PROJECT_DIR}` isn't expanded there):
```json
{
"mcpServers": {
"ooxml-ledger": {
"command": "uv",
"args": ["run", "--project", "${CLAUDE_PROJECT_DIR}", "ooxml-ledger-mcp"],
"env": { "OOXML_LEDGER_ROOTS": "${CLAUDE_PROJECT_DIR}" }
}
}
}
```
Needs `uv` on `PATH`; nothing else installed globally. Invoking the `ooxml-ledger-mcp` script
directly gives `ENOENT` — it lives in the project venv, not your shell's `PATH`.
> **`OOXML_LEDGER_ROOTS` is the security boundary.** An `os.pathsep`-separated list; every
> path any tool receives is resolved inside it and refused outside. Unset, it defaults to the
> server's working directory — set it deliberately, since `export_receipt` writes anywhere
> inside a root.
## Tools
| | Tool | |
|---|---|---|
| **session** | `open_document` · `close_document` | writes |
| **read** | `describe_structure` · `find_text` | read-only |
| **edit** | `preview_edits` · `apply_edits` · `delete_paragraph` · `insert_paragraph` | writes |
| **seal** | `commit_document` | writes · enforces the gate |
| **stateless** | `server_info` · `digest` · `verify` · `list_receipts` | read-only |
| | `export_receipt` | writes |
Typical loop:
```
open_document → find_text → preview_edits → apply_edits → commit_document → verify
```
```python
sid = open_document(document="report.docx")["session_id"]
find_text(sid, query="Q3 revenue") # → part, para_id, para_hash
preview_edits(sid, edits=[...], author="alice") # → what WOULD happen; writes nothing
apply_edits(sid, edits=[...], author="alice", mode="tracked")
commit_document(sid) # → refuses if anything is unaccounted for
verify("report.docx") # → verified | unknown | failed
```
`preview_edits` runs the **same engine function** as `apply_edits` against a throwaway copy, so
the two cannot disagree. Batches are all-or-nothing: a failing edit leaves the document
byte-identical.
`mode="tracked"` emits Word revision marks a reviewer sees in the document. `mode="direct"`
rewrites the text with none — still fully recorded, and the receipt discloses that a direct
edit touched a revision-capable part, so it is never silently indistinguishable from an
ordinary save.
## Format matrix
| Format | Verify | Edit |
|---|---|---|
| Word `.docx` | Yes | Yes — tracked + direct, paragraph insert/delete |
| PowerPoint `.pptx` | Yes | Direct only — PresentationML has **no revision model**, so every edit carries a mandatory disclosure |
| Excel `.xlsx` | Yes | **No** — editing verbs refuse, naming the format |
Verification, digests, the gate and the receipt model are format-agnostic. Only the *editing*
engines are format-specific: `wml.py` (Word) and `pml.py` (PowerPoint).
## Read-only deployment
`OOXML_LEDGER_READ_ONLY=1` leaves exactly `server_info`, `digest`, `verify`, `list_receipts`.
The others aren't merely hidden — calling one answers `Unknown tool`. No write surface inside
the roots at all.
## CLI
```bash
ooxml-ledger verify report.docx # exit 0 only when verified
```
No server, no session — digests the file, finds its receipt by content address, checks it.
Wire it into CI or a pre-commit hook and an unaccounted-for change fails the build.
## Desktop bundle (.mcpb)
Every GitHub Release attaches a `.mcpb` file — a one-click Claude Desktop install: drag it onto
the app and Desktop launches it with
`uv run --directory <bundle> --frozen --no-dev ooxml-ledger-mcp`.
Nothing is vendored — the bundle carries only `manifest.json`, `pyproject.toml`, `uv.lock`,
`README.md`, `LICENSE` and `src/`. **The host needs `uv` on `PATH`**, and the first launch
resolves the exact dependency versions `uv.lock` pins from PyPI, which needs network access;
`--frozen` means it installs precisely the versions the test suite ran against, never a fresh
resolve, and `--no-dev` keeps the dev group (pytest, ruff, pre-commit) out of the install. `mcpb/manifest.json` exposes the document root and read-only toggle as install-time
settings instead of environment variables; the tool list matches the stdio server's.
CI builds and smoke-tests the bundle on `macos-latest` only, and the manifest's
`compatibility.platforms` declares `darwin` only — **the bundle is built and proven on
macOS/arm64, nothing else.** Because nothing is vendored, `uv` itself picks a Python
satisfying `requires-python = ">=3.13"` and installs the wheels `uv.lock` pins for the host's
own platform — native ones such as pydantic-core and cryptography included. That part is not
darwin-specific, but only the darwin launch path has actually been proven end-to-end here.
## Honest limits
- **An unsigned receipt is accident-evident, not tamper-evident.** It catches an agent falling
back to a generic file write, an Office round-trip, a careless collaborator — not someone who
rewrites the receipt alongside the document. Anchoring its hash somewhere the holder doesn't
control (a git commit, a DOI, a submission portal) is what buys tamper-evidence.
- **`verify` never replays.** It checks the digest and the receipt's internal consistency; the
replay runs once, at commit, and `verify` reports that verdict rather than recomputing it.
- **pptx and xlsx have no human-visible record.** Word tracked changes are a second recording
layer inside the document; those two formats have none, so the ledger is the only record.
- **The Word engine reaches paragraph text only** (`w:p`/`w:r`/`w:t`). Styles, numbering,
settings and relationships are uneditable and covered by the accountability check alone.
## Contributing and security
[CONTRIBUTING.md](CONTRIBUTING.md) covers setup, the branch and commit naming CI
enforces, and the release flow. [SECURITY.md](SECURITY.md) covers private vulnerability
reporting, and is explicit about which of this project's documented limits are design
rather than defects.
MIT licensed. Design notes and specifications live in [`docs/superpowers/`](docs/superpowers/).
What people ask about mcp-ooxml-ledger
What is Anselmoo/mcp-ooxml-ledger?
+
Anselmoo/mcp-ooxml-ledger is mcp servers for the Claude AI ecosystem. An MCP server that edits Office documents and refuses to write one where an edit went unrecorded. It has 0 GitHub stars and its last recorded update is dated 2026-09-13.
How do I install mcp-ooxml-ledger?
+
You can install mcp-ooxml-ledger by cloning the repository (https://github.com/Anselmoo/mcp-ooxml-ledger) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.
Is Anselmoo/mcp-ooxml-ledger safe to use?
+
Our security agent has analyzed Anselmoo/mcp-ooxml-ledger and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.
Who maintains Anselmoo/mcp-ooxml-ledger?
+
Anselmoo/mcp-ooxml-ledger is maintained by Anselmoo. The last recorded GitHub activity is dated 2026-09-13, with 1 open issues.
Are there alternatives to mcp-ooxml-ledger?
+
Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.
Deploy mcp-ooxml-ledger to your cloud
Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.
Maintain this repo? Add a badge to your README
Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.
[](https://claudewave.com/repo/anselmoo-mcp-ooxml-ledger)<a href="https://claudewave.com/repo/anselmoo-mcp-ooxml-ledger"><img src="https://claudewave.com/api/badge/anselmoo-mcp-ooxml-ledger" alt="Featured on ClaudeWave: Anselmoo/mcp-ooxml-ledger" width="320" height="64" /></a>More MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl!
The fastest path to AI-powered full stack observability, even for lean teams.