Skip to main content
Glama
gray-wilbee

fub-mcp

by gray-wilbee

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
FUB_API_KEYYesYour Follow Up Boss API key (from FUB → Admin → API). Required if you did not run `fub-mcp setup`, which stores the key in ~/.fub-mcp/.env.
FUB_MCP_SYSTEM_KEYNoOnly needed if you've separately registered your own system with Follow Up Boss.
FUB_MCP_SYSTEM_NAMENoSent as X-System so FUB attributes actions to this tool and grants the better registered-system rate limit.fub-mcp
FUB_MCP_ALLOW_DELETENoSet to '1' to enable DELETE-verb tools. Otherwise delete tools are not registered at all.0

Instructions

Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.

This server publishes no instructions, or was last inspected before Glama recorded them.

Capabilities

Features and capabilities supported by this server

Protocol revision2025-11-25

CapabilityDetails
tools
{}

Tools

Functions exposed to the LLM to take actions

NameDescription
list_eventsA

Search for events. (GET /events) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_eventA

Send in a lead or an event related to a lead. (POST /events) Use this — not create_person — when a NEW LEAD needs to be registered and should trigger FUB's lead routing, automations, and per-source workflows. create_person only inserts a bare contact record and triggers none of that; this is the actual lead-ingestion event. Set type to one of Registration, Inquiry, Seller Inquiry, Property Inquiry, General Inquiry, Viewed Property, Saved Property, Visited Website, Incoming Call, Unsubscribed, Property Search, Saved Property Search, Visited Open House, or Viewed PageRegistration for a genuinely new lead. Set source (and system if relevant) since lead routing rules commonly key off source. FUB auto-deduplicates the nested person object by phone/email — no separate deduplicate flag needed here, unlike create_person. ⚠️ If occurredAt is set to more than 1 day in the past, FUB treats the event as historical and will NOT trigger routing/automations at all — leave it unset (defaults to now) or within the last day if the point is to actually trigger workflows; only backdate it deliberately for importing historical data where you specifically don't want anything to fire.

get_eventA

Retrieve a single event by id. (GET /events/{id})

list_peopleA

Search for people. (GET /people) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes. Use fields to request only what you need instead of full records when scanning many people. For custom fields, call list_custom_fields first to discover the exact field names/labels rather than guessing. FUB's docs also list a wildcard "custom*" field here for reading/writing custom fields directly (e.g. a "Closing Date" field as custom.ClosingDate) — that's not a literal field name, so it's not in this tool's fixed schema. Pass custom. entries via extraQuery instead. Call list_custom_fields first to get exact names.

create_personA

Manually add a new person. (POST /people) FUB's docs also list a wildcard "custom*" field here for reading/writing custom fields directly (e.g. a "Closing Date" field as custom.ClosingDate) — that's not a literal field name, so it's not in this tool's fixed schema. Pass custom. entries via extraBody instead. Call list_custom_fields first to get exact names. deduplicate defaults to false, meaning creating a person whose email or phone matches an existing contact creates a SEPARATE duplicate record rather than erring or merging — a common way CRMs end up full of duplicate leads. Unless the user clearly wants an intentional second/separate record (e.g. a shared household phone), pass deduplicate=true, or call get_people_check_duplicate first and confirm with the user if a likely match already exists. ⚠️ This does NOT register a new lead in FUB's sense: it creates a bare contact record only — no lead routing, no automations, no per-source workflows fire. If the user actually means "a new lead just came in" (e.g. from a website registration, an inquiry, an open house sign-in) rather than "just add this person to my CRM," use create_event instead — that's what actually triggers FUB's lead routing and automations.

get_personA

Retrieve a person by id. (GET /people/{id}) Use fields to request only what you need instead of full records when scanning many people. For custom fields, call list_custom_fields first to discover the exact field names/labels rather than guessing.

update_personA

