# io.github.Ringer/warp (npm · warp-mcp)

SIP trunking, numbers, porting, messaging, billing, and CDR analytics on the Ringer WARP platform

- Trust score: 79/100 (medium)
- Change this week: +28
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- npm · `warp-mcp`: 79/100 (this document), [markdown](https://verifymcp.io/servers/ringer-warp/warp-mcp.md), [page](https://verifymcp.io/servers/ringer-warp/warp-mcp)

## Channel facts

- Registry: `npm`
- Package: `warp-mcp`
- Version: `1.0.2`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 80/100
  - No malware found by supply-chain analysis.
  - Only part of the dependency tree could be resolved (94 of 98), so this covers what we could see, not the whole tree.
  - Runs a script at install time (postinstall) that we could not recognise. It may be perfectly ordinary, but we do not read the published tarball, so we cannot say what it does.
  - Only part of the dependency tree could be resolved (94 of 98), so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 97/100
  - Source repository is publicly reachable at the declared URL.
  - Cryptographically verified build provenance (signed, bound to Ringer/warp-mcp).
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 27 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 81/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (excellent).
  - Context-footprint check failed: tool/resource definitions use about 21646 tokens (~160/item across 135 items; 135 tools + 0 resources), over budget; trim descriptions and params.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 100/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 100% of tool parameters carry a description.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add ringer-warp -- npx -y warp-mcp
```

### Codex

```bash
codex mcp add ringer-warp -- npx -y warp-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ringer-warp": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "warp-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add ringer-warp --command npx --arg -y --arg warp-mcp
```

### Hermes

```yaml
mcp_servers:
  ringer-warp:
    command: "npx"
    args: ["-y", "warp-mcp"]
```

### Other

```json
{
  "mcpServers": {
    "ringer-warp": {
      "command": "npx",
      "args": [
        "-y",
        "warp-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 79, +1)

No change was recorded against any check on this day. Stability & Change Management went from 23 to 27. That category is still filling its 30-day observation window: 7 days of observed history at the previous scan, 8 at this one. The score rises as the window fills, whether or not the server changes.

### 2026-08-02 (score 78, +53)

- [security improvement] Known CVEs: unverified → partial
- [security improvement] Provenance: unverified → pass
- [security improvement] Install scripts: unverified → partial
- [security improvement] Malware scan: unverified → pass
- [security] Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window).
- [security] The scripts that run when this package is installed changed: postinstall
- [security] The attested source repository moved: Ringer/warp-mcp
- [functional improvement] Stability: unverified → 0.23
- [functional improvement] Maintenance: unverified → pass
- [functional improvement] Dependency health: unverified → partial
- [functional improvement] License: unverified → pass
- [functional improvement] Schema quality: unverified → excellent
- [functional improvement] MCP protocol: unverified → pass
- [functional] Licence: MIT

### 2026-08-01 (score 25, −27)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-31 (score 52, +1)

- [security regression] Malware scan: pass → unverified
- [security improvement] Install scripts: unverified → partial
- [security improvement] Provenance: unverified → pass
- [security] The scripts that run when this package is installed changed: postinstall
- [security] The attested source repository moved: Ringer/warp-mcp
- [functional improvement] Maintenance: unverified → pass
- [functional improvement] License: unverified → pass
- [functional] Licence: MIT

### 2026-07-27 (score 51)

First indexed and scored.

## MCP tools (135)

### `warp_status` (~62 tokens)

WARP MCP status

Check warp-mcp configuration and API connectivity. Use this first when any other tool returns an auth error, or to confirm the server is set up correctly. Reports the server version, API base URL, whether an API key is configured, and whether the API accepts it.

### `acct_get_capacity` (~42 tokens)

Get account capacity

Get your account's per-class × per-direction CPS (calls-per-second) and channel capacity ceilings. Use when planning traffic loads or diagnosing capacity-related call rejections.

### `acct_get_balance` (~53 tokens)

Get prepaid balance

Get your prepaid balance and currency. Use for a quick balance check; for the full billing snapshot (credit limit, available, suspension flag) use bill_get_balance. POSTPAID customers always see prepaid_balance=0.

### `acct_get_utilization` (~53 tokens)

Get capacity utilization

Get your aggregate CPS/channel capacity and current concurrent usage across trunk groups. Use to check how close live traffic is to capacity ceilings. current_* fields are null when live counters cannot be read (counters_available=false).

### `acct_list_scopes` (~48 tokens)

List permission scope catalog

List every permission scope in the WARP platform registry, grouped by category. Use when building or editing team roles or API keys to see what scopes exist. Requires the team:read scope.

### `net_get_ingress_ips` (~54 tokens)

Get WARP SIP ingress servers

Get the customer-facing WARP SIP edge servers (UDP/TCP/TLS hosts, IPs, ports) to point a trunk or PBX at. Use when configuring SIP endpoints or firewall rules toward WARP.

### `net_get_vendor_ips` (~52 tokens)

Get WARP origination IPs

Get the WARP egress/origination IPs you must allowlist in your firewall for symmetric SIP signaling. Use when inbound calls from WARP are being blocked or when setting up a new network edge.

### `key_list` (~79 tokens)

List API keys

List your API keys with their scopes and prefixes (secrets are never returned). Use to audit which keys exist and what they can do. Requires the api_keys:read scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `include_revoked` (boolean): Include revoked keys (default false)

### `key_get` (~74 tokens)

Get an API key

Get one API key's metadata and scopes by key UUID (never the secret). Use to inspect a specific key found via key_list. Requires the api_keys:read scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `key_id` (string, required): API key UUID

### `key_get_audit` (~82 tokens)

Get API key audit trail

Get the most recent 100 audit events (create/rotate/revoke/auth activity) for one API key. Use when investigating suspicious key usage or verifying rotation history. Requires the api_keys:read scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `key_id` (string, required): API key UUID

### `key_get_audit_all` (~77 tokens)

Get customer-wide API key audit trail

Get the most recent 100 audit events across ALL of your API keys. Use for a security review of key activity account-wide; for a single key's history use key_get_audit. Requires the api_keys:read scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)

### `cdr_get_details` (~222 tokens)

List call detail records

List paginated call detail records (CDRs) for a date range with optional filters. Use to investigate specific calls, verify traffic, or debug call failures. For aggregate metrics use cdr_get_statistics; for chart data use cdr_get_trends.

Input parameters:

- `ani` (string): Filter by ANI (calling number)
- `direction` (string): Filter by call direction
- `disposition` (string): Filter by call disposition (e.g. ANSWERED, NO ANSWER, BUSY, FAILED)
- `dni` (string): Filter by DNI (called number)
- `end_date` (string): End date (YYYY-MM-DD, inclusive)
- `page` (integer): Page (1-based, default 1)
- `per_page` (integer): Page size (1-500, default 50)
- `start_date` (string): Start date (YYYY-MM-DD)
- `tz_offset_minutes` (integer): Operator timezone offset in minutes, as returned by JS getTimezoneOffset() (e.g. 420 for US Mountain in summer)

### `cdr_export_csv` (~199 tokens)

Export CDRs as CSV

Export up to 10,000 call detail records for a date range as CSV text. Use only when the user explicitly wants a CSV export; for browsing or analysis prefer cdr_get_details (paginated). Output over 40k characters is truncated — narrow the date range or filters if that happens.

Input parameters:

- `ani` (string): Filter by ANI (calling number)
- `direction` (string): Filter by call direction
- `disposition` (string): Filter by call disposition (e.g. ANSWERED, NO ANSWER, BUSY, FAILED)
- `dni` (string): Filter by DNI (called number)
- `end_date` (string): End date (YYYY-MM-DD, inclusive)
- `start_date` (string): Start date (YYYY-MM-DD)
- `tz_offset_minutes` (integer): Operator timezone offset in minutes, as returned by JS getTimezoneOffset() (e.g. 420 for US Mountain in summer)

### `cdr_get_statistics` (~121 tokens)

Get call statistics

Get aggregated CDR metrics (totals, durations, dispositions) for a date range. Use for summary questions like 'how many calls last week' or ASR/ACD analysis. For individual calls use cdr_get_details.

Input parameters:

- `end_date` (string): End date (YYYY-MM-DD, inclusive)
- `start_date` (string): Start date (YYYY-MM-DD)
- `tz_offset_minutes` (integer): Operator timezone offset in minutes, as returned by JS getTimezoneOffset() (e.g. 420 for US Mountain in summer)

### `cdr_get_trends` (~128 tokens)

Get call trend data

Get time-bucketed CDR aggregates for a date range, suitable for charts and spotting traffic patterns over time. Choose hour granularity for a single day, day for weeks, week for months.

Input parameters:

- `end_date` (string): End date (YYYY-MM-DD, inclusive)
- `granularity` (string): Bucket size (default day)
- `start_date` (string): Start date (YYYY-MM-DD)
- `tz_offset_minutes` (integer): Operator timezone offset in minutes, as returned by JS getTimezoneOffset() (e.g. 420 for US Mountain in summer)

### `cdr_get_dashboard_stats` (~43 tokens)

Get dashboard statistics

Get the key dashboard metrics (counts, revenue, growth) scoped to your accessible customers. Use for a quick account health overview rather than detailed CDR analysis.

### `bill_get_balance` (~46 tokens)

Get billing balance snapshot

Get your full billing balance snapshot: current balance, credit limit, available credit, suspension flag, and currency. Use for billing questions; for just the prepaid number use acct_get_balance.

### `bill_list_ledger` (~61 tokens)

List ledger transactions

List your billing ledger journal entries, most recent first. Use to trace payments, charges, and adjustments — e.g. 'why did my balance drop yesterday'.

Input parameters:

- `limit` (integer): Max rows to return (1-500, default 100)

### `bill_list_invoices` (~33 tokens)

List invoices

List your invoices, newest billing period first. Use to find an invoice id before fetching details with bill_get_invoice.

### `bill_get_invoice` (~65 tokens)

Get an invoice

Get one invoice in full: header, line items, tax lines, and payment applications. Use after finding the invoice id via bill_list_invoices. Returns 404 for invoices not owned by you.

Input parameters:

- `invoice_id` (string, required): Invoice id (from bill_list_invoices)

### `bill_get_invoice_html` (~86 tokens)

Render invoice as HTML

Render one invoice as a branded HTML document (returned as text). Use when the user wants a presentable invoice document; for structured data use bill_get_invoice. A PDF variant exists at GET /v1/invoices/{id}/pdf but is binary — direct users to the portal for PDF downloads.

Input parameters:

- `invoice_id` (string, required): Invoice id (from bill_list_invoices)

### `msg_list` (~139 tokens)

List messages

List your SMS/MMS messages (inbound and outbound), most recent first, optionally filtered by direction or delivery status. Use to review message history or check recent delivery outcomes; for a single message use msg_get, for aggregate counts use msg_get_stats. Errors: NO_ACTIVE_CUSTOMER/UNAUTHORIZED (401).

Input parameters:

- `direction` (string): Filter by message direction
- `page` (integer): Page number, 1-based (default 1)
- `per_page` (integer): Page size (default 20, max 100)
- `status` (string): Filter by delivery status, e.g. queued, sent, delivered, failed

### `msg_send` (~315 tokens)

Send an SMS message

SENDS A REAL SMS TEXT MESSAGE to a real phone number — the recipient's device will receive it immediately; there is no test/sandbox mode, so confirm the destination and body before calling. The `from` number must be assigned to your account AND enrolled in an approved 10DLC campaign (register via msg_create_brand → msg_create_campaign → msg_assign_numbers), otherwise the request is rejected. Errors: INVALID_PAYLOAD/MISSING_PARAM/INVALID_TO (400), NO_ACTIVE_CUSTOMER/UNAUTHORIZED (401), FROM_* rejections for unenrolled numbers.

Input parameters:

- `body` (string, required): Message text, e.g. "Your verification code is 123456". Encoding (GSM-7 vs UCS-2) and segment count are computed automatically.
- `from` (string, required): Sending telephone number in NANP format, e.g. "13039813633". Must be assigned to your account and enrolled in an approved 10DLC campaign (see msg_list_numbers).
- `idempotency_key` (string): Client-supplied Idempotency-Key: retrying with the same key returns the original message instead of sending a duplicate. Strongly recommended.
- `status_callback` (string): Optional webhook URL that receives message-status callbacks (queued → sent → delivered/failed), e.g. "https://example.com/webhooks/sms"
- `to` (string, required): Destination telephone number in E.164 / NANP format, e.g. "13125551212". A real device receives the message.

### `msg_get` (~63 tokens)

Get a message

Get a single SMS/MMS message by its WARP message UUID, including delivery status. Use after msg_send or msg_list to check one message's details. Errors: INVALID_ID (400), NOT_FOUND (404).

Input parameters:

- `id` (string, required): WARP message UUID

### `msg_get_stats` (~62 tokens)

Get message statistics

Get aggregate message counts for your account: overall totals (total, inbound, outbound, delivered, failed) plus a per-campaign breakdown. Use for a quick health check of messaging volume and delivery rates. Errors: NO_ACTIVE_CUSTOMER/UNAUTHORIZED (401).

### `msg_list_brands` (~95 tokens)

List 10DLC brands

List your registered 10DLC brands (snake_case TCR brand objects). A brand is step 1 of the 10DLC flow (create brand → create campaign → assign numbers); use this to find an existing brand before creating campaigns.

Input parameters:

- `page` (integer): Page number, 1-based (default 1)
- `per_page` (integer): Page size (default 20, max 100)

### `msg_create_brand` (~586 tokens)

Create 10DLC brand

Register a new 10DLC brand with TCR (The Campaign Registry) for your account. This is STEP 1 of the 10DLC flow: create brand → msg_create_campaign → msg_assign_numbers. Check msg_list_entity_types and msg_list_verticals for valid enum values first. Registration may incur TCR fees. Errors: INVALID_PAYLOAD/TNIQ_VALIDATION (400), TNIQ_ERROR (502, upstream TCR failure).

Input parameters:

- `alt_business_id` (string): Alternate business identifier, e.g. DUNS number
- `alt_business_id_type` (string): Type of the alternate business ID, e.g. DUNS, LEI, GIIN
- `city` (string): City, e.g. "Denver"
- `company_name` (string): Legal company name as registered, e.g. "Acme Coffee LLC". Required for non-SOLE_PROPRIETOR entity types.
- `country` (string): Country as 2-letter ISO code, e.g. "US"
- `display_name` (string): Brand display/marketing name, e.g. "Acme Coffee"
- `ein` (string): Tax ID / EIN, e.g. "12-3456789" (US). Required for company registrations; improves trust score.
- `ein_issuing_country` (string): EIN issuing country as 2-letter ISO code, e.g. "US"
- `email` (string): Brand contact email address
- `entity_type` (string): Brand entity type (see msg_list_entity_types for the valid list), e.g. PRIVATE_PROFIT
- `first_name` (string): Contact first name (required for SOLE_PROPRIETOR)
- `last_name` (string): Contact last name (required for SOLE_PROPRIETOR)
- `mobile_phone` (string): Mobile phone in E.164 format (used for SOLE_PROPRIETOR OTP verification)
- `phone` (string): Support/contact phone in E.164 format, e.g. "+13035551212"
- `postal_code` (string): Postal/ZIP code, e.g. "80202"
- `reference_id` (string): Your own free-form reference ID for this brand
- `state` (string): State/region code, e.g. "CO"
- `stock_exchange` (string): Stock exchange, e.g. NASDAQ, NYSE (PUBLIC_PROFIT brands only)
- `stock_symbol` (string): Stock ticker symbol (PUBLIC_PROFIT brands only)
- `street` (string): Street address, e.g. "123 Main St"
- `vertical` (string): Industry vertical code (see msg_list_verticals for the valid list), e.g. RETAIL
- `website` (string): Brand website URL, e.g. "https://acme.example.com"

### `msg_get_brand` (~105 tokens)

Get 10DLC brand

Get one of your 10DLC brands by its messaging-backend UUID (snake_case TCR brand object, including identity status and trust score). For brands not registered in this account use msg_lookup_brand with the TCR brand ID instead. Errors: NOT_FOUND (404, includes cross-tenant access), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Brand ID (messaging-backend UUID, as returned by msg_list_brands / msg_create_brand)

### `msg_update_brand` (~583 tokens)

Update 10DLC brand

Full replace (PUT) of one of your 10DLC brands — supply the complete brand object, not just changed fields. Use to correct brand identity details, which may trigger TCR re-verification. Errors: INVALID_PAYLOAD (400), NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `alt_business_id` (string): Alternate business identifier, e.g. DUNS number
- `alt_business_id_type` (string): Type of the alternate business ID, e.g. DUNS, LEI, GIIN
- `city` (string): City, e.g. "Denver"
- `company_name` (string): Legal company name as registered, e.g. "Acme Coffee LLC". Required for non-SOLE_PROPRIETOR entity types.
- `country` (string): Country as 2-letter ISO code, e.g. "US"
- `display_name` (string): Brand display/marketing name, e.g. "Acme Coffee"
- `ein` (string): Tax ID / EIN, e.g. "12-3456789" (US). Required for company registrations; improves trust score.
- `ein_issuing_country` (string): EIN issuing country as 2-letter ISO code, e.g. "US"
- `email` (string): Brand contact email address
- `entity_type` (string): Brand entity type (see msg_list_entity_types for the valid list), e.g. PRIVATE_PROFIT
- `first_name` (string): Contact first name (required for SOLE_PROPRIETOR)
- `id` (string, required): Brand ID (messaging-backend UUID, as returned by msg_list_brands / msg_create_brand)
- `last_name` (string): Contact last name (required for SOLE_PROPRIETOR)
- `mobile_phone` (string): Mobile phone in E.164 format (used for SOLE_PROPRIETOR OTP verification)
- `phone` (string): Support/contact phone in E.164 format, e.g. "+13035551212"
- `postal_code` (string): Postal/ZIP code, e.g. "80202"
- `reference_id` (string): Your own free-form reference ID for this brand
- `state` (string): State/region code, e.g. "CO"
- `stock_exchange` (string): Stock exchange, e.g. NASDAQ, NYSE (PUBLIC_PROFIT brands only)
- `stock_symbol` (string): Stock ticker symbol (PUBLIC_PROFIT brands only)
- `street` (string): Street address, e.g. "123 Main St"
- `vertical` (string): Industry vertical code (see msg_list_verticals for the valid list), e.g. RETAIL
- `website` (string): Brand website URL, e.g. "https://acme.example.com"

### `msg_delete_brand` (~87 tokens)

Delete 10DLC brand

Permanently delete one of your 10DLC brands from TCR and this account. Campaigns under the brand become unusable — only do this when decommissioning a brand. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Brand ID (messaging-backend UUID, as returned by msg_list_brands / msg_create_brand)

### `msg_link_brand` (~92 tokens)

Link existing TCR brand

Link a brand that already exists at TCR (registered elsewhere) into this account, instead of creating a new one with msg_create_brand. Use msg_lookup_brand first to verify the TCR brand ID. Errors: INVALID_PAYLOAD (400), TNIQ_ERROR (502).

Input parameters:

- `tcr_brand_id` (string, required): TCR brand ID to link into this account, e.g. "BABC123"

### `msg_lookup_brand` (~80 tokens)

Look up TCR brand

Read brand details directly from TCR by TCR brand ID, without requiring the brand to be registered in this account. Use before msg_link_brand to verify a brand exists. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `tcr_brand_id` (string, required): TCR brand ID, e.g. "BABC123"

### `msg_list_campaigns` (~112 tokens)

List 10DLC campaigns

List your 10DLC campaigns (snake_case TCR campaign objects), optionally filtered by parent brand. A number must be attached to an approved campaign (msg_assign_numbers) before msg_send will accept it as a `from` number.

Input parameters:

- `brand_id` (string): Filter by parent brand ID (messaging-backend UUID)
- `page` (integer): Page number, 1-based (default 1)
- `per_page` (integer): Page size (default 20, max 100)

### `msg_create_campaign` (~635 tokens)

Create 10DLC campaign

Register a new 10DLC campaign under one of your brands. This is STEP 2 of the 10DLC flow: msg_create_brand → create campaign → msg_assign_numbers. Check msg_get_use_case_requirements for the chosen use case first (sample counts, opt-in rules). Carrier review can take days; monitor with msg_get_mno_status. Registration incurs recurring TCR fees. Errors: INVALID_PAYLOAD/TNIQ_VALIDATION (400), TNIQ_ERROR (502).

Input parameters:

- `age_gated` (boolean): True if content is age-gated (alcohol, gambling, etc.)
- `auto_renewal` (boolean): Auto-renew the campaign at TCR each billing cycle
- `brand_id` (string): Parent brand ID (messaging-backend UUID from msg_list_brands). Required when creating a campaign.
- `description` (string): What this campaign sends and to whom (reviewed by carriers)
- `direct_lending` (boolean): True if content relates to direct lending or loan arrangements
- `embedded_link` (boolean): True if messages may contain URLs/links
- `embedded_phone` (boolean): True if messages may contain phone numbers
- `help_keywords` (string): Comma-separated help keywords, e.g. "HELP,INFO"
- `help_message` (string): Reply sent when a subscriber texts a help keyword
- `message_flow` (string): How subscribers opt in to receive messages (consent flow description; heavily weighted in carrier review)
- `number_pool` (boolean): True if the campaign uses 50+ sending numbers (number pooling)
- `optin_keywords` (string): Comma-separated opt-in keywords, e.g. "START,SUBSCRIBE"
- `optin_message` (string): Confirmation message sent after a subscriber opts in
- `optout_keywords` (string): Comma-separated opt-out keywords, e.g. "STOP,UNSUBSCRIBE"
- `optout_message` (string): Confirmation message sent after a subscriber opts out
- `reference_id` (string): Your own free-form reference ID for this campaign
- `sample1` (string): Sample message 1 (representative outbound text)
- `sample2` (string): Sample message 2
- `sample3` (string): Sample message 3
- `sample4` (string): Sample message 4
- `sample5` (string): Sample message 5
- `sub_usecases` (array): Sub-use-case codes for MIXED/LOW_VOLUME campaigns
- `subscriber_help` (boolean): True if subscribers can request help via keyword (HELP handling)
- `subscriber_optin` (boolean): True if subscribers can opt in via keyword
- `subscriber_optout` (boolean): True if subscribers can opt out via keyword (STOP handling)
- `terms_and_conditions` (boolean): Affirm the campaign complies with carrier terms and conditions
- `usecase` (string): Campaign use case code, e.g. MARKETING, 2FA, CUSTOMER_CARE (see msg_list_use_cases; check msg_get_use_case_requirements first)

### `msg_get_campaign` (~101 tokens)

Get 10DLC campaign

Get one of your 10DLC campaigns by its messaging-backend UUID (snake_case TCR campaign object, including registration status). For campaigns not registered in this account use msg_lookup_campaign with the TCR campaign ID. Errors: NOT_FOUND (404, includes cross-tenant access), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)

### `msg_update_campaign` (~619 tokens)

Update 10DLC campaign

Update (PUT) one of your 10DLC campaigns — e.g. fix sample messages or opt-in flow after a carrier rejection, then resubmit with msg_resubmit_campaign. Errors: INVALID_PAYLOAD (400), NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `age_gated` (boolean): True if content is age-gated (alcohol, gambling, etc.)
- `auto_renewal` (boolean): Auto-renew the campaign at TCR each billing cycle
- `brand_id` (string): Parent brand ID (messaging-backend UUID from msg_list_brands). Required when creating a campaign.
- `description` (string): What this campaign sends and to whom (reviewed by carriers)
- `direct_lending` (boolean): True if content relates to direct lending or loan arrangements
- `embedded_link` (boolean): True if messages may contain URLs/links
- `embedded_phone` (boolean): True if messages may contain phone numbers
- `help_keywords` (string): Comma-separated help keywords, e.g. "HELP,INFO"
- `help_message` (string): Reply sent when a subscriber texts a help keyword
- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)
- `message_flow` (string): How subscribers opt in to receive messages (consent flow description; heavily weighted in carrier review)
- `number_pool` (boolean): True if the campaign uses 50+ sending numbers (number pooling)
- `optin_keywords` (string): Comma-separated opt-in keywords, e.g. "START,SUBSCRIBE"
- `optin_message` (string): Confirmation message sent after a subscriber opts in
- `optout_keywords` (string): Comma-separated opt-out keywords, e.g. "STOP,UNSUBSCRIBE"
- `optout_message` (string): Confirmation message sent after a subscriber opts out
- `reference_id` (string): Your own free-form reference ID for this campaign
- `sample1` (string): Sample message 1 (representative outbound text)
- `sample2` (string): Sample message 2
- `sample3` (string): Sample message 3
- `sample4` (string): Sample message 4
- `sample5` (string): Sample message 5
- `sub_usecases` (array): Sub-use-case codes for MIXED/LOW_VOLUME campaigns
- `subscriber_help` (boolean): True if subscribers can request help via keyword (HELP handling)
- `subscriber_optin` (boolean): True if subscribers can opt in via keyword
- `subscriber_optout` (boolean): True if subscribers can opt out via keyword (STOP handling)
- `terms_and_conditions` (boolean): Affirm the campaign complies with carrier terms and conditions
- `usecase` (string): Campaign use case code, e.g. MARKETING, 2FA, CUSTOMER_CARE (see msg_list_use_cases; check msg_get_use_case_requirements first)

### `msg_resubmit_campaign` (~87 tokens)

Resubmit 10DLC campaign

Resubmit a 10DLC campaign for carrier review, typically after fixing rejection reasons with msg_update_campaign. Check current per-carrier status with msg_get_mno_status first. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)

### `msg_elect_cnp` (~146 tokens)

Elect connectivity partner (CNP)

Elect a Connectivity Partner / DCA for one of your campaigns (required before carriers will pass traffic; see msg_list_dcas for available partners). The body is a free-form object passed through to the messaging backend. Check election/sharing progress with msg_get_sharing_status. Errors: INVALID_PAYLOAD (400), NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `body` (object): Free-form CNP election payload passed through to the messaging backend, e.g. {"cnp_id": "SYNIVERSE"}
- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)

