> ## Documentation Index
> Fetch the complete documentation index at: https://docs.phone.wixzel.com/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP server

> Connect Claude Code, claude.ai and Claude Desktop to your Wixzel Phone account.

Wixzel Phone ships an official [Model Context Protocol](https://modelcontextprotocol.io)
server, `wixzel-phone-mcp`. It puts every `/v1` operation in front of an AI
agent as a tool — 56 of them — with each tool annotated so the client knows
which are read-only, which delete, and which **spend money or ring a real
phone**. Those ask before they run.

Two ways to use it:

|                                                 | Runs where               | Auth                           | Best for                                                          |
| ----------------------------------------------- | ------------------------ | ------------------------------ | ----------------------------------------------------------------- |
| **Hosted** — `https://mcp.phone.wixzel.com/mcp` | Our servers              | OAuth sign-in, or a bearer key | claude.ai, Claude Desktop, Claude Code, any remote-capable client |
| **Local** — `npx -y wixzel-phone-mcp`           | Your machine, over stdio | An API key in the environment  | Claude Code, Cursor, Windsurf, offline work, a self-hosted API    |

The console's **AI clients** page at [phone.wixzel.com/connect](https://phone.wixzel.com/connect)
generates the exact commands below with a key already filled in.

## Claude Code

<Steps>
  <Step title="Add the server">
    <CodeGroup>
      ```bash Hosted, sign in when asked theme={null}
      claude mcp add --transport http wixzel-phone https://mcp.phone.wixzel.com/mcp
      ```

      ```bash Local, with a key theme={null}
      claude mcp add wixzel-phone -e WIXZEL_API_KEY=wv_live_... -- npx -y wixzel-phone-mcp
      ```

      ```json .mcp.json, shared with the repo theme={null}
      {
        "mcpServers": {
          "wixzel-phone": {
            "command": "npx",
            "args": ["-y", "wixzel-phone-mcp"],
            "env": { "WIXZEL_API_KEY": "${WIXZEL_API_KEY}" }
          }
        }
      }
      ```
    </CodeGroup>

    With the hosted form, type `/mcp` in Claude Code and choose **Authenticate**.
    Your browser opens the console, you sign in, tick what the client may do, and
    Claude Code is connected. No key changes hands.
  </Step>

  <Step title="Let it set things up">
    ```
    /mcp__wixzel-phone__quickstart
    ```

    The server ships three prompts, which Claude Code exposes as slash commands:
    `quickstart` connects a carrier, registers a number, builds an agent and
    places a first call, stopping before anything that dials; `diagnose_call`
    explains why a call failed from its record, usage events, trunk status and
    SIP logs; `spend_report` turns a period's usage into dollars by component and
    by call.
  </Step>
</Steps>

## Claude.ai and Claude Desktop

1. **Settings → Connectors → Add custom connector.**
2. Enter `https://mcp.phone.wixzel.com/mcp` and add it.
3. Press **Connect**. You are sent to the console to sign in and approve the
   scopes the client may use.
4. Approve. The client receives a key of its own; nothing is pasted anywhere.

Disconnect it at any time from **AI clients** in the console. The key stops
working immediately.

## Other clients

Any client that launches stdio servers from a JSON config — Claude Desktop's
`claude_desktop_config.json`, Cursor, Windsurf, VS Code — uses the local form:

```json theme={null}
{
  "mcpServers": {
    "wixzel-phone": {
      "command": "npx",
      "args": ["-y", "wixzel-phone-mcp"],
      "env": { "WIXZEL_API_KEY": "wv_live_..." }
    }
  }
}
```

Clients that connect over HTTP but cannot do OAuth send a key as a bearer:

```
Authorization: Bearer wv_live_...
```

## Scopes

An OAuth-connected client asks for a set of scopes, and you can untick any of
them on the consent screen. A client that asks for nothing specific is offered
the standard set for agents: everything under **Agents**, **Calls**,
**Telephony**, **Contacts**, **Knowledge & scheduling**, plus `usage:read` and
`billing:read`.

<Warning>
  `billing:write` (start a top-up) and `api_keys:write` (mint more keys) are
  never offered by default. Grant them deliberately, if at all. There is no admin
  scope, and one cannot be created.
</Warning>

For a locally run server, the key you put in the environment decides what the
agent can do. The console preselects the same standard set when you create one
from the AI clients page.

## Security

* **The token is a key.** When a client signs in with OAuth, the API mints an
  ordinary scoped API key for that grant and hands it over as the access token.
  Nothing downstream needs to know OAuth happened; revoking the grant revokes
  the key. Because the token is valid against the API directly, it carries only
  the scopes you approved, and it is hidden from the ordinary key list so that
  the AI clients page is its one home.
* **PKCE only, S256 only.** The authorization server refuses the `plain`
  method and any request without a code challenge. Redirect URIs match exactly
  against what the client registered; an unregistered one gets an error in
  place, never a redirect. A code is exchanged once and expires in a minute; a
  code presented with the wrong verifier burns the grant.
* **Money asks first.** `place_call`, `start_campaign` and `create_topup` are
  annotated as open-world and their descriptions tell the model to confirm with
  you. Every money path carries an idempotency key the server generates, so a
  retry after a timeout never dials twice.
* **Nothing leaks through tools.** SIP passwords are write-only. A minted key
  appears once, in the tool result that created it. The key the server itself
  runs with is never exposed through any tool or resource.
* **Errors are actionable.** A failure returns the API's machine-readable
  `code`, the `request_id`, and a hint: which scope is missing, that the balance
  is short, that a cursor was mangled.

## Tools

| Family          | Tools                                                                                                                                                     |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Engines         | `list_engines`                                                                                                                                            |
| Agents          | `list_agents` `get_agent` `create_agent` `update_agent` `delete_agent`                                                                                    |
| Calls           | `place_call` `list_calls` `get_call` `get_call_transcript` `hangup_call` `delete_call`                                                                    |
| SIP trunks      | `list_sip_trunks` `get_sip_trunk` `create_sip_trunk` `update_sip_trunk` `delete_sip_trunk` `check_sip_trunk_status` `test_sip_trunk` `get_sip_trunk_logs` |
| Phone numbers   | `list_phone_numbers` `get_phone_number` `create_phone_number` `update_phone_number` `delete_phone_number`                                                 |
| Leads           | `list_leads` `get_lead` `create_lead` `update_lead` `delete_lead` `import_leads`                                                                          |
| Campaigns       | `list_campaigns` `get_campaign` `create_campaign` `start_campaign` `pause_campaign` `delete_campaign`                                                     |
| Knowledge bases | `list_knowledge_bases` `get_knowledge_base` `create_knowledge_base` `update_knowledge_base` `delete_knowledge_base`                                       |
| Appointments    | `list_appointments` `get_appointment` `create_appointment` `update_appointment` `delete_appointment`                                                      |
| Billing & usage | `get_balance` `list_ledger_entries` `create_topup` `get_usage_summary` `list_usage_events`                                                                |
| API keys        | `list_api_keys` `create_api_key` `rotate_api_key` `revoke_api_key`                                                                                        |

Resources: `wixzel://guide` (the operating guide the server also sends as its
instructions) and `wixzel://connection` (base URL and whether the key is live
or test; never the key itself).

## Self-hosting

The package runs the hosted mode too:

```bash theme={null}
MCP_PORT=3939 MCP_PUBLIC_URL=http://localhost:3939/mcp npx wixzel-phone-mcp --http
```

| Variable              | Purpose                                                                                                        |
| --------------------- | -------------------------------------------------------------------------------------------------------------- |
| `MCP_PORT`            | Port to listen on. Default 3939.                                                                               |
| `MCP_BIND`            | Interface. Default `127.0.0.1`; put TLS in front rather than binding wider.                                    |
| `MCP_PUBLIC_URL`      | The URL clients use, advertised as the OAuth resource.                                                         |
| `WIXZEL_API_BASE_URL` | The API, which is also the OAuth authorization server. Default `https://api.phone.wixzel.com`.                 |
| `WIXZEL_API_KEY`      | Local only: a fallback for requests without a bearer. Refused when `MCP_PUBLIC_URL` is not a loopback address. |

A connector discovers sign-in on its own: a request without a bearer is
answered `401` with `WWW-Authenticate: Bearer resource_metadata="…"`, that
document names `https://api.phone.wixzel.com` as the authorization server, and
`/.well-known/oauth-authorization-server` there lists the endpoints.
