Skip to main content
Glama
permitzip

labelprint

by permitzip

labelprint

Local MCP server and CLI that print PNG labels to a nearby thermal label printer.

It runs on the machine that can see the printer. It does not call manufacturer cloud APIs, does not scrape template catalogs, and is not named after any printer brand.

PNG or title/body/QR  →  1-bit bitmap  →  local serial / RFCOMM  →  paper

Install

pip install git+https://github.com/permitzip/labelprint-mcp

Optional QR rendering:

pip install "labelprint[qr] @ git+https://github.com/permitzip/labelprint-mcp"

On macOS, Bluetooth printing needs Xcode Command Line Tools so the small IOBluetooth helper can compile on first use (swiftc).

Related MCP server: print-blocks

Configure

Copy examples/config.toml to ~/.config/labelprint/config.toml (or ./labelprint.toml).

[printer]
transport = "auto"
address = "AA:BB:CC:DD:EE:FF"
density = 4
max_width_px = 384

[media]
width_mm = 50
height_mm = 30
dpi = 203

Environment variables use the LABELPRINT_ prefix (LABELPRINT_ADDRESS, LABELPRINT_WIDTH_MM, …).

Roll size is local. The printer can report a chip barcode; this tool will not look that code up on the internet. Put width_mm / height_mm in config, pass --width-mm / --height-mm, or add a [[media.barcode]] row that you measured yourself.

CLI

labelprint doctor
labelprint ports
labelprint status
labelprint render --title "BOARDS" --body "Is this a controller?" --out preview.png
labelprint print --image preview.png --yes
labelprint print --title "ITEM" --qr "https://example.com/i/123" --yes
labelprint mcp

print refuses to run without --yes. That flag consumes labels.

MCP

The server is stdio-only. Point Cursor or Claude Desktop at the machine with the printer:

{
  "mcpServers": {
    "labelprint": {
      "command": "labelprint-mcp"
    }
  }
}

A full example is in examples/mcp.json.

Tool

What it does

labelprint_doctor

Config and transport check (no print)

labelprint_list_ports

Serial nodes on this machine

labelprint_status

Identity, power, on-device chip fields

labelprint_render

Preview PNG

labelprint_print

Print. Requires confirm: true.

A hosted agent (ChatGPT, a cloud Hours worker, Docker on a laptop) cannot open this printer. Run this MCP locally, or later on a Pi that sits next to the printer.

Transports

Name

When

rfcomm

macOS Bluetooth via IOBluetooth RFCOMM channel 1

bluetooth

Linux AF_BLUETOOTH RFCOMM

serial

USB or a working /dev/cu.* / COM port

auto

macOS + address → rfcomm; Linux + address → bluetooth; otherwise serial

On some Macs the Bluetooth serial node opens and then never exchanges protocol bytes after reconnect. Prefer rfcomm there.

Compatible hardware

The first adapter is protocol3: 203 dpi, ~384 px printhead, firmware that needs a 7-byte print-start and a 6-byte page-size. That matches several common Bluetooth label printers (device type 4096 is one of them).

This is an unofficial local driver. It is not affiliated with, endorsed by, or supported by any printer manufacturer. Packet framing is derived from niimprint (MIT). The print task was completed from device traces and community protocol notes. See NOTICE.

Library

from pathlib import Path
from labelprint.config import load_settings
from labelprint.printer import print_paths, render_to_path

settings = load_settings()
render_to_path(settings, Path("preview.png"), title="BOARDS", body="Controller?")
print_paths(settings, [Path("preview.png")])

License

MIT. See LICENSE and NOTICE.

Available Tools

5 tools
labelprint_doctorA

Check local config, serial ports, and which transport this machine would use.

Does not open the printer. Use this first when setup is unclear.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.9/5.0
Behavior3/5

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

With no annotations, the description carries the full disclosure burden. It usefully states the non-opening, diagnostic behavior, but says nothing about whether the check touches hardware, whether it can fail/block, or any side effects beyond not opening the printer.

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?

