WSL & containers
Connect an agent that runs in WSL, a devcontainer or on another machine to a Scalebrowser daemon on Windows: why localhost does not reach it, and what does.
An agent in WSL cannot reach the Windows daemon on 127.0.0.1, and the failure looks like a
dead daemon rather than a network boundary. This page is the way across.
Why the HTTP entry does not connect
WSL 2 runs as a virtual machine behind a network adapter of its own. Inside it, 127.0.0.1
is the Linux side. Windows forwards the other way (a service in WSL is reachable from
Windows on localhost) and not this way, so the entry that works in a Windows terminal fails
in a WSL one:
$ curl http://127.0.0.1:8787/health
curl: (7) Failed to connect to 127.0.0.1 port 8787: Connection refusedMirrored networking mode makes localhost shared, and it does fix this. It is a machine-wide change with its own trade-offs, so nothing here assumes it.
What works: start the daemon across the boundary
WSL can run Windows programs directly. Instead of reaching the daemon over the network, let your agent start it over stdio: the process attaches to the daemon the app is already running and relays to it, owning no browser of its own. Nothing is opened on the network, and no token goes into the file.
{
"mcpServers": {
"scalebrowser": {
"command": "/mnt/c/Users/<you>/AppData/Local/Programs/Scalebrowser/resources/daemon/scalebrowser-daemon.exe",
"args": ["--mcp-stdio", "--data-dir", "C:/Users/<you>/AppData/Local/Scalebrowser"]
}
}
}Two details decide whether this works:
The program is named with a Linux path, the data directory with a Windows one. WSL
resolves command on the Linux side, which is why it needs /mnt/c/.... The daemon that
starts is a Windows process and reads --data-dir with Windows rules. Forward slashes are
fine there; backslashes inside a JSON string are not, unless you double them.
/mnt/c assumes the default mount point. If you set automount.root in
/etc/wsl.conf, use yours.
The app fills both paths in for you under Settings → General → Connect an agent, on the "From WSL" tab.
--data-dir is what makes this land on the right daemon. Without it the process looks
in %ProgramData%\Scalebrowser, which is not where the desktop app keeps anything. It then
either attaches to whatever holds the address named in an old runtime.json there and
answers unauthorized to every call, or starts a second, empty daemon that responds
normally and knows none of your profiles. Since 0.9 it stops and names both directories
instead.
Devcontainers and other machines
A container has no access to the Windows filesystem, so it cannot start the program. The stdio route is out, and the daemon deliberately binds loopback only, so there is no address to point at either.
That case is what remote access is for: the daemon opens an outbound tunnel and your agent reaches it through a relay, wherever it runs. It is off until someone switches it on at the machine, in Settings → General → Remote access.
Checking which daemon you reached
One machine can hold more than one installation, and they are told apart by data directory, never by address. Ask the daemon which one it is:
curl -H "Authorization: Bearer $SCALEBROWSER_TOKEN" \
http://127.0.0.1:8787/v1/connection{
"native_addr": "127.0.0.1:8787",
"data_dir": "C:\\Users\\you\\AppData\\Local\\Scalebrowser",
"executable": "C:\\Users\\you\\AppData\\Local\\Programs\\Scalebrowser\\resources\\daemon\\scalebrowser-daemon.exe"
}If data_dir is not the one you meant, the port is being held by another installation. The
app moves up a port when something already holds 8787, so its real address is the
native_addr field of runtime.json in its own data directory.