Skip to main content
Glama
LucasNS231

redtail-mcp

by LucasNS231

redtail-mcp

An agent-agnostic FastMCP stdio server that exposes the Redtail CRM public API (TWAPI) as Model Context Protocol tools.

Any MCP client can drive it — Claude Desktop, Claude Code, or a custom agent built on the Claude Agent SDK or another MCP-aware framework. The server speaks JSON-RPC over stdio; stdout is the protocol stream, all logs go to stderr.

Two things distinguish it from a thin wrapper:

  • Firm-identity externalization. No advisor names, user ids, rep codes, or activity-code labels live in the tool modules. config.py loads them from JSON env vars (with placeholder defaults) so the same binary serves a different firm by pointing at a different .env.

  • Multi-user attribution. Optionally set REDTAIL_USER_KEYS to a map of {name: durable_user_key}. When a write tool is called with an acting_user argument, the server authenticates as that user via Redtail's UserKeyAuth, so the new record's added_by is stamped with the real person — on one shared API subscription.

Install

Requires Python 3.11 and uv.

git clone https://github.com/your-org/redtail-mcp.git
cd redtail-mcp
uv sync
cp .env.example .env    # then fill in the three required secrets

Configuration

Everything the server reads at boot is documented inline in .env.example. At minimum you must set:

Variable

Purpose

TWAPI_API_KEY

TWAPI subscription key from the Redtail developer portal.

TWAPI_USERNAME

Shared-account login (fallback attribution for writes).

TWAPI_PASSWORD

Shared-account password.

Optional — override placeholder defaults to make the server your firm's:

Variable

Purpose

REDTAIL_USER_KEYS

JSON {name: user_key} for per-user write attribution. Secret; env-only.

REDTAIL_DEFAULT_USER_ID

User id used as the attendee floor / default owner.

REDTAIL_TEAM_MAP

JSON {name: user_id} — resolves friendly names in tool args.

REDTAIL_REP_ADVISOR_MAP

JSON {rep_code: {routing}} — drives onboarding + call defaults.

REDTAIL_ACTIVITY_CODE_LEGEND

JSON {id: name} — friendly names for activity codes.

REDTAIL_ALLOWED_TOOLS

CSV allowlist — trim the exposed catalog without removing capability.

TWAPI_BASE_URL, TWAPI_MAX_RETRIES, TWAPI_CONCURRENCY, LOG_LEVEL

Transport tuning.

The server fails loud (sys.exit 2) at boot on a missing credential or a malformed JSON map — a misconfigured deployment dies instead of silently mis-routing writes.

Register with Claude Desktop

Add an entry under mcpServers in claude_desktop_config.json:

{
  "mcpServers": {
    "redtail": {
      "command": "uv",
      "args": [
        "--directory", "/path/to/redtail-mcp",
        "run", "python", "server.py"
      ]
    }
  }
}

Restart Claude Desktop; the redtail server should appear in the MCP panel with its tools listed.

Register with Claude Code

claude mcp add redtail -- uv --directory /path/to/redtail-mcp run python server.py

Or add it to a project's .mcp.json:

{
  "mcpServers": {
    "redtail": {
      "command": "uv",
      "args": ["--directory", "/path/to/redtail-mcp", "run", "python", "server.py"]
    }
  }
}

Tool reference

43 tools are implemented across four modules. The default catalog exposes them all; narrow it with REDTAIL_ALLOWED_TOOLS.

Activities (tools_activities.py)

Tool

Purpose

Key args

get_agenda

One person's or the team's activities for today / a range.

user_ids?, date_range?

get_overdue_activities

Every open activity past its due date.

user_ids?

get_activities_in_range

Activities in an explicit ISO date range.

start, end, user_ids?

get_activity

Fetch a single activity by id.

activity_id

get_contact_activity_history

Activity history for one contact.

contact_id, kind?

create_task

Create a task activity (owner defaults resolved from name).

subject, contact_id?, due_date?, user_ids?, acting_user?

log_call

Log a completed phone call against a contact.

contact_id, subject, note?, acting_user?

add_note

Add a durable note as a logged activity.

contact_id, note, acting_user?

complete_activity