Two short sentences, front-loaded with what is checked, then the constraint and the routing cue. No filler.

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 zero-arg diagnostic with an output schema covering return values, the description is nearly sufficient: it says what is inspected, that it is non-invasive, and when to reach for it. The remaining gap is clarifying its relationship to the overlapping status/list_ports siblings.

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

Parameters4/5

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

The tool takes zero parameters, so the baseline is 4; the description is consistent with a no-argument diagnostic and adds no param detail beyond the empty 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?

Specific verb ('Check') plus three concrete resources (local config, serial ports, transport) clearly state what the tool does, and the negative statement 'Does not open the printer' sharpens the scope. It doesn't explicitly distinguish itself from the overlapping sibling labelprint_list_ports, so it falls short of a 5.

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

Usage Guidelines4/5

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

'Use this first when setup is unclear' gives an explicit triggering condition, which is real routing guidance. It stops short of naming alternatives (e.g., list_ports or status) or stating 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.

labelprint_list_portsA

List serial device nodes visible on this machine.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

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

With no annotations provided, the description carries the full behavioral burden. 'List ... device nodes visible on this machine' implies a non-destructive, read-only enumeration scoped to the local host, but it does not explicitly confirm read-only behavior or mention anything about ordering, filtering, or handling of no ports found.

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 with no filler; every word (list, serial, device nodes, this machine) 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?

An output schema exists, so the description need not explain return values, and a zero-param read tool is simple enough that the sentence covers the essentials. The only gap is the absence of any routing hint versus the status/doctor siblings.

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

Parameters4/5

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

The tool takes zero parameters, so there is nothing for the description to disambiguate. Baseline 4 applies for a parameterless operation.

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 uses a specific verb ('List') and a precise resource ('serial device nodes visible on this machine'), so an agent knows exactly what comes back. It is implicitly distinct from siblings like print/render, but it never names or contrasts them, leaving differentiation to inference.

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?

There is no statement of when to call this versus alternatives such as labelprint_status or labelprint_doctor, which could plausibly surface similar machine information. The phrase 'visible on this machine' narrows scope but does not tell the agent when this tool is the right choice.

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

labelprint_printA

Print a PNG, or render title/body/QR and print that.

Consumes physical labels. confirm must be true. Preview with labelprint_render first.

ParametersJSON Schema
NameRequiredDescriptionDefault
qrNo
bodyNo
titleNo
copiesNo
confirmNo
densityNo
width_mmNo
height_mmNo
image_pathNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does disclose the critical traits: it 'consumes physical labels' (irreversible real-world side effect) and is gated behind confirm=true, which is exactly the safety information an agent needs. It omits failure modes, printer selection, and whether copies multiplies consumption, so it is strong but not exhaustive.

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?

Three short sentences, front-loaded with the core action, then the physical-consumption warning, then the confirmation gate and preview routing. No filler and nothing buried.

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?

An output schema exists, so return values need not be described, and the high-risk behavioral notes are present. However, for a 9-parameter, 0%-coverage, unannotated tool, the dimension/quantity parameters and printer targeting are left for the agent to guess.

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

Parameters2/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 explains the mode split (image_path is a pre-made PNG vs. title/body/QR being rendered) and the meaning of confirm, but leaves copies, density, width_mm, and height_mm entirely undefined in both schema and prose.

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?

Opens with a specific verb+resource ('Print') and precisely delineates its two input modes: an existing PNG via image_path, or rendering title/body/QR inline. It explicitly positions itself against the sibling labelprint_render, so an agent can route without opening either schema.

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

Usage Guidelines4/5

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

Gives a hard precondition ('confirm must be true') and a clear workflow ordering ('Preview with labelprint_render first'), which names the alternative tool explicitly. It stops short of stating when NOT to use it (e.g., when no printer is configured), so it is clear context rather than full when/when-not coverage.

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

labelprint_renderA

Render a preview PNG (title, body, and/or QR). Does not print.

