Running a CRM Sales Pipeline with Claude Code via MCP - Relaticle Blog             [  Back to blog ](https://relaticle.com/blog) 

 ![Let Claude Code Run Your Sales Pipeline](https://relaticle.com/storage/ink/01M17KWGFJTG7KWZAR40C6SZZZ.png)In one working session, five prompts to Claude Code moved through Relaticle's real MCP server: a pipeline summary with stale deals flagged, a new company and contact and linked note created from a call recap, four overdue tasks rescheduled, a custom field set on a deal, and a bulk delete blocked until explicitly approved. Total model time across all five runs was about seven and a half minutes. Add the time to type each prompt and read the answer, and the whole thing fits in fifteen. Every transcript excerpt, tool call, and screenshot below is from that actual session, not a mockup.

[](#setup-condensed "Permalink")Setup, condensed
------------------------------------------------

Relaticle is an open-source CRM whose MCP server ships as part of the product, so everything below works the same on the hosted plan or a self-hosted install. The full walkthrough lives at [relaticle.com/developers/mcp](https://relaticle.com/developers/mcp), and the blog version is [How to Connect Claude to Your CRM with MCP](https://relaticle.com/blog/how-to-connect-claude-to-your-crm-with-mcp). The short version: log in to Relaticle, open **Settings → Access Tokens**, create a token scoped to your workspace with the abilities you want (read-only if you're just trying it out, full CRUD if you want Claude to actually change things), then wire it into Claude Code:

```
claude mcp add relaticle \
  --transport streamable-http \
  https://mcp.relaticle.com \
  --header "Authorization: Bearer YOUR_TOKEN"

```

That's the whole setup. No OAuth flow to click through for Claude Code specifically, just the token and one command. (OAuth with a consent screen is also supported for clients like Claude Desktop; the [MCP guide](https://relaticle.com/blog/how-to-connect-claude-to-your-crm-with-mcp) covers both.) The server exposes 37 tools (as of August 2026) across companies, people, opportunities, tasks, and notes, plus schema resources so Claude can see your team's custom fields before it writes anything.

For this walkthrough I ran against a local Relaticle instance, not the hosted one, so I could seed a workspace and check every write against Postgres directly. One quirk worth naming: Claude Code's MCP client couldn't resolve my local `.test` domain (a Node DNS resolver issue with custom TLDs, unrelated to Relaticle), so I pointed the connector at a plain `http://127.0.0.1` loopback binding of the same app instead, same code, same auth, same database, different transport. Production's `mcp.relaticle.com` is a normal public domain and doesn't hit this.

![The Opportunities pipeline table with Stage, Amount and Close Date for every open deal](https://relaticle.com/storage/ink/01M09G7MVQV60NS0YRXK7138BQ.png)

[](#scene-1-pipeline-review "Permalink")Scene 1: pipeline review
----------------------------------------------------------------

**Prompt:** "Summarize my sales pipeline: list all open opportunities grouped by stage, and flag any that haven't been touched in over 30 days."

Claude called `who-ami-tool` first, then `list-opportunities-tool`, then checked `list-notes-tool` and `list-tasks-tool` per opportunity to see if any activity postdated the raw `updated_at` timestamp before trusting it as a staleness signal. Its answer, exactly as it printed, trimmed only for length (two $0 test-fixture rows with no stage or amount, and a caveat about a second, unrelated Relaticle connector in the same session that Claude correctly avoided using):

```
## Pipeline summary — 9 open opportunities, $318,500

| Stage | Opportunity | Amount | Close date | Last touched |
|---|---|---|---|---|
| Prospecting | Stripe Billing Migration | $30,000 | 2026-10-01 | 3d |
| Qualification | Notion API Integration | $22,000 | 2026-09-20 | **51d** |
| Value Proposition | Gumroad Data Sync Deal | $18,500 | 2026-08-05 (9d overdue) | **40d** |
| Id. Decision Makers | Bitcoin Exchange Onboarding | $65,000 | 2026-09-15 | 6d |
| Proposal/Price Quote | Apple Developer Partnership | $120,000 | 2026-09-05 | 2d |
| Proposal/Price Quote | Figma Enterprise Plan | $15,000 | 2026-07-29 (16d overdue) | 29d 16h |
| Negotiation/Review | Airbnb Host Analytics | $48,000 | 2026-08-25 | 45d |

## Flagged: stale >30 days — $88,500 (28% of pipeline)

1. **Notion API Integration** — 51 days, Qualification. Longest-idle deal.
2. **Airbnb Host Analytics** — 45 days, Negotiation/Review. Late-stage, closes in 11 days, untouched for six weeks.
3. **Gumroad Data Sync Deal** — 40 days, Value Proposition. Close date already 9 days past.

**`updated_at` is back-dated in the seed data.** Four records have `updated_at` *earlier* than `created_at` (Notion API Integration: created 2026-07-15, updated 2026-06-24; Gumroad: created 2026-08-14, updated 2026-07-05). That's impossible for real activity, so every "days since touched" figure above is derived from a synthetic value.

**No corroborating activity exists.** Zero notes and zero tasks are attached to any opportunity in this workspace — I checked notes across all opportunities and tasks against each stale candidate. So `updated_at` was the only touch signal available; there's no way to tell a genuinely neglected deal from one worked via channels the CRM didn't record.

```

The $318,500 total and every row reconcile against the database. More telling than the arithmetic: Claude flagged its own data's limits unprompted, back-dated timestamps and no corroborating activity, instead of reporting the staleness numbers at face value.

[](#scene-2-data-entry-after-a-call "Permalink")Scene 2: data entry after a call
--------------------------------------------------------------------------------

**Prompt:** "I just got off a call with Sarah Chen, VP of Sales at a new prospect called Lumen Robotics. Create a company for Lumen Robotics, add Sarah Chen as a contact there (title VP of Sales, email sarah.chen@lumenrobotics.com), and log a note titled 'Discovery call recap' with body summarizing that they're currently tracking deals in spreadsheets, want to replace that with a real CRM, and asked for a demo next week, link the note to both the new company and the new contact when you create it."

Claude checked for existing records first (`list-companies-tool`, `list-people-tool` searches for "Lumen" and "Sarah Chen" came back empty), then wrote in order: `create-company-tool`, `create-people-tool` with the new company's ID and custom fields for job title and email, then `create-note-tool` in a single call carrying both `company_ids` and `people_ids` so the links existed at creation instead of a separate attach step. It closed by re-reading the note and the contact with relationships included to confirm the links actually landed, rather than trusting the write response.

![Sarah Chen on the People list with job title and email, and the Discovery call recap note linked to Lumen Robotics and Sarah Chen](https://relaticle.com/storage/ink/01M09G7PE5NSS641M2B6G64YB9.png)

Checked in the app: Lumen Robotics exists, Sarah Chen is listed under its People tab with the right title and email, and "Discovery call recap" shows up in Notes with both Lumen Robotics and Sarah Chen in the Companies and People columns. One call, three linked records, verified without a separate attach-note-to-entities-tool call because the create tool already accepted the relationship IDs.

[](#scene-3-bulk-hygiene-on-overdue-tasks "Permalink")Scene 3: bulk hygiene on overdue tasks
--------------------------------------------------------------------------------------------

**Prompt:** "Find all my tasks that are past due and not marked done. For each one, push the due date out by exactly 7 days from its current due date so I have room to catch up, and tell me what you changed."

This one didn't execute on the first pass, and that's the interesting part. Claude read the task list, checked assignees, and stopped:

> I held off on writing anything, because the data doesn't match the premise of the request. \[...\] **Tasks assigned to you: 2 — neither is past due.** **Tasks past due and not done: 4 — all assigned to other people.** \[...\] So "my tasks" resolves two different ways and they lead to opposite actions: assigned-to-you means there is nothing to reschedule, workspace-wide means I'd be moving three other people's deadlines. I didn't want to silently do the second one.

It also flagged that pushing "Follow up with Dylan" exactly 7 days from its old due date would still leave it 2 days overdue, and asked whether I meant 7 days from today instead. I answered in a follow-up turn: workspace-wide, and 7 days from today for the one that would still be overdue. Claude then ran four `update-task-tool` calls, one per task, sending only `due_date` in `custom_fields` so status and priority stayed untouched, and re-read every task afterward to confirm nothing else moved.

![The Tasks list with Send renewal terms to Notion, Integration meeting with Ivan, Follow up with Dylan and Discovery call with Brian all due Aug 21, 2026](https://relaticle.com/storage/ink/01M09G7QX65S3R9TN449447KJ5.png)

All four tasks now show the new due date in the app, with their original status and priority values intact. Assignees were unchanged too, which Claude called out as worth checking explicitly since the update tool's assignee parameter isn't documented as leave-unchanged-when-omitted the way the other relationship fields are.

[](#scene-4-setting-a-custom-field "Permalink")Scene 4: setting a custom field
------------------------------------------------------------------------------

**Prompt:** "On the Bitcoin Exchange Onboarding opportunity, set the Deal Source custom field to Referral."

`Deal Source` is a field my team added through the Custom Fields admin, not one of the built-in ones the app ships with. Claude found the opportunity, read the `relaticle://schema/opportunity` resource to confirm "Referral" was a valid option for that field (rather than guessing at the option ID), then called `update-opportunity-tool` with just the one field:

> Done. Deal Source on **Bitcoin Exchange Onboarding** is now **Referral**. Was `null` before the write; a fresh read-back confirms `deal_source: {id: ..., label: "Referral"}`. Other fields untouched, amount $65,000, close date 2026-09-15, stage "Id. Decision Makers."

![The Bitcoin Exchange Onboarding opportunity with Deal Source set to Referral and Amount, Close Date and Stage unchanged](https://relaticle.com/storage/ink/01M09G7SE8SXP59X44WV69KT53.png)

This is the part that matters more than the specific field: nothing about `deal_source` is hardcoded into Relaticle's MCP tools. It's exposed automatically because the schema resource describes whatever custom fields exist on your team, which is why a team-specific field worked with no extra setup on either side.

[](#scene-5-the-guarded-delete "Permalink")Scene 5: the guarded delete
----------------------------------------------------------------------

**Prompt (fresh session, no prior context):** "Delete the two junk opportunities you flagged earlier as import test artifacts with no stage and no amount: br-rel-186b-ws-date and br-rel-186b-good-date. Clean them up."

First response: Claude refused, correctly, because "earlier" didn't mean anything in a session with no prior turns. It offered three options rather than guessing.

I replied confirming the deletion in a follow-up turn, still without pre-granting any tool permissions. Claude tried `who-ami-tool`, then `list-opportunities-tool`, then `delete-opportunity-tool`, and all three came back the same way:

> `Claude requested permissions to use mcp__relaticle-local__delete-opportunity-tool, but you haven't granted it yet.`

It fell back to a read-only database query through Bash to confirm the two records actually existed and matched the description, then stopped instead of routing around the blocked tool:

> I could delete these with a tinker `->delete()`, but that's not what you authorized and it bypasses the `DeleteOpportunity` action, so any side effects that action owns wouldn't fire. Substituting a different write path for the one you named isn't mine to decide.

That refusal is Claude Code's own permission system, not something Relaticle's server enforces. The `delete-*` tools carry an `IsDestructive` annotation in their MCP metadata, but that's descriptive, not a protocol-level gate. The actual gate is whatever tool-approval policy the client applies, same as for any other tool call. Once I granted `delete-opportunity-tool` for the session, both calls went through immediately and were verified against the database: soft-deleted with a `deleted_at` timestamp, restorable if that had been a mistake.

![The Opportunities list down to 8 records after the two duplicate test deals were deleted](https://relaticle.com/storage/ink/01M09G7V096R2VSC8RJZRX2RTC.png)

| Scene | Prompt (trimmed) | Tools used | Time |
|---|---|---|---|
| 1. Pipeline review | "Summarize my sales pipeline... flag any untouched over 30 days" | who-ami-tool, list-opportunities-tool, list-notes-tool, list-tasks-tool ×4 | 87s |
| 2. Data entry after a call | "Create Lumen Robotics, add Sarah Chen, log a linked discovery call note" | list-companies-tool, list-people-tool, create-company-tool, create-people-tool, create-note-tool, get-note-tool, get-people-tool | 90s |
| 3. Bulk hygiene | "Find overdue tasks, push due dates out 7 days" (2 turns, 1 clarifying) | list-tasks-tool ×2, get-task-tool ×8, update-task-tool ×4 | 130s |
| 4. Custom field usage | "Set Deal Source to Referral on Bitcoin Exchange Onboarding" | list-opportunities-tool, update-opportunity-tool, get-opportunity-tool | 28s |
| 5. Guarded delete | "Delete two junk opportunities" (3 turns: refuse, block, execute) | who-ami-tool, list-opportunities-tool, delete-opportunity-tool | 118s |

[](#what-this-means-for-daily-work "Permalink")What this means for daily work
-----------------------------------------------------------------------------

The pattern across all five scenes is the same: Claude reads before it writes, checks its own assumptions against the schema instead of guessing field names or option values, and re-reads after a write to confirm the change actually landed rather than trusting the tool's own success message. That's not something Relaticle's server enforces, it's how Claude Code chose to use the tools it was given. A less careful client could skip all of that and just fire writes.

For a working session, that means the CRM chores that eat ten minutes between calls, a pipeline check, logging a call, clearing a backlog of stale tasks, filling in a team-specific field, all move into the same terminal window you're already using. None of it needed more than the token and one `claude mcp add` command.

[](#honest-limits "Permalink")Honest limits
-------------------------------------------

**There's no approval gate over MCP.** Relaticle's in-app chat assistant has a proposal-card flow where writes wait for a click before they commit. MCP doesn't work that way: once a tool call reaches Relaticle's server, it runs. The server's only gate is your token's abilities (create/read/update/delete) and standard authorization, same as a person clicking the same button in the UI. The only approval layer in this walkthrough was Claude Code's own client-side permission system, and scene 5 showed exactly how far that goes: it blocks an unapproved call, but once granted, even for a destructive tool, it runs with no further confirmation. Mistakes made through MCP are real writes, not proposals.

**Ambiguity gets escalated, not guessed.** Scene 3 is the clearest example: "my tasks" had two readings that led to opposite actions, and Claude stopped and asked rather than picking one. That's good behavior, but it means a bulk-hygiene prompt might take two turns instead of one if your phrasing is genuinely ambiguous, which is worth knowing before you count on a single prompt finishing a batch job unattended.

**Rate limits exist, and they're the MCP server's own.** MCP calls are throttled at 120 requests per minute per user, separately from the REST API's limits. I didn't get anywhere near that across five scenes and some verification calls, but a script doing bulk operations across hundreds of records would want to budget for it.

**What didn't fully work in this run:** the first attempt at scene 3 produced no writes at all, it was a clarifying question, not a bug, but it means the "bulk hygiene" scene as originally scoped took two prompts instead of one. Scene 5's first two attempts also produced no writes, by design. If you're counting scenes as pass/fail, this run is 5 for 5 on eventually doing the right thing, and 2 of those 5 needed a second turn to get there.

 Tagged: [ #mcp ](https://relaticle.com/blog/tag/mcp) [ #claude ](https://relaticle.com/blog/tag/claude) 

 Related posts
-------------

 [  Guides   Sep 1, 2026  

 What 'Agent-Native CRM' Actually Means 
----------------------------------------

Agent-native CRM is a checklist, not a marketing label: full write access, approvals for chat, self-host parity, markdown for agents, first-party tooling.

 ![What 'Agent-Native CRM' Actually Means](https://relaticle.com/storage/ink/01M17KWER35G1NK6TDDS6KQSZN.png) ](https://relaticle.com/blog/what-agent-native-crm-actually-means) [  Guides   Aug 28, 2026  

 How to Connect Claude to Your CRM with MCP 
--------------------------------------------

Connect Claude to Relaticle via MCP in minutes: OAuth setup, all 37 tools explained, and why MCP writes commit directly with no approval gate.

 ![How to Connect Claude to Your CRM with MCP](https://relaticle.com/storage/ink/01M17KWD0RMP42X0P5Z8T29ZYP.png) ](https://relaticle.com/blog/how-to-connect-claude-to-your-crm-with-mcp) [  Guides   Aug 18, 2026  

 Self-Hosting an AI-Native CRM in 2026 
---------------------------------------

Self-hosting Relaticle with Docker, Coolify, or Dokploy, plus a local Ollama model: the AI chat and full MCP tool suite with no cloud subscription.

 ![Self-Hosting an AI-Native CRM in 2026](https://relaticle.com/storage/ink/01M17KW7J3RKP1743041AJCDMP.png) ](https://relaticle.com/blog/self-hosting-an-ai-native-crm-in-2026) 

    ###    On this page
