Container Proxy

The external interface of the container proxy: the WebSocket paths a provider’s server opens on port 14979 of every container it runs, the messages each carries, and the rules under which each opens and ends.

A provider places one program, the container proxy, beside the entrypoint of every container it runs, and it reaches the container through the proxy alone. The proxy is not a layer of the protocol; it is a binary whose external interface this section defines at this revision. This section does not define what the proxy offers the program beside it.

  • The listener. The proxy listens on TCP port 14979 on every interface of the container. Every path this section defines is a WebSocket path on that listener, carried as WebSocket provides, under the ws URI scheme. The server opens every path. The proxy opens no connection.
  • Messages. Every message on every path is exactly one WebSocket binary data frame. A message carries what its path defines and nothing more: no header, no scope, no channel, and no finish. Each party ignores a text data frame.
  • No handshake. The WebSocket upgrade is the whole of a path’s opening. No message precedes the first message the path defines.
  • Asks and answers. The proxy sends every ask on /requests. Each ask carries a channel, a u32 that the proxy mints and that is unique among the asks it has sent and the server has not yet answered. The server answers an ask by opening the ask’s own path with that channel in the path, by sending the answer as the messages that path defines, and by closing the connection. The clean close is the end of the answer. A path that the proxy or the server closes cleanly with no message before the close states that the ask was not served.
  • Openings. /requests accepts one connection at a time; while one is open, the proxy refuses a second with HTTP status 409 before the upgrade. The proxy accepts an answer path for a channel that it has announced and that the server has not yet opened; it refuses a channel it does not know with 404, and a second opening of a known channel with 409, each before the upgrade. The /fuse/mount, /filesystem/*, /agent/* and /tool/* paths accept every opening the server makes.
  • Endings. A clean close — the WebSocket closing handshake — states that an answer is complete or that a session is over. An abrupt end states that the connection died. The two are distinguished, and each path’s page states what each means there. When /requests ends, cleanly or abruptly, every ask announced on it and not yet answered is lost to the server; each kind’s page states what the proxy does with such an ask.
  • No timeout. No path defines a timeout. A connection on which no message has arrived for any length of time remains open.
PathCarries
/requestsevery ask the proxy makes; no message in return
/mcp/list-tools/{channel}exactly one MCP response frame
/mcp/list-resources/{channel}exactly one MCP response frame
/mcp/call-tool/{channel}exactly one MCP response frame
/mcp/read-resource/{channel}exactly one MCP response frame
/mcp/notifications/{channel}one frame per notification, for the life of the path
/vault/get/{channel}exactly one vault answer
/vault/set/{channel}exactly one vault answer
/vault/delete/{channel}exactly one vault answer
/vault/lock/{channel}exactly one vault answer, sent when the lock is held
/vault/unlock/{channel}exactly one vault answer
/fuse/mountone mount to make; exactly one answer, sent when the mount is serving
/fuse/stat/{channel}exactly one answer for a mounted entry
/fuse/read/{channel}exactly one answer for a mounted file
/fuse/write/{channel}exactly one answer for a mounted file
/fuse/list/{channel}exactly one answer for a mounted directory
/fuse/remove/{channel}exactly one answer for a mounted entry
/fuse/rename/{channel}exactly one answer for a mounted entry
/fuse/mkdir/{channel}exactly one answer for a mounted directory
/command/{channel}one frame per item the command produces
/postgres/{channel}the bytes of one database connection, in both directions
/filesystem/treethe paths to leave out; the tree as a snapshot and its changes
/filesystem/readone file out of the container
/filesystem/writeone file into the container
/agent/registerthe agent, once; exactly one answer
/agent/runa prompt; the chunks of one loop
/agent/schemaexactly one answer carrying the agent’s JSON Schema
/agent/enqueuea message for the loop’s queue; exactly one answer, its fate
/agent/dequeueexactly one answer stating whether the queue held anything
/tool/list-toolsMCP params; exactly one MCP response frame
/tool/list-resourcesMCP params; exactly one MCP response frame
/tool/call-toolMCP params; exactly one MCP response frame
/tool/read-resourceMCP params; exactly one MCP response frame
/tool/notificationsone frame per notification of the container’s MCP server, for the life of the path