### `msg_nudge_cnp` (~93 tokens)

Nudge connectivity partner

Prompt the elected Connectivity Partner to re-review a campaign that is stuck in review. Use when msg_get_sharing_status shows a pending CNP review for too long. Returns 202 Accepted with no body. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)

### `msg_get_mno_status` (~100 tokens)

Get campaign MNO status

Get per-mobile-carrier (MNO) registration status for one of your campaigns — shows whether AT&T, T-Mobile, Verizon, etc. have approved it. Use after msg_create_campaign or msg_resubmit_campaign to track carrier approval. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)

### `msg_get_sharing_status` (~104 tokens)

Get campaign sharing status

Get the connectivity-partner (CNP) sharing status for one of your campaigns — whether the campaign has been shared with and accepted by the elected CNP/DCA. Use after msg_elect_cnp; if stuck, try msg_nudge_cnp. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)

### `msg_link_campaign` (~92 tokens)

Link existing TCR campaign

Link a campaign that already exists at TCR (registered elsewhere) into this account, instead of creating a new one with msg_create_campaign. Use msg_lookup_campaign first to verify the TCR campaign ID. Errors: INVALID_PAYLOAD (400), TNIQ_ERROR (502).

Input parameters:

- `tcr_campaign_id` (string, required): TCR campaign ID to link into this account, e.g. "CABC123"

