Skip to content

docs: Muse using a home residential-IP browser via the switchboard - #8

Merged
thepagent merged 8 commits into
openabdev:mainfrom
chaodu-agent:docs/reference-architecture-muse-home-browser
Oct 26, 2026
Merged

thepagent merged 8 commits into
openabdev:mainfrom
chaodu-agent:docs/reference-architecture-muse-home-browser

Conversation

@chaodu-agent

@chaodu-agent chaodu-agent commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Muse's built-in browser runs in Muse's own environment: it shows that environment's network address and holds none of the user's logins. This adds docs/reference-architecture-muse-home-browser.md, a reference for the use case Muse browses from a home residential IP, with the home browser profile's cookies, instead of its built-in browser.

The home computer is outbound-only and Muse cannot enter the home network, so neither can reach the other. openab-sb is where they meet: the home computer dials /vm/attach, Muse calls POST /mcp/<computer>, and the per-caller allowlist limits Muse to browser tools.

The doc covers the problem, roles (Muse as caller vs. muse-vm as computer), components, call flow, openab-sb.toml with a browser-only allowlist, the oab-instance-mcp --switchboard … --upstream browser=… invocation, exposure options, verification and trust/risk.

Architecture

flowchart LR
    subgraph cloud["Cloud"]
        muse["Muse agent<br/>remote MCP client<br/>Bearer client token"]
        grok["Grok Bot<br/>remote MCP client<br/>own Bearer token"]
        dots["OpenAI Dots<br/>remote MCP client<br/>own Bearer token"]
        duet["Claude Duet<br/>remote MCP client<br/>own Bearer token"]
    end

    subgraph edge["Switchboard host (you run it)"]
        front["TLS front<br/>tailscale serve (PoC)<br/>or a public tunnel"]
        sb["openab-sb<br/>POST /mcp/macmini<br/>allowlist: browser_* only"]
        front --> sb
    end

    subgraph home["Home — outbound only"]
        subgraph mac["macmini (logged-in Aqua session)"]
            imcp["oab-instance-mcp<br/>--switchboard … --switchboard-profile desktop<br/>--upstream browser=…"]
            pw["Playwright MCP :8794<br/>loopback"]
            chromium["Chromium (headed)<br/>persistent profile"]
            imcp -- "loopback MCP" --> pw --> chromium
        end
    end

    muse -- "HTTPS, Bearer" --> front
    grok -- "HTTPS, Bearer" --> front
    dots -- "HTTPS, Bearer" --> front
    duet -- "HTTPS, Bearer" --> front
    imcp == "WSS /vm/attach<br/>dialled by macmini<br/>Bearer computer secret" ==> front
Loading

Both sides dial out; nothing at home listens. Calls flow Muse → switchboard → macmini → Playwright MCP → Chromium, so the browser acts from the home residential IP with that profile's cookies and sessions.

Checked against source

  • instance-mcp Switchboard.client serves server.scoped(to: profile) with upstreams kept, so --switchboard-profile desktop carries the 15 browser_* tools (ToolProfile.desktopBrowserTools).
  • --switchboard exists only in the Swift daemon; the Linux Rust node (poc/reverse-attach-linux) has no switchboard mode. The doc says so.

Not verified

  • No end-to-end run with Muse. Whether a given Muse deployment can add a remote MCP server with a custom Authorization header is stated as a prerequisite, not confirmed.
  • The TOML snippet was not run through openab-sb check.
  • Docs only; no code changes.

Callers

Muse is the worked example. Grok Bot, OpenAI Dots and Claude Duet are drawn as additional callers (own [[client]] token and allowlist each). Not yet checked: that each can add a remote MCP server with a custom Authorization header.

PoC deployment (as observed)

The switchboard runs on its own tailnet host, p1 (Ubuntu, systemd), and is published by
tailscale serve on port 443, tailnet only. The Mac mini is just an outbound-only computer: it dials
wss:// to p1 and nothing at home listens.

flowchart LR
    muse["Muse<br/>client: muse<br/>Bearer token<br/>client-only tailnet member"]
    owner["Owner CLI / Connect<br/>client: pahud<br/>allowlist: * on *"]

    subgraph p1["p1 (Linux, tailnet)"]
        ts["tailscale serve<br/>https :443 (tailnet only)<br/>→ 127.0.0.1:8796"]
        subgraph svc["systemd: openab-sb.service (openab-sb)"]
            sb["openab-sb 0.2.0<br/>127.0.0.1:8796<br/>POST /mcp/macmini<br/>GET /vm/attach"]
        end
        ts --> sb
    end

    subgraph mini["Pahud's Mac mini (outbound only)"]
        subgraph imp["LaunchAgent dev.openab.instance-mcp (oab-instance-mcp)"]
            imcp["oab-instance-mcp 0.8.0<br/>--switchboard wss://p1.‹tailnet›.ts.net/vm/attach<br/>--switchboard-profile desktop<br/>--upstream browser=…:8794"]
        end
        subgraph pwp["LaunchAgent dev.openab.instance-mcp.pw-mcp (Playwright MCP)"]
            pw["Playwright MCP<br/>127.0.0.1:8794"]
            chromium["Chromium (headed)<br/>persistent profile<br/>home residential IP"]
            pw --> chromium
        end
        imcp -- "loopback MCP" --> pw
    end

    muse -- "HTTPS p1.‹tailnet›.ts.net/mcp/macmini<br/>Bearer (via Muse CONNECT proxy)" --> ts
    owner -- "same route" --> ts
    imcp == "WSS /vm/attach<br/>dialled by macmini<br/>Bearer computer secret" ==> ts
    chromium -- "outbound web traffic" --> web[("Websites<br/>see the home IP")]
