Spoke Phone MCP by usefulapi

Read Spoke calls, transcripts, directory and users; manage phonebook contacts and send SMS.

Should I use this

Quality & Safety

A
Description quality
92%
Schema completeness
88%
Naming quality
75%
Poisoning risk
100%
Permission match
100%
Protocol compliance
100%

Findings (7)

  • LOWTool 'spokephone_list_call_content_analysis' name length outside 3-30 rangein spokephone_list_call_content_analysis
  • LOWTool 'spokephone_get_phonebook_contact' name length outside 3-30 rangein spokephone_get_phonebook_contact
  • LOWTool 'spokephone_get_transcript_segments' name length outside 3-30 rangein spokephone_get_transcript_segments
  • LOWTool 'spokephone_list_content_analysis' name length outside 3-30 rangein spokephone_list_content_analysis
  • LOWTool 'spokephone_get_content_analysis' name length outside 3-30 rangein spokephone_get_content_analysis
  • LOWTool 'spokephone_save_phonebook_contact' name length outside 3-30 rangein spokephone_save_phonebook_contact
  • LOWTool 'spokephone_delete_phonebook_contact' name length outside 3-30 rangein spokephone_delete_phonebook_contact

Based on automated analysis of tool definitions and protocol compliance.

Context Cost

~4,369Tokens (tool definitions)
~1.2 KBTypical response size
Significant attention impact (3.41% of 128k context)

This is the approximate number of tokens consumed each time the server's tools are loaded into a model's context. Higher counts reduce the attention available for other tasks.

Install

One-Click Install

Add this to your `claude_desktop_config.json` file:

{
  "mcpServers": {
    "spoke-phone": {
      "url": "https://spoke-phone.usefulapi.io/mcp"
    }
  }
}

Remote endpoints

https://spoke-phone.usefulapi.io/mcpstreamable-http

What it can do

Tool inventory

Tools (27)

🟢 Read-only🟡 Write🔴 Delete⚪ Unknown
🟢spokephone_list_calls(since, before, modified, contactNumber, includeActive, ...)

List call records (oldest first by default; pass sortOrder descending for the latest calls), with caller, direction, duration, assigned user/team and recording URLs. Filter by time window or the external party's number. Returns { meta: { next }, calls }.

Input Schema

