Skip to main content
Glama
README.md
# barcode-mcp

Stateless barcode tools for LLM agents, exposed via the [Model Context Protocol](https://modelcontextprotocol.io) (protocol `2025-11-25` via SDK 1.30.0, negotiable down to `2024-10-07`).

Extracted from the engines proven in the QR Saver PWA: one WASM engine (zxing-cpp via `zxing-wasm`) does both render and decode — no DOM, no browser, fully headless.

## Tools

| Tool | Input | Output |
|---|---|---|
| `decode_barcode` | `image_base64`, optional `formats[]` | `[{format, text}]` — QR, Aztec, DataMatrix, Code128/39/93, EAN-13/8, UPC-A/E, ITF, PDF417, Codabar |
| `render_barcode` | `text`, `format`, optional `scale` | base64 PNG + `decoded` self-check flag |
| `validate_gtin` | `code` | `{valid, type, normalized}` — length + mod-10 checksum |
| `list_formats` | — | format table with capabilities |

`render_barcode` decodes its own output before returning; failures come back with `warning`, never silently.

## Connect (hosted, no install)

Live endpoint, no API key — registered in the official MCP Registry as `io.github.appvantagelabs2-a11y/barcode`.

`list_formats` and `validate_gtin` are free. `decode_barcode` and `render_barcode` cost fractions of a cent per call, two ways:

1. **x402 (permissionless)** — unpaid calls return HTTP `402` with USDC payment instructions; an x402-capable client pays and retries automatically. `GET /health` shows the current price.
2. **Trial key** — send `X-API-Key: <key>` for a free quota of 50 decode/render calls per key. Responses carry `X-Trial-Remaining: N`; when exhausted the call falls back to x402. Ask for a trial key via a GitHub issue.

**Claude Code**
```bash
claude mcp add barcode --transport http https://mcp.casuyi.com/mcp
```

**Cursor / VS Code (Copilot) / Windsurf / any `mcpServers` JSON client**
```json
{
  "mcpServers": {
    "barcode": { "type": "http", "url": "https://mcp.casuyi.com/mcp" }
  }
}
```

**Claude Desktop** — Settings → Connectors → *Add custom connector* → URL above.

**Programmatic (JSON-RPC)** — MCP `2025-11-25`, Streamable HTTP:
```bash
curl -X POST https://mcp.casuyi.com/mcp \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

## Examples and clients

- [`examples/curl.md`](examples/curl.md) — raw JSON-RPC: tools/list, free validation call, render (x402)
- [`examples/claude-code.md`](examples/claude-code.md) — connect from Claude Code / Desktop / Cursor / any MCP client
- [`clients/python.py`](clients/python.py) — minimal Python client (stdlib only)

## Run (self-host)

```bash
npm install
node test/run.mjs   # 24 tests: round-trips, GTIN, small-image, MCP smoke
node index.js       # stdio MCP server
```

Register the stdio variant in an MCP client:

```json
{
  "mcpServers": {
    "barcode": { "command": "node", "args": ["/path/to/barcode-mcp/index.js"] }
  }
}
```

## Known behaviors

- **UPC-A** verifies as zero-padded EAN-13 (`042100005264` → `0042100005264`) — inherent to the GTIN family, reported in `warning`.
- Heavy resampling of a large render (non-integer downscale with lanczos) can alias modules below zxing's detection floor — same in native zxing-cpp. Real camera captures (native small sizes) decode fine, including a nearest-upscale retry inside `decode()`.
- WASM loading in Node requires the `wasmBinary` override (see `lib/decoder.js`); the browser-style `locateFile` path fails in Node.

## Roadmap (agent-commerce)

- HTTP transport + x402 pay-per-call for agent marketplaces (Agentic.Market, MCP registries)
- Migration to spec `2026-07-28` (stateless core, `Mcp-Method`/`Mcp-Name` headers) once the SDK line ships it — the HTTP/gateway mode is exactly what a public paid endpoint wants.