Skip to main content
Glama

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.


Related MCP server: mcp-server-markdown

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

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

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)

{
  "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.replaces 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

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

Available Tools

4 tools
count_pagesA

Estimate page count for a rendered artifact.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesArtifact path
chars_per_pageNoChars per page

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must carry the behavioral burden; 'estimate' usefully connotes a non-destructive, approximate calculation rather than an exact guarantee. However, it does not disclose what happens if the artifact is not rendered, what characters-per-page default is used, or what the return value looks like.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single seven-word sentence with no filler; the core operation is front-loaded and the description is appropriately sized for a simple parameter-light tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter tool with no output schema or annotations, this is adequate but thin: it implies a page count is returned but never states the return format, default behavior when chars_per_page is omitted, or error conditions. A sentence on output and defaults would make it complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both parameters. The description does not add meaningful detail about defaults, units, or how chars_per_page affects the estimate, so it stays at the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description has a clear verb ('estimate'), a clear output object ('page count'), and a scoping phrase ('for a rendered artifact'). This is enough to differentiate count_pages from render_markdown, verify_delivery, and ship.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'rendered artifact' implies the tool should be used after rendering and before delivery, but no alternatives or exclusions are named. An agent can infer the timing from context rather than from explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_markdownA

Render a Markdown string to an HTML document.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoHTML document title
markdownYesMarkdown source

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full responsibility for behavioral disclosure. It clearly states the transformation but does not mention details such as whether raw HTML in Markdown is preserved/sanitized, how the title parameter affects output, or the exact return type. For a simple pure conversion this is acceptable but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence perfectly captures the tool's purpose with no filler. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter conversion tool with fully documented schema, the description is largely complete. It would be stronger if it clarified the return value and sanitization behavior, but nothing essential is missing for an agent to understand the basic call.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters. The description adds little semantic value beyond restating the conversion; it does not clarify how title interacts with markdown or what kind of HTML document is produced.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb and resource: 'Render a Markdown string to an HTML document.' This unambiguously identifies the input and output format and distinguishes it from the unrelated sibling tools (count_pages, verify_delivery, ship).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage context is implied: the tool is for converting Markdown to HTML. However, there is no explicit guidance about when to prefer this tool over alternatives or when not to use it, though none of the listed siblings are directly related.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

shipC

Copy a verified artifact into a public directory.

ParametersJSON Schema
NameRequiredDescriptionDefault
srcYes
dest_dirYes
overwriteNo

TDQS

C2.6/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It does not mention permissions, side effects, overwrite semantics (despite the overwrite parameter), verification mechanics, or error behavior. Minimal transparency beyond the basic action.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, direct sentence with no wasted words, and the action is front-loaded. While it is terse, that is a completeness issue rather than a conciseness problem.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 3 parameters, no annotations, and no output schema, the description is incomplete. It fails to explain overwrite behavior, the meaning of 'verified artifact', required permissions, or what the tool returns. An agent cannot reliably invoke it correctly based on this description alone.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate by explaining the parameters. It mentions 'artifact' and 'public directory' but does not map them to src/dest_dir or explain the overwrite flag. It adds essentially no value beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description states a specific verb (copy) and resource (artifact) with a destination (public directory), which clearly distinguishes it from siblings like render_markdown, count_pages, and verify_delivery. However, 'verified artifact' is vague without further explanation, so it is clear but not fully precise.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives, nor are there any conditions, prerequisites, or exclusions. The description simply states the action without contextual direction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

verify_deliveryC

Verify an artifact exists, is non-empty, and is within size bounds.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
max_bytesNo
min_bytesNo

TDQS

C2.9/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It reveals what checks are performed, but does not disclose what happens on success or failure — whether it returns a boolean, throws an error, or exits with a non-zero code. This is critical for a verification tool and is left entirely unspecified.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with zero filler. It is efficiently structured and each clause corresponds to a parameter or core behavior. Slightly more structure could have accommodated usage guidance, but as written it is appropriately tight.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema and no annotations, the description is under-specified. Missing: what the tool returns, how failure is signaled, whether the operation is read-only, and how min_bytes/max_bytes behave when omitted. An agent cannot fully predict invocation consequences from this definition.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does connect 'within size bounds' to the min_bytes/max_bytes parameters and 'exists' to path, adding meaning the bare schema lacks. However, it does not clarify whether the bounds are inclusive, what happens when only one bound is supplied, or what kind of path is expected.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Verify') and resource ('artifact') and enumerates precise conditions: existence, non-emptiness, and size bounds. It is clearly distinct from siblings like ship, render_markdown, and count_pages, though it does not explicitly name them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is given about when to invoke this tool versus alternatives. The siblings are obviously different operations, so context is weakly implied rather than stated, but there is no mention of prerequisites, appropriate calling context, or when NOT to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

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

  1. 4 tool updatesv0.1.0
    • First observedcount_pages
    • First observedrender_markdown
    • First observedship
    • First observedverify_delivery

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

Related MCP Connectors

Related MCP Servers