### `msg_lookup_campaign` (~80 tokens)

Look up TCR campaign

Read campaign details directly from TCR by TCR campaign ID, without requiring the campaign to be registered in this account. Use before msg_link_campaign to verify a campaign exists. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `tcr_campaign_id` (string, required): TCR campaign ID, e.g. "CABC123"

### `msg_list_campaign_numbers` (~125 tokens)

List campaign numbers

List the telephone numbers attached to one of your 10DLC campaigns. Use to verify which numbers can send under a campaign; for account-wide messaging status of every DID use msg_list_numbers. Errors: NOT_FOUND (404), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)
- `page` (integer): Page number, 1-based (default 1)
- `per_page` (integer): Page size (default 50, max 500)

### `msg_assign_numbers` (~172 tokens)

Attach numbers to campaign

Attach telephone numbers you own to one of your 10DLC campaigns. This is STEP 3 of the 10DLC flow (msg_create_brand → msg_create_campaign → assign numbers) and is required before msg_send will accept a number as `from`. Returns per-TN assigned/failed lists (failure reasons: not_found, not_owned, lookup_error, write_error); the response is NOT wrapped in the standard envelope. Errors: INVALID_PAYLOAD (400), NOT_FOUND (404, campaign not owned), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)
- `phone_numbers` (array, required): Telephone numbers to attach, NANP format, e.g. ["13039813633"]