Loading

What Muse can call is the intersection of two filters:

Layer Set
oab-instance-mcp profile desktop (computer ceiling) sys_info, screenshot, mouse, key, osascript, and 15 browser_* (20, plus vm_status = 21 as seen by the owner client)
[[client]] muse allowlist in openab-sb.toml sys_info, screenshot, and 8 browser tools: browser_navigate, browser_snapshot, browser_click, browser_type, browser_press_key, browser_wait_for, browser_tabs, browser_take_screenshot
Muse sees those 10, plus vm_status (always present) = 11, as listed by Muse on 2026-10-26 (before the move to p1)

Observed on the p1 deployment: openab-sb is active under systemd; the Mac mini attached after the
URL change; /readyz/macmini is 200; /computers shows macmini as attached and ready; the owner
client's tools/list through p1 returns 21 tools. A first request to a new tailscale serve
hostname can hang while the certificate is issued.

Two things the move surfaced. The computer needs to resolve the *.ts.net name: the Mac mini had
Tailscale DNS (MagicDNS) off until it was turned on. And Muse can only call hosts its owner has
registered, so the new host needs a new registered connection.

Not verified: a public front with a Cloudflare certificate, and "residential" in the strictest sense (the
address is on the same consumer-ISP ASN as the Mac mini, which is an inference, not a proof). Note
screenshot captures the whole desktop, not only the browser.

Muse results (2026-10-26)

Reported by Muse from its connector docs and a live check against this PoC:

  • Reachability: Muse's VM is a client-only tailnet member (enrolled 2026-10-03) and reaches the switchboard through its runtime HTTP CONNECT proxy, TCP only. The tailnet route works, so no public front is needed. The *.ts.net certificate is accepted.
  • Connector: not a native pasted-URL tool. Muse uses CLI connector code (muse.exec) with a credential registered by the owner for specific api_hosts; the model sees only a surrogate token. Moving the switchboard to another host needs a new registered connection.
  • Stock template limits: it refuses ports other than 443 and times out at 45 s (the switchboard allows 60 s). A bespoke client works on :8445 today.
  • Live results: tools/list returned 11 tools in 0.24 s; sys_info worked (macOS 15.7.4, accessibility=false); mouse was refused by switchboard policy ("not allowed for muse on macmini"), not as "unknown tool"; screenshots of about 0.9 MB arrived intact.
  • Still open: Cloudflare-certificate acceptance. "Residential" in the strict sense stays an inference from a consumer-ISP ASN.
  • Operating notes: a client for a tailnet-only host needs Muse's tailnet proxy, which Muse handles with a small wrapper because the connector descriptor has no proxy setting. "Always allow" is a network rule for the tailnet domain and its subdomains, not a credential scope, and can be narrowed in Muse Settings > Permissions. A token can be rotated on the existing connection without a new host registration. Disconnecting a connector does not revoke its token on the switchboard.

Muse results against p1 (2026-10-26)

Reported by Muse after the switchboard moved to p1 and the owner registered the new host:

  • Stock template works unchanged on port 443, but only through Muse's tailnet proxy (egress proxy host, port 3130). Through the default egress proxy it fails in about 0.4 s, because the tailnet-only name is not reachable there. Port 443 alone does not make a tailnet host reachable.
  • tools/list: 11 tools, no mouse, key, exec or browser_evaluate. mouse is refused by policy as a normal tool result; the server stays connected.
  • IP-echo: the returned address differs from Muse's own egress address and belongs to AS18616, Natural Wireless, LLC (hosting, mobile and proxy flags false), the same ASN as the Mac mini's own egress. So the browser call leaves from the Mac mini's network, on consumer ISP egress rather than a datacenter. The address was withheld.
  • Screenshots through p1: screenshot (whole desktop) 2.7 s, JPEG 1920x1080, about 165 KB; browser_take_screenshot 0.8 s, PNG about 7.5 KB. Both intact.
  • Persistent profile: a signed-in site loaded its signed-in interface, with no login wall or captcha. No account details were recorded.
  • Latency: list-tools 0.8 to 1.1 s; browser_navigate 2.7 s to 10.9 s; first manual initialize 17 s. Nothing over the stock template's 45 s.

@chaodu-agent chaodu-agent changed the title docs: reference architecture for an agent driving a home computer's browser docs: Muse using a home residential-IP browser via the switchboard Oct 26, 2026
@thepagent
thepagent merged commit 022b06c into openabdev:main Oct 26, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants