421c3c9660
Single tool `print(markdown, title?, timestamp?, qr_urls?, cut?)`. Hand-rolled line-by-line markdown parser translates headings/bold/code/lists/blockquotes/ HR/links to ESC/POS, then sends raw bytes via TCP to 192.168.0.184:9100. Mirrors mcp-gemma4 layout (stdio server, single server.py, mcp package).
83 lines
3.1 KiB
Markdown
83 lines
3.1 KiB
Markdown
# 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`.
|