Files
goldyard2025 3fe919e37c refactor(halcon): single-skill plugin layout → invoke as /halcon (not /halcon:halcon)
Move SKILL.md + references/ scripts/ evals/ from skills/halcon/ up to the
plugin root. Per Claude Code plugins-reference, a plugin with SKILL.md at its
root and no skills/ subdir is auto-loaded as a single-skill plugin (v2.1.142+),
so the invocation name = frontmatter name = halcon → clean /halcon.
Bump plugin.json 2.0.0 → 2.0.1 so existing installs receive the update.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 23:14:39 +08:00

5.6 KiB
Raw Permalink Blame History

Remote HALCON over MCP (halcon-remote)

A remote HALCON compute service exposed as an MCP server. Use it when there is no local HALCON (e.g. MacOS, a plain Linux box, a colleague's machine) — it runs HALCON 24.11 on a headless Linux server and is reachable over the public internet. Client needs only network + a bearer token; no HALCON, no minio creds, no VPN/tailnet.

  • Endpoint: https://halcon-mcp.totoro.studio/mcp (Streamable HTTP, Bearer auth)
  • Token: server-side /opt/halcon-mcp/.env (HALCON_MCP_TOKEN); in configs reference ${HALCON_MCP_TOKEN}, never hardcode.
  • Source/ops: repo halcon-mcp-remote/; server 192.168.1.13:/opt/halcon-mcp (systemd halcon-mcp). Full deploy facts: repo halcon-tools.yamlhalcon_mcp_remote.

Register the server (client side)

# user scope (works across all projects)
claude mcp add --scope user --transport http halcon-remote \
  https://halcon-mcp.totoro.studio/mcp --header "Authorization: Bearer $HALCON_MCP_TOKEN"
claude mcp list   # expect: halcon-remote ... ✔ Connected

Or project .mcp.json: { "type":"http", "url":".../mcp", "headers":{"Authorization":"Bearer ${HALCON_MCP_TOKEN}"} }.

Tools (full names: mcp__halcon-remote__<tool>)

Tool Does Key args
halcon_get_env Self-check: version/hostid/arch
halcon_create_upload Presigned PUT URL to upload one file (image or zip), no creds filename, expires_minutes
halcon_find_circles Subpixel find circles → list + preview image or image_b64
halcon_measure_overlay Bullseye overlay: Top/Bottom center deviation (µm) image or image_b64, apply_registration
halcon_overlay_batch Batch overlay over a minio prefix → CSV prefix, max_images
halcon_find_circles_zip Batch find circles: image zip → 4 ring-mark centers (TL/TR/BL/BR) → CSV zip_key, min/max_radius
halcon_exec_hdev Run an HDevelop script via hrun → stdout (destructive) script_text

Image I/O — how images get in and results out

An image argument accepts one of:

  • file:/abs/path — a file on the server (testing only; e.g. file:/tmp/amm_test/2-zuoshang.bmp).
  • <key> — a minio object key in the default bucket halcon (e.g. inbox/die.png).
  • minio://<bucket>/<key> — explicit bucket.

Or pass image_b64 (inline base64, may include data: prefix) — best for a single small image, no upload step.

Results: numeric metrics come back inline (structuredContent). Heavy artifacts (preview jpg, CSV) are uploaded to minio and returned as a key + presigned URL on the public host minio-home.totoro.studio (openable from anywhere). Small files (preview/CSV) — just GET the URL.

Three usage patterns (pick by size)

1. Single small image → inline (simplest).

halcon_measure_overlay(image_b64="<base64 of the bullseye image>")
→ {status:"ok", overlay_dX_um, overlay_dY_um, top/bottom centers, n_circles}

2. Single/few images from an external client → presigned PUT (no creds).

k = halcon_create_upload(filename="die.bmp")        # → {put_url, key}
curl -T die.bmp "<put_url>"                          # public PUT, no creds
halcon_measure_overlay(image=k.key)

3. Large batch (hundredsthousands) → zip once, then process (recommended). Zip is the right move: one file = one upload = works with presigned PUT (external users too), vs mirroring many files (needs minio creds).

zip -0 -q -j batch.zip *.png                         # store mode (PNG already compressed)
k = halcon_create_upload(filename="batch.zip")
curl -T batch.zip "<k.put_url>"                       # one PUT
halcon_find_circles_zip(zip_key=k.key)               # server unzips + batch + CSV
→ {total, ok, seconds, per_image_ms, csv_key, csv_url}
# then GET csv_url

CSV columns: file,status,n_found,TL_col,TL_row,TL_r,TR_...,BL_...,BR_... (4 ring-mark centers per image, ordered by position).

D2W overlay conventions (this project's domain)

  • Axes: X = image right +, Y = image up +; pixel size 271.048 nm/px; overlay = Bottom Top.
  • Mark grouping: outer thick ring = Top Die Mark; inner dot + mid ring = Bottom Die Mark.
  • apply_registration=True adds the +13.5/+9.6 nm offset (0627-JC 2-point calibration; drop for other tools/batches).
  • Sanity values (die-2 four corners, raw dev µm): TL 0.778/+0.794 · TR 0.265/+0.391 · BL 0.171/+1.022 · BR +0.230/+0.435.

Performance (measured, single HALCON process, 16 threads)

  • find_circles on 5312×4608 (24MP): ~92 ms/image (~11 img/s). 1920 images ≈ 176 s compute.
  • 90 MB zip public PUT: ~20 s. End-to-end 1920 images ≈ 3.3 min.
  • Circle-center repeatability across 1920 shots: std 0.010.04 px.

Gotchas

  • Sync execution. halcon_find_circles_zip / halcon_overlay_batch run synchronously. ~1920 images (~3 min) is near the comfortable ceiling — set a long client timeout. For much larger jobs, chunk or use async (not yet built).
  • License SESSIONS=1 → cannot multi-process; rely on HALCON's internal 16-thread parallelization (already fast).
  • Preview/CSV URLs use minio-home.totoro.studio (public), not the internal 192.168.1.2:9000 — openable off-LAN.
  • Big batches: always zip (one PUT). Per-file create_upload for N files is N round-trips — only for a handful.
  • file: paths are server-side, not the client's filesystem — only for images already on 192.168.1.13.
  • Tool errors return isError + an actionable message (e.g. "先用 halcon_create_upload 传图") — read it and self-correct.