Give your AI agent a printer.

shortorder is a tiny Go binary that turns a USB thermal printer into an HTTP + MCP service. Agents discover it, scripts hit it — and it cooks up text, receipts, QR codes, barcodes and SVG. No drivers. No cloud. No spooler.

Get cooking
$ curl -X POST localhost/api/print/text
EPSON TM-T20II USB · connected

The printer your agent can actually use.

One tiny binary. An HTTP API and an MCP server over a USB thermal printer — so anything that speaks HTTP, and any MCP-aware LLM, can print a receipt on demand.

SHORT ORDER
est. 2026 · serving agents & scripts

ORDER #0042 ........ TABLE: localhost
SERVER: claude ...... 09 JUN 2026

print_text0.4ms
print_document1.1ms
print_qr0.9ms
cut0.1ms

NO DRIVERS$0.00
NO CLOUD$0.00

QR code linking to shortorder on GitHub
github.com/aphexddb/shortorder
*** THANK YOU — COME AGAIN ***

Agents discover it. Then they print.

shortorder ships an MCP server, an OpenAPI spec, and mDNS advertising — so an LLM can find your thermal printer on the LAN and use it as a tool, no integration code required.

USER → AGENT
Print a kitchen ticket for order #42: 2 coffee, 1 muffin.
mcp · print_document
elements: [ header, table, total ]
cut: true
ORDER #42

Coffee$6.00
Muffin$3.25

TOTAL$9.25

For AI agents 🤖

Three ways an agent finds the printer.

This is the part that makes it AI-enabled. Point an agent at the box and it discovers the print tools on its own — no integration to write.

MCP server

Exposes the printer as Model Context Protocol tools. MCP-aware agents get the schemas automatically — over stdio (subprocess) or HTTP streamable transport.

OpenAPI 3.1

A descriptor at /openapi.json (and /.well-known/) for function-calling agents and tool loaders that import an OpenAPI spec.

mDNS discovery

Advertises _shortorder._tcp on the LAN with TXT records, so an agent can find the box without ever being told its IP.

// claude_desktop_config.json — or any MCP client
{
  "mcpServers": {
    "shortorder": {
      "command": "shortorder",
      "args": ["mcp"]
    }
  }
}
# HTTP streamable transport — live whenever the service runs
POST http://localhost/mcp

# tools advertised to the agent:
list_printers   print_text     print_document
print_qr        print_barcode  print_svg
print_image     cut
# OpenAPI 3.1 descriptor for function-calling agents
GET http://localhost/openapi.json
GET http://localhost/.well-known/openapi.json
# the service advertises itself on the local network
$ dns-sd -B _shortorder._tcp
$ avahi-browse _shortorder._tcp

# TXT records: version · path · api · mcp · openapi

Reach for print_document to lay out a whole receipt — header, itemized table, totals, a code, footer — in one job using the printer's crisp native text. print_svg is the escape hatch for anything the character grid can't express.

list_printers print_text print_document print_qr print_barcode print_svg print_image cut

Try it

Or just POST it. Any language, any shell.

Once it's running, print from anything that speaks HTTP. Copy a line, point it at your box, watch it cut.

# Plain text, centered and bold, then cut
curl -X POST http://localhost/api/print/text \
  -H 'Content-Type: application/json' \
  -d '{"text":"ORDER #42","align":"center","bold":true,"cut":true}'
# A whole receipt in one job: header, table, total, cut
curl -X POST http://localhost/api/print/document \
  -H 'Content-Type: application/json' \
  -d '{
    "elements": [
      {"type":"text","text":"SHORT ORDER","align":"center","bold":true},
      {"type":"rule"},
      {"type":"table",
       "columns":[{"width":3},{"width":0},{"width":8,"align":"right"}],
       "rows":[["2","Coffee","$6.00"],["1","Muffin","$3.25"]]},
      {"type":"rule","char":"="},
      {"type":"row","left":"TOTAL","right":"$9.25","bold":true}
    ],
    "cut": true
  }'
# A QR code with a caption
curl -X POST http://localhost/api/print/qr \
  -H 'Content-Type: application/json' \
  -d '{"data":"https://example.com","caption":"scan me"}'
# A CODE128 barcode with the value printed beneath
curl -X POST http://localhost/api/print/barcode \
  -H 'Content-Type: application/json' \
  -d '{"data":"SHORTORDER42","format":"code128","caption":"SHORTORDER42"}'
# Arbitrary layout via SVG — logos, shapes, free positioning
curl -X POST http://localhost/api/print/svg \
  -H 'Content-Type: application/json' \
  -d '{"svg":"<svg xmlns=... width=384 height=80>...</svg>"}'
# Built-in samples — no body required
curl -X POST http://localhost/api/print/sample/receipt
curl -X POST http://localhost/api/print/sample/svg

# Any PNG/JPEG/GIF, scaled to fit and dithered
curl -X POST 'http://localhost/api/print/image?align=center' \
  --data-binary @logo.png -H 'Content-Type: application/octet-stream'
what comes out
ORDER #42

Coffee$6.00
Muffin$3.25

TOTAL$9.25
SHORTORDER42

How it works

Straight to the USB endpoint. No driver to install.

Receipt printers speak ESC/POS — a byte stream of text plus control sequences. shortorder renders each request to ESC/POS and writes it directly to the printer's USB device. No spooler, no print queue, no driver.

01

Request

An HTTP / MCP call arrives — text, document, QR, barcode, image or SVG.

02

Render

Composed to the printer's native font grid, or rasterized to a 1-bit bitmap.

03

ESC/POS

Emitted as a single byte stream with formatting, raster and cutter commands.

04

Print

Written straight to the USB device node — then the receipt is cut.

Native text grid crisp · small

  • Text and full layouts via /api/print/document — rows, tables and rules over a fixed character grid.
  • Composed in code from the printer's native font, so it prints sharp and tiny.

1-bit raster universal

  • QR, barcodes, images and /api/print/svg rendered to a 1-bit raster (Floyd–Steinberg dithered).
  • SVG drawn by a pure-Go engine with fonts bundled in the binary — identical on every host, no system fonts needed.

Windows

Finds the printer via the USB printer device interface (GUID_DEVINTERFACE_USBPRINT) and writes with CreateFile / WriteFile.

Linux & Raspberry Pi

Finds the printer in sysfs, matches USB VID/PID against the allowlist, and writes to its usblp node (/dev/usb/lp0).


Supported hardware

Most cheap USB receipt printers just work.

It's a REST and MCP interface to an ESC/POS USB printer. If yours is Epson-compatible, you're already most of the way there.

PrinterInterfaceStatus
Volcora v-WRP2-A1W USB · ESC/POS Supported
Epson TM-series & compatible clones USB · ESC/POS Works · same USB identity

Most inexpensive 80mm and 58mm USB receipt printers are ESC/POS and Epson-compatible. Adding one is a one-line allowlist change — put a Model (USB vendor/product ID and/or a name substring) in internal/printer/printer.go. The print path is already shared across models.


Install

One binary. No dependencies. Pick your platform.

Prebuilt binaries and packages ship for every release. The commands below use the GitHub CLI (gh) to resolve the latest version for you.

# Debian, Ubuntu, Raspberry Pi OS — installs a boot service
gh release download -R aphexddb/shortorder -p '*_linux_arm64.deb'
sudo dpkg -i shortorder_*_linux_arm64.deb

# serves the UI + API on port 80, reachable at shortorder.local
gh release download -R aphexddb/shortorder -p '*_linux_amd64.tar.gz'
tar -xzf shortorder_*_linux_amd64.tar.gz
./shortorder

# on macOS, use the darwin_arm64 (Apple Silicon) or darwin_amd64 build

Download shortorder_<version>_windows_amd64.zip from Releases, unzip it, then run:

shortorder.exe

# listens on http://localhost:8080/
# requires Go 1.26 or newer
make build       # single static binary into ./bin
./bin/shortorder -list   # see what's detected
./bin/shortorder         # run the service

Then open the web UI — it lists connected devices, runs test prints, and documents the full API. localhost on Linux/macOS, localhost:8080 on Windows.


Open source

Contributions & new printer models welcome.

shortorder is Apache-2.0 and built in the open. Adding support for your printer is usually a one-line allowlist change — and the print path is already shared. Bring a model, a bug, or an idea.

1
static Go binary
0
drivers required
3
platforms · Win/Linux/Pi
8
MCP tools out of the box