Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,20 @@ older builds are on the
> "mcpServers": {
> "arduino": {
> "command": "node",
> "args": ["/path/to/arduino-mcp-extension/bridge/arduino-agent-bridge.js"]
> "args": ["<install>/resources/mcp-bridge/bridge/arduino-agent-bridge.js"]
> }
> }
> }
> ```
>
> It needs no token configuration (it reads `~/.arduinoIDE/mcp-token` itself)
> and no dependencies. See [the bridge README](arduino-mcp-extension/bridge/README.md)
> for auto-launch and other options.
> Releases after v0.6.1 ship the bridge inside the app: `<install>` is the
> unzipped folder on Windows/Linux; on macOS the path is
> `Arduino IDE.app/Contents/Resources/mcp-bridge/bridge/arduino-agent-bridge.js`.
> From a source checkout, use `arduino-mcp-extension/bridge/arduino-agent-bridge.js`
> after building the extension. It needs no token configuration (it reads
> `~/.arduinoIDE/mcp-token` itself) and no dependencies. See
> [the bridge README](arduino-mcp-extension/bridge/README.md) for auto-launch
> and other options.

> **Claude Code users:** the server sends workflow guidance automatically,
> and ships three slash commands (`/bringup`, `/debug-serial`,
Expand Down
20 changes: 15 additions & 5 deletions arduino-mcp-extension/bridge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,28 @@ is closed:
"mcpServers": {
"arduino": {
"command": "node",
"args": ["/path/to/arduino-mcp-extension/bridge/arduino-agent-bridge.js"],
"args": ["/path/to/mcp-bridge/bridge/arduino-agent-bridge.js"],
"env": { "ARDUINO_AGENT_PATH": "/path/to/Arduino IDE executable" }
}
}
}
```

Where to find it:

| Running from | Bridge path |
|--------------|-------------|
| Release, Windows / Linux | `<unzipped folder>/resources/mcp-bridge/bridge/arduino-agent-bridge.js` |
| Release, macOS | `Arduino IDE.app/Contents/Resources/mcp-bridge/bridge/arduino-agent-bridge.js` |
| Source checkout | `arduino-mcp-extension/bridge/arduino-agent-bridge.js`, after `yarn build` in `arduino-mcp-extension` |

Releases after v0.6.1 include the bridge; earlier zips don't, so use a checkout
with those. Either way the bridge sits next to the compiled extension modules it
loads (`../lib/common/`), which supply the offline tool list and answers.

No dependencies (node builtins only) and no token setup — it reads
`~/.arduinoIDE/mcp-token` itself, re-reading per request so it survives the IDE
regenerating the token on restart. Run it from a **built** checkout or install
(`yarn build` in `arduino-mcp-extension`): the offline tool list and answers
come from the compiled extension in `lib/`.
regenerating the token on restart.

## Options

Expand All @@ -62,7 +72,7 @@ Example on Windows:
"mcpServers": {
"arduino": {
"command": "node",
"args": ["C:/path/to/bridge/arduino-agent-bridge.js"],
"args": ["C:/Arduino/resources/mcp-bridge/bridge/arduino-agent-bridge.js"],
"env": { "ARDUINO_AGENT_PATH": "C:/Arduino/Arduino IDE.exe" }
}
}
Expand Down
27 changes: 27 additions & 0 deletions arduino-mcp-extension/test/bridge/bridge.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -310,3 +310,30 @@ test('a rejected token gives a readable tool error, and tools/list still answers
await ide.close();
}
});

test('release packaging ships the bridge with every compiled module it loads', needsLib, () => {
// The bridge loads ../lib/common/<name> at runtime; electron-builder's
// extraResources must copy each of those (and what they require) next to it.
const loaded = [...fs.readFileSync(BRIDGE, 'utf8').matchAll(/loadCompiled\('([\w-]+)'\)/g)].map((m) => m[1]);
assert.ok(loaded.length > 0);
const needed = new Set();
const visit = (name) => {
if (needed.has(name)) return;
needed.add(name);
const src = fs.readFileSync(path.join(LIB, `${name}.js`), 'utf8');
for (const m of src.matchAll(/require\("\.\/([\w-]+)"\)/g)) visit(m[1]);
};
loaded.forEach(visit);

const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '..', '..', '..', 'electron-app', 'package.json'), 'utf8'));
const resources = pkg.build.extraResources;
const bridgeEntry = resources.find((r) => r.from === '../arduino-mcp-extension/bridge');
const libEntry = resources.find((r) => r.from === '../arduino-mcp-extension/lib/common');
assert.ok(bridgeEntry && libEntry, 'electron-app extraResources must copy bridge/ and lib/common/');
assert.ok(bridgeEntry.filter.includes(path.basename(BRIDGE)));
for (const name of needed) {
assert.ok(libEntry.filter.includes(`${name}.js`), `extraResources is missing lib/common/${name}.js`);
}
// Same relative layout as the checkout, so the bridge's ../lib/common still resolves.
assert.strictEqual(path.posix.dirname(bridgeEntry.to), path.posix.dirname(path.posix.dirname(libEntry.to)));
});
17 changes: 17 additions & 0 deletions electron-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,23 @@
{
"from": "plugins",
"to": "app/plugins"
},
{
"from": "../arduino-mcp-extension/bridge",
"to": "mcp-bridge/bridge",
"filter": [
"arduino-agent-bridge.js"
]
},
{
"from": "../arduino-mcp-extension/lib/common",
"to": "mcp-bridge/lib/common",
"filter": [
"mcp-instructions.js",
"mcp-prompts.js",
"mcp-tool-router.js",
"mcp-tools.js"
]
}
],
"win": {
Expand Down
5 changes: 3 additions & 2 deletions skills/arduino-agent/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ skill adds the judgment that comes from real hardware sessions.

If the MCP config points at `http://127.0.0.1:3847/mcp` directly, the whole
server shows "failed to connect" whenever the IDE is closed. Prefer the stdio
bridge (`arduino-mcp-extension/bridge/arduino-agent-bridge.js` in the repo or
install): it always connects with the full tool list, starts the IDE when a tool
bridge (`resources/mcp-bridge/bridge/arduino-agent-bridge.js` inside a release
install newer than v0.6.1, or `arduino-mcp-extension/bridge/` in a built
checkout): it always connects with the full tool list, starts the IDE when a tool
needs it (with `ARDUINO_AGENT_PATH` set; otherwise it returns "open the IDE" as
a normal tool error), and recovers without a client restart.

Expand Down
Loading