Skip to content

Picodev Lab

by PICODEV-SAS · remote · no sign-in to list tools · v0.9.1 · published by GitHub user PICODEV-SAS

Arduino benches simulated in the browser: sessions, sketch push, simulation, tests, challenges.

Deletes · 1Final · 5Changes · 9

21 tools: 1 can delete or cancel things, 5 do something that can't be undone, 9 change things and 6 only read.

Scanned Oct 21, 2026

1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http picodev-lab https://lab.picodev.fr/mcp

Findings

Matches of fixed checks, with the text they matched.

1 warn
  • The server marks "bench_snapshot" as not read-only (readOnlyHint: false), and its words say it reads.

    Matched text

    annotations: {"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false}; The name "bench_snapshot" says "snapshot": a word for reading.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

21 tools

Deletes or cancels 1Claude Code: deny
  • close_sessionEnd the session now, as when it expires: the place or turn ends, viewers and the browser are disconnected, everything is forgotten.No findings

    Why it is in this group

    • The name "close_session" says "close": a word for a change.
    • The server marks it destructive (destructiveHint: true).
    Description, as the server wrote it
    End the session now, as when it expires: the place or turn ends, viewers and the browser are disconnected, everything is forgotten.

    Annotations the server declares

    • destructiveHint: true
    • openWorldHint: false
    • readOnlyHint: false
Can't be undone 5Claude Code: ask
  • brief_submitSend Picodev the specification of the visitor's project, as a PDF, or only return its preview (send=false).No findings

    Why it is in this group

    • The name "brief_submit" says "submit": a word for a change.
    • The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
    Description, as the server wrote it
    Send Picodev the specification of the visitor's project, as a PDF, or only return its preview (send=false). sections: {id: text in simple Markdown}, ids envelope, fonctionPrincipale, fonctions, alimentation, format, environnement, production, preferences (the 8 sections of a product specification), 4000 characters at most each; a missing section reads "À préciser" (to be specified). send=false: preview, nothing is sent, contact and consent are not required. send=true: requires contact {name, email, company?, phone?} and consent=true. nda=true: the visitor wants a non-disclosure agreement first; without sections, only contact and title are sent, without PDF. session and agent_token, optional: the mail also says what the visitor did in the lab. language: fr or en, the PDF's headings. sections.contact and figures: as for spec_draft (refused with nda=true, as sections). Write the sections with spec_draft first. Before passing consent=true, show the visitor the consent text in the visitor's language, and wait until they accept it. In French: "J'accepte que mes coordonnées et la description de mon projet soient envoyées à Picodev par courriel, pour qu'ils me répondent. Picodev les garde 3 ans après le dernier échange et ne les utilise pour rien d'autre. Détails : lab.picodev.fr/confidentialite" In English: "I agree that my contact details and the description of my project are sent to Picodev by e-mail, so that they can answer me. Picodev keeps them for 3 years after our last exchange and uses them for nothing else. Details: lab.picodev.fr/en/privacy" Returns {sent, filename, pdf (base 64, absent with nda), missing (empty or too short sections), next (a sentence for the visitor, to say in their language)}}: write the PDF on the visitor's machine.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: true
    • readOnlyHint: false
  • capture_analogSample the voltage of 1 to 4 board pins (0-13 digital, 14-21 = A0-A7; by default the setup's scope probes) at rate_hz (100 to 10 000) for duration_ms (1 to 10 000 simulated ms), 20…No findings

    Why it is in this group

    • The name "capture_analog" says "capture": a word that usually means money moves, which cannot be taken back.
    Description, as the server wrote it
    Sample the voltage of 1 to 4 board pins (0-13 digital, 14-21 = A0-A7; by default the setup's scope probes) at rate_hz (100 to 10 000) for duration_ms (1 to 10 000 simulated ms), 200 000 samples at most in all. An ADC input reads the voltage the circuit applies; any other pin, its logic level times the supply (PWM shows as a square wave). Simulation only: refused during a turn on a real bench, whose analyser has no analog channel. Read the result with read_capture.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • capture_logicRecord every edge of the requested pins (probes of the setup sheet; by default the logic ones) for duration_ms (1 to 10 000 ms).No findings

    Why it is in this group

    • The name "capture_logic" says "capture": a word that usually means money moves, which cannot be taken back.
    Description, as the server wrote it
    Record every edge of the requested pins (probes of the setup sheet; by default the logic ones) for duration_ms (1 to 10 000 ms). In the browser's simulation, in simulated time; during the session's turn on a real bench, at the bench's logic analyser, in real time (no browser or running simulation needed then). Read the result with read_capture.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • push_programSend a program compiled on the visitor's machine (Intel HEX text, 48 KiB at most, e.g.No findings

    Why it is in this group

    • The name "push_program" says "push": a word for a change.
    • The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
    Description, as the server wrote it
    Send a program compiled on the visitor's machine (Intel HEX text, 48 KiB at most, e.g. arduino-cli's <sketch>.ino.hex) to the human's browser, which loads it in the simulator without compiling and, if run, starts it. files: the sources, shown read-only in the editor, never compiled. During a turn on a real bench, the bench gets it too. Prefer it to push_to_editor, which is the fallback when the local toolchain is missing.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • request_meetingSend Picodev a meeting request.No findings

    Why it is in this group

    • The name "request_meeting" says "request": a word for a change.
    • The description's first verb is "send": a word for sending, and what is sent cannot be taken back.
    Description, as the server wrote it
    Send Picodev a meeting request. contact: {name, email, company?, phone?}. context: the project in a few sentences (2000 characters at most): what the visitor wants to do, where they stand, what they did in the lab. availabilities: 1 to 10 slots {from, to}, ISO 8601 dates with a time zone, within the next 60 days; or {text}, one sentence ("Tuesday mornings"). Requires consent=true. session and agent_token, optional: the mail also says what the visitor did in the lab. Before passing consent=true, show the visitor the consent text in the visitor's language, and wait until they accept it. In French: "J'accepte que mes coordonnées et la description de mon projet soient envoyées à Picodev par courriel, pour qu'ils me répondent. Picodev les garde 3 ans après le dernier échange et ne les utilise pour rien d'autre. Détails : lab.picodev.fr/confidentialite" In English: "I agree that my contact details and the description of my project are sent to Picodev by e-mail, so that they can answer me. Picodev keeps them for 3 years after our last exchange and uses them for nothing else. Details: lab.picodev.fr/en/privacy" Returns {sent, next}: Picodev answers by e-mail to confirm a slot.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: true
    • readOnlyHint: false
Changes things 9Claude Code: ask
  • bench_snapshotDuring the session's turn on a real bench: a photo of the bench, as an image, and t_ms, the instant of the photo in ms since the start of the turn (null when unknown).1 finding

    Why it is in this group

    • The name "bench_snapshot" says "snapshot": a word for reading.
    • The server marks it as not read-only (readOnlyHint: false).

    Findings

    • Warn

      The server marks "bench_snapshot" as not read-only (readOnlyHint: false), and its words say it reads.

      Matched text

      annotations: {"readOnlyHint":false,"destructiveHint":false,"openWorldHint":false}; The name "bench_snapshot" says "snapshot": a word for reading.

      What this check looks for
    Description, as the server wrote it
    During the session's turn on a real bench: a photo of the bench, as an image, and t_ms, the instant of the photo in ms since the start of the turn (null when unknown). One every 2 seconds.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • next_levelChallenge mode: move to the next level, as the bench's "Next level" button, and only when it would be offered: every test of the current level passed and a next level exists.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Challenge mode: move to the next level, as the bench's "Next level" button, and only when it would be offered: every test of the current level passed and a next level exists. Returns {level, levels}, the new level (index); session_status's level changes with the bench's next state. No level skipping.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • open_sessionCreate a session (mode: free or challenge).No findings

    Why it is in this group

    • The name "open_session" says "open": a word for a change.
    Description, as the server wrote it
    Create a session (mode: free or challenge). Give open_url to the human: nothing simulates until they open it in their browser.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • push_circuitFree mode only: replace the circuit in the human's browser (the simulation stops).No findings

    Why it is in this group

    • The name "push_circuit" says "push": a word for a change.
    Description, as the server wrote it
    Free mode only: replace the circuit in the human's browser (the simulation stops). components: [{type, id, properties, x?, y?}] (the board is not a component), wires: [{id, start: {componentId, pinName}, end: {...}, color?}], in the shape of the setup sheet's circuit; 40 components, 120 wires, 48 KiB. The editor checks types and pins: read the outcome with read_simulation (circuit, circuit_error). 6 per minute.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • push_to_editorReplace the code in the human's browser and, if run, compile it in the lab's cloud and start it.No findings

    Why it is in this group

    • The name "push_to_editor" says "push": a word for a change.
    Description, as the server wrote it
    Replace the code in the human's browser and, if run, compile it in the lab's cloud and start it. The fallback of push_program: use it only when the toolchain to compile locally is missing (no arduino-cli, core or library).

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • queue_joinTake a place in the queue for benches of this kind (for example real or sim).No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Take a place in the queue for benches of this kind (for example real or sim). The browser must be connected.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • queue_leaveGive back the place in the queue, or the turn if it has started.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    Description, as the server wrote it
    Give back the place in the queue, or the turn if it has started.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • set_visibilityChange the visibility (private, link, public).No findings

    Why it is in this group

    • The name "set_visibility" says "set": a word for a change.
    Description, as the server wrote it
    Change the visibility (private, link, public). Returns the viewer link; current viewers are disconnected.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: false
  • spec_draftDraft the specification of the visitor's own project with Picodev's interview: you ask the visitor, this tool says what to ask next and makes the PDF.No findings

    Why it is in this group

    • Nothing in its name or description says what it does, so it is counted as a write.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.
    Description, as the server wrote it
    Draft the specification of the visitor's own project with Picodev's interview: you ask the visitor, this tool says what to ask next and makes the PDF. Nothing is sent and nothing is kept. Call it with the sections written so far (none at first). sections: {id: text in simple Markdown}, ids envelope, fonctionPrincipale, fonctions, alimentation, format, environnement, production, preferences, 4000 characters at most each. sections.contact, optional: the contact details the visitor wants printed at the end of the document (1000 characters at most; not part of the interview's progress). language: fr or en, the one the visitor answers in (headings, look_for and questions, the PDF). pdf=true: also the PDF, with Picodev Lab's template; requires title (one line). figures, with pdf=true, optional: the drawings the visitor approved, 3 at most, each {section (a section id), caption (one line), type (png or svg), data (base 64, 200 KiB at most decoded)}, placed after their section's text; an SVG loads nothing (no script, no DTD, href # or data:image/ only). Returns {rules (how to run the interview: follow them), sections [{id, heading, required, state (empty, thin, filled), look_for and questions while not filled}], next (the section to ask about, or null), ready (the four required sections filled: enough for Picodev to start), filename and pdf (base 64) with pdf=true}.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: true
Only reads 6Claude Code: allow
  • list_setupsThe available setups, their modes (free, challenge) and their benches.No findings

    Why it is in this group

    • The name "list_setups" says "list": a word for reading.
    Description, as the server wrote it
    The available setups, their modes (free, challenge) and their benches.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: true
  • queue_statusThe session's place: state none, waiting (position, estimated wait eta_s) or turn (bench, end of the turn ends_at, Unix seconds).No findings

    Why it is in this group

    • The name "queue_status" says "status": a word for reading.
    Description, as the server wrote it
    The session's place: state none, waiting (position, estimated wait eta_s) or turn (bench, end of the turn ends_at, Unix seconds).

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: true
  • read_captureState of a capture (recording, ready, failed) and its kind (logic, analog).No findings

    Why it is in this group

    • The name "read_capture" says "read": a word for reading.
    Description, as the server wrote it
    State of a capture (recording, ready, failed) and its kind (logic, analog). Once ready, the measures per pin and, for a logic capture, the edges [t_us, pin, v], 2000 from offset; for an analog one, rate_hz and the samples, rows [mv_1, ...] in the order of pins (row k at k / rate_hz), 2000 rows from offset. next: the following offset, or null. t0_ms: the first sample on the session's clock (ms since the simulation's launch, or since the start of the turn on a real bench), null when unknown; t_us and rows count from the capture's start. format="png": the same without edges or samples, plus a chart of the signals as an image (from_ms and to_ms, from the capture's start, to zoom; 4 per minute).

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: true
  • read_setupA served setup sheet (setup.json, files included; never a solution): board, components and wires (circuit), probes, levels.No findings

    Why it is in this group

    • The name "read_setup" says "read": a word for reading.
    Description, as the server wrote it
    A served setup sheet (setup.json, files included; never a solution): board, components and wires (circuit), probes, levels. Plus, when it exists, schema.png, the starting circuit as the editor draws it, as an image.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: true
  • read_simulationLast state (with circuit, the browser's components and wires), last compilation and the events after since_ms (2000 at most).No findings

    Why it is in this group

    • The name "read_simulation" says "read": a word for reading.
    Description, as the server wrote it
    Last state (with circuit, the browser's components and wires), last compilation and the events after since_ms (2000 at most). In challenge mode: the level's brief and its results. circuit_modified: the circuit differs from the setup sheet's (types, ids, properties, wires; not positions or colours), null when unknown. circuit_error: the editor's last refusal of a pushed circuit, returned once.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: true
  • session_statusThe session's state without its events, cheap enough to poll: browser connected (owner), visibility, current viewer link (not renewed), viewers, created_at and expires_at (Unix sec…No findings

    Why it is in this group

    • The name "session_status" says "status": a word for reading.
    Description, as the server wrote it
    The session's state without its events, cheap enough to poll: browser connected (owner), visibility, current viewer link (not renewed), viewers, created_at and expires_at (Unix seconds), run (compilations so far: event times restart at each), level and levels (null in free mode), capture ({id, kind, state} of the session's capture, logic or analog, or null). Not reported to the human's journal.

    Annotations the server declares

    • destructiveHint: false
    • openWorldHint: false
    • readOnlyHint: true

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.9.1. Values in angle brackets are yours to fill in.

claude mcp add --transport http picodev-lab https://lab.picodev.fr/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__picodev-lab__list_setups",
      "mcp__picodev-lab__read_simulation",
      "mcp__picodev-lab__queue_status",
      "mcp__picodev-lab__session_status",
      "mcp__picodev-lab__read_capture",
      "mcp__picodev-lab__read_setup"
    ],
    "ask": [
      "mcp__picodev-lab__open_session",
      "mcp__picodev-lab__push_to_editor",
      "mcp__picodev-lab__push_program",
      "mcp__picodev-lab__set_visibility",
      "mcp__picodev-lab__queue_join",
      "mcp__picodev-lab__queue_leave",
      "mcp__picodev-lab__next_level",
      "mcp__picodev-lab__capture_logic",
      "mcp__picodev-lab__capture_analog",
      "mcp__picodev-lab__push_circuit",
      "mcp__picodev-lab__bench_snapshot",
      "mcp__picodev-lab__spec_draft",
      "mcp__picodev-lab__brief_submit",
      "mcp__picodev-lab__request_meeting"
    ],
    "deny": [
      "mcp__picodev-lab__close_session"
    ]
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as picodev-lab. Review it before you use it.