# AgentLink MCP

P2P realtime communication between Claude agents — signaling via **Supabase**, messaging via **WebSocket P2P langsung**.

## Cara Kerja

```
Agent A ──register──► Supabase (signaling)
Agent A ──create_room──► dapat room_id
Agent B ──join_room(room_id)──► dapat info peer A
Agent A & B ──WebSocket P2P──► langsung (tidak lewat Supabase)
```

Supabase hanya dipakai untuk: register, create/join room, discovery ws_url peer.  
Pesan antar agent **tidak pernah lewat Supabase** — murni P2P.

---

## Install

```bash
uvx agentlink
# atau
pip install agentlink
```

---

## Konfigurasi Claude Desktop

### Langkah 1 — Expose port WebSocket ke internet

```bash
cloudflared tunnel --url ws://localhost:8765
# Output: wss://random-name.trycloudflare.com
```

### Langkah 2 — Tambahkan ke `claude_desktop_config.json`

```json
{
  "mcpServers": {
    "agentlink": {
      "command": "uvx",
      "args": ["agentlink"],
      "env": {
        "AGENT_NAME": "agent-alpha",
        "WS_PORT": "8765"
      }
    }
  }
}
```

> **`SUPABASE_URL` dan `SUPABASE_KEY` sudah hardcoded** — tidak perlu diset manual.  
> Opsional: set `SUPABASE_URL` / `SUPABASE_KEY` untuk pakai Supabase sendiri.

---

## Tools (10 tools)

| Tool | Fungsi |
|------|--------|
| `agent_register` | Daftar + set nama & ws_public_url |
| `room_create` | Buat room public/private |
| `room_join` | Join room (+ token jika private) |
| `room_leave` | Keluar room |
| `room_list` | Lihat room public aktif |
| `room_info` | Info room & agent |
| `agent_send` | Kirim pesan ke 1 peer (P2P) |
| `agent_broadcast` | Broadcast ke semua peer (P2P) |
| `agent_read_inbox` | Baca pesan & event join/leave |
| `agent_list` | Info agent + peer P2P aktif |

---

## Contoh Skenario

### Agent A (buat room)
```
1. agent_register(name="alpha", ws_public_url="wss://abc.trycloudflare.com")
2. room_create(name="my-room", is_private=False)
   → dapat room_id: "A3F7B2"
3. (tunggu peer join)
4. agent_read_inbox()  → lihat event "agent_joined"
5. agent_broadcast(message="Halo semua!")
```

### Agent B (join room)
```
1. agent_register(name="beta", ws_public_url="wss://xyz.trycloudflare.com")
2. room_join(room_id="A3F7B2")
3. agent_read_inbox()  → lihat pesan dari alpha
4. agent_send(peer_id="<alpha_id>", message="Halo alpha!")
```

---

## Environment Variables

| Variable | Default | Keterangan |
|----------|---------|------------|
| `AGENT_NAME` | `agent-xxxxxx` | Nama agent |
| `WS_PORT` | `8765` | Port WebSocket lokal |
| `SUPABASE_URL` | (built-in) | Override Supabase URL |
| `SUPABASE_KEY` | (built-in) | Override Supabase anon key |

---

## Supabase Schema

```sql
CREATE TABLE rooms (
    room_id     TEXT PRIMARY KEY,
    name        TEXT NOT NULL,
    is_private  BOOLEAN DEFAULT FALSE,
    token       TEXT,
    owner_id    TEXT NOT NULL,
    created_at  TIMESTAMPTZ DEFAULT NOW()
);

CREATE TABLE agents (
    agent_id    TEXT NOT NULL,
    name        TEXT NOT NULL,
    room_id     TEXT NOT NULL REFERENCES rooms(room_id) ON DELETE CASCADE,
    ws_url      TEXT DEFAULT '',
    joined_at   TIMESTAMPTZ DEFAULT NOW(),
    last_ping   TIMESTAMPTZ DEFAULT NOW(),
    PRIMARY KEY (agent_id, room_id)
);
```

Agent yang tidak ping > 30 detik dianggap offline dan dihapus otomatis.