Update a person by id. (PUT /people/{id}) FUB's docs also list a wildcard "custom*" field here for reading/writing custom fields directly (e.g. a "Closing Date" field as custom.ClosingDate) — that's not a literal field name, so it's not in this tool's fixed schema. Pass custom. entries via extraBody instead. Call list_custom_fields first to get exact names. Tag removal has no dedicated endpoint: to remove a tag, first GET this person, filter the tag out of their current tags array yourself, then PUT the full filtered array back (with mergeTags left at its default of false so it replaces rather than merges). To add tags, just pass the new tags with mergeTags=true (this tool's default) so they're unioned with the person's existing tags. ⚠️ DATA LOSS RISK, confirmed against the live API: emails, phones, and addresses are REPLACED wholesale if you include them — there is no merge flag for these like there is for tags. Sending a single new phone number wipes out every other phone number the person had. To add one without losing the rest, GET the person first, append to their existing emails/phones/addresses array yourself, and PUT the complete merged array back. Never send a partial list unless the user explicitly wants everything else removed. collaborators is also settable here even though FUB's own docs don't list it on this endpoint (confirmed working in practice) — it has the same replace-not-merge behavior as tags/phones: omitting an existing collaborator's user id removes them, so GET the person first and merge if you only want to add one. Pass it via extraBody. Setting stage to "Trash" hides the person from default list views (FUB excludes trashed people from GET /people unless includeTrash is set) — it's reversible, but feels like the contact vanished to someone who isn't expecting it, so this requires confirm=true just like a delete, even though it isn't one.

list_usersA

Search for users. (GET /users) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes. Use fields to request only what you need instead of full records when scanning many people. For custom fields, call list_custom_fields first to discover the exact field names/labels rather than guessing.

list_smart_listsA

Get a list of Smart Lists. (GET /smartLists) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

get_smart_listB

Retrieve a Smart List by id. (GET /smartLists/{id})

get_templateA

Retrieve an email template by id, optionally merging fields. (GET /templates/{id})

update_templateA

Update an email template. (PUT /templates/{id}) FUB templates support %merge_field% placeholders that FUB substitutes when a human actually sends the template (not by this tool — this just saves the template text as-is). Reference: Contact: %contact_name% (full), %contact_first_name%, %contact_last_name%, %contact_email%, %contact_phone%, %contact_address%, %contact_street%, %contact_city%, %contact_state%, %contact_zipcode%, %contact_country%, %contact_rels_first_name% (first names of the contact's linked relationships, e.g. spouse/family added via peopleRelationships). Company (from Admin > Company settings): %company_name%, %company_phone%. Agent / Lender / Sender — same field set, swap the prefix (agent = assigned agent, lender = assigned lender, sender = whoever is actually sending this particular message, which may be neither): %agent_name%, %agent_first_name%, %agent_last_name%, %agent_email%, %agent_phone% (the FUB-assigned calling/texting number), %agent_mobile_phone% (their real/personal number), %agent_merge_field_1% (one free-form field each user sets in My Settings > Other Settings > Edit User Merge Field — commonly a booking link or social profile). ⚠️ %_phone% vs %mobile_phone% is genuinely ambiguous — always confirm with the user which one they mean before using either; picking wrong sends the recipient the wrong callback number. Inquiry (how the contact became a lead, e.g. clicking "Get more info" on a listing site): %inquiry_address%, %inquiry_address_url% (only if the lead source provided one), %inquiry_address_preview% (renders an HTML photo+link box — email only, meaningless in a plain-text SMS template). Recently viewed (populated only when synced with a provider that shares property views): %viewed_address%, %viewed_address_url%, %viewed_address_preview%, %last_5_preview% (up to 5 as HTML boxes, email only). Other: %source_name% (lead source, e.g. "Zillow" — "I saw your inquiry on %source_name%"), %greeting_time% ("Morning"/"Afternoon"/"Evening" based on send time — "Good %greeting_time%, %contact_first_name%"), %tour_time% (populated if the contact scheduled a tour via Zillow). Custom fields: %custom% (e.g. %custom_website%, %custom_birthday%, %custom_spouse_name%). Call list_custom_fields to confirm a field exists — but note its API name (e.g. customBirthday, camelCase) and its merge-field name (%custom_birthday%, snake_case) are different spellings of the same field, and there's no API that returns the merge-field spelling directly, so confirm the exact form with the user (or FUB's own Merge Fields dropdown in the template composer) if it's not obvious from the label. A merge field with no value for a given contact is simply left blank when the template is used — not an error, not a visible placeholder.

list_custom_fieldsA

List all custom fields. (GET /customFields) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_custom_fieldC

Create a custom field. (POST /customFields)

create_noteA

Add a note. (POST /notes) If body contains HTML markup, you must also pass isHtml=true — unlike email templates, FUB does not auto-detect HTML in notes.

get_userC

Retrieve a user by id. (GET /users/{id})

list_templatesA

Lists all email templates. (GET /templates) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_templateA

Create a new email template. (POST /templates) body is the raw HTML of the email template directly — there is no separate isHtml/html flag for templates (unlike notes, which need isHtml=true explicitly). FUB templates support %merge_field% placeholders that FUB substitutes when a human actually sends the template (not by this tool — this just saves the template text as-is). Reference: Contact: %contact_name% (full), %contact_first_name%, %contact_last_name%, %contact_email%, %contact_phone%, %contact_address%, %contact_street%, %contact_city%, %contact_state%, %contact_zipcode%, %contact_country%, %contact_rels_first_name% (first names of the contact's linked relationships, e.g. spouse/family added via peopleRelationships). Company (from Admin > Company settings): %company_name%, %company_phone%. Agent / Lender / Sender — same field set, swap the prefix (agent = assigned agent, lender = assigned lender, sender = whoever is actually sending this particular message, which may be neither): %agent_name%, %agent_first_name%, %agent_last_name%, %agent_email%, %agent_phone% (the FUB-assigned calling/texting number), %agent_mobile_phone% (their real/personal number), %agent_merge_field_1% (one free-form field each user sets in My Settings > Other Settings > Edit User Merge Field — commonly a booking link or social profile). ⚠️ %_phone% vs %mobile_phone% is genuinely ambiguous — always confirm with the user which one they mean before using either; picking wrong sends the recipient the wrong callback number. Inquiry (how the contact became a lead, e.g. clicking "Get more info" on a listing site): %inquiry_address%, %inquiry_address_url% (only if the lead source provided one), %inquiry_address_preview% (renders an HTML photo+link box — email only, meaningless in a plain-text SMS template). Recently viewed (populated only when synced with a provider that shares property views): %viewed_address%, %viewed_address_url%, %viewed_address_preview%, %last_5_preview% (up to 5 as HTML boxes, email only). Other: %source_name% (lead source, e.g. "Zillow" — "I saw your inquiry on %source_name%"), %greeting_time% ("Morning"/"Afternoon"/"Evening" based on send time — "Good %greeting_time%, %contact_first_name%"), %tour_time% (populated if the contact scheduled a tour via Zillow). Custom fields: %custom% (e.g. %custom_website%, %custom_birthday%, %custom_spouse_name%). Call list_custom_fields to confirm a field exists — but note its API name (e.g. customBirthday, camelCase) and its merge-field name (%custom_birthday%, snake_case) are different spellings of the same field, and there's no API that returns the merge-field spelling directly, so confirm the exact form with the user (or FUB's own Merge Fields dropdown in the template composer) if it's not obvious from the label. A merge field with no value for a given contact is simply left blank when the template is used — not an error, not a visible placeholder.

list_action_plansA

Get a list of Action Plans. (GET /actionPlans) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes. ⚠️ Action Plans are a deprecated FUB feature — Automations are the current, recommended mechanism going forward. Unless the user specifically names an existing legacy Action Plan they already rely on, prefer the automationsPerson tools (create_automations_person to trigger one, update_automations_person to pause/unpause) over this one for new workflows.

get_noteA

Retrieve a note by id. (GET /notes/{id})

update_noteB

Edit a note. (PUT /notes/{id}) If body contains HTML markup, you must also pass isHtml=true.

get_custom_fieldB

Get a custom field by id. (GET /customFields/{id})

update_custom_fieldC

Update a custom field. (PUT /customFields/{id})

get_meB

Retrieve information about the currently authenticated user. (GET /me)

list_callsA

Search for calls. (GET /calls) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_callC

Add a call. (POST /calls)

update_action_plans_personA

Update the status of an Action Plan to Person relationship. (PUT /actionPlansPeople/{id}) ⚠️ Action Plans are a deprecated FUB feature — Automations are the current, recommended mechanism going forward. Unless the user specifically names an existing legacy Action Plan they already rely on, prefer the automationsPerson tools (create_automations_person to trigger one, update_automations_person to pause/unpause) over this one for new workflows.

get_callB

Retrieve a call by id. (GET /calls/{id})

update_callC

Update a call. (PUT /calls/{id})

list_action_plans_peopleA

List Action Plans applied to a particular person or list people on a particular Action Plan. (GET /actionPlansPeople) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes. ⚠️ Action Plans are a deprecated FUB feature — Automations are the current, recommended mechanism going forward. Unless the user specifically names an existing legacy Action Plan they already rely on, prefer the automationsPerson tools (create_automations_person to trigger one, update_automations_person to pause/unpause) over this one for new workflows.

create_action_plans_personA

Apply an Action Plan to a person. (POST /actionPlansPeople) ⚠️ Action Plans are a deprecated FUB feature — Automations are the current, recommended mechanism going forward. Unless the user specifically names an existing legacy Action Plan they already rely on, prefer the automationsPerson tools (create_automations_person to trigger one, update_automations_person to pause/unpause) over this one for new workflows.

list_em_eventsA

List email marketing events. (GET /emEvents) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_em_eventB

Notify Follow Up Boss about marketing emails sent, opens, clicks, bounces, unsubscribes and spam reports. (POST /emEvents)

list_stagesA

Retrieve a list of stages. (GET /stages) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_stageB

Create a new stage. (POST /stages)

get_stageC

Get a stage by id. (GET /stages/{id})

update_stageC

Update a stage. (PUT /stages/{id})

get_webhookB

Get details of a specific webhook. (GET /webhooks/{id})

update_webhookC

Update a webhook. (PUT /webhooks/{id})

list_webhooksA

Get a list of webhooks. (GET /webhooks) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_webhookB

Subscribe to a new webhook. (POST /webhooks)

get_webhook_eventA

Get a list of events for a given webhook. (GET /webhookEvents/{id})

list_tasksC

Get a list of tasks. (GET /tasks)

create_taskB

Create a new task. (POST /tasks)

get_taskA

Get a task by id. (GET /tasks/{id})

update_taskC

Update a task. (PUT /tasks/{id})

list_em_campaignsA

List email marketing campaigns. (GET /emCampaigns)

create_em_campaignC

Create an email marketing campaign. (POST /emCampaigns)

update_em_campaignC

Update an email marketing campaign. (PUT /emCampaigns/{id})

get_dealA

Retrieve a deal by id. (GET /deals/{id})

update_dealC

Update a deal. (PUT /deals/{id})

get_pipelineB

Retrieve a pipeline by id. (GET /pipelines/{id})

update_pipelineC

Update a pipeline. (PUT /pipelines/{id})

list_dealsC

Search for deals. (GET /deals)

create_dealC

Add a deal. (POST /deals)

list_pipelinesC

Search for pipelines. (GET /pipelines)

create_pipelineB

Add a pipeline. (POST /pipelines)

get_identityB

Get identity and authentication information. (GET /identity)

list_text_messagesA

List text messages for a person or phone number. (GET /textMessages)

create_text_messageA

Create a record of an externally sent text message. (POST /textMessages)

get_text_messageA

Retrieve a text message by id. (GET /textMessages/{id})

list_appointmentsA

Search for appointments. (GET /appointments) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_appointmentC

Create an appointment. (POST /appointments)

get_appointmentC

Retrieve an appointment by id. (GET /appointments/{id})

update_appointmentC

Update an appointment. (PUT /appointments/{id})

list_people_relationshipsC

Get relationships between people in Follow Up Boss. (GET /peopleRelationships)

create_people_relationshipB

Create a new relationship for a person. (POST /peopleRelationships)

get_people_relationshipA

Get a specific relationship. (GET /peopleRelationships/{id})

update_people_relationshipC

Update details of a specific relationship. (PUT /peopleRelationships/{id})

post_templates_mergeA

Merge an email template with multiple recipients. (POST /templates/merge) Despite the name, this almost certainly does NOT send anything — inferred from its identical-shaped sibling post_text_message_templates_merge, which was verified live 2026-09 (firing it at a real phone number produced no delivery and no new record in list_text_messages, only a rendered string back); the email variant itself wasn't separately fired to avoid sending an unwanted email. It's a preview/render utility for the edge case of one message greeting multiple recipients at once (e.g. "Hey Bob, Alice and Carol...") — useful for composing that combined greeting, not for actually delivering it.

post_text_message_templates_mergeA

Merge a text message template with multiple recipients. (POST /textMessageTemplates/merge) Despite the name, this does NOT send anything — verified live 2026-09: firing this at a real phone number produced no delivery and no new record in list_text_messages, only a rendered string back ({"mergedTemplate": "..."}). It's a preview/render utility for the edge case of one text greeting multiple recipients at once (e.g. "Hey Bob, Alice and Carol..."), not an actual send.

get_people_check_duplicateB

Check whether a person exists in Follow Up Boss. (GET /people/checkDuplicate)

get_people_unclaimedA

Get unclaimed leads. (GET /people/unclaimed) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

post_people_claimB

Claim a lead. (POST /people/claim)

post_people_ignore_unclaimedC

Ignore a lead. (POST /people/ignoreUnclaimed)

list_text_message_templatesA

Lists all text message templates. (GET /textMessageTemplates) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

get_text_message_templateB

Retrieve a text message template by id. (GET /textMessageTemplates/{id})

update_text_message_templateA

Update a text message template. (PUT /textMessageTemplates/{id}) FUB templates support %merge_field% placeholders that FUB substitutes when a human actually sends the template (not by this tool — this just saves the template text as-is). Reference: Contact: %contact_name% (full), %contact_first_name%, %contact_last_name%, %contact_email%, %contact_phone%, %contact_address%, %contact_street%, %contact_city%, %contact_state%, %contact_zipcode%, %contact_country%, %contact_rels_first_name% (first names of the contact's linked relationships, e.g. spouse/family added via peopleRelationships). Company (from Admin > Company settings): %company_name%, %company_phone%. Agent / Lender / Sender — same field set, swap the prefix (agent = assigned agent, lender = assigned lender, sender = whoever is actually sending this particular message, which may be neither): %agent_name%, %agent_first_name%, %agent_last_name%, %agent_email%, %agent_phone% (the FUB-assigned calling/texting number), %agent_mobile_phone% (their real/personal number), %agent_merge_field_1% (one free-form field each user sets in My Settings > Other Settings > Edit User Merge Field — commonly a booking link or social profile). ⚠️ %_phone% vs %mobile_phone% is genuinely ambiguous — always confirm with the user which one they mean before using either; picking wrong sends the recipient the wrong callback number. Inquiry (how the contact became a lead, e.g. clicking "Get more info" on a listing site): %inquiry_address%, %inquiry_address_url% (only if the lead source provided one), %inquiry_address_preview% (renders an HTML photo+link box — email only, meaningless in a plain-text SMS template). Recently viewed (populated only when synced with a provider that shares property views): %viewed_address%, %viewed_address_url%, %viewed_address_preview%, %last_5_preview% (up to 5 as HTML boxes, email only). Other: %source_name% (lead source, e.g. "Zillow" — "I saw your inquiry on %source_name%"), %greeting_time% ("Morning"/"Afternoon"/"Evening" based on send time — "Good %greeting_time%, %contact_first_name%"), %tour_time% (populated if the contact scheduled a tour via Zillow). Custom fields: %custom% (e.g. %custom_website%, %custom_birthday%, %custom_spouse_name%). Call list_custom_fields to confirm a field exists — but note its API name (e.g. customBirthday, camelCase) and its merge-field name (%custom_birthday%, snake_case) are different spellings of the same field, and there's no API that returns the merge-field spelling directly, so confirm the exact form with the user (or FUB's own Merge Fields dropdown in the template composer) if it's not obvious from the label. A merge field with no value for a given contact is simply left blank when the template is used — not an error, not a visible placeholder. Texting-specific, per FUB's own Compliance/Carrier Filtering guidance: initial/first-outreach text templates should include opt-out language ("Reply STOP to unsubscribe") and introduce the sender/company by name. Avoid designing a template purely for identical mass-blasting — carriers filter messages that look like spam, personalization (via merge fields) reduces that risk. If the template includes a URL, use the full URL rather than a shortened link, since shorteners are more likely to get carrier-filtered.

list_groupsC

List groups. (GET /groups)

create_groupC

Create a new group. (POST /groups)

get_groups_round_robinC

Lists groups and includes round-robin data. (GET /groups/roundRobin)

get_groupB

Retrieve a group by id. (GET /groups/{id})

update_groupB

Update a group. (PUT /groups/{id})

list_teamsA

Get a list of teams. (GET /teams) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_teamB

Create a new team. (POST /teams)

get_teamA

Get a team by id. (GET /teams/{id})

update_teamB

Update a team by id. (PUT /teams/{id})

list_pondsA

Get a list of ponds. (GET /ponds) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_pondB

Create a pond. (POST /ponds)

get_pondA

Get a pond by id. (GET /ponds/{id})

update_pondB

Update a pond by id. (PUT /ponds/{id})

create_text_message_templateA

Create a text message template. (POST //textMessageTemplates) FUB templates support %merge_field% placeholders that FUB substitutes when a human actually sends the template (not by this tool — this just saves the template text as-is). Reference: Contact: %contact_name% (full), %contact_first_name%, %contact_last_name%, %contact_email%, %contact_phone%, %contact_address%, %contact_street%, %contact_city%, %contact_state%, %contact_zipcode%, %contact_country%, %contact_rels_first_name% (first names of the contact's linked relationships, e.g. spouse/family added via peopleRelationships). Company (from Admin > Company settings): %company_name%, %company_phone%. Agent / Lender / Sender — same field set, swap the prefix (agent = assigned agent, lender = assigned lender, sender = whoever is actually sending this particular message, which may be neither): %agent_name%, %agent_first_name%, %agent_last_name%, %agent_email%, %agent_phone% (the FUB-assigned calling/texting number), %agent_mobile_phone% (their real/personal number), %agent_merge_field_1% (one free-form field each user sets in My Settings > Other Settings > Edit User Merge Field — commonly a booking link or social profile). ⚠️ %_phone% vs %mobile_phone% is genuinely ambiguous — always confirm with the user which one they mean before using either; picking wrong sends the recipient the wrong callback number. Inquiry (how the contact became a lead, e.g. clicking "Get more info" on a listing site): %inquiry_address%, %inquiry_address_url% (only if the lead source provided one), %inquiry_address_preview% (renders an HTML photo+link box — email only, meaningless in a plain-text SMS template). Recently viewed (populated only when synced with a provider that shares property views): %viewed_address%, %viewed_address_url%, %viewed_address_preview%, %last_5_preview% (up to 5 as HTML boxes, email only). Other: %source_name% (lead source, e.g. "Zillow" — "I saw your inquiry on %source_name%"), %greeting_time% ("Morning"/"Afternoon"/"Evening" based on send time — "Good %greeting_time%, %contact_first_name%"), %tour_time% (populated if the contact scheduled a tour via Zillow). Custom fields: %custom% (e.g. %custom_website%, %custom_birthday%, %custom_spouse_name%). Call list_custom_fields to confirm a field exists — but note its API name (e.g. customBirthday, camelCase) and its merge-field name (%custom_birthday%, snake_case) are different spellings of the same field, and there's no API that returns the merge-field spelling directly, so confirm the exact form with the user (or FUB's own Merge Fields dropdown in the template composer) if it's not obvious from the label. A merge field with no value for a given contact is simply left blank when the template is used — not an error, not a visible placeholder. Texting-specific, per FUB's own Compliance/Carrier Filtering guidance: initial/first-outreach text templates should include opt-out language ("Reply STOP to unsubscribe") and introduce the sender/company by name. Avoid designing a template purely for identical mass-blasting — carriers filter messages that look like spam, personalization (via merge fields) reduces that risk. If the template includes a URL, use the full URL rather than a shortened link, since shorteners are more likely to get carrier-filtered.

list_deal_custom_fieldsA

List all deals custom fields available in your account. (GET /dealCustomFields) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_deal_custom_fieldB

Create a deals custom field. (POST /dealCustomFields)

get_deal_custom_fieldB

Get a deals custom field by ID. (GET /dealCustomFields/{id})

update_deal_custom_fieldB

Update a deals custom field. (PUT /dealCustomFields/{id})

list_appointment_typesA

List appointment types. (GET /appointmentTypes) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_appointment_typeC

Create an appointment type. (POST /appointmentTypes)

get_appointment_typeC

Retrieve an appointment type by ID (GET /appointmentTypes/{id})

update_appointment_typeC

Update an appointment type. (PUT /appointmentTypes/{id})

list_appointment_outcomesA

List appointment outcomes. (GET /appointmentOutcomes) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

create_appointment_outcomeC

Create an appointment outcome. (POST /appointmentOutcomes)

get_appointment_outcomeB

Retrieve an appointment outcome by ID. (GET /appointmentOutcomes/{id})

update_appointment_outcomeC

Update an appointment outcome. (PUT /appointmentOutcomes/{id})

create_person_attachmentB

Attach a file to a person. (POST /personAttachments)

create_deal_attachmentB

Add an attachment to a deal. (POST /dealAttachments)

get_person_attachmentC

Retrieve an attachment by ID. (GET /personAttachments/{id})

update_person_attachmentC

Update an attachment by ID. (PUT /personAttachments/{id})

get_deal_attachmentC

Get a deal attachment by id. (GET /dealAttachments/{id})

update_deal_attachmentB

Update a deal attachment. (PUT /dealAttachments/{id})

list_automations_peopleA

Get a list of pairings of Automations and the People on which they have or will be run. (GET /automationsPeople)

create_automations_personB

Manually trigger an Automation for a specified Person. (POST /automationsPeople)

get_automations_personB

Retrieve an Automation-Person pairing. (GET /automationsPeople/{id})

update_automations_personB

Pause or unpause an Automation for a Person. (PUT /automationsPeople/{id})

list_team_inboxesC

Get a list of Team Inboxes (GET /teamInboxes)

create_reactionB

Add a reaction to a corresponding reference data object, e.g. "Note" or "ThreadedReply" (POST /reactions/{refType}/{refId})

post_inbox_apps_messageB

Adds a message to an existing or new Inbox App conversation. (POST /inboxApps/{inboxAppId}/message)

put_inbox_apps_messageC

Update an Inbox App Message. (PUT /inboxApps/{inboxAppId}/message)

post_inbox_apps_noteB

Adds a note to an Inbox App conversation. (POST /inboxApps/{inboxAppId}/note)

update_conversationB

Updates an Inbox App conversation. (PUT /inboxApps/{inboxAppId}/conversations/{extConversationId})

get_reactionA

Fetch a reaction (GET /reactions/{id})

get_threaded_replyB

Fetches a threaded reply (GET /threadedReplies/{id})

post_inbox_apps_installC

Installs your Inbox App for an account. (POST /inboxApps/install)

get_inbox_apps_conversations_participantsC

Retrieves participants in an Inbox App conversation. (GET /inboxApps/{inboxAppId}/conversations/{extConversationId}/participants)

post_inbox_apps_conversations_participantsA

Adds a participant to an Inbox App conversation. (POST /inboxApps/{inboxAppId}/conversations/{extConversationId}/participants)

list_timeframesC

Get a list of timeframes. (GET /timeframes)

list_automationsA

Get a list of Automations (GET /automations) Defaults to limit=100 (FUB's max per page) rather than its own default of 10 — bulk requests are the common case here. If the response's _metadata shows more results remain, keep paginating: use offset for offset-based endpoints, or the _metadata.next cursor value (as the next argument) for cursor-based endpoints like notes.

get_automationC

Retrieve an Automation by ID. (GET /automations/{id})

get_installed_appB

Lists Inbox App installation(s) and ID(s) for your Published Inbox App on the current FUB account. (GET /inboxApps/installedApps/{publishedInboxAppId})

post_inbox_apps_system_messageC

Adds a system confirmation message to an existing or new Inbox App conversation. (POST /inboxApps/{inboxAppId}/systemMessage)

get_rate_limit_usageB

24-hour request volume, rate-limit hits, and currently-configured limits for the calling partner system. (GET /rateLimit/usage)

get_rate_limit_limitsA

Currently-configured rate limits for the calling partner system. Cheaper than /v1/rateLimit/usage (no Redis fan-out). (GET /rateLimit/limits)

list_notesA

List notes, optionally filtered by person. This endpoint is NOT in FUB's published API docs (only GET /notes/{id} is documented there), but the plural GET /notes endpoint works today and supports filtering by personId — confirmed against the live API. Since it's undocumented, treat it as best-effort: if FUB changes this behavior, fall back to get_note by id. (GET /notes) Defaults to limit=100. This endpoint paginates via a cursor, not offset: pass the previous response's _metadata.next value as next to get the following page.

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

TDQS

C2.7/5.0

Scored across 133 tools

Disambiguation3/5

Most tools map cleanly to a resource+action, but the sheer number (133) and similar names create real ambiguity: create_event vs. create_person, list_events vs. list_em_events, and the people/claim/ignore_unclaimed cluster are easy to confuse. Descriptions help, but the boundaries are not immediately evident from the names alone.

Naming Consistency2/5

The dominant list_/get_/create_/update_ pattern is undermined by several post_/put_ prefixed tools (post_people_claim, put_inbox_apps_message) and inconsistent singular/plural forms (create_automations_person vs. list_automations_people). This mixes verb styles and noun forms within the same resource families, making the naming pattern unreliable.

Tool Count1/5

133 tools is an extreme count for any MCP server; it far exceeds the 50+ threshold for a severe mismatch. While a full CRM API is inherently large, exposing every endpoint as a separate tool creates a heavy, unwieldy surface that is hard for agents to navigate.

Completeness3/5

The surface is remarkably broad, covering people, deals, pipelines, stages, notes, calls, tasks, appointments, templates, webhooks, teams, automations, and custom fields. However, there are notable gaps: no delete operation exists for any resource, events lack update, and there is no actual send capability for emails/texts (only template merge/render utilities).

Maintenance

ActivityMaintained
ResponsivenessNo issues