Give your coding agents a "phone" to call each other directly over Tailscale.
You and a colleague are debugging together. Each of you has a local coding agent with deep context about your respective code. But the agents can't talk to each other — so you copy-paste AI responses into WeChat/Slack, acting as a human router between two perfectly capable AI agents.
acall is an MCP server that gives each agent a set of communication tools. Agents call each other over your Tailscale network — no human relay needed.
Your machine (Tailscale) Colleague's machine (Tailscale)
┌───────────────────┐ ┌───────────────────┐
│ Coding Agent │ │ Coding Agent │
│ ↕ MCP │ │ ↕ MCP │
│ acall server │◄─── HTTP ──►│ acall server │
│ (port 8770) │ encrypted │ (port 8770) │
└───────────────────┘ └───────────────────┘
- Python 3.10+
- Tailscale installed and connected
- Both machines on the same Tailnet
cd acall
pip install -e .Or with uv:
cd acall
uv pip install -e .Add acall to your MCP client config.
Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"acall": {
"command": "acall",
"args": ["--name", "Alice", "--port", "8770"]
}
}
}VS Code (.vscode/mcp.json):
{
"servers": {
"acall": {
"command": "acall",
"args": ["--name", "Alice", "--port", "8770"]
}
}
}| Flag | Default | Description |
|---|---|---|
--name |
Agent |
Your display name |
--port |
8770 |
HTTP listen port |
--address |
auto | Tailscale IP (auto-detected via tailscale ip -4) |
| Tool | Description |
|---|---|
call(peer, message, topic?) |
Start a new conversation with a peer agent |
check_inbox() |
Check for unread incoming messages |
reply(conversation_id, message) |
Reply to an ongoing conversation |
read_conversation(conversation_id) |
Read full message history |
list_conversations() |
List all conversations |
Step 1 — Alice tells her agent:
"Ask Bob's agent how token refresh works in his auth service."
Alice's agent calls:
call(peer="100.64.0.2:8770", message="How does token refresh work in your auth service?", topic="Auth")
Step 2 — Bob tells his agent:
"Check for incoming messages."
Bob's agent calls:
check_inbox()
→ 📬 1 new message from Alice (100.64.0.1:8770)
Topic: Auth
"How does token refresh work in your auth service?"
Step 3 — Bob's agent reviews the code and replies:
reply(conversation_id="abc-123", message="We use rotating refresh tokens stored in Redis with a 7-day TTL...")
Step 4 — Alice's agent checks for the reply:
check_inbox()
→ 📬 1 new message from Bob
"We use rotating refresh tokens stored in Redis with a 7-day TTL..."
The entire exchange happens without Alice or Bob copy-pasting anything.
- MCP stdio transport connects acall to your local coding agent
- HTTP server (port 8770) receives messages from remote agents
- Tailscale provides the encrypted mesh network between machines
- SQLite (
~/.acall/messages.db) persists conversation history locally - Source IP verification ensures messages come from the claimed sender
- All traffic is encrypted end-to-end by Tailscale
- Only devices on your Tailnet can reach the HTTP endpoint
- Source IP is verified against claimed sender address
- Message deduplication prevents replay attacks
- Request body size is capped at 256 KB
MIT