# mcp-pos-print MCP server that prints markdown to the Epson TM-m30 receipt printer at `192.168.0.184:9100`. Mirrors the [`mcp-gemma4`](../mcp-gemma4/) layout. See `~/bin/POS_PRINT.md` for the printer reference (Font B columns, native QR, troubleshooting) and `DECISIONS.md` for design rationale. ## Tool `print(markdown, title?, timestamp?, qr_urls?, cut?)` - **`markdown`** *(required)* — body to print. Supports `# / ## / ###` headings, `**bold**` and `` `code` `` inline, fenced ```` ``` ```` code blocks (no wrap), `---` / `***` horizontal rules, `-` / `*` / `1.` lists, `> blockquotes`, `[text](url)` links, blank lines. Long lines word-wrap at 57 cols. - **`title`** — bold centered header above the body. - **`timestamp`** — bool, default `true`. Prints `Mon, May 25 14:32 ET` under title. - **`qr_urls`** — list of URLs printed as native hardware QR codes at the end. - **`cut`** — bool, default `true`. Auto-cut paper. Returns `Printed N bytes to 192.168.0.184:9100.` on success, or a clear error string if the printer is unreachable. ## Install ```bash cd ~/bin/mcp-pos-print python3 -m venv .venv .venv/bin/pip install -e . ``` Register in `~/.claude.json` (global scope): ```json { "mcpServers": { "pos-print": { "command": "/home/claude/bin/mcp-pos-print/.venv/bin/python", "args": ["/home/claude/bin/mcp-pos-print/server.py"] } } } ``` Restart Claude Code or run `/mcp` to reconnect. ## Test ```bash .venv/bin/python test_server.py ``` Prints a self-test page covering headings, inline formatting, lists, code blocks, blockquotes, horizontal rules, and a QR code. Requires the printer reachable at `192.168.0.184:9100`. ## Config - `POS_PRINTER_IP` — default `192.168.0.184` - `POS_PRINTER_PORT` — default `9100` - `POS_PRINTER_TIMEOUT` — TCP timeout in seconds, default `10` ## Markdown subset Hand-rolled line-by-line parser, no markdown-it-py dependency. Supported: | Markdown | Output | |---|---| | `# Heading` | bold + 2x size, centered | | `## Heading` / `### Heading` | bold, left | | `**bold**` inline | bold run | | `` `code` `` inline | passed through (already monospace) | | ```` ```fenced``` ```` | preserved verbatim, no wrap; `»` marks chars truncated past col 57 | | `---` / `***` / `___` | thin separator across full width | | `- item` / `* item` | `* item`, hanging-indented continuation | | `1. item` | `1. item`, hanging-indented continuation | | `> quote` | `\| ` prefix | | `[text](url)` | `text (url)` | | blank line | blank line | | anything else | word-wrapped at 57 cols | Not supported (by design): images, tables, nested lists, footnotes, HTML. Use `qr_urls` for QR codes — there's no QR markdown syntax. ## Troubleshooting - **`cannot reach printer`** — power, network, paper, or ARP issue. `ping 192.168.0.184` first. - **`timed out`** — same. The TM-m30's WiFi sometimes drops ARP entries; a ping usually re-resolves. - **Garbled output** — most likely you mixed an external script that uses Font A; this server hard-codes Font B (57 cols). If you're seeing it from `print`, file a bug. - **No paper feed at end** — make sure `cut` isn't explicitly `false`.