Antigravity Swarms
Architecture Pattern 3 Standardized Tool & State Fabric

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.

flowchart TB subgraph Fleet ["Distributed Antigravity Fleet"] A1["Instance 1: MacBook
(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 & Messaging
send_agent_message"] Q["Task Queue & Polling
claim_task / poll_inbox"] L["Distributed Lock Manager
acquire_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_inbox or external webhook triggers to wake an idle agent turn.
  • External Infrastructure: Requires hosting an MCP server process and Redis/DB instance.
← Method 2 (AgentAPI & SDK) Next: Method 4 (Tailscale + NATS) →