{
  "type": "object",
  "properties": {
    "since": {
      "description": "Only calls created at or after this time (unix timestamp in milliseconds).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "before": {
      "description": "Only calls created before this time (unix timestamp in milliseconds).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "modified": {
      "description": "Only calls created or modified since this time (calls gain notes/recordings after they end) (unix timestamp in milliseconds).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "contactNumber": {
      "description": "Only calls with this external party number (+E.164).",
      "type": "string",
      "pattern": "^\\+[1-9]\\d{6,14}$"
    },
    "includeActive": {
      "description": "Also return calls still in progress (default false).",
      "type": "boolean"
    },
    "includeRecordingUrl": {
      "description": "Include recording/voicemail URLs (default true).",
      "type": "boolean"
    },
    "sortOrder": {
      "description": "ascending = oldest first (the API default); descending = latest first.",
      "type": "string",
      "enum": [
        "ascending",
        "descending"
      ]
    },
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_call(id, includeRecordingUrl)

Get one call record by call id.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "description": "Call id."
    },
    "includeRecordingUrl": {
      "type": "boolean"
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_call_recording(id, recordingId)

Get the details and download URL of one recording of a call.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "description": "Call id."
    },
    "recordingId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id",
    "recordingId"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_call_content_analysis(id, artifact, limit, next)

List the Enlighten AI content-analysis results (summaries etc.) stored for one call.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "description": "Call id."
    },
    "artifact": {
      "description": "Artifact schema name, e.g. \"generalSummary\".",
      "type": "string"
    },
    "limit": {
      "description": "Page size (default 5, max 10).",
      "type": "integer",
      "minimum": 0,
      "maximum": 10
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_directory(extension, phoneNumber, ivrKey, includeSuspendedUsers, includeHiddenCallGroups, ...)

List or search the unified Spoke directory (users, teams, devices) with extensions and live availability. Exactly one of extension, phoneNumber or ivrKey may be used to look up an entry. Returns { meta: { next }, entries }.

Input Schema

{
  "type": "object",
  "properties": {
    "extension": {
      "description": "Exact extension number.",
      "type": "string"
    },
    "phoneNumber": {
      "description": "Exact phone number assigned to an entry.",
      "type": "string"
    },
    "ivrKey": {
      "description": "Exact IVR key.",
      "type": "string"
    },
    "includeSuspendedUsers": {
      "type": "boolean"
    },
    "includeHiddenCallGroups": {
      "type": "boolean"
    },
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_directory_entry(entryId)

Get one directory entry (user, team or device) by entry id.

Input Schema

{
  "type": "object",
  "properties": {
    "entryId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "entryId"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_users(email)

List active Spoke users with real-time availability. Optionally filter by email address.

Input Schema

{
  "type": "object",
  "properties": {
    "email": {
      "description": "Return only the user with this email address.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_user(id)

Get one Spoke user with availability, by user id.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_teams(limit, next)

List Spoke teams (call groups) with their members and availability.

Input Schema

{
  "type": "object",
  "properties": {
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_locations(limit, next)

List the locations of the organisation.

Input Schema

{
  "type": "object",
  "properties": {
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_location(locationId)

Get one location by id.

Input Schema

{
  "type": "object",
  "properties": {
    "locationId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "locationId"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_location_users(locationId, limit, next)

List the users assigned to one location.

Input Schema

{
  "type": "object",
  "properties": {
    "locationId": {
      "type": "string",
      "minLength": 1
    },
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "required": [
    "locationId"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_phonebooks(search, excludeEmpty, limit)

List shared phonebooks (the CRM contact containers used for caller ID), each with its contacts. Use limit 0 to list phonebooks without contacts.

Input Schema

{
  "type": "object",
  "properties": {
    "search": {
      "description": "Filter contacts (at least 3 characters).",
      "type": "string",
      "minLength": 3
    },
    "excludeEmpty": {
      "description": "Skip phonebooks that have no matching contacts.",
      "type": "boolean"
    },
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_phonebook(id, search, limit, next)

Get one phonebook and a page of its contacts. The id may also be a user's email address for that user's personal phonebook.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    },
    "search": {
      "type": "string",
      "minLength": 3
    },
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_phonebook_contact(id, contactId)

Get one contact of a phonebook.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "description": "Phonebook id."
    },
    "contactId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id",
    "contactId"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_transcripts(since, before, sourceId, sourceContextId, limit, ...)

List call and voicemail transcripts. Filter by time window or source.

Input Schema

{
  "type": "object",
  "properties": {
    "since": {
      "description": "Created at or after (unix timestamp in milliseconds).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "before": {
      "description": "Created before (unix timestamp in milliseconds).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "sourceId": {
      "type": "string"
    },
    "sourceContextId": {
      "type": "string"
    },
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_transcript(id)

Get one transcript by id.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_transcript_segments(id)

Get the per-speaker segments of one transcript.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1,
      "description": "Transcript id."
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_content_analysis(since, before, sourceId, participantId, contactNumber, ...)

List AI content-analysis results (needs the Enlighten entitlement). Filter by time, source, participant or artifact name.

Input Schema

{
  "type": "object",
  "properties": {
    "since": {
      "description": "First recording/transcript started at or after (unix timestamp in milliseconds).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "before": {
      "description": "First recording/transcript started before (unix timestamp in milliseconds).",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "sourceId": {
      "type": "string"
    },
    "participantId": {
      "type": "string"
    },
    "contactNumber": {
      "type": "string",
      "pattern": "^\\+[1-9]\\d{6,14}$"
    },
    "artifact": {
      "description": "Artifact schema name, e.g. \"generalSummary\".",
      "type": "string"
    },
    "limit": {
      "description": "Page size (default 5, max 10).",
      "type": "integer",
      "minimum": 0,
      "maximum": 10
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_content_analysis(id)

Get one content-analysis result by id.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_webhooks(limit, next)

List the webhook subscriptions of the account.

Input Schema

{
  "type": "object",
  "properties": {
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_webhook(id)

Get one webhook subscription by id.

Input Schema

{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "id"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_list_trunks(limit, next)

List the SIP trunks that overlay a legacy PBX onto Spoke.

Input Schema

{
  "type": "object",
  "properties": {
    "limit": {
      "description": "Page size (default 100, max 1000).",
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "next": {
      "description": "Cursor from the previous reply's meta.next; omit for the first page.",
      "type": "string"
    }
  },
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟢spokephone_get_trunk(trunkId)

Get one SIP trunk by id.

Input Schema

{
  "type": "object",
  "properties": {
    "trunkId": {
      "type": "string",
      "minLength": 1
    }
  },
  "required": [
    "trunkId"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🟡spokephone_send_sms(to, body, fromNumber, fromUserEmail, conversationName, ...)

WRITE: send a real SMS to a phone number (or a group MMS to several) from a company number or from a Spoke user's conversation number. The message appears in the Spoke conversation. Confirm the recipient and text with the user first. Needs an SMS-enabled number. POST /conversationMessages.

Input Schema

{
  "type": "object",
  "properties": {
    "to": {
      "minItems": 1,
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "string",
        "pattern": "^\\+[1-9]\\d{6,14}$"
      },
      "description": "Recipient number(s) in +E.164 form. More than one sends a group MMS."
    },
    "body": {
      "type": "string",
      "minLength": 1,
      "maxLength": 1600,
      "description": "Message text, up to 1600 characters."
    },
    "fromNumber": {
      "description": "Company number to send from (+E.164). Give this OR fromUserEmail.",
      "type": "string",
      "pattern": "^\\+[1-9]\\d{6,14}$"
    },
    "fromUserEmail": {
      "description": "Email of the Spoke user whose conversation number sends the message. Give this OR fromNumber.",
      "type": "string",
      "format": "email",
      "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
    },
    "conversationName": {
      "type": "string",
      "maxLength": 100
    },
    "notificationMode": {
      "type": "string",
      "enum": [
        "notify_unread",
        "silent_read",
        "silent_unread"
      ]
    },
    "routingAction": {
      "description": "Who handles replies in a new conversation.",
      "type": "string",
      "enum": [
        "assign_owner",
        "assign_users",
        "do_not_route"
      ]
    },
    "assignUsers": {
      "description": "User emails to assign (required with routingAction assign_users).",
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "string",
        "format": "email",
        "pattern": "^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"
      }
    },
    "confirm": {
      "type": "boolean",
      "const": true,
      "description": "Must be true: the user approved sending this exact text to these recipients."
    }
  },
  "required": [
    "to",
    "body",
    "confirm"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴spokephone_save_phonebook_contact(phonebookId, contactId, phoneNumbers, firstName, lastName, ...)

WRITE: add a contact to a phonebook, REPLACING any contact there with the same contactId (other contacts are untouched). The phonebook id may be a user's email for a personal phonebook. Contacts feed caller ID. PUT /phonebooks/{id}/contacts.

Input Schema

{
  "type": "object",
  "properties": {
    "phonebookId": {
      "type": "string",
      "minLength": 1,
      "description": "Phonebook id (from spokephone_list_phonebooks) or a user's email address."
    },
    "contactId": {
      "description": "Your own stable id for the contact; reuse it to replace that contact.",
      "type": "string",
      "minLength": 1
    },
    "phoneNumbers": {
      "minItems": 1,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "description": "e.g. work, mobile, home"
          },
          "value": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "label",
          "value"
        ]
      },
      "description": "At least one number, e.g. { label: 'work', value: '+442071234567' }."
    },
    "firstName": {
      "type": "string"
    },
    "lastName": {
      "type": "string"
    },
    "companyName": {
      "type": "string"
    },
    "jobTitle": {
      "type": "string"
    },
    "emails": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "minLength": 1,
            "description": "e.g. work, mobile, home"
          },
          "value": {
            "type": "string",
            "minLength": 1
          }
        },
        "required": [
          "label",
          "value"
        ]
      }
    },
    "countryIso": {
      "description": "ISO country code for formatting local numbers, e.g. GB.",
      "type": "string",
      "minLength": 2,
      "maxLength": 2
    }
  },
  "required": [
    "phonebookId",
    "phoneNumbers"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}
🔴spokephone_delete_phonebook_contact(phonebookId, contactId, confirm)

WRITE, destructive: delete one contact from a phonebook (it stops showing in caller ID). DELETE /phonebooks/{id}/contacts/{contactId}.

Input Schema

{
  "type": "object",
  "properties": {
    "phonebookId": {
      "type": "string",
      "minLength": 1
    },
    "contactId": {
      "type": "string",
      "minLength": 1
    },
    "confirm": {
      "type": "boolean",
      "const": true,
      "description": "Must be true: the user approved deleting this contact."
    }
  },
  "required": [
    "phonebookId",
    "contactId",
    "confirm"
  ],
  "$schema": "https://json-schema.org/draft/2020-12/schema"
}

Community

Rate this Server

Evidence

Recent observations

verifiedversion not recorded27 tools