ParametersJSON Schema
NameRequiredDescriptionDefault
qrNo
bodyNo
titleNo
out_pathNo
width_mmNo
height_mmNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden, and it does disclose the key non-mutating trait: no print is issued. It is silent on whether the render writes to disk (the out_path parameter implies a possible file side effect), what permissions are needed, or whether output is returned inline, leaving meaningful gaps for a tool with side effects.

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?

Two short sentences, no filler, with the core action front-loaded and the disambiguating constraint second. Every clause earns its place.

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?

The output schema exists, so return values need not be explained. But for a 6-parameter tool with zero schema descriptions and no annotations, the description leaves three parameters and the file-write behavior unexplained, which is only marginally sufficient.

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

Parameters2/5

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

Schema coverage is 0% across 6 parameters, so the schema contributes no descriptions at all. The description names only title, body, and qr, leaving out_path, width_mm, and height_mm completely undocumented in either source.

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?

States a specific verb (render) and resource (preview PNG) and enumerates the content it composes (title, body, and/or QR). The clause "Does not print" explicitly differentiates it from the sibling labelprint_print, so an agent can route between them without opening a schema.

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 "Does not print" strongly implies this is the preview path and that printing belongs to another tool, which is useful routing context. However, it never names labelprint_print or states the when-to-use condition explicitly, so the guidance is implied rather than declared.

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

labelprint_statusB

Open the configured local printer and return identity, power, and on-device media chip data.

Media size is not fetched from the internet. If a barcode is present, match it against the local config table or pass width_mm/height_mm when printing.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

B3.4/5.0
Behavior3/5

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

With no annotations, the description carries the full behavioral burden. It usefully discloses that media size is not fetched from the internet (local/offline behavior), but does not say whether 'opening' the printer has side effects, what happens if no printer is configured, or whether the operation is safe/read-only.

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?

Two short sentences with the core action front-loaded. The trailing print/barcode guidance is somewhat off-topic for a status tool, adding minor noise, but overall it is tight.

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?

An output schema exists, so return-value explanation is not required, and the description names what data comes back. For a zero-parameter status tool this is nearly sufficient, missing only error/failure conditions and the safety profile that absent annotations would otherwise supply.

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

Parameters4/5

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

The tool takes zero parameters and the schema is empty, so the baseline is 4. The mention of width_mm/height_mm refers to a different tool (labelprint_print) and is not a parameter of this one, but it does not misrepresent this tool's 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?

States a concrete verb+resource ('open the configured local printer') and enumerates the returned data (identity, power, on-device media chip). An agent can distinguish it from labelprint_print or labelprint_render, though it never explicitly contrasts itself with the closest sibling, labelprint_doctor.

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?

The only guidance ('If a barcode is present, match it against the local config table or pass width_mm/height_mm when printing') describes downstream printing behavior rather than when to call this status tool versus labelprint_doctor or labelprint_list_ports. No prerequisites, no when-not-to-use conditions.

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. 5 tool updatesv0.1.0
    • First observedlabelprint_doctor
    • First observedlabelprint_list_ports
    • First observedlabelprint_print
    • First observedlabelprint_render
    • First observedlabelprint_status

TDQS

A3.9/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct role: doctor performs setup diagnostics without opening the printer, list_ports only enumerates serial nodes, status opens the printer for identity/media, render previews, and print consumes labels. The doctor/list_ports boundary is explicitly clarified by the descriptions.

Naming Consistency4/5

All tools use the same labelprint_ prefix and snake_case, making them predictable and grouped. Minor inconsistency: doctor and status are noun-like diagnostics while render/print/list_ports are action verbs.

Tool Count5/5

Five tools is well-scoped for a label-printing server: three diagnostic tools, one preview tool, and one print tool. Each earns its place without redundancy.

Completeness4/5

The surface covers diagnostics, preview, and printing, which are the core lifecycle operations. Minor gaps include no explicit configuration-setting or job-management tool, though doctor covers config inspection.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables printing structured documents to ESC/POS thermal printers via a CUPS queue, with tools for printer info, print jobs, and template management.
    1
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables printing text, QR codes, and images directly to NIIMBOT B1 BLE label printers without vendor apps or cloud, with orientation control, fit validation, and local preview tools.
    -