### `msg_remove_numbers` (~149 tokens)

Detach numbers from campaign

Detach telephone numbers from one of your 10DLC campaigns — those numbers can no longer send SMS until re-attached to an approved campaign. Returns per-TN removed/failed lists (failure reasons: not_found, not_owned, lookup_error, write_error); the response is NOT wrapped in the standard envelope. Errors: INVALID_PAYLOAD (400), NOT_FOUND (404, campaign not owned), TNIQ_ERROR (502).

Input parameters:

- `id` (string, required): Campaign ID (messaging-backend UUID, as returned by msg_list_campaigns / msg_create_campaign)
- `phone_numbers` (array, required): Telephone numbers to detach, NANP format, e.g. ["13039813633"]

### `msg_list_numbers` (~79 tokens)

List messaging-enabled numbers

List every active DID you own joined to its messaging association: attached campaign/brand, messaging status, MMS enablement, and whether a per-TN inbound webhook is configured (has_webhook). Use to check which numbers are ready to send with msg_send or still need msg_assign_numbers. Errors: NO_ACTIVE_CUSTOMER/UNAUTHORIZED (401).

### `msg_list_carriers` (~49 tokens)

List mobile carriers (MNOs)

List the mobile network operators (MNOs) relevant to 10DLC registration (AT&T, T-Mobile, Verizon, etc.). Reference data for interpreting msg_get_mno_status results.

### `msg_list_dcas` (~54 tokens)

List connectivity partners (DCAs/CNPs)

List the Direct Connect Aggregators / connectivity partners (CNPs) that WARP elects against (only the common ones, not the full upstream list). Use before msg_elect_cnp to pick a partner.

### `msg_list_entity_types` (~41 tokens)

List brand entity types

List the valid 10DLC brand entity types (e.g. PRIVATE_PROFIT, NON_PROFIT). Reference data — check before msg_create_brand.

### `msg_list_use_cases` (~51 tokens)

List campaign use cases

List the valid 10DLC campaign use cases (e.g. MARKETING, 2FA). Reference data — check before msg_create_campaign, then fetch details with msg_get_use_case_requirements.

### `msg_get_use_case_requirements` (~91 tokens)

Get use case requirements

Get the submission requirements for a specific 10DLC campaign use case: required sample-message count, opt-in rules, approval difficulty, and notes. Use before msg_create_campaign to build a compliant submission. Errors: MISSING_PARAM/INVALID_USE_CASE (400).

Input parameters:

- `use_case` (string, required): Use case code from msg_list_use_cases, e.g. MARKETING, 2FA

### `msg_list_verticals` (~35 tokens)

List industry verticals

List the valid 10DLC brand industry verticals. Reference data — check before msg_create_brand or msg_update_brand.

### `msg_get_throughput_estimate` (~110 tokens)

Get throughput estimate

Estimate messaging throughput (messages/sec, daily cap) and get a recommendation for a brand given its trust score and vetting status. Use after msg_get_brand (which includes the trust score) to understand sending capacity and whether external vetting would help. Errors: MISSING_PARAM/INVALID_PARAM (400).

Input parameters:

- `trust_score` (integer, required): Brand trust score, 0-100 (from the TCR brand object)
- `vetted` (boolean): Whether the brand is externally vetted

### `num_list` (~197 tokens)

List your numbers

List the telephone numbers you own, with each number's voice/SMS configuration state. Use to browse or audit your DID/TFN inventory; filter by status, type, search text, or configuration flags. To find NEW purchasable numbers use num_search instead; to inspect one owned number use num_get.

Input parameters:

- `page` (integer): Page number, 1-based (default 1)
- `search` (string): Free-text search on TN digits or metadata
- `size` (integer): Results per page (default 50)
- `sms_configured` (boolean): Filter to numbers with (true) or without (false) SMS configuration
- `status` (string): Filter by number status
- `type` (string): Filter by number type: did (local) or tfn (toll-free)
- `voice_configured` (boolean): Filter to numbers with (true) or without (false) voice configuration

### `num_search` (~270 tokens)

Search available numbers

Search upstream inventory for PURCHASABLE telephone numbers by area code, rate center, locality, or digit pattern. Returns paginated candidates you do not yet own. Use this before ordering; then buy a candidate with num_order (or many with num_bulk_order). For numbers you already own use num_list.

Input parameters:

- `city` (string): City name
- `last_4_prefix` (string): Prefix the last 4 digits must start with
- `locality` (string): Locality name
- `npa` (string): Area code (NPA), 3 digits, e.g. "303"
- `nxx` (string): Exchange (NXX), 3 digits, e.g. "629"
- `page` (integer): Page number, 1-based (default 1)
- `pattern` (string): Digit pattern to match within the number, e.g. "1234"
- `rate_center` (string): LERG rate center name, e.g. "DENVER"
- `size` (integer): Results per page (default 25)
- `state` (string): 2-letter state code, e.g. "CO"
- `type` (string): Number type: "did" (local, default) or "tfn" (toll-free)

### `num_get` (~80 tokens)

Get a number

Get one telephone number you own, including its voice and SMS usage configuration. Use after num_list to inspect a specific TN before updating it with num_update_voice, num_update_sms, or num_update_metadata.

Input parameters:

- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_update_metadata` (~126 tokens)

Update number metadata

Update the friendly name and/or description on a number you own. Use to label numbers for humans; for routing/E911/CNAM use num_update_voice, for messaging use num_update_sms. Errors: INVALID_REQUEST, TN_NOT_OWNED.

Input parameters:

- `description` (string): Longer free-text description of the number's purpose
- `friendly_name` (string): Human-friendly label for the number, e.g. "Support line"
- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_order` (~161 tokens)

Order (assign) a number

Procure a telephone number from upstream inventory and assign it to your account. THIS COSTS MONEY — ordering a number incurs purchase and recurring charges, so confirm the TN with the user first. Find candidates with num_search; after ordering, configure it with num_update_voice / num_update_sms. For up to 200 numbers at once use num_bulk_order. Errors: TN_ALREADY_ASSIGNED, TN_UNAVAILABLE, TNIQ_UPSTREAM_ERROR.

Input parameters:

- `description` (string): Free-text description to set on the new number
- `friendly_name` (string): Human-friendly label to set on the new number
- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_bulk_order` (~298 tokens)

Bulk order (assign) numbers

Procure and assign up to 200 telephone numbers in one idempotent batch. THIS COSTS MONEY — each number incurs purchase and recurring charges, so confirm the list with the user first. Requires a UUID idempotency key (reused as procurement_request_id); reuse the same key to safely retry. Per-TN failures do not abort the batch. Find candidates with num_search; for a single number use num_order; to route many held numbers to a trunk use num_bulk_route. Errors: INVALID_REQUEST, MISSING_IDEMPOTENCY_KEY, INVALID_IDEMPOTENCY_KEY, TRUNK_UNOWNED (whole-request 403 on default_trunk_id).

Input parameters:

- `default_trunk_id` (string): Trunk-group UUID to route all assigned numbers to (403 TRUNK_UNOWNED if not yours)
- `idempotency_key` (string, required): UUID idempotency key for the batch (sent as the Idempotency-Key header; reuse it to retry the same batch safely)
- `note` (string): Free-text note recorded on the procurement request
- `per_tn_overrides` (object): Map of TN -> per-number override object, overriding tn_metadata/default_trunk_id for that TN
- `tn_metadata` (object): Metadata applied to every TN in the batch (e.g. friendly_name, description fields)
- `tns` (array, required): Telephone numbers to procure and assign (max 200)

### `num_bulk_route` (~118 tokens)

Bulk route numbers to a trunk

Assign up to 200 HELD numbers you already own to a single voice trunk-group in one request (idempotent at the SQL level). Use after num_bulk_order to bring purchased numbers into service, or to re-home existing numbers. For per-number routing details use num_update_voice. Errors: INVALID_REQUEST, TRUNK_UNOWNED (whole-request 403).

Input parameters:

- `tns` (array, required): Held telephone numbers to route (max 200)
- `trunk_id` (string, required): Voice trunk-group UUID to route all listed numbers to

### `num_release` (~124 tokens)

Release a number

Release a telephone number you own back to inventory. IRREVERSIBLE from your account's perspective — the number leaves your inventory and may be picked up by others, so confirm with the user first. Errors: TN_NOT_OWNED, POI_LOCKED (number is a POI fallback ANI), TNIQ_UPSTREAM_ERROR.

Input parameters:

- `reason` (string): Free-text reason for releasing the number (for audit)
- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_update_voice` (~290 tokens)

