Connect your agent

Point your AI at a virtual chip

VirtMCU is an MCP server. Connect the agent you already use — Claude Code, Cursor, any MCP client — and ask it to write, compile, run, and debug firmware on a deterministic virtual microcontroller. No board, no toolchain, no debugger.

What a session looks like

You hand your agent the key and a goal. It does the rest — here, catching a CAN bit-timing bug on a virtual NXP S32K344, at the register level, in one pass:

claude code · virtmcuillustrative session
you ▸Here's my VirtMCU key. Use the nxp-s32k-canpair world — two S32K344 ECUs on one CAN bus. Write firmware so ECU-A broadcasts a CAN frame (ID 0x123, payload "HELLO") every 100 ms, run it, and show me the frame actually reaching ECU-B.
virtmcu ▸Connecting to the session and looking around the board.
list_nodesecu_a — NXP S32K344 · ecu_b — NXP S32K344
get_topologyecu_a.CAN0 ──canbus── ecu_b.CAN0
virtmcu ▸Two S32K344s on a shared CAN bus. I'll write a FlexCAN transmitter for ECU-A and a receiver for ECU-B, compile them in-session (no local toolchain), and load them.
upload_firmware { node: ecu_a }compiled can_tx.c → 4.2 KB ELF · loaded
upload_firmware { node: ecu_b }compiled can_rx.c → 3.9 KB ELF · loaded
start_node ecu_a, ecu_brunning
run_until { vtime_ms: 250 }advanced 250 ms (deterministic)
read_link { link: canbus }(no frames)
virtmcu ▸Nothing on the bus after 250 ms — the transmit isn't going out. Let me inspect ECU-A's CAN controller.
read_registers { node: ecu_a, peripheral: FlexCAN0 }CTRL1.PRESDIV=9 → 250 kbit/s @ 40 MHz PE clock · MCR.FRZACK=1
read_fault { node: ecu_a }no hard fault — controller stuck re-arbitrating
virtmcu ▸Found it. I sized the prescaler for an 80 MHz CAN clock, but on this part FlexCAN is fed from the 40 MHz peripheral clock — so my "500 kbit/s" init actually programs 250 kbit/s. ECU-B runs at 500k and never ACKs, so ECU-A keeps re-arbitrating and never completes a frame. Halving PRESDIV fixes the bit timing.
upload_firmware { node: ecu_a }recompiled with PRESDIV=4 · loaded
reset_node ecu_a · start_noderunning
run_until { vtime_ms: 250 }advanced 250 ms
read_link { link: canbus }frame ID=0x123 DLC=5 data=48 45 4C 4C 4F ("HELLO") ×2
read_console { node: ecu_b }RX 0x123: HELLO
Fixed. ECU-A broadcasts 0x123 "HELLO" every 100 ms and ECU-B receives it. Because the simulator is deterministic, that trace is bit-identical on every run — so it's a regression test, not a one-off. ~40 seconds, no board, no CAN analyzer, no toolchain, no debugger.

Illustrative — the tools shown (list_nodes, upload_firmware, run_until, read_link, read_registers, read_fault, read_console) are the real MCP surface your agent drives.

Connect in two steps

1

Generate an API key on your dashboard and export it as VIRTMCU_API_KEY.

2

Create a session and connect your agent to it:

Claude Code
# 1. Create a session with your key (returns an mcp_url)
curl -s -X POST https://api.virtmcu.com/v1/sessions \
  -H "Authorization: Bearer $VIRTMCU_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"world":"st_usart_pair"}'
#  -> {"session_id":"…","mcp_url":"<MCP_URL>","expires_at":"…"}

# 2. Point Claude Code at that session
claude mcp add --transport http virtmcu "<MCP_URL>" \
  --header "Authorization: Bearer $VIRTMCU_API_KEY"
Cursor
// .cursor/mcp.json — paste the mcp_url from step 1
{
  "mcpServers": {
    "virtmcu": {
      "url": "<MCP_URL>",
      "headers": { "Authorization": "Bearer YOUR_VIRTMCU_KEY" }
    }
  }
}

The session's mcp_url is bearer-protected and scoped to keys you own — only your agent can drive it.

Hand your agent a chipGrab a key and ask your AI to build something.
Get your API key