# exult-mcp-ringcentral-admin

Streamable HTTP MCP server wrapping the RingCentral Platform API with the Exult
"Remote Admin" JWT app. Covers account-level admin operations that Keragon's
RingCentral MCP does **not** expose.

Phase C of MCP consolidation (2026-05): migrated from stdio to bearer-gated
Streamable HTTP via `tools/mcp-shared/python`. Hosted on the claude-cloud VM
at `:18814`, fronted by Tailscale funnel at `/ringcentral-admin`. Clients
connect over HTTPS with `Authorization: Bearer ...` rather than spawning a
local subprocess.

## Tools

Read-only by default. All write tools are narrowly gated behind
`EXULT_RC_ALLOW_WRITES=1` at server startup AND an exact per-request
`approval_text` at call time (the dry-run preview returns the exact string to
confirm). Current write tools: `update_call_queue_members`,
`set_call_queue_ring_type`, `set_call_queue_member_order`, and
`create_ai_scheduling_extension`.

`read_device_sip_info` returns a redacted view by default; revealing raw SIP
credentials additionally requires the startup-only `EXULT_RC_ALLOW_SECRET_READS=1`
operator gate plus an exact `approval_text`.

Note: the queue/routing write tools and the SIP-reveal path are pending a scope
decision (see PR #67) on whether they ship here or in a dedicated RC PR.

- `get_account_info`
- `get_auth_context`
- `list_extensions` (with type/status filters)
- `get_extension`
- `list_call_queues`
- `get_call_queue_members`
- `list_extension_devices`
- `read_device_sip_info` (redacted by default; raw reveal gated, see above)
- `pull_call_log` (detailed, paginated, recording URLs)
- `get_voicemails` (message store listing)
- `get_voicemail_transcript` (AudioTranscription attachment)
- `get_ivr_menus`
- `list_phone_numbers`
- `get_service_status`
- `update_call_queue_members` (write-gated; exact approval text required)
- `set_call_queue_ring_type` (write-gated; exact approval text required)
- `set_call_queue_member_order` (write-gated; exact approval text required)
- `create_ai_scheduling_extension` (write-gated; exact approval text required)

## Install (deploy host)

Requires `uv` or Python 3.11+. The supervisor expects a venv at
`tools/ringcentral-admin/.venv`:

```bash
uv venv tools/ringcentral-admin/.venv --python 3.12
uv pip install --python tools/ringcentral-admin/.venv/bin/python \
  "mcp>=1.2.0" "httpx>=0.27.0" "PyJWT>=2.8.0" \
  "starlette>=0.37" "uvicorn>=0.30"
uv pip install --python tools/ringcentral-admin/.venv/bin/python \
  -e tools/mcp-shared/python
```

## Run

The supervisor handles boot + restart on crash:

```bash
~/run-ringcentral-admin-mcp.sh
```

Required env (loaded from `~/.config/ringcentral-admin-mcp.env`, mode 0600):

- `EXULT_RC_CONFIG` — path to the RC credentials JSON (`client_id`,
  `client_secret`, `jwt`, `server`).
- `MCP_BEARER_TOKEN` — bearer token clients must present.
- `EXULT_RC_ALLOW_WRITES` (optional, default `0`) — set `1` to enable
  write tools (Gautam-approval gate).

## Smoke test

```bash
# health (unauth)
curl https://<host>/ringcentral-admin/health

# initialize (auth)
curl -X POST https://<host>/ringcentral-admin/mcp \
  -H 'authorization: Bearer <token>' \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"x","version":"0"}}}'
```

## Client wiring

The `tools/mcp-config` renderer emits a `streamable-http` entry for clients
that share the bearer token via the per-host `.env`:

```json
{
  "mcpServers": {
    "ringcentral-admin": {
      "type": "streamable-http",
      "url": "https://claude-cloud.tail053faf.ts.net/ringcentral-admin/mcp",
      "headers": { "Authorization": "Bearer <MCP_BEARER_TOKEN>" }
    }
  }
}
```

## Config

Reads credentials from `EXULT_RC_CONFIG` (default
`/Users/agent/pi-mono/.config/exult/ringcentral.json`). The file must contain
`client_id`, `client_secret`, `jwt`, and `server`. Never commit this file.

## claude.ai remote MCP

Not suitable for claude.ai remote hosting as-is because:

1. It reads a local JWT file — would need OAuth-based user-credential wrapping.
2. PHI in call logs (caller numbers are PHI under some interpretations).

For a hosted variant, wrap in a Cloudflare Worker + OAuth provider gated on
Exult SSO — see `/Users/agent/pi-mono/packages/exult-mcp/README.md` for the
hosting recipe outline.
