Method 3: Networked Model Context Protocol (MCP) Intermediary Bus
Leveraging the open Model Context Protocol over Server-Sent Events (SSE) and Redis to turn multiple Antigravity instances into a coordinated cluster with shared mailboxes and atomic file locks.
1. Architecture & Coordination Flow
Because Google Antigravity natively implements MCP client bindings (agy mcp add), instances on separate machines can connect to a shared networked MCP server over Streamable HTTP / SSE.
(Dev Lead)"] A2["Instance 2: dell5040
(Linux Build Node)"] A3["Instance 3: Cloud VM
(GPU Inference)"] end subgraph Bus ["Central Inter-Agent MCP Server (FastMCP :8080/sse)"] P["Presence & Discovery
register_presence"]
M["Mailbox & Messagingsend_agent_message"]
Q["Task Queue & Pollingclaim_task / poll_inbox"]
L["Distributed Lock Manageracquire_distributed_lock"]
end
subgraph Storage ["Durable State Store"]
R[("Redis (Pub/Sub & Streams)or PostgreSQL / SQLite WAL")] end A1 -- "agy mcp (SSE/HTTP)" --> Bus A2 -- "agy mcp (SSE/HTTP)" --> Bus A3 -- "agy mcp (SSE/HTTP)" --> Bus Bus <--> Storage
2. The Core Challenge: MCP is Request-Response (Client-Driven)
In the standard MCP specification, the agent is the client and initiates calls. A server cannot unilaterally "push" a prompt into an idle LLM's brain. To make multi-agent swarms autonomous, systems use four proven mitigation patterns:
Pattern A: Blocking Long-Poll (`poll_inbox`)
The agent calls poll_inbox(timeout_sec=60) at the end of its turn. The MCP server holds the HTTP connection open until Redis publishes a task, returning immediately when work arrives.
Pattern B: Hybrid Webhook Trigger
The MCP server receives a message, enqueues it, and immediately makes a local HTTP call to agy agentapi send-message on the target machine, instantly waking the agent to claim the task.
Pattern C: Distributed Redlock / CAS Locks
Agents acquire atomic resource locks before modifying shared files or Git repositories, preventing merge conflicts across concurrent workers.
Pattern D: Emerging A2A & SEP-1686
The emerging Agent-to-Agent (A2A) protocol and MCP SEP-1686 Task Primitives standardize asynchronous task state machines (SUBMITTED → WORKING → COMPLETED).
3. Complete Production FastMCP Server Code
"""
inter_agent_bus.py - Networked MCP Server for Antigravity Swarms
Requirements: pip install mcp redis
Run: python3 inter_agent_bus.py (Listens on port 8080 via SSE)
"""
import json
import time
from typing import List, Dict, Optional
from mcp.server.fastmcp import FastMCP
import redis
# Initialize FastMCP server with SSE transport
mcp = FastMCP("Antigravity-Agent-Bus", host="0.0.0.0", port=8080)
r = redis.Redis(host="localhost", port=6379, db=0, decode_responses=True)
@mcp.tool()
def register_presence(agent_id: str, machine_name: str, capabilities: List[str]) -> str:
"""Register this Antigravity instance and advertise capabilities."""
data = {
"agent_id": agent_id,
"machine_name": machine_name,
"capabilities": json.dumps(capabilities),
"last_seen": time.time()
}
r.hset(f"swarm:agents:{agent_id}", mapping=data)
r.expire(f"swarm:agents:{agent_id}", 300) # 5 min TTL heartbeat
return f"Instance {agent_id} ({machine_name}) registered."
@mcp.tool()
def list_active_agents() -> List[Dict]:
"""Discover all active peer Antigravity agents in the swarm."""
keys = r.keys("swarm:agents:*")
agents = []
for k in keys:
node = r.hgetall(k)
if node:
node["capabilities"] = json.loads(node.get("capabilities", "[]"))
agents.append(node)
return agents
@mcp.tool()
def send_agent_message(from_agent: str, to_agent: str, task_name: str, payload_json: str = "{}") -> str:
"""Enqueue a task envelope for a specific target agent or broadcast ('*')."""
envelope = {
"from": from_agent,
"to": to_agent,
"task_name": task_name,
"payload": json.loads(payload_json),
"timestamp": time.time()
}
raw = json.dumps(envelope)
r.rpush(f"swarm:inbox:{to_agent}", raw)
r.publish(f"swarm:events:{to_agent}", raw)
return f"Task '{task_name}' queued for agent '{to_agent}'."
@mcp.tool()
def check_inbox(agent_id: str, limit: int = 5) -> List[Dict]:
"""Check and consume up to `limit` pending messages from this agent's mailbox."""
messages = []
for _ in range(limit):
item = r.lpop(f"swarm:inbox:{agent_id}")
if not item:
break
messages.append(json.loads(item))
return messages
@mcp.tool()
def acquire_distributed_lock(resource_key: str, owner_id: str, ttl_seconds: int = 60) -> bool:
"""Acquire an atomic lock (Redlock/CAS) to prevent concurrent file editing."""
return bool(r.set(f"swarm:lock:{resource_key}", owner_id, nx=True, ex=ttl_seconds))
@mcp.tool()
def release_distributed_lock(resource_key: str, owner_id: str) -> bool:
"""Release an acquired lock safely."""
key = f"swarm:lock:{resource_key}"
if r.get(key) == owner_id:
r.delete(key)
return True
return False
if __name__ == "__main__":
mcp.run(transport="sse")
Registering the Bus in Antigravity
# Register in CLI
agy mcp add --transport sse inter-agent-bus https://mcp-bus.internal/sse
# Or add to ~/.gemini/config/mcp_config.json:
{
"mcpServers": {
"inter_agent_bus": {
"url": "https://mcp-bus.internal/sse",
"transport": "sse",
"headers": {
"Authorization": "Bearer AGENT_CLUSTER_SECRET"
}
}
}
}
4. Detailed Engineering Assessment
Advantages
- Vendor & Model Agnostic: Allows Antigravity to collaborate with Claude Code, Cursor, and custom Python agents via identical MCP tools.
- Shared State & Locking: Prevents Git and file corruption via atomic distributed locks.
- Rich Context Passing: Structured JSON payloads avoid token bloat by passing artifact URLs and Git commits rather than massive transcripts.
Limitations
- Requires Long-Polling: Needs
poll_inboxor external webhook triggers to wake an idle agent turn. - External Infrastructure: Requires hosting an MCP server process and Redis/DB instance.