MCP Server
Set up @zeph-to/mcp-server so your agent can reach your phone.
Your agent calls zeph_ask; the question lands on your phone as buttons and a text field; your
reply comes back into the same tool call and the agent keeps going.
@zeph-to/mcp-server is the agent side of that round trip, plus one-way notifications, clipboard,
files, and channel broadcasts — all over the
Model Context Protocol. It works with Claude Code, Cursor,
Windsurf, Gemini CLI, and any MCP client.
Setup
The easiest way to set up every agent at once:
npm install -g @zeph-to/cli
zeph installThat saves credentials to ~/.zeph/config.json and configures your agents automatically. The MCP
server reads from that file — no environment variables needed.
Install globally so zeph cc works and hooks skip an npx cold start. npx @zeph-to/cli install
is a notifications-only alternative.
Claude Code, by hand
Add this to ~/.claude/settings.json:
{
"mcpServers": {
"zeph": {
"command": "npx",
"args": ["-y", "@zeph-to/mcp-server"]
}
}
}No env block is needed — credentials come from ~/.zeph/config.json, written by
zeph install. Add environment variables only to override the file, for example a second
account:
"env": { "ZEPH_API_KEY": "ak_other_account" }Cursor and other MCP clients
{
"command": "npx",
"args": ["-y", "@zeph-to/mcp-server"]
}Environment variables
| Variable | Required | Description |
|---|---|---|
ZEPH_API_KEY | Yes* | API key from Settings → API Keys |
ZEPH_HOOK_ID | No | Hook ID. Only needed for the interactive tools zeph_ask, zeph_prompt, and zeph_input |
ZEPH_DEVICE_ID | No | Target device ID, again only for the interactive tools. Omit to send to all devices |
ZEPH_BASE_URL | No | API base URL (default: https://api.zeph.to/v1) |
ZEPH_WS_URL | No | WebSocket endpoint for the hook-response fast path — answers arrive the moment the user submits them instead of on the next poll. Falls back to pure polling when unset. Also read from wsUrl in ~/.zeph/config.json |
ZEPH_DISABLE_SESSION_CACHE | No | Set to 1 or true to skip writing the session-id handoff file under ~/.cache/zeph/. Useful for read-only filesystems, ephemeral CI runners, or sandboxes that audit filesystem writes. The plugin's stop hook still works without it — transcript-path UUID extraction is the primary path and the cache is a fallback for older Claude Code versions |
ZEPH_SESSION_ID | No | Override the session id attached to pushes, which controls grouping in the app. Auto-detected from the newest Claude Code transcript when unset |
ZEPH_DISABLE_ENCRYPTION | No | Set to 1 or true to force push encryption off even when the account has it enabled. A local override for debugging what the server actually received — encryption is already off unless the account opted in |
* If the environment variables are not set, the server reads ~/.zeph/config.json, created by
zeph install. Unresolved ${...} interpolations are also treated as unset.
API key permissions
The API key needs these scopes:
push:read— forzeph_listpush:write— forzeph_notify,zeph_clipboard,zeph_dismiss,zeph_dismiss_all,zeph_filehook:write— forzeph_ask,zeph_prompt, andzeph_inputdevice:write— forzeph_session_renamechannel:read— for thezeph://channelsresource
Create an API key with the MCP preset in Settings → API Keys to get the right permissions.
Encryption
Push bodies and file attachments are encrypted with AES-256-GCM once the account opts in. Encryption is off by default and requires Zeph Pro; the threat model and its limits are documented once, under CLI & SDK → Encryption.
Two things are specific to this server:
- Its keypair lives in
~/.config/zeph/device-keys.json, not~/.zeph/device-keys.json. - The encryption opt-in is read once at startup, so turning it on in the app while the server is running takes effect only after a restart.