Update voice configuration

Set or update the voice routing, E911, and CNAM configuration on a number you own. Use after ordering a number (num_order) to bring it into voice service, or to change routing later. To disable voice entirely use num_delete_voice_config; to route many numbers to one trunk use num_bulk_route. Errors: INVALID_REQUEST, TN_NOT_OWNED.

Input parameters:

- `cnam_display_name` (string): CNAM display name shown to called parties (typically max 15 chars)
- `cnam_enabled` (boolean): Enable or disable outbound CNAM (caller name) on this number
- `e911_address_id` (string): Validated E911 address record ID to associate with this number
- `e911_enabled` (boolean): Enable or disable E911 emergency service on this number
- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1
- `trunk_id` (string): Voice trunk-group UUID to route inbound calls to
- `voice_destination` (string): Primary inbound voice destination (e.g. SIP URI or endpoint)
- `voice_failover_destination` (string): Failover destination used when the primary is unreachable
- `voice_routing_type` (string): Routing type for inbound voice (e.g. "trunk" or a URI-based type per your account setup)

### `num_delete_voice_config` (~88 tokens)

Clear voice configuration

Remove the voice usage row from a number you own, DISABLING voice routing on it (inbound calls will stop routing). To change routing instead of removing it, use num_update_voice. Errors: TN_NOT_OWNED.

Input parameters:

- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_update_sms` (~179 tokens)

Update SMS configuration

Update the customer-owned SMS fields on a number you own: inbound webhook URL/secret, fallback URL, and MMS toggle. Requests containing tniq-owned fields are rejected. To remove SMS entirely use num_delete_sms_config. Errors: INVALID_REQUEST, TN_NOT_OWNED.

Input parameters:

- `fallback_inbound_url` (string): Fallback URL used when the primary inbound webhook fails
- `inbound_webhook_secret` (string): Shared secret used to sign inbound webhook deliveries
- `inbound_webhook_url` (string): HTTPS URL that receives inbound SMS webhooks, e.g. "https://example.com/sms"
- `mms_enabled` (boolean): Enable or disable MMS on this number
- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_delete_sms_config` (~79 tokens)

Clear SMS configuration

Remove the SMS usage row from a number you own, disabling SMS on it. To change SMS settings instead of removing them, use num_update_sms. Errors: TN_NOT_OWNED.

Input parameters:

- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_get_port_out_pin` (~106 tokens)

Get port-out PIN status

Check whether a port-out PIN is set on a number you own, and if verification attempts locked it out, when the lock expires (locked_until). The PIN itself is never returned. Set a PIN with num_set_port_out_pin; clear it with num_remove_port_out_pin. Errors: TN_NOT_OWNED.

Input parameters:

- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_set_port_out_pin` (~136 tokens)

Set port-out PIN

Set the customer-chosen 4-10 digit port-out PIN on a number you own (hashed at rest; also resets the failed-attempt lock). Requires step-up MFA on the session. Check current state with num_get_port_out_pin; clear with num_remove_port_out_pin. Errors: INVALID_REQUEST, INVALID_PIN, TN_NOT_OWNED.

Input parameters:

- `pin` (string, required): Port-out PIN, 4-10 digits, e.g. "482913"
- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `num_remove_port_out_pin` (~105 tokens)

Clear port-out PIN

Clear the port-out PIN on a number you own (idempotent), removing PIN protection against port-outs. Requires step-up MFA. Returns 204 No Content on success. Check state with num_get_port_out_pin; set a new PIN with num_set_port_out_pin. Errors: TN_NOT_OWNED.

Input parameters:

- `tn` (string, required): Telephone number, 10 digits (e.g. "3035551234") or 11 digits with leading 1

### `port_preview` (~133 tokens)

Preview a port-in

Run an instant Telique-backed portability preview for a free-form list of TNs, grouped by current losing-carrier SPID. No project is created — use this BEFORE port_create_request to see which carriers hold the numbers and whether they are portable. For numbers already on-net (WARP-to-WARP), use port_preview_transfer instead. Errors: NO_ACTIVE_CUSTOMER, INVALID_PAYLOAD, VALIDATION_ERROR, GATEWAY_UNAVAILABLE.

Input parameters:

- `tns` (array, required): Free-form list of 10-digit telephone numbers to check for portability, e.g. ["3035551234", "7205556789"]

### `port_list_requests` (~53 tokens)

List port-in requests

List the active customer's port-in requests, most-recent first. Use to find an existing port request's UUID before calling port_get_request or any other per-request tool. Errors: NO_ACTIVE_CUSTOMER, INTERNAL_ERROR.

### `port_create_request` (~153 tokens)

Create a port-in draft

Create a draft port-in request (TNIQ project + WARP mirror row). This is step 1 of the port-in lifecycle: create draft → port_add_tns → port_set_group_details → port_validate_request → port_generate_loa → port_submit_request → track with port_get_progress → port_activate. Run port_preview first to check portability. Errors: NO_ACTIVE_CUSTOMER, INVALID_PAYLOAD, TNIQ_ERROR, INTERNAL_ERROR, GATEWAY_UNAVAILABLE.

Input parameters:

- `desired_due_date` (string): Desired port due date (FOC date), ISO 8601 date, e.g. 2026-08-01
- `name` (string): Human-friendly name for the port request

### `port_get_request` (~107 tokens)

Get a port-in request

Get one port-in request: the WARP mirror row, the live TNIQ project, and per-SPID grouped TN details. Also reconciles any ACTIVATED TNs into inventory (idempotent). Use this as the primary status view for a port; for the lighter progress snapshot use port_get_progress. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, CONFLICT.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_delete_draft` (~90 tokens)

Delete a port-in draft

Delete a pre-submission draft port request (TNIQ project + WARP mirror row). Only allowed in states with zero submitted TNs — after submission use port_cancel_request instead. Requires step-up MFA. Errors: NOT_FOUND, CONFLICT (already submitted), TNIQ_ERROR, INTERNAL_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_add_tns` (~115 tokens)

Add TNs to a port-in request

Normalise a free-form TN list and upload it to the draft port request's TNIQ project. Step 2 of the port-in lifecycle, after port_create_request and before port_set_group_details / port_validate_request. Errors: INVALID_PAYLOAD, VALIDATION_ERROR, NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `tns` (array, required): Free-form list of 10-digit telephone numbers to add to the port request

### `port_validate_request` (~108 tokens)

Validate a port-in request

Trigger a TNIQ-side re-validation of ALL TNs in the port request. Run after adding TNs (port_add_tns) and applying carrier details (port_set_group_details), then inspect failures via port_get_error_groups and fix them with port_auto_fix. To revalidate only a subset of TNs use port_revalidate_tns. Errors: NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_revalidate_tns` (~109 tokens)

Revalidate selected port-in TNs

Send a REVALIDATE bulk action for selected (or all) TNs in the port request. Use after fixing individual TN errors when you don't need the full re-validation of port_validate_request. Errors: NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `tns` (array): Optional subset of 10-digit TNs to revalidate; omit to revalidate all TNs in the request

### `port_submit_request` (~170 tokens)

Submit a port-in request

Submit the port to NPAC. Gated on (1) every off-net SPID group having a current LOA (generate one with port_generate_loa or upload with port_upload_document) and (2) the project being submittable (validate first with port_validate_request). Requires step-up MFA. On the LOA gate a 409 CONFLICT is returned whose error.details has reason="loa_required" and groups=[{spid, tn_count, reason: "missing"|"stale"}]; other 409s carry error.details.reason from the submit blocker. After submitting, track with port_get_progress and port_get_statistics. Errors: NOT_FOUND, CONFLICT, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_resubmit_request` (~86 tokens)

Resubmit a port-in request

Resubmit a port that is in an error/rejection/exception state (e.g. after fixing issues with port_auto_fix or port_set_group_details). Only valid from those states — a CONFLICT is returned otherwise. Errors: NOT_FOUND, CONFLICT, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_activate` (~94 tokens)

Activate ported numbers

Activate numbers that have reached FOC (the final step of the port-in lifecycle). Gated on the project being activatable — check port_get_progress first. Requires step-up MFA. To have this happen automatically instead, use port_set_auto_activation. Errors: NOT_FOUND, CONFLICT (not activatable), TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_set_auto_activation` (~166 tokens)

Set auto-activation policy

