Skip to content

Remote over SSH

To keep your parts on a home server and design from a laptop, run the MCP server over SSH. Every MCP client can start a stdio server, and ssh is one: the client runs ssh you@server, and SSH does the rest. Login and encryption come from SSH keys you probably already have, so there are no certificates, tokens or open ports to set up.

For how SSH compares with local and HTTP mode, see Which mode?.

The server must be macOS or Linux (the forced command needs a POSIX sshd; on Windows, run the server in WSL2 or use HTTP). The laptop can be anything with an OpenSSH client, Windows 10/11 included: its built-in ssh.exe works for the MCP connection, pull and push.

Set it up

1. On the server, install b123d-print with uv (on Linux also install bubblewrap, the sandbox):

uv tool install b123d-print

Note

SSH mode needs b123d-print 0.2.0 or later.

2. Copy the laptop's public key to the server (e.g. scp ~/.ssh/id_ed25519.pub server:laptop.pub), then on the server:

b123d-print setup-ssh --key laptop.pub --workspace laptop --add

That creates the workspace ~/parts/laptop, adds one line to ~/.ssh/authorized_keys and prints the client configuration to match. Without --add it only prints the line, for you to add yourself. Running it again changes nothing; with another --workspace it replaces that key's line. --host sets the name clients reach the server by (default: its FQDN).

3. On the laptop, check that the key works. This also accepts the server's host key, which the MCP client cannot do for you:

ssh you@server version

It prints the version, the workspace and the sandbox. Then add the server to your client. Claude Code:

claude mcp add b123d-print -- ssh you@server

Claude Desktop, Cursor (~/.cursor/mcp.json), Gemini CLI and most others:

{"mcpServers": {"b123d-print": {"command": "ssh", "args": ["you@server"]}}}

VS Code (.vscode/mcp.json):

{"servers": {"b123d-print": {"type": "stdio", "command": "ssh", "args": ["you@server"]}}}

If the key is not your default one, add "-i", "/home/you/.ssh/b123d_print" before you@server, or give the server a Host entry in ~/.ssh/config. A key with a passphrase needs ssh-agent: the MCP client cannot type it.

Done. Repeat step 2 for each machine, with its own key and workspace name.

What the line allows

restrict,command="/home/you/.local/bin/b123d-print ssh-serve --workspace /home/you/parts/laptop --dest you@server" ssh-ed25519 AAAA... laptop

sshd runs that command whatever the client asks for (a forced command), and restrict turns off terminals and every kind of forwarding. ssh-serve then answers only four requests:

The client runs It gets
ssh you@server (what the MCP client does) the MCP server, in that workspace
ssh you@server pull <part> --tree [--formats ...] [--variant ...] the whole part, script, out/ and ref/ (what b123d-print pull uses), read-only; without --tree only its out/ files (what 0.3.0 clients ask for)
ssh you@server push <part> <file> [--overwrite] stores what it sends as parts/<part>/ref/<file>, a model to remix (what b123d-print push uses): STL, 3MF or STEP only, up to 50 MB, nowhere else
ssh you@server version the version, workspace and sandbox

Anything else (a shell, scp, sftp, rsync, other options for the server) is refused. The workspace comes from the line on the server, never from the client, so a machine's key reaches only its own workspace. Builds still run in the sandbox.

To revoke a machine, delete its line from ~/.ssh/authorized_keys.

Per machine, not per tool

SSH decides by key, and any program running as you on the laptop can use your key: a second AI tool there gets the same access as the first. That is the same as running the server locally, but it means SSH cannot give two tools on one machine different access. For that, give each tool its own key (with -i) and its own line, or use HTTP.

Use a key that is only for b123d-print if the same key also logs you in to that server: setup-ssh refuses to turn a key with normal login access into a restricted one (sshd uses only the first line for a key). ssh-keygen -t ed25519 -f ~/.ssh/b123d_print makes one.

Get the files

The files the server writes stay on the server, a working copy that is not yours: bring the part home. download_part (and export) end with the command that copies it to the laptop, for example:

b123d-print pull bracket --from you@server

Run it in the project folder: it writes the same layout a local install does, parts/bracket/bracket.py, parts/bracket/out/... and parts/bracket/ref/.... --formats 3mf and --variant <key> narrow the out/ files. The key allows nothing but this, the MCP server, push and version: no shell, ssh session or scp, and the results tell the agent so.

pull runs on the laptop (install b123d-print there too, or use uvx --from b123d-print b123d-print pull ...) and uses the same SSH key. -o <folder> picks the project folder (default: the current folder); --ssh 'ssh -i ~/.ssh/b123d_print -p 2222' passes options to ssh. On Windows, backslashes in --ssh are path separators and quotes group words: --ssh 'ssh -i C:\Users\you\.ssh\b123d_print'.

The other way, a model to remix goes to the server with push:

b123d-print push bracket.stl --part bracket --to you@server

export(..., embed=true) instead puts each file up to 2 MB (8 MB in all) into the tool result, over SSH as well as locally; it costs a lot of context, so it is off by default.

SSH workspaces are folders you chose on the server (setup-ssh --workspace), so the server never removes them on its own (retention is for HTTP workspaces); clean them up yourself when you no longer need them.

A server older than 0.3.1 does not know pull --tree: pull then says to upgrade it.

Several machines at once

Each SSH connection runs its own server process. The build limit (B123D_PRINT_MAX_BUILDS, default half the CPU cores) holds across all of them together, through lock files in ~/.cache/b123d-print/build-slots/: further builds wait their turn.

Settings come from the server's user config (~/.config/b123d-print/config.toml) and each workspace's b123d-print.toml. Over SSH, use_printer saves the printer and material in the workspace's b123d-print.toml, so one machine never changes another's printer.

If it does not work

Symptom Fix
The client says the server closed or never started run ssh you@server version in a terminal and fix what it says
Permission denied (publickey) the client uses another key: add -i, or check the line is in the right user's authorized_keys
Host key verification failed run ssh you@server version once and accept the key
The client hangs, or reports invalid JSON your shell startup files on the server print something (e.g. echo in .zshenv or .bashrc): sshd runs the command through your shell, and anything printed breaks the MCP stream
refused: ... the key allows only the three requests above; for a shell, log in with another key
no ... files for part from pull export the part first