Mark an activity done with an optional result.

activity_id, result?, acting_user?

reschedule_activity

Move an activity's start / end.

activity_id, new_start, new_end?, acting_user?

assign_activity

Change an activity's owner / attendees.

activity_id, user_ids, acting_user?

create_activity

General activity create with full field control.

subject, activity_code_id, start, end?, ...

update_activity

Patch fields on an existing activity.

activity_id, patch, acting_user?

batch_update_activities

Apply the same patch across many activities.

activity_ids, patch, acting_user?

delete_activity

Delete an activity.

activity_id, acting_user?

Contacts (tools_contacts.py)

Tool

Purpose

Key args

search_contacts

Full-text contact search.

q, limit?

find_contact_by_email

Exact-email lookup.

email

get_contact

Full contact record.

contact_id

get_contact_notes

Notes attached to a contact.

contact_id

get_important_info

Memberships / important-info sheet.

contact_id

get_professional_contacts

Attorneys / CPAs / other advisors linked to a contact.

contact_id

get_family

Family + spouse links.

contact_id

get_contact_photo

Profile photo URL.

contact_id

get_household

Household record.

household_id

resolve_contact

Fuzzy identity resolution — "which contact do you mean?".

q

create_contact

Create a new contact.

first_name, last_name, ...

update_contact

Patch fields on an existing contact.

contact_id, patch, acting_user?

add_phone

Add a phone number.

contact_id, number, type?, acting_user?

add_email

Add an email address.

contact_id, email, type?, acting_user?

add_address

Add a mailing address.

contact_id, street, city, state, zip, type?, acting_user?

link_family

Link a family relationship.

contact_id, related_id, relation, acting_user?

add_tag_member

Put a contact on a tag (cohort).

tag, contact_id, acting_user?

add_contact_keyword

Add a keyword to a contact.

contact_id, keyword, acting_user?

update_important_info

Patch important-info fields.

contact_id, patch, acting_user?

remove_contact_subresource

Remove a phone / email / address / etc.

contact_id, resource, resource_id, acting_user?

Onboarding (tools_onboarding.py)

Tool

Purpose

Key args

create_onboarding_tasks

Example workflow: create a bundle of onboarding tasks for a new client, routed off the rep code. Override the plan by passing tasks=[...].

contact_id, rep_code, effective_date?, tasks?, acting_user?

Reference (tools_reference.py)

Tool

Purpose

Key args

list_database_users

Enumerate every user in the Redtail database.

list_activity_codes

Enumerate activity codes.

list_contact_categories

Enumerate contact categories.

list_tags

Enumerate tags.

list_tag_members

List contacts on a tag (cohort).

tag

list_contacts

Filtered contact list (category / status / updated-since).

category_id?, status_id?, updated_since?

remove_tag_member

Take a contact off a tag.

tag, contact_id

Usage examples

Once the server is registered, natural-language prompts flow through the tools. All examples below use the fictional client Jane Sample.

Read. "Who's on my calendar this week?" — the client calls get_agenda with user_ids resolved from the caller's name via REDTAIL_TEAM_MAP.

Write with default attribution. "Log a call with Jane Sample: reviewed her rollover paperwork, will send the DocuSign tomorrow." — the client calls log_call(contact_id=..., subject="Rollover paperwork review", note="..."). The record's added_by is the shared TWAPI user.

Write with per-user attribution. With REDTAIL_USER_KEYS populated and an agent that tags the inbound user (e.g. [alice|100001]), pass acting_user="alice" on any write tool. The server switches to UserKeyAuth for that call and Redtail stamps the record as coming from Alice — even though the API subscription is shared.

Onboarding. "Start onboarding for Jane Sample, rep code REP01." — create_onboarding_tasks(contact_id=..., rep_code="REP01") creates the example task bundle, routed to the owner mapped in REDTAIL_REP_ADVISOR_MAP.

Development

uv sync --extra dev
uv run pytest
uv run python tests/smoke_stdio.py

DESIGN.md covers the architecture — request path, auth model, per-user attribution decision, truncation contract, and the firm-identity externalization pattern.

License

MIT. See LICENSE.

-
license - not tested
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/LucasNS231/redtail-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server