deliverable-mcp
by Diski7
README.md
# deliverable-mcp
A **zero-dependency MCP server** that exposes a document delivery pipeline — render, page-count, verify, ship — as tools any MCP client can call.
Built because shipping a document reliably is the part people get wrong: the file renders, but it's empty, or it's the wrong page count, or it overwrote the wrong path. This server makes those failures impossible to ignore.
> Speaks **Model Context Protocol** (JSON-RPC 2.0 over stdio) directly. No SDK, no framework, nothing to install but Python.
---
## Why this exists
I run a content pipeline that produces resumes, reports, and decks. Every failure mode I hit was a *delivery* failure, not a *generation* failure:
| Failure | What it looked like |
|---|---|
| Empty artifact shipped | `pdftoppm` produced 0 pages, link still went out |
| Wrong page count | 2-page resume rendered as 4 pages, unnoticed |
| Silent overwrite | New build clobbered the previous approved version |
| Wrong destination | File written to a path no one serves |
Each of those is now a **gate** in the pipeline. The MCP server is how any agent — Claude Desktop, Cursor, a fleet of my own agents — calls those gates without reimplementing them.
---
## Tools
| Tool | Purpose | Returns |
|---|---|---|
| `render_markdown` | Markdown → HTML | HTML document |
| `count_pages` | Estimate rendered page count | `{pages_estimate, bytes, basis}` |
| `verify_delivery` | Assert exists, non-empty, within size bounds | `{verified: true, bytes}` |
| `ship` | Atomically copy into a public directory | `{shipped, bytes}` |
---
## Run it
```bash
python -m deliverable_mcp
```
It reads newline-delimited JSON-RPC on stdin and writes responses on stdout — the standard MCP stdio transport.
### Manual smoke test
```bash
printf '%s\n' \
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \
'{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
'{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"render_markdown","arguments":{"markdown":"# Hello"}}}' \
| python -m deliverable_mcp
```
### Client configuration (e.g. Claude Desktop)
```json
{
"mcpServers": {
"deliverable": {
"command": "python",
"args": ["-m", "deliverable_mcp"],
"cwd": "/path/to/deliverable-mcp"
}
}
}
```
---
## Protocol coverage
| Method | Implemented |
|---|---|
| `initialize` | ✅ handshake + capabilities |
| `tools/list` | ✅ |
| `tools/call` | ✅ |
| `ping` | ✅ |
| `notifications/*` | ✅ accepted, no response (per spec) |
| unknown method | ✅ `-32601` |
| malformed JSON | ✅ `-32700` |
| bad tool input | ✅ `-32602` |
Errors are returned as proper JSON-RPC error objects — the server never crashes on bad input.
---
## Design decisions
**No SDK on purpose.** The official `mcp` package is convenient, but the wire protocol is small and worth owning. Implementing it directly means the server runs anywhere Python runs, with zero install friction, and the whole thing is auditable in one sitting. That auditability is the point for a tool that gates what gets shipped.
**Escape-then-format rendering.** `render_markdown` escapes HTML *before* applying inline formatting, so `<script>` in input becomes text, never markup. Injection-safe by construction rather than by blocklist.
**Atomic ship.** `ship` writes to a `.tmp` file and `os.replace`s it into place, and refuses to overwrite unless explicitly told to. A partially-written artifact never becomes the live one.
**Gates as tools.** Verification isn't a side effect tucked inside a render function — it's a separately callable tool. That means a client can verify *anything*, including artifacts it didn't produce.
---
## Tests
```bash
pip install pytest
pytest
```
**16 tests** covering the full protocol surface (initialize, list, call, notifications, unknown methods, parse errors) and every tool including the failure paths: HTML escaping, page estimation, empty/oversized rejection, overwrite protection, and stdio transport with real JSON-RPC lines.
No network. No API keys. No SDK. Pure stdlib + pytest.
---
## Layout
```
deliverable_mcp/
├── __init__.py public exports
├── __main__.py python -m deliverable_mcp
├── server.py JSON-RPC transport + method dispatch
└── tools.py the four tool implementations + MCP schemas
tests/
└── test_server.py protocol and tool tests
```
---
## License
MIT
TDQS
B3.4/5.0
Scored across 4 tools
Disambiguation5/5
Each tool performs a distinct, non-overlapping operation: rendering, counting, verifying, and shipping. There is no ambiguity about which tool to choose for a given step in the workflow.
Naming Consistency4/5
Three tools follow the verb_noun pattern (render_markdown, count_pages, verify_delivery), but 'ship' breaks the pattern with a bare verb. Still, the names are clear and predictable overall.
Tool Count5/5
Four tools cover a focused deliverable pipeline without redundancy or excess. The count is well-suited to the server's narrow purpose.
Completeness4/5
The suite covers the core lifecycle from rendering to shipping, but lacks features like listing or retrieving existing deliverables. This is a minor gap that agents can work around.
Maintenance
ActivityMaintained
ResponsivenessNo issues