Update the port project's auto-activation mode so numbers activate without a manual port_activate call. Modes: DISABLED (manual only), ASAP (activate as soon as FOC is reached), SCHEDULED (activate at scheduled_at, which is required for that mode). Errors: INVALID_PAYLOAD, NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `mode` (string, required): Auto-activation mode: DISABLED | ASAP | SCHEDULED (SCHEDULED requires scheduled_at)
- `scheduled_at` (string): ISO 8601 timestamp for SCHEDULED mode, e.g. 2026-08-01T14:00:00Z; required when mode=SCHEDULED

### `port_cancel_request` (~78 tokens)

Cancel a port-in request

Cancel a submitted port. Gated on the project being cancellable — a CONFLICT is returned otherwise. For unsubmitted drafts use port_delete_draft instead. Requires step-up MFA. Errors: NOT_FOUND, CONFLICT, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_supplement_due_date` (~142 tokens)

Supplement the due date

Change the desired due date of a submitted port (SUP_DDD), optionally for a subset of TNs. Only valid before activation — a CONFLICT is returned otherwise. Errors: INVALID_PAYLOAD, NOT_FOUND, CONFLICT, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `new_ddd` (string, required): New desired due date (FOC date), ISO 8601 date, e.g. 2026-08-15
- `tns` (array): Optional subset of 10-digit TNs to supplement; omit to apply to all TNs

### `port_get_error_groups` (~88 tokens)

Get port-in error groups

Get the TNIQ validation/port error groups for the project. Use after port_validate_request or a rejected submission to see what's blocking the port, then resolve with port_auto_fix (pass an error_group_id) or port_set_group_details. Errors: NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_auto_fix` (~134 tokens)

Auto-fix port-in errors

Apply TNIQ auto-fixes to the project, optionally scoped to one error group (from port_get_error_groups) or a TN subset. After fixing, run port_revalidate_tns or port_resubmit_request as appropriate. Errors: NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `error_group_id` (string): Error group ID (from port_get_error_groups) to scope the fix to
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `tns` (array): Optional subset of 10-digit TNs to fix; omit to fix all affected TNs

### `port_set_group_details` (~222 tokens)

Apply carrier-group details

