Switchboard
Enables AI agents to send questions, notifications, and documents to the user's Android phone via the Switchboard Android app, supporting quick replies and conversation management.
Integrates with Firebase Realtime Database and Cloud Messaging for data persistence, state synchronization, and push notifications across Switchboard clients.
Allows AI agents to interact with users through a Wear OS smartwatch app, providing notifications and quick replies for away-mode workflows.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Switchboardask me which environment to deploy to"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Switchboard
A human-in-the-loop input gateway for AI coding agents.
Switchboard is a locally-hosted MCP server that lets AI agents pause mid-task and ask you a question via a native Android app. Designed for away-from-desk workflows where you want your agents to continue working unsupervised until they hit a decision that genuinely requires human input.

The Android app in away mode. In a single conversation an agent posts a status update, delivers a document, and asks a question with one-tap quick replies, and you answer from your phone.

The phone's conversation board: every agent conversation in one place, with away mode, context/quota, and pending-question counts at a glance.

Operator: the launch-on-demand web cockpit (conversation board + detail + status), served by the Python server at /dashboard.
Features
Session-id routing: Each agent session is identified by a
cli_session_idinjected automatically by the PreToolUse hook. Agents only passsenderand tool arguments.Conversations: Messages, members, and state persist in Firebase as named conversations (Active / Ended). At most one is "open" — joinable by any new agent via
enter_conversation.Asynchronous updates: Send non-blocking notifications or deliver documents directly to your phone.
In-line replies: View your responses directly in the chat history for full context.
Global away mode: Single server-wide flag. Toggle from the phone's top-bar pill or via the
set_away_modeMCP tool.Activity indicators: Prominent high-visibility indicators for unseen activity or pending questions.
Session spawning: Launch fresh agent sessions on your desktop directly from your phone — choose surface (Windows / WSL), project, optional prompt, and whether to create a new conversation or add to an existing one.
Conversation composition: Open + enter, resume dormant sessions, or combine two conversations into one — all from the phone's long-press menu.
Rich Markdown: Full support for bold, italic, code blocks, checklists, and tables.
Related MCP server: TaskSync
Design & Architecture
Switchboard is one Python process fronting a single Firebase Realtime Database, with four surfaces reading and writing that shared hub. Agents speak MCP to the server; the server is the only writer of authoritative state; the human-facing clients render and command it.
AI agents (Claude Code, ...)
| MCP over HTTP
v
+--------------------------------+
| Switchboard MCP server | Python . asyncio
| gateway + /dashboard + |
| /stats + /healthz |
+---------------+----------------+
| Firebase Admin SDK
v
+---------------------------+
| Firebase Realtime DB | one shared hub:
| + Cloud Messaging (FCM) | conversations, away mode, commands
+-------------+-------------+
| direct RTDB reads/writes + push
+-----------------+------------------+
v v v
Android + Wear OS Operator Watchtower
Kotlin / Compose Preact web .NET 9 / WinForms
(phone + watch) cockpit taskbar widgetThe model is built around away mode (a single global flag: when set, agents route every prompt to the phone instead of the terminal) and conversations (the persistence + routing unit; multiple agents can share one conversation, and while pending in-flight questions do not survive a restart, conversation state itself rehydrates from Firebase).
Built with: Python (asyncio), the Model Context Protocol, Firebase (Realtime Database + Cloud Messaging), Kotlin / Jetpack Compose (Android + Wear OS), Preact (web), and .NET 9 / WinForms (Windows).
Switchboard was architected and built by John Anthony, directing a multi-agent workflow of off-the-shelf coding agents (Claude Code among them) coordinated, fittingly, through Switchboard itself.
For an agent-oriented project tour, see CLAUDE.md. The current design is documented in docs/switchboard-design-spec-comprehensive.md — covers the Conversation primitive, session-id routing, MCP tool surface, hook plumbing, Firebase schema, spawn (fresh / resume / combine), away mode, hydration, and the Android UI surface.
Install
git clone <this-repo>
cd switchboard
python -m venv .venv
source .venv/Scripts/activate # Git Bash on Windows
pip install -e ".[dev]"Configure
Switchboard reads its configuration from OS env vars. A .env file is loaded as a fallback if present — OS env wins.
Environment Variables
Variable | Required | Default | Purpose |
Server Settings | |||
| No |
| Local bind address for the SSE/HTTP server. |
| No |
| Local port for the SSE/HTTP server. |
| No |
| How long |
| No |
| Path to the event audit log. |
| No |
| Max messages per minute per conversation before |
Android & Firebase | |||
| Yes | The URL of your Firebase Realtime Database. | |
| Yes | Absolute path to your Firebase service account key JSON file. | |
| No | Hostname of your Firebase Storage bucket. | |
Spawn | |||
| For spawn | Windows root containing your project folders (e.g. | |
| No |
| Segment appended to the resolved WSL home to locate the workspace root (e.g. |
| No | (auto-detected) | Override for the resolved WSL home path; escape hatch for the NSSM Session 0 case where the |
Firebase is mandatory. The server exits at startup with a ConfigError if FIREBASE_DATABASE_URL or FIREBASE_SERVICE_ACCOUNT_JSON is unset; there is no Android-disabled run mode.
Realtime Database security rules
database.rules.json locks the RTDB down to a single owner identity. It ships with a placeholder UID: replace YOUR_FIREBASE_UID with your own Firebase Auth UID (the one your Android app and the web Operator sign in as) and deploy the rules to your project (firebase deploy --only database, or paste them in the Firebase console under Realtime Database → Rules). Without this, the server's reads and writes are rejected.
Wire your agent to it
Switchboard ships as a Claude Code plugin. From any Claude Code session:
/plugin marketplace add C:/Work/switchboard
/plugin install switchboard@switchboardThe plugin install wires the skill and the Claude turn-end + agent-status hooks. The MCP server connection is bootstrapped per host by a parallel chezmoi dotfiles effort (Windows uses localhost:9876; WSL uses the Windows host IP, resolvable from /etc/resolv.conf or ip route show default | awk '{print $3}'). If you are not using chezmoi, run claude mcp add switchboard --scope user --transport http <resolved-url> per host.
WSL must use bridge networking (NOT mirrored). The Windows server requires SWITCHBOARD_HOST=0.0.0.0 and a firewall inbound rule for TCP 9876 from the WSL subnet.
Android App
The project includes a native Android app in the android/ directory.
Build and Install
Credentials: Download
google-services.jsonfrom your Firebase project and place it inandroid/app/.Deploy: Connect your phone via USB or Wifi (with Debugging enabled) and run:
.\scripts\install-client.ps1This script builds the debug APK, installs it, and launches the app automatically.
Alternative: Open the
android/folder in Android Studio and deploy to your phone.
Troubleshooting & Manual Wifi Pairing
If you encounter issues pairing your device over Wifi (e.g., "protocol fault" or the device not appearing in Android Studio), follow these manual steps:
Restart ADB Server:
adb kill-server adb start-serverManual Pairing: On your phone, go to Developer Options > Wireless Debugging > Pair device with pairing code. Note the IP address, port, and pairing code.
adb pair <IP_ADDRESS>:<PAIRING_PORT> # Enter the pairing code when promptedManual Connection: After successful pairing, look at the IP address & Port on the main Wireless Debugging screen (note: this port is usually different from the pairing port).
adb connect <IP_ADDRESS>:<CONNECTION_PORT>Common Fixes:
Toggle Wireless Debugging: If a pairing attempt fails, turn Wireless Debugging OFF and back ON to reset the ports.
Check VPNs: Ensure neither your PC nor your phone is connected to a VPN, as this often blocks local ADB discovery.
Forget Old Pairings: If issues persist, select "Forget all paired devices" in the Wireless Debugging settings and start over.
The app uses Firebase Cloud Messaging (FCM) for instant push notifications and Realtime Database for two-way communication.
Pair with Watch
In Android Studio, look at the device dropdown (top center) and select "Pair Devices Using Wi-Fi".
On your watch, in the Wireless debugging screen, tap "Pair new device". You will see a 6-digit pairing code and an IP address.
In Android Studio, select the "Pair using pairing code" tab.
Wait for your watch to appear in the list (it usually shows up as Google Pixel Watch), click it, and enter the 6-digit code shown on the watch.
Once the "Pairing successful" message appears, your watch will show up as a connected device in the target dropdown.
Troubleshooting Tips
The "Invisible" Watch: If the watch doesn't show up in the pairing list, toggle the Wi-Fi on your watch off and back on. Sometimes the broadcast gets stuck.
Battery Saver: Ensure Battery Saver is off on the watch. It will often kill the ADB process to save juice.
Prompt for Authorization: Keep an eye on your watch face when you first click Run; it will ask you to "Always allow debugging from this computer?" Tap Allow.
Using
Away mode
Away mode activates when you tell your agent you're stepping away — any phrasing like "I'm stepping away" is sufficient. The agent immediately routes all output through ask_human or notify_human.
Human-facing tools:
ask_human(question, sender, title?, format?, suggestions?)— blocks until you reply.notify_human(message, sender, title?, format?)— fire-and-forget status update.send_document_human(path, sender, title?, caption?)— delivers a file to your phone.set_away_mode(value)— toggle the global away-mode flag (agents use this; you can also toggle the phone pill).
Multi-agent (conversation) tools:
message_and_await_agent(sender, message, title?)— speak to peers in your conversation and block for the next reply.open_conversation(sender, title?)— promote your conversation to the global "open" singleton so other agents can join viaenter_conversation.enter_conversation(sender)— join the open conversation (or queue for the next intro in your current one) and block until a peer speaks.combine_conversations(source_id, target_id)— merge two conversations; dormant members ofsource_idare migrated and auto-resumed.lookup_conversation_ids(cwd_filter?, sender_contains?, title_contains?)— find conversation IDs to feedcombine_conversations.leave_conversation(sender, parting_message)— leave the conversation with a final summary; session falls back to its home conversation (away on) or terminal output (away off).
To exit away mode, reply "I'm back". The agent will provide a Welcome Back Summary of what was accomplished while you were away and then resume normal terminal output.
Replying to messages
Switchboard correlates your reply to the waiting ask_human call via the Android app's reply input at the bottom of the conversation tab. Type your answer and tap Send. If the question included suggestion buttons, tap one to reply instantly without typing.
Conversation composition
Multiple agents can share a conversation without spawning. Open one with open_conversation(sender, title?), then have additional agents join via enter_conversation(sender). Agents in the same conversation communicate through message_and_await_agent.
You can also merge two existing conversations with combine_conversations(source_id, target_id) — dormant members of the source are migrated into the target and revived. All three flows are also available from the phone's long-press menu on any conversation row.
Spawning a new agent session
With a spawn root configured, you can launch a fresh agent session directly from the Android app. Tap the + (spawn) button in the app and fill out the dialog:
Surface: Windows or WSL.
Project: Pick from projects under your configured spawn root for that surface.
Prompt: Optional starting prompt for the agent.
Conversation: Create a new conversation, or add the spawned agent into an existing one.
Spawn auto-enables global away mode if it is currently off; the phone shows a confirmation toast. Claude is the only supported spawn target.
Prerequisites:
Set the spawn root env vars in
.envand restart the service:SWITCHBOARD_WINDOWS_SPAWN_ROOT— Windows root path containing your project folders (e.g.C:\Work). Alias:SWITCHBOARD_SPAWN_ROOT.SWITCHBOARD_WSL_SPAWN_ROOT_SEGMENT— segment appended to the resolved WSL home (defaultwork, giving e.g./home/john/work).
Register the
SwitchboardSpawnscheduled task (one-time, elevated PowerShell):.\scripts\register-spawn-task.ps1The task fires in your interactive desktop session so
claudeis reachable. The WSL surface additionally requires WSL to be installed and reachable from the same desktop session.
The spawn is audit-logged to logs/switchboard.jsonl.
Formatting messages
ask_human and notify_human accept an optional format parameter. The default is "plain". Pass format="markdown" to render the message with Markdown in the Android app — bold, italic, inline code, code blocks, links, checklists, and tables are all supported. Use standard Markdown syntax.
Manual smoke test
With the server running, the Android app installed, and an agent wired up:
Open a Claude Code session and spawn an agent via the Android app (or say "I'm stepping away" to an existing session).
Ask the agent to do something that should trigger a question, e.g. "Delete the oldest file in
logs/."Watch your phone: you should receive a push notification and see the question appear in the conversation tab.
Type your answer in the reply field at the bottom and tap Send (or tap a suggestion button if provided).
The agent's
ask_humantool call unblocks with your reply text.Check
logs/switchboard.jsonl— you should seerequest_createdandrequest_resolvedevents.
Tests
pytestAll unit tests are offline; no credentials required.
Project layout
See CLAUDE.md for the agent-oriented project tour, or design spec §11 for the canonical tree.
The repo is a monorepo of components: server/ (the Python MCP), android/ (the Android + Wear client), and watchtower/ (the Windows client — Switchboard Watchtower, a .NET 9 taskbar widget).
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/johnjanthony/Switchboard'
If you have feedback or need assistance with the MCP directory API, please join our Discord server