Zeph Docs
MCP Server

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 install

That 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

VariableRequiredDescription
ZEPH_API_KEYYes*API key from Settings → API Keys
ZEPH_HOOK_IDNoHook ID. Only needed for the interactive tools zeph_ask, zeph_prompt, and zeph_input
ZEPH_DEVICE_IDNoTarget device ID, again only for the interactive tools. Omit to send to all devices
ZEPH_BASE_URLNoAPI base URL (default: https://api.zeph.to/v1)
ZEPH_WS_URLNoWebSocket 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_CACHENoSet 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_IDNoOverride the session id attached to pushes, which controls grouping in the app. Auto-detected from the newest Claude Code transcript when unset
ZEPH_DISABLE_ENCRYPTIONNoSet 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 — for zeph_list
  • push:write — for zeph_notify, zeph_clipboard, zeph_dismiss, zeph_dismiss_all, zeph_file
  • hook:write — for zeph_ask, zeph_prompt, and zeph_input
  • device:write — for zeph_session_rename
  • channel:read — for the zeph://channels resource

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.

On this page