Give your AI agent a shell on every Pi.
raspberry-pi-connect-mcp lets Claude Code, Claude Desktop or any MCP client run commands on your Raspberry Pi devices through the Raspberry Pi Connect remote shell. If the Pi shows up in Connect, the agent can use it.
- SSH
- port forwarding
- VPN
- public IP
behind
NAT!
> check disk space on lab-pi and restart the sensor service ● rpi-connect · list_devices lab-pi online shell ✓ kiosk online shell ✓ garage offline ● rpi-connect · run_command(lab-pi, "df -h /") Filesystem Size Used Avail Use% Mounted on /dev/root 29G 11G 17G 40% / exitCode 0 ● rpi-connect · run_command(lab-pi, "sudo systemctl restart sensord") exitCode 0 ✦ lab-pi has 17G free (40% used). sensord restarted cleanly.
how it worksConnect has no shell API. So it uses the web one.
The server drives the Connect web UI with a headless Chrome: it opens the device's remote-shell page, hooks the xterm.js terminal, types your agent's commands and reads the output back.
Sign in once
A Chrome window opens, you log in to Connect by hand, and the session cookies are saved to your machine.
Register the server
Add it to Claude Code, Claude Desktop or any MCP client with one command or a few lines of JSON.
Ask for things
The agent lists your devices and runs commands on them, getting back the output and the exit code.
featuresSmall server, real shell.
Everything you'd expect from sitting at the Pi, minus the sitting.
RPI_CONNECT_ALLOW restricts the agent to the devices you name.setupThree commands from npm.
You need Node.js 18+, a Raspberry Pi Connect account with remote shell enabled on your devices, and Chrome for Testing (installed below, no sudo).
# 1. a Chrome the server can drive npx @puppeteer/browsers install chrome@stable --path ~/.cache/rpi-connect-mcp # 2. sign in by hand in the window that opens npx -p raspberry-pi-connect-mcp raspberry-pi-connect-mcp-login # 3. register it with Claude Code claude mcp add rpi-connect -- npx -y raspberry-pi-connect-mcp
git clone https://github.com/kritzerenkrieg/raspberry-pi-connect-mcp.git cd raspberry-pi-connect-mcp npm install npx @puppeteer/browsers install chrome@stable --path ~/.cache/rpi-connect-mcp npm run login
{
"mcpServers": {
"rpi-connect": {
"command": "npx",
"args": ["-y", "raspberry-pi-connect-mcp"],
"env": { "RPI_CONNECT_ALLOW": "lab-pi,kiosk" }
}
}
}Login saves the session to ~/.config/rpi-connect-mcp/session.json (mode 600). Connect cookies are session-only, so sign in again when the tools say the session expired.
toolsFive tools. That's the API.
device can be the exact name, a unique part of the name, or the device UUID.
list_devicesDevices on the account: id, name, client version, last seen, online, and whether remote shell and screen sharing are allowed.
run_command(device, command, timeout_sec=60)Runs a bash command line and returns { device, exitCode, output }. Still running at the timeout? You get timedOut: true and the output so far.
send_keys(device, keys)Sends raw keystrokes (\n, \t, \x03 Ctrl-C, \x04 Ctrl-D, \x1b[A Up…) and returns the screen.
read_screen(device, lines=0)The current terminal screen plus a little scrollback.
close_session(device)Closes the shell session for a device.
configurationEnvironment variables.
All optional.
| Variable | What it does |
|---|---|
| RPI_CONNECT_ALLOW | Comma-separated name substrings. Only matching devices can be used. |
| RPI_CONNECT_HEADED=1 | Show the browser window, for debugging. |
| RPI_CONNECT_CHROME | Path to a Chrome binary. |
| RPI_CONNECT_SESSION | Path to the saved session file. |
| RPI_CONNECT_PROFILE | Chrome profile directory used by the login step. |
read this bitIt's a real shell. Treat it like one.
This hands an AI agent a shell on your devices with the privileges of the Connect user, which often includes passwordless sudo.
- Use
RPI_CONNECT_ALLOWto limit which devices the agent can use, and keep your MCP client's per-call approval prompts on. - Keep
session.jsonprivate. Anyone holding it can use your Connect account until the session expires. - Commands that wait for input (sudo passwords, editors,
[Y/n]) will time out inrun_command. Usesend_keysandread_screen, or pass-ystyle flags. - The server doesn't try to get around bot detection. If Cloudflare challenges the session, sign in again by hand.