Atlas / MCP servers / pghdma / callrail-mcp

callrail-mcpCAUTION

mcp/pghdma/callrail-mcp

Model Context Protocol (MCP) server for the CallRail REST API v3: 57 tools for calls, leads, form submissions, trackers, tags and agency reporting, usable from Claude Code, Claude Desktop, Cursor or any MCP client.

Verdict
CAUTION
Grade
B
Trust score
89 /100
Exposed tools
57 34r · 17w · 6d
Transport
stdio
License
MIT
Stars
2
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://pypi.org/project/callrail-mcp/) [](https://pypi.org/project/callrail-mcp/) [](https://github.com/pghdma/callrail-mcp/actions/workflows/ci.yml) [](https://opensource.org/licenses/MIT) [](https://modelcontextprotocol.io/) [](https://codeguilds.dev/packages/callrail-mcp)

A Model Context Protocol server for the CallRail REST API v3. Point Claude Code, Claude Desktop, Cursor, or any other MCP client at it and ask about your call tracking in plain English.

I'm [Steve Japalucci](https://github.com/pghdma). I run Pittsburgh Digital Marketing Agency (PGHDMA), and I built this for my own client work. CallRail bills per tracking number and per minute across every client I manage, and I was tired of clicking through its reports to answer questions like "which client is burning my minutes this month". Now I ask Claude.

Works with both major versions of the MCP Python SDK (1.x and 2.x).

What I use it for

These are the kinds of questions I ask it every week:

Reporting

  • "Pull last week's calls for Alan Construction, grouped by source"
  • "Show me every missed call this month"
  • "Find any calls from 412-555-1234 across all clients in the last 90 days"
  • "Get the transcript for call CAL019abc..."

Agency cost attribution

  • "Why is my CallRail bill $174? Break it down by client"
  • "Which client is the biggest minute user this cycle?"

Conversion debugging

  • *"
Read from source at commit e32faf50c487OBSERVED · 2026-10-11
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control. Replace the environment placeholders with a token scoped to the least it needs.

claude-code (pypi)
claude mcp add callrail-mcp --env CALLRAIL_API_KEY=${CALLRAIL_API_KEY} -- None callrail-mcp==1.3.1
03

Exposed tools (57)

34 read · 17 write · 6 destructive. Blast radius: 6 tools can delete or overwrite — an agent that can be talked into calling a tool can be talked into calling this one.

