# 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 | 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`). - `` — a minio object key in the default bucket `halcon` (e.g. `inbox/die.png`). - `minio:///` — 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="") → {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 "" # public PUT, no creds halcon_measure_overlay(image=k.key) ``` **3. Large batch (hundreds–thousands) → 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 "" # 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.01–0.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.