CallRail MCP
PYPI · CALLRAIL-MCP
CallRail REST API v3: 57 tools for calls, leads, trackers, tags, users, and agency reporting.
Available components
Last scanned (14 hours ago)
Scores higher than 69% of PyPI servers
Category CRM and Sales
Recent critical change
GHSA-6q48-6c7w-9gw2 affects this package (21 Oct 2026). See the changelog before you install this server.
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. How we score → Why this is hard to score →
Supply Chain Security50
- Malware scan not yet available for this package.Unverified
- No known CVEs affecting this package version or its production dependencies.Pass
- Runs hatchling.build at install time, a recognised build step with no custom scripting around it. View diagnostics → Pass
- 1 of 32 dependencies flagged as unhealthy. View diagnostics → Partial
Provenance & Transparency100
- Source repository is publicly reachable at the declared URL. View diagnostics → Pass
- Cryptographically verified build provenance (signed, bound to pghdma/callrail-mcp). View diagnostics → Pass
- Clear OSI-approved license (MIT).Pass
- Actively maintained (last published 26 days ago).Pass
- Publishes a security disclosure policy (SECURITY.md).Pass
Schema Quality & AI Usability58
- AI-judged instruction clarity (good).Pass
- Context-footprint check failed: tool/resource definitions use about 14990 tokens (~262/item across 57 items; 57 tools + 0 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management77
- Stability observed for 23 of 30 days with no destabilising changes; credit accrues until the full window elapses.Partial
Tool Coverage71
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 0% of tool parameters carry a description.Fail
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- All 6 tool(s) whose name or description implies an irreversible operation declare an MCP destructiveHint annotation.Pass
- An AI judge read all 57 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Checks we ran (15)
- Known CVEs
- Install scripts
- Dependency health
- Source repository
- Provenance
- License
- Maintenance
- Security disclosure
- Schema quality
- Stability
- Tool coverage
- Injection markers
- Destructive annotations
- Judged manipulation
- MCP protocol
Checks we could not complete (1)
These are gaps on our side, not findings about this package. We only credit what we can confirm, so a category made up entirely of them scores 0.
- Malware scan in Supply Chain SecurityMalware scan not yet available for this package.
Does not apply to this package (2)
- Endpoint SecurityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
- Transport & ReachabilityScored on hosted endpoints only. A package has no live endpoint of its own for us to probe.
The score does not measure everything. What the score does not measure →
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 5 Nov 26 −14
- Malware scan: pass → unverified ▼ security
- 3 Nov 26 −4
- Stability: fail → 0.70 functional
- 25 Oct 26 +1
- Security disclosure: unverified → pass ▲ functional
- 24 Oct 26 −1
- Security disclosure: pass → unverified ▼ functional
- 22 Oct 26 +90
- GHSA-6q48-6c7w-9gw2 no longer affects this package ▲ security
- Known CVEs: fail → pass ▲ security
- Score status: failed → scored ▲ functional
- 21 Oct 26 −90
- GHSA-6q48-6c7w-9gw2 affects this package: none ▼ critical
- Known CVEs: pass → fail ▼ critical
- Score status: scored → failed ▼ critical
- 17 Oct 26 +2
No change was recorded against any check on this day. Stability & Change Management went from 82 to 99.
- 16 Oct 26 +1
No change was recorded against any check on this day. Stability & Change Management went from 79 to 82.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Analysed pypi/callrail-mcp@1.3.1
Provenance Verified
A signed build attestation was found and verified, binding this exact artifact to the source repository it claims to come from.
| Result | Verified |
|---|---|
| Ecosystem | pypi |
| Reason | Verified |
| Discovered via | Registry attestation endpoint |
| Source repo | pghdma/callrail-mcp |
| Certificate issuer | https://token.actions.githubusercontent.com |
| Certificate SAN | https://github.com/pghdma/callrail-mcp/.github/workflows/publish.yml@refs/tags/v1.3.1 |
| Rekor log index | 3169782742 |
| Predicate type | PyPI publish attestation https://docs.pypi.org/attestations/publish/v1 |
| Subject digest | sha256:ffd788688cfc2fa1d5d25b7204c7680c9c2344bb16efd48996db209c2e0198d2 |
Background: How many MCP packages publish verified provenance →
Install scripts 1 script
| Hook | Tier | Command |
|---|---|---|
| build_backend | Known build tool | hatchling.build |
Background: Why install scripts are a supply-chain risk →
Dependencies 32 packages
| Packages resolved | 32 |
|---|---|
| No linked repository | 1 |
| Tree resolution | Complete |
Background: SBOMs and build attestations, explained →
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
search_calls_by_number ~121
Find calls from/to a specific phone number. Matches on the last 10 digits of the stored `customer_phone_number` so any format works. Args: phone_number: Any format, normalized to digits-only. Must contain at least 7 digits to avoid false positives. account_id: Auto-resolves. company_id: Optional company filter. days: Lookback window (default 90).
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| company_id | – | – | – |
| days | integer | – | – |
| phone_number | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
spam_detector ~364
Heuristically identify likely-spam calls and (optionally) tag them. Spam scoring (additive): +2 if duration < 10 seconds +1 if not answered +1 if first_call AND duration < 30 seconds +1 if same caller appears >=3 times in window (likely auto-dialer) A call scoring >= 3 is flagged as likely spam. Args: company_id: Restrict to one company (recommended). days: Lookback window (1-90; 90 is hard-capped to avoid memory blowup on high-volume clients: full call list is materialized for scoring before truncating the response). auto_tag: If True, ADD `tag_name` to each likely-spam call after the scan. Default False (preview only). Note: we deliberately do NOT mark calls as spam=True automatically: CallRail HIDES spam-flagged calls from default GET endpoints, so self-reviewing them later becomes painful. Tag first, manually spam-flag if confirmed. tag_name: The tag to add when auto_tag=True. Default 'auto_detected_spam'. Auto-creates the tag at company level if it doesn't exist (CallRail's behavior). account_id: Auto-resolves if omitted. Returns: - score breakdown by call - histogram of caller phone numbers (so you can spot a single dialer hammering you) - if auto_tag: count tagged + failures
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| auto_tag | boolean | – | – |
| company_id | – | – | – |
| days | integer | – | – |
| tag_name | string | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_call ~415
Update an existing call: notes, tags, spam flag, customer name, lead status. Args: call_id: 'CAL...' id of the call to update. account_id: Auto-resolves if omitted. note: Replace the call's note text. tags: REPLACE the call's tag list with this set of tag names. (Use `add_call_tags`/`remove_call_tags` for additive changes.) spam: True to mark as spam. False is rejected: CallRail cannot un-mark spam via the API. Note: spam-flagged calls are HIDDEN from default GET endpoints; re-reads will 404. Tag the call BEFORE flagging spam if you need both. customer_name: Override the auto-detected caller name. lead_status: 'good_lead' or 'not_a_lead'. CallRail returns 400 when a call already at previously_marked_good_lead is set to good_lead. Note: `value` is intentionally NOT exposed here. CallRail's API returns a 500 server error when `value` is included in the PUT body to /calls (verified via live testing 2026-04-24). It IS supported on form submissions. See `update_form_submission`. Empty-string fields (e.g. `note=""`) are rejected because CallRail interprets them as "clear this field", which is almost always a mistake. To intentionally clear a field, set it to None and use a separate UI operation, or contact CallRail support. Length caps (rejected pre-network): - `note`: 4000 chars - `customer_name`: 200 chars - `tags`: 100 entries max
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| call_id | string | yes | – |
| customer_name | – | – | – |
| lead_status | – | – | – |
| note | – | – | – |
| spam | – | – | – |
| tags | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_company ~584
Update mutable settings on a company. Pass None to leave a field unchanged; only fields with explicit values are sent in the PUT body. CRITICAL: Any boolean toggle you set will OVERRIDE current state. If a company has CallScribe enabled and you call `update_company(name='New Name')` without passing `callscribe_enabled`, CallScribe stays on. But passing `callscribe_enabled=False` will DISABLE CallScribe (a paid feature). Be deliberate with bool args. Empty-string `name` / `time_zone` are rejected (almost always a mistake; pass None to leave them alone). Args: company_id: 'COM...' id. name: New display name. Empty string rejected. Max 255 chars. time_zone: IANA tz string (e.g. 'America/New_York'). callscore_enabled: CallScore AI lead scoring. PAID add-on. lead_scoring_enabled: NOT settable via the API (read-only field); passing it returns an error. Toggle it in the CallRail UI. swap_exclude_jquery: Deprecated by CallRail, has no effect. Not sent; reported under `api_warnings` in the response. callscribe_enabled: Conversation Intelligence (transcripts + call highlights). PAID feature. keyword_spotting_enabled: Deprecated by CallRail, has no effect. Not sent; reported under `api_warnings` in the response. form_capture: Enable CallRail Form Tracking on this company. Sent as CallRail's `external_form_capture` PUT field. swap_ppc_override: Override the original source when a visitor arrives via PPC. swap_landing_override: Landing-page URL parameter (for example 'utm_source') that overrides the original source. Pass "" to turn the override off (sent as null). swap_cookie_duration: Visitor cookie lifetime, with `swap_cookie_duration_unit` ('months' | 'weeks' | 'days'). CallRail caps it at 6 months. account_id: CallRail account ID. Auto-resolves if omitted. Returns: JSON string with the updated company object, plus `api_warnings` whe…
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| callscore_enabled | – | – | – |
| callscribe_enabled | – | – | – |
| company_id | string | yes | – |
| form_capture | – | – | – |
| keyword_spotting_enabled | – | – | – |
| lead_scoring_enabled | – | – | – |
| name | – | – | – |
| swap_cookie_duration | – | – | – |
| swap_cookie_duration_unit | – | – | – |
| swap_exclude_jquery | – | – | – |
| swap_landing_override | – | – | – |
| swap_ppc_override | – | – | – |
| time_zone | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_form_submission ~335
Update an existing form submission: note, tags, value, lead status. Args: submission_id: CallRail form-submission id (prefix 'FOR...'). account_id: Auto-resolves if omitted. note: Free text (max 4000 chars). tags: Tag names. REPLACES the submission's tags unless `append_tags=True` (CallRail's documented flag). Unknown names are auto-created at the company level. value: Monetary value; sent as a currency string ("12.50"), which is what PUT /form_submissions accepts. spam: NOT supported for form submissions (the PUT body has no spam field); passing it returns an error. Spam flagging exists for calls only (`update_call`). lead_status: 'good_lead' or 'not_a_lead'. CallRail returns 400 when a submission already at previously_marked_good_lead is set to good_lead. append_tags: Add `tags` to the existing ones instead of replacing. Empty-string fields (e.g. `note=""`) are rejected to prevent accidental field-clearing. See `update_call` docstring. Length caps (rejected pre-network): - `note`: 4000 chars - `tags`: 100 entries max
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| append_tags | boolean | – | – |
| lead_status | – | – | – |
| note | – | – | – |
| spam | – | – | – |
| submission_id | string | yes | – |
| tags | – | – | – |
| value | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_notification ~337
Update a notification rule. Pass None to leave a field unchanged; only fields with explicit values are sent in the PUT body. Notification rules trigger emails / desktop pushes / SMS when calls or form submissions match conditions. Use this to rewire targets, change triggering events, or silence a noisy rule without deleting it (set all `send_*` to False). Args: notification_id: Notification rule ID. name: Display name for the rule. alert_type: Common values: 'all_calls', 'first_time_callers', 'missed_calls', 'voicemails', 'all_texts', 'first_time_texters', 'all_form_submissions' (same set as `create_notification`). Plan-specific: unknown values warn but do not reject. send_email: Send email notification. send_desktop: Send desktop browser push. send_push: Send mobile push notification. call_enabled: Trigger on call events. sms_enabled: Trigger on SMS events. email: Override target email (defaults to user's primary). Validated as RFC-822-ish. account_id: CallRail account ID. Auto-resolves if omitted. Returns: JSON string with the updated notification rule.
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| alert_type | – | – | – |
| call_enabled | – | – | – |
| company_id | – | – | – |
| – | – | – | |
| name | – | – | – |
| notification_id | string | yes | – |
| send_desktop | – | – | – |
| send_email | – | – | – |
| send_push | – | – | – |
| sms_enabled | – | – | – |
| tracker_id | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_sms_thread ~255
Update an SMS thread's lead-management fields. This is the texting equivalent of `update_call`. Closes the gap where texting leads couldn't be tagged / noted / qualified via API. Args: thread_id: Thread id (from `list_sms_threads`). notes: Note text (max 4000 chars). Empty string rejected. value: Monetary value; sent as a currency string ("12.50"), which is what PUT /sms-threads accepts. tags: Tag names to apply (max 100). append_tags: If True (default), `tags` are ADDED to existing ones (CallRail's `append_tags` flag). If False, `tags` REPLACES the thread's tag list. lead_qualification: 'good_lead' or 'not_a_lead' (CallRail docs; null clears it, which this tool does not expose). account_id: Auto-resolves if omitted.
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| append_tags | boolean | – | – |
| lead_qualification | – | – | – |
| notes | – | – | – |
| tags | – | – | – |
| thread_id | string | yes | – |
| value | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_tag ~174
Rename, recolor, disable or re-enable a tag. Args: tag_id: Numeric tag id. account_id: Auto-resolves if omitted. name: New display name (changes the tag everywhere it is applied). disabled: True hides the tag from new interactions (existing applications stay); False re-enables it. color: One of the 24 CallRail-supported colors (see VALID_TAG_COLORS): gray1-2, blue1-2, cyan1-2, purple1-2, pink1-4, red1-2, orange1-4, yellow1-2, green1-4.
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| color | – | – | – |
| disabled | – | – | – |
| name | – | – | – |
| tag_id | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_tracker ~482
Update a tracker's mutable settings: name, whisper, SMS, swap targets, campaign name, and the basic call flow (destination, recording, greeting). CallRail's PUT /trackers replaces the entire `call_flow` object, so when any call-flow field is given this tool first reads the tracker and merges the change into its current basic flow; the destination, recording flag and greeting you did not mention are preserved. Trackers on an advanced call flow (IVR menus, schedules, voicemail steps) are refused for call-flow edits because the API could only replace that flow with a basic one. Args: tracker_id: 'TRK...' id. account_id: Auto-resolves if omitted. name: New display name. destination_number: Where calls forward (e.g. "+14129548337"). whisper_message: New whisper text (max 500 chars). greeting_text: New text-to-speech greeting (max 500 chars). sms_enabled: Toggle SMS on/off. recording_enabled: Toggle call recording for this tracker. greeting_recording_url: http(s) URL of a .wav/.mp3 greeting. CallRail copies the file once; greeting_text is cleared so the recording takes effect (pass one or the other, not both). swap_targets: Phone numbers on the website that this tracker's number replaces (any formatting). Replaces the current list. campaign_name: Campaign label for reports. Source trackers only. Field-level rules: - `name`, `destination_number`, `whisper_message`, `greeting_text` must be non-empty strings if provided. Pass `None` (the default) to leave a field unchanged. NOTE: Setting `status` via this PUT is silently ignored by CallRail. To disable a tracker, use `delete_tracker(tracker_id)` (soft-delete / disabled, keeps history). To permanently remove, contact CallRail support.
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| campaign_name | – | – | – |
| destination_number | – | – | – |
| greeting_recording_url | – | – | – |
| greeting_text | – | – | – |
| name | – | – | – |
| recording_enabled | – | – | – |
| sms_enabled | – | – | – |
| swap_targets | – | – | – |
| tracker_id | string | yes | – |
| whisper_message | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
update_user ~254
Update a user's name or company access. Pass None to leave unchanged. CallRail's PUT /users accepts first_name, last_name, email and companies only, with two documented restrictions: names and email can be changed only for the user who owns the API key, and an email change requires that user's current password in the request. This server never handles passwords, so `email` is rejected; `role` is rejected because the API has no way to change it (recreate the user, or use the CallRail UI). Updates are only accepted for users who have accepted their invitation. Args: user_id: 'USR...' id. first_name, last_name: Only for the API key's own user. email: Rejected (see above). role: Rejected (see above). company_ids: REPLACES the user's company access list (send the full list the user should keep). Admin-only; applies to manager and reporting users.
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| company_ids | – | – | – |
| – | – | – | |
| first_name | – | – | – |
| last_name | – | – | – |
| role | – | – | – |
| user_id | string | yes | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
usage_summary ~389
Per-company cost-attribution summary for the current cycle. Aggregates active trackers + per-company call minutes and projects what each client is contributing to the agency's CallRail bill. Useful for: - Deciding which client to renegotiate / upsell / drop - Sanity-checking the upcoming invoice - Quarterly reviews Pricing assumes Call Tracking Starter ($50 base + 5 numbers + 250 mins bundled; $3/local number, $5/toll-free number, $0.05/local minute, $0.08/toll-free minute over bundle). Edit PRICING_* constants in server.py if you're on a different plan. Args: account_id: Auto-resolves if omitted. days: Lookback window in days (default 30 = roughly one cycle). Ignored if `start_date` provided. start_date: 'YYYY-MM-DD'. end_date: 'YYYY-MM-DD' (defaults to today). Returns: - `agency`: plan + totals + bundle utilization + cycle estimate - `by_company[]`: each company's minutes, active numbers, cost share (sorted by cost-share descending) - `biggest_cost_driver`: name of top company - `partial_failures[]`: per-company API errors. Each entry carries `partial_calls_before_failure`, `partial_minutes_before_failure`, `partial_local_numbers`, `partial_tollfree_numbers` so an under- reporting agency_total is observable, not silent. - `notes`: caveats about the cost model (toll-free minute pricing not yet differentiated; SMS not included). Cost shares sum exactly to `agency.estimated_cycle_total` via largest- remainder rounding.
| Name | Type | Req | Description |
|---|---|---|---|
| account_id | – | – | – |
| days | integer | – | – |
| end_date | – | – | – |
| start_date | – | – | – |
| Name | Type | Req | Description |
|---|---|---|---|
| result | string | yes | – |
No examples provided.
How do I install the CallRail MCP server?
CallRail MCP runs locally as a PyPI package, launched with uvx callrail-mcp. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
pypi · callrail-mcp
claude mcp add pghdma-callrail-mcp -- uvx callrail-mcp
What is the CallRail MCP server?
CallRail MCP is listed in the public MCP registry as io.github.pghdma/callrail-mcp. CallRail REST API v3: 57 tools for calls, leads, trackers, tags, users, and agency reporting. This page covers its PyPI package (callrail-mcp).
Is the CallRail MCP server safe to use?
CallRail MCP scores 72 out of 100 on VerifyMCP. We found no known CVEs affecting it as of 5 November 2026. Its build provenance is signed and verified. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the CallRail MCP server expose?
CallRail MCP exposes 57 tools: list_accounts, list_companies, list_trackers, get_tracker, create_tracker, and 52 more. Their descriptions and schemas cost roughly 14,990 tokens of context every time the server is loaded.
Is the CallRail MCP server still maintained?
CallRail MCP is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What licence is the CallRail MCP server under?
CallRail MCP declares the MIT licence, which is OSI-approved. That covers the source only, and says nothing about the cost of any service it calls.
What did VerifyMCP test on the CallRail MCP server?
VerifyMCP ran 15 checks on CallRail MCP, covering Known CVEs, Install scripts, Dependency health, Source repository and 11 more. One item could not be completed, a gap on our side rather than a finding about CallRail MCP: Malware scan. Endpoint Security and Transport & Reachability do not apply to a PyPI package, so they were not tested. The score does not measure everything, and the scoring documentation lists what it leaves out.