Demo CRM MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Demo CRM MCP ServerShow today's new leads in Victoria, check duplicates, suggest owners."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Demo CRM MCP Server
Let an AI assistant work a sales pipeline safely: search leads, catch duplicates before they are created, and route each lead to the right salesperson.
This is a Model Context Protocol (MCP) server written in Python. Connect it to an MCP client such as Claude Desktop and you can manage a CRM in plain English:
"Show me today's new leads in Victoria, check them for duplicates, and suggest who should own each one."
It is based on the kind of lead automation I build in production (duplicate detection, territory-based allocation, audit trails), rebuilt from scratch as an open demo with 100% fictional data.
Why this project
AI assistants are most useful when they can act on real business systems, but giving them write access to a CRM is risky. This server shows how to do it responsibly:
Risk | How this server handles it |
AI creates duplicate records | Every |
Black-box decisions | Duplicate matches and salesperson recommendations always come with reasons |
Unwanted changes | Tools are labelled read-only or write, and |
No accountability | Every change is recorded in an audit log, readable as an MCP resource |
Bad input | Strict validation on every field; all SQL is parameterised |
Related MCP server: MCP Suite CRM
Architecture
flowchart LR
U[You] -->|plain English| C[MCP client<br/>e.g. Claude Desktop]
C <-->|MCP over stdio| S[crm-mcp server]
S --> T1[Read tools<br/>search · get · duplicates<br/>recommend · summary]
S --> T2[Write tools<br/>create · status · note · assign]
T2 --> G{Guards<br/>validation · duplicate check<br/>read-only mode}
T1 --> DB[(SQLite demo CRM)]
G --> DB
G --> A[(Audit log)]What the AI can do
Tools
Tool | Type | What it does |
| read | Search by name, email, phone, postcode, status, state or owner |
| read | Full lead record with owner and notes |
| read | Compares a lead with every other lead and explains each match |
| read | Ranks salespeople by territory coverage and current workload |
| read | Counts by status and source, unassigned leads, win rate |
| write | Creates a lead, with built-in duplicate protection |
| write | Moves a lead through New → Contacted → Qualified → Quote Sent → Won/Lost |
| write | Adds a note to a lead |
| write | Assigns a lead to a salesperson |
Resources: crm://schema (fields, statuses, duplicate rules) and crm://audit-log (recent changes).
Prompt: daily_triage, a ready-made workflow that reviews new leads, flags duplicates and proposes assignments, then asks you to confirm before changing anything.
Duplicate detection
Phone numbers and emails are normalised first, so +61 491 570 156, 0491-570-156 and (04) 9157 0156 are treated as the same number.
Confidence | Rule |
High | Same email (case-insensitive) |
High | Same phone number (formatting ignored) |
High | Same full name and postcode |
Medium | Very similar name (85%+ similarity) in the same postcode, e.g. Sophia / Sofia |
Low | Same full name in the same state |
A lead is never matched against itself. Example output:
{
"lead_id": 38,
"possible_duplicates": [
{
"lead_id": 6,
"name": "Jack Khan",
"confidence": "high",
"reasons": [
"Same phone number (after removing formatting)",
"Same full name and postcode"
]
}
]
}And when the AI tries to create a lead that already exists:
{
"created": false,
"message": "Not created: this looks like an existing lead. Review the matches, then call create_lead again with allow_duplicate=true if it really is a new person.",
"possible_duplicates": [
{ "lead_id": 1, "name": "Ruby Singh", "confidence": "high", "reasons": ["Same email address"] }
]
}Quick start
Requires Python 3.10 or later.
git clone https://github.com/hayathi06/crm-mcp-server.git
cd crm-mcp-server
python -m venv .venv
# Windows: .venv\Scripts\activate macOS/Linux: source .venv/bin/activate
pip install -e ".[dev]"
pytest # run the testsOn first run the server creates demo_crm.db with 40 fictional leads, 6 salespeople and four planted duplicates for the detector to find.
Connect to Claude Desktop
In Claude Desktop, open Settings → Developer → Edit Config and add the server to claude_desktop_config.json. Use the full path to the Python inside your virtual environment:
{
"mcpServers": {
"demo-crm": {
"command": "C:\\path\\to\\crm-mcp-server\\.venv\\Scripts\\python.exe",
"args": ["-m", "crm_mcp"],
"env": {
"CRM_MCP_DB": "C:\\path\\to\\crm-mcp-server\\demo_crm.db",
"CRM_MCP_READ_ONLY": "0"
}
}
}
}On macOS or Linux the command is /path/to/crm-mcp-server/.venv/bin/python. Restart Claude Desktop and the CRM tools appear.
Try these prompts
"Give me a pipeline summary for NSW."
"Find leads that are probably duplicates and explain why."
"Add a new lead: Ruby Singh, RUBY.SINGH0@example.com, Perth 6000." (watch the duplicate check block it)
"Which new leads have no owner? Recommend a salesperson for each and assign them once I confirm."
"Run the daily triage for VIC."
Configuration
Variable | Default | Purpose |
|
| Path to the SQLite file, created and seeded if missing |
| off | Set to |
Project structure
src/crm_mcp/
server.py MCP tools, resources and prompt
crm.py CRM logic, validation, audit log, demo data
duplicates.py Normalisation and duplicate rules
tests/
test_crm.py Unit tests for the CRM logic
test_server.py End-to-end tests over a real MCP stdio sessionAbout the data
Everything is invented. Names are made up, emails use the reserved example.com domain, and phone numbers come from the ranges the Australian Communications and Media Authority reserves for fiction.
Author
Noor Hayathi Jamal Mohammed, AI Automation Engineer, Melbourne Portfolio · LinkedIn
MIT licensed.
Available Tools
9 toolsadd_noteC
Add a note to a lead.
| Name | Required | Description | Default |
|---|---|---|---|
| note | Yes | ||
| lead_id | Yes | The lead's numeric id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=false, and openWorldHint=false, so the safety profile is covered. The description adds nothing beyond that: it does not say whether the note is appended or replaces existing notes, whether the 2000-char limit applies, or what happens on failure. Minimal added value.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single six-word sentence with the action front-loaded and zero filler. It is appropriately terse, though the brevity edges toward under-specification rather than genuine conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple mutation tool with no output schema this is on the thin side: the description omits append-vs-replace semantics, note length limits, and any indication of the response. Annotations cover safety only, leaving behavioral expectations undocumented.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% — lead_id is documented but the 'note' parameter has no description despite carrying a maxLength constraint. The description says nothing about either parameter, so it fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Add a note to a lead'), which is unambiguous and distinguishable from siblings like create_lead or update_lead_status. It lacks any explicit sibling differentiation, but the action is clear enough to select correctly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives such as update_lead_status, nor any mention of prerequisites or context (e.g., after a call, for logging interactions). Usage must be entirely inferred.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
assign_leadAIdempotent
Assign a lead to a salesperson (use recommend_salesperson first).
| Name | Required | Description | Default |
|---|---|---|---|
| lead_id | Yes | The lead's numeric id | |
| salesperson_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false and idempotentHint=true, so safety and repeatability are covered structurally. The description adds no behavioral context beyond that — it never says whether an existing assignment is overwritten, whether notifications are sent, or what happens if the salesperson is invalid.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with the action first and the workflow hint second. No filler and nothing redundant with the schema.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-required-parameter mutation with an idempotency annotation and no output schema, the essentials are covered. Missing: what the tool returns, how it behaves on an already-assigned lead, and any indication of error conditions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: lead_id is documented, salesperson_id is bare. The description implies salesperson_id should be sourced from recommend_salesperson, which is a genuinely useful origin hint, but adds no format or validity detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ('Assign a lead to a salesperson') that an agent can distinguish from siblings like recommend_salesperson (suggestion) and create_lead (creation). The parenthetical routing makes the boundary explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names the prerequisite step ('use recommend_salesperson first'), which is real sequencing guidance against an alternative. It stops there: no when-not-to-use, no note about reassigning an already-assigned lead, and no permission prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_leadA
Create a lead. Runs duplicate detection first and refuses high-confidence duplicates unless allow_duplicate is true.
| Name | Required | Description | Default |
|---|---|---|---|
| No | |||
| phone | No | ||
| state | No | ||
| source | No | e.g. Website form, Email enquiry, Phone, Event, Referral | |
| interest | No | ||
| postcode | No | 4-digit Australian postcode | |
| last_name | Yes | ||
| first_name | Yes | ||
| allow_duplicate | No | Create even if a high-confidence duplicate exists |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only declare it is a non-read-only, non-destructive, closed-world write. The description adds genuinely non-obvious behavior: an implicit duplicate-detection pre-check that can refuse the creation, and the allow_duplicate escape hatch. It does not say what the caller receives on refusal or on success, but the key operational hazard is disclosed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler, front-loading the core action before the duplicate-detection caveat. Every clause carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 9-parameter creation tool with no output schema and low schema coverage, the description covers the main behavioral risk (silent or refused duplicate creation). It omits the return shape (e.g., new lead id) and the exact refusal semantics, which are minor gaps given the schema handles field definitions.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 33% (only source, postcode, allow_duplicate), so the description should compensate. It clarifies allow_duplicate as 'create even if a high-confidence duplicate exists', but that largely restates the schema's own description, and the 6 other parameters (including the required first_name/last_name) get no added meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a lead') and immediately adds the distinguishing behavior that it runs duplicate detection first, which separates it from the sibling find_duplicates tool. It stops short of naming any sibling explicitly, so it is clear but not fully differentiated from the rest of the lead toolset.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear context for the primary use case and discloses the condition under which the call will fail (high-confidence duplicate) plus the override flag. It does not route the agent to alternatives (e.g., find_duplicates to pre-check, or update_lead_status for existing leads), so it lacks explicit when-not/exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_duplicatesARead-only
Check an existing lead against every other lead and explain any likely duplicates.
| Name | Required | Description | Default |
|---|---|---|---|
| lead_id | Yes | The lead's numeric id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds meaningful context beyond that: the scan is against 'every other lead' (full-corpus scope, implying cost) and the return is an explanation of likely duplicates rather than a bare list.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence that front-loads the core action and stays free of filler. Nothing redundant or padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool with annotations covering safety and closed-world scope, the description conveys scope (all other leads) and the nature of the output (explanations). No output schema exists, but the description adequately characterizes the response shape; only detailed return structure is left unspecified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single lead_id parameter is documented as 'The lead's numeric id'. The description adds no format, range, or behavioral detail beyond the schema, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (check) and resource (an existing lead vs every other lead) with the outcome being duplicate detection plus explanation. No sibling (get_lead, search_leads, pipeline_summary, etc.) performs duplicate detection, so the purpose is unambiguous even without an explicit sibling callout.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the description — call it to check one lead for duplicates — and the phrase 'existing lead' hints that the lead must already exist. However there is no explicit when-to-use, when-not-to-use, or alternative named, so guidance stays at the implied level.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_leadBRead-only
Get one lead with its owner and notes.
| Name | Required | Description | Default |
|---|---|---|---|
| lead_id | Yes | The lead's numeric id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds useful context about the response contents (owner and notes), but says nothing about behavior for a missing/invalid lead_id or permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short sentence with zero filler, and the key information (single lead, returned owner/notes) is front-loaded. It is appropriately sized for a trivial getter, though it could carry a bit more substance without bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only getter with full schema coverage and annotations, the definition is nearly sufficient, and it helpfully describes the returned fields in the absence of an output schema. Missing only edge-case behavior (invalid id) and explicit sibling routing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single lead_id parameter is documented in the schema itself. The description adds no syntax, format, or constraint detail beyond what the schema provides, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ("Get one lead") and adds what is returned (owner and notes). It implies a single-record fetch distinct from search_leads, but never names the sibling or contrasts scope, so differentiation is only implicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit when-to-use guidance and no alternatives named. The agent must infer from "one lead" that this requires a known lead_id and is not a search, but search_leads is never mentioned as the discovery path.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
pipeline_summaryBRead-only
Lead counts by status and source, unassigned open leads, and win rate.
| Name | Required | Description | Default |
|---|---|---|---|
| state | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds the shape of what is computed, which is genuinely useful behavioral context, but says nothing about time window, caching, or scope of the aggregation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence that lists the three metric groups with no filler. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only aggregate with no output schema, the description usefully enumerates the returned metrics, but it leaves open the time period, the definition of win rate, and the undocumented state filter. Adequate but with clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is exactly one parameter (state, an enum of Australian states) with 0% schema description coverage, and the description never mentions filtering by state at all. Because a parameter exists, the baseline-4 rule for zero-param tools does not apply, and the description fails to compensate for the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (leads/pipeline) and enumerates the specific aggregates returned: counts by status and source, unassigned open leads, and win rate. That clearly distinguishes it from record-returning siblings like search_leads and get_lead. It lacks an explicit verb, but the resource and output scope are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance about when to use this aggregate tool versus siblings such as search_leads or get_lead, and no mention of prerequisites or filters. An agent must infer that this is a reporting/overview call rather than a record lookup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recommend_salespersonBRead-only
Rank salespeople for a lead by territory coverage and current workload.
| Name | Required | Description | Default |
|---|---|---|---|
| lead_id | Yes | The lead's numeric id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this is a safe read (readOnlyHint=true) and closed-world (openWorldHint=false), so the safety profile is covered. The description adds above that baseline by disclosing the ranking factors (territory coverage, workload), but says nothing about return shape, ordering guarantees, tie-breaking, or empty-result behavior for a tool with no output schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single tight sentence with the ranking criteria front-loaded alongside the purpose. Nothing is repeated or wasted, though it is arguably too short given the gaps noted in usage and return behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is low-complexity (one required param, read-only), and annotations carry the safety profile, so the bar is modest. Still, with no output schema the description should state what an agent gets back (a ranked list of candidates), and it should distinguish recommendation from the actual assignment step. Those gaps keep it at minimum-viable completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There is a single parameter with 100% schema description coverage ('The lead's numeric id'), so the schema fully documents it. The phrase 'for a lead' in the description merely restates this and adds no syntax, format, or semantic detail beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a specific verb (Rank), resource (salespeople), and scope condition (for a lead), plus the ranking criteria (territory coverage, current workload). It is clear what the tool produces. However, it does not distinguish itself from the closely related sibling assign_lead, which an agent could easily confuse with an advisory ranking tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies the context (ranking candidates for a lead) but gives no explicit when-to-use, when-not-to-use, or alternative routing. In particular it never clarifies that this is advisory only and that the actual write action belongs to assign_lead, leaving the most likely sibling confusion unresolved.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_leadsBRead-only
Search leads by text, status, state or owner. Newest first.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| owner | No | Salesperson name, or 'unassigned' | |
| query | No | Text to match in name, email, phone or postcode | |
| state | No | ||
| status | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description contributes one behavioral fact beyond the schema — result ordering ("Newest first") — but says nothing about pagination, the default limit of 20, or what an empty result looks like.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the filtering capability front-loaded and the sort behavior as a trailing qualifier. Nothing to trim.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-argument-required search tool with no output schema and 40% schema coverage, the description covers the filter surface and sort order but leaves limit/pagination semantics and result shape unexplained. Adequate but with clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 40%, and the description name-drops four of the five filters (text, status, state, owner) while ignoring limit entirely. The schema itself already documents the query and owner matching scope, so the description adds only marginal meaning over structured data.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Search) and resource (leads) plus the filter dimensions it accepts, so the agent knows exactly what it retrieves. It stops short of differentiating itself from siblings such as get_lead or find_duplicates, which is the only thing keeping it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description lists what can be filtered but gives no when-to-use, when-not-to-use, or alternative routing (e.g. get_lead for a single record, find_duplicates for dedupe). Usage is only implied by the filter list.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_lead_statusCIdempotent
Move a lead to a new pipeline status.
| Name | Required | Description | Default |
|---|---|---|---|
| status | Yes | ||
| lead_id | Yes | The lead's numeric id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, idempotentHint=true, and openWorldHint=false, so the safety profile is covered. The description adds nothing beyond that: it does not say whether the change is reversible, whether it triggers notifications or automation, or whether any status transition is restricted. For a mutation tool it leaves the behavioral surface thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single eight-word sentence with the action front-loaded and zero waste. It is efficient, though its brevity borders on under-specification rather than deliberate conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter mutation tool with no output schema and only 50% parameter documentation, the description should convey what happens after the move (side effects, resulting state, failure modes). None of that is present, so an agent cannot fully predict the call's consequences.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 50%: lead_id is documented in the schema, while status is only an enum with no description. The description's phrase "pipeline status" marginally clarifies that status draws from the pipeline vocabulary, but adds nothing about lead_id's numeric identity or transition rules. Baseline 3 given the schema handles most of the meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
"Move a lead to a new pipeline status" states a specific verb (move) and resource (lead) with the field being changed, which distinguishes it from get_lead, search_leads, and create_lead. It stops short of naming an alternative sibling explicitly, so it stays at a solid 4.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this versus assign_lead, create_lead, or add_note, nor any statement of prerequisites (e.g., lead must exist, valid transitions). Usage is only implied by the verb, leaving the agent to infer the context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
9 tool updates
v1.0.0- First observed
add_note - First observed
assign_lead - First observed
create_lead - First observed
find_duplicates - First observed
get_lead - First observed
pipeline_summary - First observed
recommend_salesperson - First observed
search_leads - First observed
update_lead_status
TDQS
Scored across 9 tools
Most tools have clearly distinct resource+action targets (search, get, create, add_note, assign, summarize). Minor overlap exists: find_duplicates partially duplicates the duplicate check built into create_lead, and assign_lead vs update_lead_status both mutate a lead's fields, though descriptions clarify intent.
The set is overwhelmingly consistent snake_case verb_noun (search_leads, get_lead, create_lead, assign_lead, add_note). The only deviation is pipeline_summary, which is a bare noun phrase without a verb, but it remains readable and predictable.
Nine tools is well-scoped for a CRM server, covering discovery, reading, mutation, and analytics without redundancy. Each tool earns its place and none feels like padding.
Core lead lifecycle is covered: create, search, get, status update, note, assignment, duplicate check, plus a pipeline analytics view. Gaps include no delete/archive lead, no general field-edit tool beyond status, and no way to list or manage salespeople outside recommend_salesperson.
Maintenance
Related MCP Connectors
Read-only sales CRM for AI clients: leads, pipeline, AI-agent chats, calls, ad attribution.
Hosted CRM and email desk for AI agents: key per agent, audit log, one-click undo, opt-in approval.
CRM, inbox, meetings, revenue intelligence, analytics and automations for AI agents.
Lead Friendly pricing, industries and capabilities for AI agents, plus demo and lead hand-off
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI agents to perform secure Salesforce Lead management operations including CRUD actions, status updates, and idempotent syncing. It features TRD-compliant audit logging and OAuth 2.0 authentication to ensure reliable CRM interactions.-
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to interact with a CRM covering companies, people, leads, deals, and more, with role checks, scoped agent keys, approval gates, and a shared audit trail.AGPL 3.0
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with GoHighLevel CRM via natural language for lead lookup, pipeline management, messaging, and calendar operations, with read-only mode by default.12MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI sales agents to interact with a CRM via event-sourced actions, identity resolution, guard checks, and an approval inbox, managing communications and tasks while adhering to compliance rules.-