Meshfleet v0.7.0 — Real-time push via SSE
Agents can now subscribe to their inbox via Server-Sent Events. Incoming P2P messages arrive in real-time instead of polling. Per-agent connection cap, backpressure handling, heartbeat keep-alive.
Meshfleet v0.7.0 — Real-time push via SSE
We just shipped v0.7.0 of the Agent Mesh MCP server. The new subscribe_inbox MCP tool lets agents receive P2P messages in real-time via Server-Sent Events instead of polling get_inbox. This post walks through what changed, why it matters, and how to use it.
Install v0.7.0 · Read the v0.7.0 design doc · Browse the API
What’s new
1. subscribe_inbox MCP tool
Until v0.7.0, agents received P2P messages by polling get_inbox(agent_id, since?) on a schedule. That works but has costs: latency (agents wake up, check inbox, find nothing, go back to sleep), CPU (polling is wasteful — most polls find nothing), and wasted agent time (an agent waiting for a result message can be blocked for minutes while polling).
subscribe_inbox(agent_id) solves that. It returns an SSE stream URL the agent opens via HTTP GET. When a new message arrives in the agent’s inbox, it’s pushed immediately.
const { stream_url } = await callTool("subscribe_inbox", { agent_id: "a2" });
// Open an HTTP GET to stream_url. Each event is SSE-formatted:
// event: message
// data: {"message_id": "...", "from_agent_id": "...", "payload": "...", "timestamp": ...}
Polling still works as a fallback. If SSE is unreachable (e.g. behind a proxy that buffers), the agent can continue to poll get_inbox with the same since parameter — there’s no behavioral change for existing callers.
2. How the SSE server works
The mesh starts a second HTTP listener alongside the MCP stdio transport, bound to 127.0.0.1:13579 by default. The MESHFLEET_SSE_PORT and MESHFLEET_SSE_HOST env vars override this. The listener accepts:
GET /inbox/:agent_id/stream— SSE stream of events for that agentGET /healthz— liveness check
Each connection sends a heartbeat comment every 30 seconds to keep the connection alive through proxies. Per-agent connection cap (default 5, configurable via setMaxConnectionsPerAgent for tests) prevents a misbehaving client from monopolizing the server.
Write failures drop the subscriber automatically — backpressure handling. If the underlying TCP socket is gone, the subscriber is removed on the next write attempt.
3. Integration with send_message
Every existing message path now triggers a push to active SSE subscribers. The send_message handler in src/index.ts calls notifySubscribers(to_agent_id, ...) after the message is persisted to the JSON ledger. This is additive — existing polling callers see no change.
// Old: poll
const { messages } = await callTool("get_inbox", { agent_id: "a2", since: lastSeen });
// New: subscribe
const { stream_url } = await callTool("subscribe_inbox", { agent_id: "a2" });
// ... open HTTP GET, receive events in real-time
Both paths are supported. Agents that want sub-second latency use subscribe_inbox. Agents that want simpler integration keep polling.
4. 15 new unit tests
src/realtime.ts has 15 unit tests covering: subscriber registration, per-agent cap enforcement, write failure detection, multi-event delivery, SSE format, shutdown, and idempotency. 90 total tests pass.
5. Version bumped to 0.7.0
package.json and the server’s MCP name field both report 0.7.0. The startup log now reports the SSE port when the HTTP server starts successfully.
Why this matters
The mesh’s whole point is agents that collaborate in real-time. Polling adds a gap — when agent A asks agent B a question, B doesn’t see it until its next poll. With SSE, the latency drops from “however often you poll” to “however long the network takes” — usually single-digit milliseconds on localhost.
For the common case (orchestrator + 2-3 specialists), this means the orchestrator can ask a question, get an answer, and follow up — all in a single user-visible interaction. Without SSE, that loop is bounded by the polling interval.
How to use it
- Update the mesh:
cd ~/.config/opencode/mcp-servers/agent-mesh && git pull && npm install && npm run build - Restart OpenCode so the new MCP server process is picked up
- Agents call
subscribe_inboxinstead of pollingget_inbox— same data, lower latency - Fall back to polling if SSE is unreachable — there’s no behavioral change
See docs/api for the full tool reference.
What’s next
v0.7.0 is the last feature before v1.0. The plan:
- v0.7.x hardening: per-fleet timeouts, automatic retry with exponential backoff, heartbeat watchdog
- v0.8 embedding routing: smart routing via local embedding model
- v1.0 stable: API freeze, schema versioning, npm publish, optional auth token
Roadmap: meshfleet.app/next
Meshfleet v0.7.0 is MIT licensed. Use it, fork it, ship it in your product. No attribution beyond the license file.