Skip to main content
Glama
CrossPad

crosspad-mcp-server

Official
by CrossPad

crosspad_flash

Destructive

Flash firmware to CrossPad ESP32-S3 or STM32G0 boards: preflight checks block wrong ports, stale builds, and board-revision mismatches before any write.

Instructions

[ESP HW | STM HW] Flash firmware. Danger tier: it always runs a preflight first, always returns that preflight (refusal included), and needs a confirmation before writing anything. Preflight reports: the device's USB mode, which role the target port plays (the STM32 bridge console is refused as a flash target), the binary's own version string, whether it is older than the newest file under main/ or components/, and whether the build's board revision matches the device's — a mismatch is a blocker, because the revisions differ in pinout and the wrong image looks like dead hardware. target='esp': transport='ota' streams over USB CDC with the device running (no bootloader mode); transport='uart' runs idf.py flash and needs download mode. wait_boot=true then opens the console and returns a BootResult. target='stm': method='swd' (ST-Link) or 'dfu' (system bootloader, hold pad 1 at boot). The flash runs as a job: wait_seconds=0 (default) returns a task handle for crosspad_task; wait_seconds>0 inlines the final status. dry_run=true stops after the preflight. force=true overrides every blocker except the port-role refusal.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
portNoESP only. Serial port to flash. Omit to let the daemon choose. The STM32 bridge console port is refused — it carries logs, not the flash.
forceNoProceed despite preflight blockers (stale build, board-revision mismatch, missing device). The port-role and no-board refusals are never overridden.
deviceNoESP only. Device id (dev_xxxx) or one of its port paths; omit when exactly one CrossPad is connected.
methodNoSTM only. 'swd' = ST-Link; 'dfu' = the STM32 system bootloader (hold pad 1 at boot).
targetNo'esp' = ESP32-S3 application firmware (transport uart|ota); 'stm' = STM32G0 bridge firmware via STM32_Programmer_CLI (method swd|dfu).esp
dry_runNoRun the preflight and stop: no confirmation token is minted and nothing is written.
build_dirNoESP only. Build directory holding the binary and its sdkconfig (default: '<idf-root>/build_<rev>' of the board being flashed, from tools/crosspad_board.py; per-revision dirs are build_v1 / build_v2).
transportNoESP only. 'ota' streams the binary over USB CDC with the device running (no bootloader mode); 'uart' runs idf.py flash and needs download mode.
wait_bootNoESP only. After flashing, open the console and wait for the boot markers; the job result carries a BootResult {complete, missing, fatal, errors, bootloops, seconds}. Default false.
build_typeNoSTM only. Picks the build/<preset> dir for the default binary. Default Debug.
delta_baseNoESP OTA only. Previously flashed binary to diff against — sends a delta instead of the whole image.
wait_secondsNo0 (default) returns the task handle immediately — poll it with crosspad_task. >0 waits that long and inlines the task status; a timeout is not an error, the job keeps running.
confirm_tokenNoToken from a previous confirmation_required result. Re-issue the identical call with it to proceed.
firmware_pathNoCustom binary. ESP default '<build_dir>/CrossPad.bin'; STM default '<stm-root>/build/<preset>/CrossPad_STM32_r20.bin'.
boot_timeout_sNowait_boot: how long to wait for a complete boot (default 45, the firmware's own boot budget).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
tsNo
hintNo
taskNo
toolNo
errorNo
deviceNo
statusNo
targetNo
detailsNo
dry_runNo
successYes
preflightNo
transportNo
resultTypeNo
confirmationNo
firmware_pathNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changedv10.3.0
    • changedInput schema / properties / build_dir / description
      Previous value: -"ESP only. Build directory holding the binary and its sdkconfig (default '<idf-root>/build'; per-revision dirs are build_v1 / build_v2)."New value: +"ESP only. Build directory holding the binary and its sdkconfig (default: '<idf-root>/build_<rev>' of the board being flashed, from tools/crosspad_board.py; per-revision dirs are build_v1 / build_v2)."
    • changedInput schema / properties / force / description
      Previous value: -"Proceed despite preflight blockers (stale build, board-revision mismatch, missing device). The port-role refusal is never overridden."New value: +"Proceed despite preflight blockers (stale build, board-revision mismatch, missing device). The port-role and no-board refusals are never overridden."
  2. Changed41 schema fields changedv10.2.0
    • addedInput schema / properties / boot_timeout_s
      Added value: +{
      +  "description": "wait_boot: how long to wait for a complete boot (default 45, the firmware's own boot budget).",
      +  "maximum": 180,
      +  "minimum": 5,
      +  "type": "number"
      +}
    • addedInput schema / properties / build_dir
      Added value: +{
      +  "description": "ESP only. Build directory holding the binary and its sdkconfig (default '<idf-root>/build'; per-revision dirs are build_v1 / build_v2).",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • changedInput schema / properties / build_type / description
      Previous value: -"STM only. Selects the build/<preset> dir for the default firmware binary. Defaults to Debug."New value: +"STM only. Picks the build/<preset> dir for the default binary. Default Debug."
    • addedInput schema / properties / confirm_token
      Added value: +{
      +  "description": "Token from a previous confirmation_required result. Re-issue the identical call with it to proceed.",
      +  "type": "string"
      +}
    • addedInput schema / properties / delta_base
      Added value: +{
      +  "description": "ESP OTA only. Previously flashed binary to diff against — sends a delta instead of the whole image.",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / device
      Added value: +{
      +  "description": "ESP only. Device id (dev_xxxx) or one of its port paths; omit when exactly one CrossPad is connected.",
      +  "minLength": 1,
      +  "type": "string"
      +}
    • addedInput schema / properties / dry_run
      Added value: +{
      +  "description": "Run the preflight and stop: no confirmation token is minted and nothing is written.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / firmware_path / description
      Previous value: -"Custom firmware binary path. ESP: OTA only, defaults to <idf-root>/build/CrossPad.bin. STM: defaults to <stm-root>/build/<preset>/CrossPad_STM32_r20.bin."New value: +"Custom binary. ESP default '<build_dir>/CrossPad.bin'; STM default '<stm-root>/build/<preset>/CrossPad_STM32_r20.bin'."
    • addedInput schema / properties / firmware_path / minLength
      Added value: +1
    • addedInput schema / properties / force
      Added value: +{
      +  "description": "Proceed despite preflight blockers (stale build, board-revision mismatch, missing device). The port-role refusal is never overridden.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / method / description
      Previous value: -"STM only. 'swd' = ST-Link/SWD; 'dfu' = USB DFU system bootloader."New value: +"STM only. 'swd' = ST-Link; 'dfu' = the STM32 system bootloader (hold pad 1 at boot)."
    • changedInput schema / properties / port / description
      Previous value: -"Serial port path (e.g. /dev/ttyACM0, COM3). Auto-detected if omitted; required when multiple devices connected."New value: +"ESP only. Serial port to flash. Omit to let the daemon choose. The STM32 bridge console port is refused — it carries logs, not the flash."
    • addedInput schema / properties / port / minLength
      Added value: +1
    • removedInput schema / properties / port / pattern
      Removed value: -"^(?:\\/dev\\/(?:tty(?:ACM|USB)\\d+|cu\\.usb[A-Za-z0-9._-]+|cu\\.usbmodem[A-Za-z0-9._-]+|cu\\.usbserial[A-Za-z0-9._-]+)|COM\\d+)$"
    • changedInput schema / properties / target / description
      Previous value: -"'esp' = ESP32-S3 (transport uart/ota); 'stm' = STM32G0 firmware via STM32_Programmer_CLI (method swd/dfu)."New value: +"'esp' = ESP32-S3 application firmware (transport uart|ota); 'stm' = STM32G0 bridge firmware via STM32_Programmer_CLI (method swd|dfu)."
    • changedInput schema / properties / transport / description
      Previous value: -"ESP only. 'uart' = bootloader-mode flash via idf.py; 'ota' = USB-CDC OTA flash via ota_flash.py."New value: +"ESP only. 'ota' streams the binary over USB CDC with the device running (no bootloader mode); 'uart' runs idf.py flash and needs download mode."
    • addedInput schema / properties / wait_boot
      Added value: +{
      +  "description": "ESP only. After flashing, open the console and wait for the boot markers; the job result carries a BootResult {complete, missing, fatal, errors, bootloops, seconds}. Default false.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / wait_seconds
      Added value: +{
      +  "description": "0 (default) returns the task handle immediately — poll it with crosspad_task. >0 waits that long and inlines the task status; a timeout is not an error, the job keeps running.",
      +  "maximum": 900,
      +  "minimum": 0,
      +  "type": "number"
      +}
    • addedOutput schema / properties / confirmation
      Added value: +{
      +  "additionalProperties": {},
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / details
      Added value: +{
      +  "additionalProperties": {},
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / device
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / dry_run
      Added value: +{
      +  "type": "boolean"
      +}
    • removedOutput schema / properties / duration_seconds
      Removed value: -{
      -  "type": "number"
      -}
    • addedOutput schema / properties / error / additionalProperties
      Added value: +{}
    • addedOutput schema / properties / error / properties
      Added value: +{
      +  "code": {
      +    "type": "string"
      +  },
      +  "details": {
      +    "additionalProperties": {},
      +    "propertyNames": {
      +      "type": "string"
      +    },
      +    "type": "object"
      +  },
      +  "hint": {
      +    "type": [
      +      "string",
      +      "null"
      +    ]
      +  },
      +  "message": {
      +    "type": "string"
      +  }
      +}
    • addedOutput schema / properties / error / required
      Added value: +[
      +  "code",
      +  "message"
      +]
    • changedOutput schema / properties / error / type
      Previous value: -"string"New value: +"object"
    • addedOutput schema / properties / hint
      Added value: +{
      +  "type": "string"
      +}
    • removedOutput schema / properties / method
      Removed value: -{
      -  "enum": [
      -    "uart",
      -    "ota",
      -    "swd",
      -    "dfu"
      -  ],
      -  "type": "string"
      -}
    • removedOutput schema / properties / output_tail
      Removed value: -{
      -  "items": {
      -    "type": "string"
      -  },
      -  "type": "array"
      -}
    • removedOutput schema / properties / port
      Removed value: -{
      -  "type": "string"
      -}
    • addedOutput schema / properties / preflight
      Added value: +{
      +  "additionalProperties": {},
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • removedOutput schema / properties / programmer
      Removed value: -{
      -  "type": "string"
      -}
    • addedOutput schema / properties / resultType
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / status
      Added value: +{
      +  "additionalProperties": {},
      +  "propertyNames": {
      +    "type": "string"
      +  },
      +  "type": "object"
      +}
    • addedOutput schema / properties / target
      Added value: +{
      +  "enum": [
      +    "esp",
      +    "stm"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / task
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / tool
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / transport
      Added value: +{
      +  "type": "string"
      +}
    • addedOutput schema / properties / ts
      Added value: +{
      +  "type": "number"
      +}
    • changedOutput schema / required
      Previous value: -[
      -  "success",
      -  "method",
      -  "duration_seconds",
      -  "output_tail"
      -]New value: +[
      +  "success"
      +]
  3. First observedv9.2.0

TDQS

A5/5.0
Behavior5/5

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

Goes far beyond annotations: discloses the danger tier, preflight always running, confirmation requirement, refusal rules, revision mismatch blocking, and job mechanics. It explains what force does and does not override, and the difference between wait_seconds modes. No contradictions with annotations.

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?

The description is long but each sentence carries essential information. It is front-loaded with the danger warning and preflight summary, then organized by target and parameter groups. No fluff; every detail is actionable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with 15 parameters, the description covers all critical aspects: preflight checks, transport/method selection, job handling, confirmation token flow, force/dry_run semantics, and board revision implications. The output schema (BootResult) is not described but exists, so no need to repeat. Nothing an agent needs to call it correctly is missing.

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

Parameters5/5

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

While the schema already documents every parameter (100% coverage), the description adds significant semantic depth: it explains the preflight checks, the meaning of confirm_token flow, the behavior of wait_seconds=0 vs >0, default paths for firmware, and the board-revision blocking logic. This enriches the schema descriptions substantially.

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?

The description explicitly states 'Flash firmware' with clear scope for ESP and STM targets. It distinguishes itself from siblings by detailing the preflight, confirmation, and job-based execution, making its unique role obvious.

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

Usage Guidelines5/5

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

Provides explicit when-to-use guidance: it explains when to use each transport/method, what is refused (STM32 bridge console), how to handle confirmation, and when to use dry_run or force. It references crosspad_task for polling, giving clear routing.

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