Apply losing-carrier account details (account number, BTN, PIN, service address, names) to EVERY TN in one SPID group. Group membership is recomputed from live TNIQ details, not client-supplied. Get SPID groups from port_get_request; run before port_validate_request. Errors: INVALID_PAYLOAD, INVALID_PARAM, NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `account_number` (string): Account number with the losing carrier
- `btn` (string): Billing telephone number (10-digit) on the losing account
- `business_name` (string): Business name on the losing account
- `end_user_name` (string): End-user name on the losing account
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `pin` (string): Account PIN/passcode with the losing carrier
- `service_address` (string): Service address on file with the losing carrier
- `spid` (string, required): Losing-carrier SPID (from port_get_request's SPID groups)

### `port_generate_loa` (~249 tokens)

Generate a Letter of Authorization

Render a WARP-branded LOA PDF for one off-net SPID group and upload it to the project, superseding prior LOAs for that group. Only valid BEFORE the port is submitted; every off-net group needs a current LOA before port_submit_request will succeed. Requires attestation=true plus all authorizing-party, losing-carrier, and signer fields. Requires step-up MFA. Alternatively upload an existing signed LOA with port_upload_document. Errors: INVALID_PAYLOAD (error.details.fields lists missing fields), INVALID_PARAM, CONFLICT (already submitted), TNIQ_ERROR, INTERNAL_ERROR, GATEWAY_UNAVAILABLE.

Input parameters:

- `attestation` (boolean, required): Must be true — attests the signer is authorized to port the numbers
- `authorizing_party` (object): Authorizing party details for the LOA
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `losing_carrier` (object): Losing-carrier account details for the LOA
- `signer` (object): Signer details for the LOA
- `spid` (string, required): Losing-carrier SPID (from port_get_request's SPID groups)

### `port_list_documents` (~117 tokens)

List port documents

List the port project's documents (LOAs, bills, CSRs, etc.), optionally filtered by doc_type or TN. signer_ip is present only for operator callers. Use to verify LOA coverage before port_submit_request. Errors: NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `doc_type` (string): Filter by document type: LOA | BILL | CSR | OTHER
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `tn` (string): Filter by 10-digit telephone number

### `port_upload_document` (~150 tokens)

Upload a port document

Upload a supporting document (LOA, bill copy, CSR, or other; max 25MB) to the port's TNIQ project from a local file. Use for a customer-signed LOA or supporting evidence; to have WARP generate the LOA instead, use port_generate_loa. Errors: INVALID_PAYLOAD, NOT_FOUND, TNIQ_VALIDATION, TNIQ_ERROR.

Input parameters:

- `doc_type` (string, required): Document type: LOA | BILL | CSR | OTHER
- `file_path` (string, required): Absolute path to the local file to upload (max 25MB)
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_download_document` (~105 tokens)

Download a port document

Download one port document's raw bytes (Content-Type mirrors the stored document). Get document IDs from port_list_documents. Note: binary content (e.g. PDF) is returned inline and may not be readable as text. Errors (JSON): NOT_FOUND, TNIQ_VALIDATION, TNIQ_ERROR.

Input parameters:

- `doc_id` (string, required): Document ID (from port_list_documents)
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_delete_document` (~93 tokens)

Delete a port document

Delete a document from the port project. Get document IDs from port_list_documents. Deleting a group's only current LOA will re-block port_submit_request for that group. Errors: NOT_FOUND, TNIQ_VALIDATION, TNIQ_ERROR.

Input parameters:

- `doc_id` (string, required): Document ID (from port_list_documents)
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_get_progress` (~87 tokens)

Get port-in progress

Get the live TNIQ progress snapshot for the port project. Use to track a submitted port (per-TN states, FOC readiness) and to check whether it is activatable before port_activate. For aggregate counts use port_get_statistics. Errors: NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_get_statistics` (~77 tokens)

Get port-in statistics

Get the live TNIQ statistics for the port project (also opportunistically refreshes the WARP snapshot). Use for aggregate TN state counts; for per-TN detail use port_get_progress. Errors: NOT_FOUND, TNIQ_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_get_history` (~72 tokens)

Get port-in audit history

Get the audit timeline for the port request (tenant-scoped, newest-first). Use to see who did what and when — submissions, cancels, document uploads, state changes. Errors: NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_list_notes` (~64 tokens)

List port-in notes

List the port request's notes. Operators also see internal notes; customers see only customer-visibility notes. Add notes with port_add_note. Errors: NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)

### `port_add_note` (~119 tokens)

Add a port-in note

Add a note to the port request. visibility="internal" is operator-only (customers get FORBIDDEN); customers may only post "customer" notes. Read notes with port_list_notes. Errors: INVALID_PAYLOAD, FORBIDDEN, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `body` (string, required): Note text
- `id` (string, required): Port request UUID (from port_list_requests or port_create_request)
- `visibility` (string): Note visibility: "customer" (default; visible to the customer) or "internal" (operator-only)

### `port_preview_transfer` (~131 tokens)

Preview an on-net transfer

For a free-form TN list, report which numbers are on-net (an active WARP assignment) and eligible for on-net transfer between WARP tenants (no NPAC port needed). The owning customer's BAN is masked. Per-TN ineligibility reasons: not_in_warp_inventory, already_yours, poi_locked, lookup_failed. Use before port_execute_transfer; for off-net numbers use port_preview instead. Errors: NO_ACTIVE_CUSTOMER, INVALID_PAYLOAD, VALIDATION_ERROR.

Input parameters:

- `tns` (array, required): Free-form list of 10-digit telephone numbers to check for on-net transfer eligibility

### `port_execute_transfer` (~135 tokens)

Execute an on-net transfer

Transfer on-net numbers between WARP tenants without an NPAC port. Each item authorizes with the current owner's port-out PIN; items succeed or fail INDEPENDENTLY within an HTTP 200 response — check per-TN results. Per-TN failure reasons: not_in_warp_inventory, already_yours, poi_locked, invalid_pin, pin_locked, lookup_failed, transfer_failed, invalid_tn. Preview eligibility first with port_preview_transfer. Requires step-up MFA. Errors: NO_ACTIVE_CUSTOMER, INVALID_PAYLOAD.

Input parameters:

- `items` (array, required): Numbers to transfer, each with the owning tenant's port-out PIN

### `port_lookup_company_details` (~150 tokens)

Lookup company details by name and address

Retrieve detailed company information from TinComply by company name and optional address. Used during the port-in flow for entity verification (e.g. before drafting an LOA). See also port_lookup_ein (by EIN) and port_verify_tin_name (TIN/name match). Errors: INVALID_REQUEST, COMPANY_NAME_REQUIRED, TINCOMPLY_ERROR, LOOKUP_FAILED.

Input parameters:

- `city` (string): City
- `company_name` (string, required): Legal company name to look up
- `state` (string): State, 2-letter code, e.g. CO
- `street` (string): Street address
- `zip_code` (string): ZIP code, e.g. 80202

### `port_lookup_ein` (~100 tokens)

Lookup company by EIN

Retrieve company information from TinComply by EIN/Tax ID. Used during the port-in flow for entity verification. Validate the format first with port_validate_ein_format if unsure. Errors: EIN_REQUIRED, INVALID_EIN, TINCOMPLY_ERROR, LOOKUP_FAILED.

Input parameters:

- `ein` (string, required): EIN/Tax ID, 9 digits with or without hyphen, e.g. 12-3456789 or 123456789

### `port_validate_ein_format` (~75 tokens)

Validate EIN format

Check whether an EIN is well-formed (9 digits) WITHOUT calling the external TinComply API. Use as a cheap pre-check before port_lookup_ein or port_verify_tin_name. Errors: EIN_REQUIRED.

Input parameters:

- `ein` (string, required): EIN to validate, e.g. 12-3456789

### `port_verify_tin_name` (~121 tokens)

Verify TIN and company name match

Verify that a TIN matches the provided company name via IRS TIN-Name matching. Used during the port-in flow to confirm the authorizing entity before submission. See also port_lookup_ein and port_lookup_company_details. Errors: INVALID_REQUEST, INVALID_TIN, COMPANY_NAME_REQUIRED, TINCOMPLY_ERROR, VERIFICATION_FAILED.

Input parameters:

- `company_name` (string, required): Legal company name to match against the TIN
- `tin` (string, required): TIN/EIN to verify, 9 digits, e.g. 123456789

### `team_list_members` (~81 tokens)

List team members

List every user holding a role in this customer, alphabetical by email. Use to see who is on the team and which role each member holds, or to find a user UUID for team_update_member_role / team_remove_member. Requires the team:read scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)

### `team_remove_member` (~118 tokens)

Remove a team member

Remove a user's membership (role assignment) from this customer. HIGH IMPACT: the user immediately loses access and all their sessions are invalidated. You cannot remove yourself. Find the user UUID via team_list_members first. To change a member's permissions instead of removing them, use team_update_member_role. Requires the team:write scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `user_id` (string, required): User UUID of the team member (find it via team_list_members)

### `team_update_member_role` (~140 tokens)

Set a member's role

Assign a role (system or customer-owned, never superadmin) to a member of this customer, replacing their current role. The caller must hold every scope the role grants (no privilege escalation). Find user UUIDs via team_list_members and role UUIDs via team_list_roles. Requires the team:write scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `role_id` (string, required): UUID of the role to assign (from team_list_roles); superadmin roles cannot be assigned
- `user_id` (string, required): User UUID of the team member (find it via team_list_members)

### `team_list_roles` (~75 tokens)

List roles

List the system roles plus this customer's custom roles. Use to find a role UUID for team_update_member_role, team_get_role, team_update_role, team_duplicate_role, or team_delete_role. Requires the team:read scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)

### `team_get_role` (~93 tokens)

Get a role

Get one role (system or customer-owned) with its full scope list. Use to inspect exactly what a role grants before assigning it (team_update_member_role) or editing it (team_update_role). Requires the team:read scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `role_id` (string, required): Role UUID (find it via team_list_roles)

### `team_create_role` (~191 tokens)

Create a custom role

Create a customer-owned role with the given scope set. Scopes must exist in the platform registry (discover them with acct_list_scopes), be non-superadmin, and be held by the caller (no privilege escalation). To start from an existing role's scopes instead, use team_duplicate_role. Requires the team:write scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `description` (string): Optional free-text description of the role's purpose
- `display_name` (string, required): Human-readable role name, e.g. 'Billing Viewer'
- `name` (string, required): Machine name for the role (unique within the customer), e.g. 'billing_viewer'
- `scopes` (array, required): Permission scopes the role grants, e.g. ['team:read', 'billing:read']. Use acct_list_scopes to see the full catalog.

### `team_update_role` (~178 tokens)

Update a custom role

Update the display name, description, and/or scope set of a customer-owned role. System roles are immutable. HIGH IMPACT when changing scopes: session invalidation fans out to every user holding the role. Only provided fields are changed. Use acct_list_scopes to discover valid scopes. Requires the team:write scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `description` (string): New free-text description of the role's purpose
- `display_name` (string): New human-readable role name
- `role_id` (string, required): Role UUID (find it via team_list_roles)
- `scopes` (array): Replacement scope set, e.g. ['team:read', 'billing:read']. Replaces the role's entire scope list and invalidates sessions of affected users.

### `team_duplicate_role` (~162 tokens)

Duplicate a role

Create a new customer-owned role copying the source role's scope set (the source may be a system role). Useful for customizing a system role: duplicate it, then adjust scopes with team_update_role. The caller must hold every copied scope. Requires the team:write scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `description` (string): Optional free-text description of the new role
- `display_name` (string, required): Human-readable name for the new role
- `name` (string, required): Machine name for the new role (unique within the customer), e.g. 'support_admin_custom'
- `role_id` (string, required): Source role UUID to copy scopes from (find it via team_list_roles)

### `team_delete_role` (~97 tokens)

Delete a custom role

Permanently delete a customer-owned role. HIGH IMPACT and irreversible. Fails when the role is still assigned to any user (reassign members via team_update_member_role first) or when it is a system role. Requires the team:write scope.

Input parameters:

- `customer_id` (string, required): Your customer UUID (shown in the WARP portal under Settings)
- `role_id` (string, required): Role UUID (find it via team_list_roles)

### `trunk_list` (~45 tokens)

List my trunks

List all of your trunk groups, each with its IP ACL entries. Use this first to find a trunk_id for the other trunk_* tools. Errors: UNAUTHORIZED, INTERNAL_ERROR.

### `trunk_get` (~60 tokens)

Get a trunk

Get one trunk group you own, including its IP ACL entries. Use trunk_list first to find the trunk id. Errors: UNAUTHORIZED, INVALID_ID, NOT_FOUND.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_create` (~309 tokens)

Create a trunk

Create a new trunk group on your account. Enforces your account's allowed number-classes and per-direction capacity ceilings (check acct_get_capacity first). Note: a capacity of 0 means 'direction disabled' — calls in that direction are rejected with 503 + Retry-After. Errors: NO_ACTIVE_CUSTOMER, INVALID_PAYLOAD, VALIDATION_ERROR, INTERNAL_ERROR.

Input parameters:

- `allowed_number_classes` (array): Number classes this trunk may carry (must be within the account's allowed classes)
- `auth_type` (string, required): Authentication mode: IP_ACL (source-IP allowlist), DIGEST (SIP username/password), EITHER, or BOTH
- `capacity_channels_inbound` (integer): Max concurrent inbound channels; 0 disables inbound
- `capacity_channels_outbound` (integer): Max concurrent outbound channels; 0 disables outbound
- `capacity_cps_inbound` (integer): Max inbound calls-per-second. 0 is valid and means the direction is disabled (runtime gate returns 503 + Retry-After)
- `capacity_cps_outbound` (integer): Max outbound calls-per-second; 0 disables outbound
- `description` (string): Free-text description of the trunk
- `name` (string, required): Trunk name (required)
- `sip_config` (object): SIP config object persisted as JSONB (e.g. { codecs: [...], dtmf_mode: '...' }). The customer portal only writes codecs and dtmf_mode; other keys are admin-surface.

### `trunk_update` (~303 tokens)

Update a trunk

Update an owned trunk's settings (name, auth type, capacities, SIP config). The trunk being updated is excluded from the account capacity-sum check. POI assignment is silently ignored (admin-only). Step-up MFA required. Use trunk_list first to find the trunk id. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INVALID_PAYLOAD, VALIDATION_ERROR, INTERNAL_ERROR.

Input parameters:

- `allowed_number_classes` (array): Number classes this trunk may carry
- `auth_type` (string): Authentication mode: IP_ACL, DIGEST, EITHER, or BOTH
- `capacity_channels_inbound` (integer): Max concurrent inbound channels; 0 disables inbound
- `capacity_channels_outbound` (integer): Max concurrent outbound channels; 0 disables outbound
- `capacity_cps_inbound` (integer): Max inbound calls-per-second; 0 disables inbound (503 + Retry-After at runtime)
- `capacity_cps_outbound` (integer): Max outbound calls-per-second; 0 disables outbound
- `description` (string): Free-text description of the trunk
- `name` (string): Trunk name
- `sip_config` (object): SIP config object persisted as JSONB (e.g. { codecs: [...], dtmf_mode: '...' }). The customer portal only writes codecs and dtmf_mode; other keys are admin-surface.
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_delete` (~107 tokens)

Delete a trunk

Delete an owned trunk. Rejected with CONFLICT when the trunk has live calls (drain first — check trunk_get_throttle_state) or is referenced by CDRs (disable it via trunk_update instead). Run trunk_get_cascade_preview first to see what will be removed. Step-up MFA required. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, CONFLICT, INTERNAL_ERROR.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_get_cascade_preview` (~93 tokens)

Preview trunk deletion cascade

Get per-trunk cascade-preview counts (src_ips, tns_routed_here, active_calls, cdr_count) for an owned trunk. Use before trunk_delete to see what would be affected; active_calls is read live from Redis. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_get_throttle_state` (~89 tokens)

Get trunk live throttle state

Get an owned trunk's configured capacity plus live CPS/channel counters. Use to check current load before draining, deleting, or resizing a trunk. On a Redis read failure the counters are null and counters_available=false (still HTTP 200). Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, NOT_FOUND.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_list_credentials` (~83 tokens)

List SIP credentials

List SIP Digest credentials for an owned trunk (no HA1, no password), each enriched with live registration_count and active_call_count. Use trunk_list first to find the trunk id. Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, INTERNAL_ERROR.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_create_credential` (~122 tokens)

Create a SIP credential

Create a SIP Digest credential on an owned trunk. The trunk's auth_type must be DIGEST, EITHER, or BOTH (check with trunk_get). The plaintext password is returned exactly once — save it immediately. Step-up MFA required. Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, VALIDATION_ERROR, INVALID_PAYLOAD, CONFLICT, INTERNAL_ERROR.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)
- `username` (string, required): SIP auth username for the new credential (required)

### `trunk_update_credential` (~140 tokens)

Enable or disable a SIP credential

Toggle a SIP credential's enabled flag. Disabling drops the Redis HA1 + AOR and tears down active registrations (in-progress dialogs are NOT terminated); enabling restores them. Use trunk_list_credentials first to find the credential id. Step-up MFA required. Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, INVALID_PAYLOAD, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `cred_id` (string, required): SIP credential UUID (find it with trunk_list_credentials)
- `enabled` (boolean): true to enable the credential, false to disable it
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_delete_credential` (~112 tokens)

Delete a SIP credential

Delete a SIP credential and cascade removal from Redis + Kamailio usrloc. Idempotent (returns 204 when already gone). Use trunk_list_credentials first to find the credential id. Step-up MFA required. Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `cred_id` (string, required): SIP credential UUID (find it with trunk_list_credentials)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_rotate_credential` (~110 tokens)

Rotate a SIP credential's password

Generate a new password + HA1 for a SIP credential (username and realm unchanged). The old password stops working immediately and the new plaintext password is returned exactly once — save it immediately. Step-up MFA required. Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `cred_id` (string, required): SIP credential UUID (find it with trunk_list_credentials)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_list_credential_calls` (~111 tokens)

List a credential's active calls

List active SIP dialogs for a credential's AOR. Note: the dialog-tracking store is not yet live, so this currently returns an empty array. Use trunk_list_credentials first to find the credential id. Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `cred_id` (string, required): SIP credential UUID (find it with trunk_list_credentials)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_list_credential_registrations` (~116 tokens)

List a credential's live registrations

List the current Kamailio usrloc bindings (live SIP registrations) for a credential's AOR. Use to see which devices are registered, or to find a contact_id for trunk_revoke_registration. Errors: INVALID_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, NOT_FOUND, GATEWAY_UNAVAILABLE.

Input parameters:

- `cred_id` (string, required): SIP credential UUID (find it with trunk_list_credentials)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_revoke_registration` (~143 tokens)

Revoke a single SIP registration

Evict one SIP contact binding from Kamailio usrloc for a credential's AOR. Use trunk_list_credential_registrations first to find the contact_id. Step-up MFA required. Errors: INVALID_ID, MISSING_ID, NO_ACTIVE_CUSTOMER, TRUNK_UNOWNED, NOT_FOUND, GATEWAY_UNAVAILABLE.

Input parameters:

- `contact_id` (string, required): usrloc contact ID of the registration binding to revoke (from trunk_list_credential_registrations)
- `cred_id` (string, required): SIP credential UUID (find it with trunk_list_credentials)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_list_endpoints` (~73 tokens)

List trunk endpoints

List the dispatcher endpoints (SIP destinations WARP delivers calls to) for an owned trunk. Use trunk_list first to find the trunk id. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_get_endpoint` (~84 tokens)

Get a trunk endpoint

Get one dispatcher endpoint on an owned trunk. Use trunk_list_endpoints first to find the endpoint id. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `endpoint_id` (integer, required): Endpoint ID (integer, find it with trunk_list_endpoints)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_create_endpoint` (~245 tokens)

Create a trunk endpoint

Add a dispatcher endpoint (SIP destination) to an owned trunk, either as structured host/port/transport or as a raw_uri. Returns HTTP 207 with a warning when the Kamailio sync is deferred. Step-up MFA required. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INVALID_PAYLOAD, VALIDATION_ERROR, INTERNAL_ERROR.

Input parameters:

- `description` (string): Free-text label for the endpoint
- `enabled` (boolean): Whether the endpoint is active in the dispatcher
- `host` (string): SIP destination hostname or IP (structured form; mutually alternative to raw_uri)
- `port` (integer): SIP destination port (e.g. 5060)
- `priority` (integer): Failover priority (lower is tried first)
- `raw_uri` (string): Raw SIP URI (alternative to structured host/port/transport, e.g. sip:pbx.example.com:5061;transport=tls)
- `transport` (string): SIP transport protocol
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)
- `weight` (integer): Load-balancing weight among endpoints of the same priority

