Expand description
isb serve: the MCP server layer, with the tools supplied by the embedder.
Security model:
- TCP listeners bind loopback only. Remote clients arrive through a cloudflared tunnel, behind a Cloudflare Access application with Managed OAuth; Cloudflare runs the OAuth flow and isb stays the resource origin.
- With Access configured, every
/mcprequest must carry a validCf-Access-Jwt-Assertionfor the application’s audience, so a request reaching the port by another route is still refused. - A TCP listener without Access is refused unless the embedder opts in, and
then only accepts browser requests whose
Originis localhost, which blocks DNS rebinding. - The unix socket (0600, in a 0700 directory) is the trusted local path:
filesystem permissions are the gate, and its callers are
Caller::Local, whichCaller::is_trustedreports. /healthznever requires auth and reveals only what the embedder puts in it.- A listener can carry extra
Routes(isb servemounts the identity endpoints,/api/v1/auth/*, this way). They authenticate their own callers; with Access configured they sit behind it, as/mcpdoes. Listener::public_routesare served ahead of Access, for requests that carry their own credential (app webhooks, signed by the sender).Listener::previewsees every request first, and takes the ones addressed to a preview host (a workspace port’s own origin), which it authenticates itself; nothing of isb’s (UI, API, headers) is served on those hosts.
Re-exports§
pub use access::AccessValidator;pub use access::Identity;pub use http::Shutdown;pub use mcp::Authenticated;pub use mcp::Caller;pub use mcp::Hooks;pub use mcp::Registry;pub use mcp::Tool;pub use mcp::ToolHandler;pub use mcp::ToolPolicy;
Modules§
- access
- Cloudflare Access JWT validation.
- aliases
- Argument spellings a newcomer reaches for, mapped to the canonical ones before a call is authorized. The schemas and docs show only the canonical names; the aliases make a guess work instead of failing on an unknown field.
- client
- Calling
isb servetools from the CLI over its unix socket. - http
- A minimal synchronous HTTP/1.1 server: one request per connection, a thread per connection, a hard cap on connections, and every read and write bounded.
- mcp
- MCP over Streamable HTTP, hand-rolled JSON-RPC 2.0.
- openapi
GET /api/v1/openapi.json: the whole HTTP surface as one OpenAPI 3.1 document, generated from what serves it:- service
- Installing
isb serveas a systemd user service. - ssh
- SSH without open ports:
GET /orgs/<org>/api/v1/ssh?instance=NAMEupgrades to a websocket whose binary frames are an SSH connection’s bytes, both ways, to an sshd the embedder starts inside the instance (isb serve:sshd -ithrough incus exec, docs/guides/ssh.md). Nothing in the instance listens, and nothing on the host opens a port: the websocket is the daemon’s own, behind its usual authentication. - ssh_
config - What
isb ssh-configwrites:Hostblocks whoseProxyCommandisisb ssh-proxy, and a known_hosts file of the instances’ host keys under each block’sHostKeyAlias, so plainssh,scp, editors andherdr machine addpin the right key without ever trusting on first use. - tailnet
- Tailnet identity, for
isb serve --superadmin-tailnetand orgs’ agent identities: who is at the other end of a TCP connection from a tailnet address, asked of the local tailscaled. - terminal
- A terminal over a websocket:
GET /orgs/<org>/api/v1/terminal?app=NAME(or?instance=NAME) upgrades to a websocket bridged to a pseudo-terminal the embedder opens (isb serve: a shell in one of the app’s replicas, or in an instance of the org).
Structs§
- Listener
- One address the server answers on, with its own gate and tool policy.
Enums§
Functions§
- default_
socket_ path - Where the CLI and the server meet:
$ISB_SERVE_SOCKET, else$XDG_RUNTIME_DIR/isb/serve.sock, else a per-uid directory under /tmp. On macOS, where the daemon runs inside theisb machine, it is that machine’s forwarded socket,~/.isb/machine/isb/serve.sock. - handler
- What a listener’s requests go to:
/healthz,/mcp, the REST surface and its routes, through its hooks and policy. - serve
- Serve until SIGINT or SIGTERM.
- serve_
shared serve, with a registry the embedder also keeps (to serve it on listeners it adds later,spawn_private).- serve_
until - Serve until
shutdownis triggered, then give in-flight requests up to 10s. Every listener is bound before any is served, so a bad one fails startup. - serve_
until_ shared serve_untilwith a shared registry.- spawn_
private - Serve
handleron a private (RFC 1918) address that is not loopback, such as an org bridge’s, untilstop(or a bind failure, returned at once). The caller’shandlerdecides who gets in: nothing about such an address keeps anyone out.