printbridge
printbridge
Let an AI assistant print on your own printer. You paste one link into Claude, ChatGPT or any other MCP client, then type "print this on my printer" — and the page comes out at home. No print cloud, no third party ever sees the document, no ports opened on your home router.
New here and not a developer? Start with docs/SETUP.md — a seven-station guide, from a printer without a fixed address to a printed test page. Everything below is the technical layer underneath it.
MIT licensed · self-hosted · Python + FastMCP + CUPS.
What it is
printbridge is an MCP server. Assistants call its tools (print_text, print_url, print_file,
list_printers, get_job, cancel_job, printer_status, recent_jobs); the server renders the
document to PDF and hands it to a CUPS queue that reaches your printer over a private route —
Tailscale by default, but any route works.
┌───────────────────────── Internet ─────────────────────────┐
│ Claude.ai ChatGPT Grok Claude Desktop Claude Code │
│ └──────────┴────────┴──────────┴──────────────┘ │
│ remote MCP (Streamable HTTP on a per-person key) │
└───────────────────────────────┬────────────────────────────┘
▼ HTTPS (Caddy, Funnel or Cloudflare Tunnel)
┌──────────────────── Server (tailnet node) ──────────────────┐
│ printbridge 127.0.0.1:8000 — never public │
│ ├─ MCP server (FastMCP) ← local agents: bearer │
│ ├─ Renderer markdown/html/text → PDF (WeasyPrint) │
│ ├─ Auth per-person connector keys → Principal │
│ ├─ Job log SQLite: metadata only, never content │
│ └─ Spooler CUPS (driverless IPP Everywhere queue) │
│ │ ipp://PRINTER_IP:631 │
└─────────────────────┼───────────────────────────────────────┘
│ private route (Tailscale subnet router, WireGuard, or same LAN)
┌─────────────────────▼──── Home network ─────────────────────┐
│ Subnet router: UDM Pro | Raspberry Pi | any Linux box │
│ │ │
│ Printer (any IPP Everywhere / AirPrint printer) │
└─────────────────────────────────────────────────────────────┘The server is the only thing with a public surface, and that surface is one authenticated MCP endpoint. The printer only ever sees traffic from your own private network.
Quickstart (10 minutes, for people who know a terminal)
git clone https://github.com/starkshtlm/printbridge && cd printbridge
cp .env.example .env && $EDITOR .env # PRINTERS, PUBLIC_URL, EXPOSE
docker compose up -d
docker compose exec printbridge printbridge init # wizard: printer → exposure → first key
docker compose exec printbridge printbridge doctor # green table + your connector URLOr let the installer do all of it:
curl -fsSL https://raw.githubusercontent.com/starkshtlm/printbridge/main/install.sh | bashThen paste the connector URL from doctor into your assistant
(see docs/clients.md) and say "print a test page on my printer".
One key per person, not per assistant
printbridge keys add daniel --role admin
printbridge keys add fanny --printers home --max-pages 20
printbridge keys listEach person gets one link, https://print.example.com/mcp/<key>, and pastes the same link into
every assistant they use. Which assistant they used is detected automatically from the MCP
handshake, so printbridge status can say "fanny via chatgpt, 2 jobs today" without anybody
configuring anything. Revoking one person leaves everyone else alone.
What it will not do
It will not print more than
MAX_PAGES(default 100), and aboveCONFIRM_ABOVE_PAGES(default 10) it refuses until the assistant passesconfirmed=true. An injected "print 500 pages" fails safely.print_urlwill not fetch from your LAN, your tailnet or localhost unless you setALLOW_PRIVATE_URLS=true. Every redirect hop is re-checked.It never stores what you printed — only that you printed: title, pages, printer, person, assistant, status. The spool file is deleted when the job leaves the queue.
It never binds a public interface.
127.0.0.1:8000for MCP,127.0.0.1:8001for admin and metrics; a reverse proxy is the only public face.
Documentation
Document | For |
Non-technical, start to finish, seven stations | |
Claude.ai, ChatGPT, Grok, Claude Desktop/Code, agents, stdio | |
Threat model; what a connector key does and does not protect | |
update, backup, watchdog, alerts, | |
VPS+Tailscale, home box, WireGuard/Headscale, local only | |
One entry per | |
UDM Pro, Raspberry Pi, generic Linux | |
Optional: print PDFs sent to a mailbox |
Status
v0.9.0 — feature complete for v1.0, pending live verification with a physical printer and the three chat assistants. Grok is untested; the README will not claim it until it passes.
Licence
MIT — see LICENSE.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/starkshtlm/printbridge'
If you have feedback or need assistance with the MCP directory API, please join our Discord server