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

97 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.yaml``halcon_mcp_remote`.
## Register the server (client side)
```bash
# 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.