### `trunk_update_endpoint` (~270 tokens)

Update a trunk endpoint

Update a dispatcher endpoint on an owned trunk (structured host/port/transport fields or a raw_uri). Returns HTTP 207 with a warning when the Kamailio sync is deferred. Use trunk_list_endpoints first to find the endpoint id. Step-up MFA required. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INVALID_PAYLOAD, VALIDATION_ERROR, INTERNAL_ERROR.

Input parameters:

- `description` (string): Free-text label for the endpoint
- `enabled` (boolean): Whether the endpoint is active in the dispatcher
- `endpoint_id` (integer, required): Endpoint ID (integer, find it with trunk_list_endpoints)
- `host` (string): SIP destination hostname or IP (structured form; mutually alternative to raw_uri)
- `port` (integer): SIP destination port (e.g. 5060)
- `priority` (integer): Failover priority (lower is tried first)
- `raw_uri` (string): Raw SIP URI (alternative to structured host/port/transport, e.g. sip:pbx.example.com:5061;transport=tls)
- `transport` (string): SIP transport protocol
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)
- `weight` (integer): Load-balancing weight among endpoints of the same priority

### `trunk_delete_endpoint` (~96 tokens)

Delete a trunk endpoint

Remove a dispatcher endpoint from an owned trunk and drop it from Kamailio. Use trunk_list_endpoints first to find the endpoint id. Step-up MFA required. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `endpoint_id` (integer, required): Endpoint ID (integer, find it with trunk_list_endpoints)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_list_ips` (~81 tokens)

List trunk IP ACL entries

List all IP ACL entries for an owned trunk. Use to audit which source IPs may send calls, or to find an ip_id for trunk_update_ip_acl / trunk_delete_ip_acl. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_add_ip_acl` (~195 tokens)

Add a trunk IP ACL entry

Add an IP/netmask to an owned trunk's ACL and sync it to Kamailio, allowing that source IP to send calls. The trunk's auth_type should include IP_ACL (IP_ACL, EITHER, or BOTH — check with trunk_get). Step-up MFA required. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INVALID_PAYLOAD, INTERNAL_ERROR.

Input parameters:

- `description` (string): Free-text label for this ACL entry (e.g. 'HQ PBX')
- `enabled` (boolean): Whether the entry is active (default true)
- `ip` (string, required): IPv4 address to allow (e.g. 203.0.113.10)
- `netmask` (integer): CIDR netmask bits, 0-32 (e.g. 32 for a single host)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_update_ip_acl` (~132 tokens)

Update a trunk IP ACL entry

Update the description and/or enabled flag of an owned trunk's IP ACL entry. Use trunk_list_ips first to find the ip_id. Step-up MFA required. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INVALID_PAYLOAD, INTERNAL_ERROR.

Input parameters:

- `description` (string): New free-text label for the ACL entry
- `enabled` (boolean): true to enable the ACL entry, false to disable it
- `ip_id` (string, required): IP ACL entry UUID (find it with trunk_list_ips)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

### `trunk_delete_ip_acl` (~101 tokens)

Delete a trunk IP ACL entry

Remove an IP ACL entry from an owned trunk; that source IP can no longer send calls via IP auth. Use trunk_list_ips first to find the ip_id. Step-up MFA required. Errors: NO_ACTIVE_CUSTOMER, INVALID_ID, NOT_FOUND, INTERNAL_ERROR.

Input parameters:

- `ip_id` (string, required): IP ACL entry UUID (find it with trunk_list_ips)
- `trunk_id` (string, required): Trunk group UUID (find it with trunk_list)

## Diagnostics

Captured diagnostic sections: Provenance, Install scripts, Dependencies. The full working is on the page: https://verifymcp.io/servers/ringer-warp/warp-mcp#diagnostics

## Score history

- 2026-08-03: 79
- 2026-08-02: 78
- 2026-08-01: 25
- 2026-07-31: 52
- 2026-07-29: 51
- 2026-07-28: 51
- 2026-07-27: 51

## Links

- npm package: https://www.npmjs.com/package/warp-mcp
- Socket report: https://socket.dev/npm/package/warp-mcp
- Repository: https://github.com/Ringer/warp-mcp
- Website: https://warp.ringer.tel/
- Changelog RSS feed: https://verifymcp.io/servers/ringer-warp/warp-mcp/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/ringer-warp/warp-mcp/changelog.json
- HTML version of this page: https://verifymcp.io/servers/ringer-warp/warp-mcp
