The Node API (REST + MCP)
The node connects the public edge to tenant-private workloads. It exposes public application ingress, an OpenAPI-described REST surface, and an MCP endpoint over Streamable HTTP. REST, MCP, CLI, and console coverage are partial and do not expose every operation through every interface.
The control endpoint lives at https://api.tabbify.io behind HTTPS. Public
applications use https://app.tabbify.io/app/<uuid>/ or a configured custom
domain. Raw host ports are implementation details behind those edges.
REST surface
Every protected endpoint expects Authorization: Bearer <TABBIFY_TOKEN> — your
Tabbify API token — checked in constant time. GET /health, GET /openapi.json,
and GET /swagger-ui are open.
# Discover what's running across all supervisors
curl -H 'Authorization: Bearer <TABBIFY_TOKEN>' \
https://api.tabbify.io/v1/apps
# Start, stop, and reset app instances
curl -X POST -H 'Authorization: Bearer <TABBIFY_TOKEN>' \
https://api.tabbify.io/v1/apps/<uuid>/start
Current operations include application and supervisor reads, selected lifecycle
actions, topology, and asynchronous deployment status. Endpoint coverage changes
as slices are published, so /openapi.json is the source of truth for paths,
methods, request bodies, and response schemas in the deployed version. It is
browsable at /swagger-ui.
/app/{uuid} routing
This is the data path. The node derives an app's mesh address from its
UUID — blake3(uuid)[0:6] mapped into fd5a:1f02:...::1 — and dials it on port
8730 through the production relay route. No supervisor query or cache lookup is
needed; the node and supervisor compute the same address independently. See
Routing for the address scheme.
curl https://app.tabbify.io/app/0191e7c2-1111-7222-8333-444455556666/
GET /app/{uuid} proxies /; ANY /app/{uuid}/{*rest} forwards method, headers,
query, and body to the subpath. Bodies stream both directions with no
buffering — large uploads and downloads pass straight through, but a slow upstream
holds the connection (no per-hop timeout). An unreachable app returns 502; a
malformed UUID returns 400.
App ingress is public by default. A configured custom domain reaches the same workload through the TLS edge. Your application remains responsible for its own user authentication and authorization.
MCP tools
The same node serves MCP at /mcp. The server advertises the tools enabled in
the deployed version and authorized for the session. Coverage is intentionally
partial: do not assume that every console or REST operation has an MCP tool, or
that a tool name remains available without discovery. Let the client call MCP
tool discovery and use the returned names and schemas.
How apps get there
Deploy through the tabbify-io/deploy GitHub Action or run
tcli deploy --remote manually. Both submit an asynchronous request; the node
clones the selected revision, builds an OCI image, pushes it to the registry,
selects one eligible workload target, and activates a CPU-only Firecracker
microVM after the configured health gate passes. See the
deploy pipeline and the CLI reference.
Config and caveats
The node joins the mesh automatically — the coordinator address is baked into the joiner, so there is nothing to point it at. Requests authenticate with a Bearer token (your network token), or — for MCP clients — via the node's OAuth flow.
Connect an MCP client
The same node serves the Model Context Protocol alongside the REST API, at
https://api.tabbify.io/mcp. Interactive clients authorize via the node's full
OAuth 2.1 surface (/.well-known/oauth-protected-resource,
/.well-known/oauth-authorization-server, dynamic client /register,
/authorize, /token) — nothing to paste; a static Bearer token works for
headless/CI use. For step-by-step setup of Claude, OpenAI, and other clients,
see Connect an MCP client.
Deploy status and lifecycle reads describe current state. They are not a durable
release history, and application output is available only as a bounded local
tail when the selected host retains it. Production workload traffic uses the
managed relay. A self-hosted supervisor still needs NET_ADMIN, /dev/net/tun,
and /dev/kvm for Firecracker workloads. See Self-hosting a node.