ToolRiskDescription
add_call_tagswriteAppend tags to a call WITHOUT replacing existing ones.
bulk_update_callswriteApply the same update to every call matching a filter.
call_eligibility_checkreadAudit whether a specific call is/was eligible to count as a Google Ads
call_statsreadServer-side call aggregation via CallRail
call_summaryreadSummarize calls over a date window.
call_timeseriesreadCall volume over time via CallRail
compare_periodsreadCompare current N-day window vs the previous N-day window.
create_companywriteCreate a new company (client) under the account.
create_form_submissionwriteManually create a form submission (e.g. backfill an offline lead).
create_notificationwriteCreate a notification rule (who gets pinged on which event).
create_outbound_callwritePlace an outbound call. THIS ACTUALLY DIALS REAL PHONES.
create_tagwriteCreate a new tag, scoped to one company or to the whole account.
create_trackerwrite⚠️ Create a new tracking phone number (tracker). **THIS COSTS MONEY.**
create_userwriteInvite a new user. CallRail emails them an account-creation link.
delete_companydestructiveSoft-delete a company. Status flips to
delete_notificationdestructiveDelete a notification rule. The rule is gone. To keep but mute
delete_tagdestructiveDelete a tag definition from the account. Removes it from any
delete_trackerdestructiveDelete (disable) a tracker. Soft-removes it from active trackers; the
delete_userdestructiveRemove a user from the account.
form_statsreadServer-side form-submission totals via /forms/summary.json.
get_callreadGet full detail for a specific call.
get_call_page_viewsreadGet the visitor
get_call_recordingreadGet the recording URL for a call. CallRail documents the link as
get_call_transcriptreadGet the transcript and conversation-intelligence fields for a call.
get_companyreadGet full detail for one company.
get_form_submissionreadGet full detail for one form submission, including all submitted
get_integrationreadGet full detail for one integration.
get_lead_timelinereadGet a lead
get_sms_threadreadGet one SMS thread
get_tagreadGet full detail for one tag.
get_text_messagereadGet full detail for one SMS conversation, including all messages.
get_trackerreadGet full detail for a specific tracker.
get_userreadGet full detail for one user on the account.
list_accountsreadList CallRail accounts accessible to this API key.
list_callsreadList calls. Paginated. Filterable by company, date window, and
list_companiesreadList companies (client businesses) under a CallRail account.
list_form_submissionsreadList form submissions captured by CallRail
list_integrationsreadList integrations attached to one company (GMB, Google Ads,
list_leadsreadList leads (unique people) across calls, forms, and texts.
list_notificationsreadList notification rules on the account.
list_sms_threadsreadList SMS threads. Unlike `list_text_messages` (conversation
list_tagsreadList all tags in the account, or filtered to one company.
list_text_messagesreadList SMS/text message conversations sent to or received via
list_trackersreadList tracking phone numbers (trackers). Each tracker maps a pool of
list_usersreadList users on the account. Paginated.
remove_call_tagsdestructiveRemove specific tags from a call (case-sensitive on tag name).
search_calls_by_numberreadFind calls from/to a specific phone number. Matches on the last 10 digits
spam_detectorreadHeuristically identify likely-spam calls and (optionally) tag them.
update_callwriteUpdate an existing call: notes, tags, spam flag, customer name, lead status.
update_companywriteUpdate mutable settings on a company. Pass None to leave a field
update_form_submissionwriteUpdate an existing form submission: note, tags, value, lead status.
update_notificationwriteUpdate a notification rule. Pass None to leave a field
update_sms_threadwriteUpdate an SMS thread
update_tagwriteRename, recolor, disable or re-enable a tag.
update_trackerwriteUpdate a tracker
update_userwriteUpdate a user
usage_summaryreadPer-company cost-attribution summary for the current cycle.
04

Trust audit

CAUTIONgrade B · trust 89/100 Install with care. The audit found things worth knowing before you trust its output.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeWARN
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfaceWARN
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (1 observation(s))
Network
none-observed
Shell
declared (1 observation(s))
Dependencies
pinned
Secrets in source
none-found

Findings (6)

MEDIUMCode injection · code.dynamic_import · CWE-78, CWE-94, CWE-95
src/callrail_mcp/server.py:50
module = importlib.import_module(module_name)
MEDIUMFilesystem / path · mcp.destructive_tools · CWE-22, CWE-59
delete_company, delete_notification, delete_tag, delete_tracker, delete_user, remove_call_tags
Why it matters. 6 tool(s) can delete or overwrite
Fix. prefer a read-only mode or scoped tokens; the page states the blast radius
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_client.py:266
_safe_path("a/ACC1/calls/../../../etc/passwd.json")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_client.py:302
client.get("a/ACC1/calls/../../etc/passwd.json")
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
tests/test_server.py:264
("TRK_xyz/../../admin", False),     # deeper slash injection
LOWNetwork egress · net.beacon_words · CWE-200, CWE-319
tests/test_client.py:396
status=302, headers={"Location": "https://evil.com/exfil"})

Gates applied: no_behavioural_pass.

Audited 2026-10-11 · audit v0.4.1 · source sha e32faf50c487full audit observations/trust-audit/mcp-server/pghdma__callrail-mcp.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-11e32faf50c487CAUTIONB89first audit
06

Questions

What is the callrail-mcp MCP server?

Model Context Protocol (MCP) server for the CallRail REST API v3: 57 tools for calls, leads, form submissions, trackers, tags and agency reporting, usable from Claude Code, Claude Desktop, Cursor or any MCP client.

What tools does callrail-mcp expose?

57 in total: 34 read-only, 17 that write, and 6 that can delete or overwrite (delete_company, delete_notification, delete_tag, delete_tracker, delete_user). Every one is listed on this page with its risk.

Is callrail-mcp safe to connect to an agent?

With care. The audit graded it B (89/100) and found 6 things worth knowing before you trust this server, listed below with the exact line each was found on. Separately from the audit: 6 of its tools can destroy data, so scope the token you give it to what you actually need.

What credentials does callrail-mcp need?

It reads CALLRAIL_API_KEY and CALLRAIL_API_KEY_FILE from the environment. Give it a token scoped to the least it needs — an agent that can be talked into calling a tool can be talked into calling it with your credentials.

How does callrail-mcp run?

It speaks stdio, so it runs as a local process your client starts. It is published on PyPI as callrail-mcp.

How current is this page?

The grade is for one exact copy of the source (e32faf50c487), read on 2026-10-11. The repository is watched and re-audited when it changes.

Advertisement