contact-dedupe
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., "@contact-dedupeDedupe my contacts export, merge the duplicates, and list the conflicts."
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.
contact-dedupe — MCP server
An MCP (Model Context Protocol) server that lets Claude, or any MCP client, work on a contact export: profile it, find the rows that are the same person, and write a merged file — with every conflicting value reported instead of quietly dropped.
Built for the job I get asked for most often: a CRM or Google Contacts export
where the same person appears three times as Ali Raza, Raza, Ali and
Ali R., with the phone number on one row and the email on another.
Tools
Tool | What it does |
| rows, columns, fill rate per column, and the detected name/email/phone/company mapping |
| duplicate groups with the evidence behind each match — read-only |
| merges each group into one row, writes a cleaned CSV ( |
| scores a single pair 0–1 and lists the signals, for tuning the threshold |
Related MCP server: MCP Data Integration Server
Matching rules
Exact-match dedupe misses most real duplicates, and fuzzy name matching alone merges people who merely share a surname. So the score comes from several signals:
Email —
Ali.Raza+crm@gmail.comandaliraza@gmail.comare the same mailbox, buta.b@outlook.comandab@outlook.comare not; the dot rule is a Gmail behaviour, not a general one.Phone — compared on the last 9 digits, so
+92 300 1234567,0300-1234567and00923001234567line up without guessing a country.Name — accent- and punctuation-insensitive, order-insensitive (
Raza, Ali=Ali Raza), Levenshtein for the rest.Company — only ever a tie-breaker on top of a name match.
A shared email or phone is strong evidence; a similar name on its own is not enough to merge. Groups form transitively (A–B by phone, B–C by email puts all three together), and the threshold is a parameter, not a hard-coded constant.
Merging keeps the most complete row as the base, fills blanks from the others,
prefers the longer value when one contains the other (Beta Foods →
Beta Foods Pvt Ltd), and reports everything else as a conflict.
Install
npm installRegister it with an MCP client (Claude Desktop / Claude Code):
{
"mcpServers": {
"contact-dedupe": {
"command": "node",
"args": ["/absolute/path/to/csv-dedupe-mcp/src/server.mjs"]
}
}
}Try it
node test/server.e2e.mjsRuns the real stdio protocol against sample/contacts.csv (10 rows, messy on
purpose) and prints:
duplicate groups: 3 | rows involved: 7
group 1: rows 2, 3, 4 — same email + same name + same company ; same phone
group 2: rows 5, 6 — same email + same name
group 3: rows 8, 9 — same email
dedupe_csv (dry run) → { input: 10, output: 6, removed: 4 }
conflicts flagged: Company: kept "Beta Foods Pvt Ltd" / dropped "Beta Foods" | …Tests
node --test test/dedupe.test.js # 9 tests: normalisation, scoring, grouping, merge, CSV
node test/server.e2e.mjs # protocol-level run over stdioLayout
src/server.mjs MCP server (stdio) — tool definitions and zod schemas
src/dedupe.js matching, grouping and merge logic (no protocol code)
src/csv.js RFC 4180 CSV reader/writer, no dependencies
sample/ messy sample export
test/ unit tests + end-to-end MCP client testThe matching logic holds no MCP code on purpose — the rules that decide whether two people are the same are the part worth testing on their own.
Available Tools
4 toolscompare_recordsCompare two recordsB
Score a single pair 0-1 and list the signals behind the score — useful for tuning the threshold.
| Name | Required | Description | Default |
|---|---|---|---|
| a | Yes | First record as field/value pairs | |
| b | Yes | ||
| fields | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It states the tool 'scores' a pair, which implies a read-only computation, but it does not explicitly disclose that it has no side effects, nor does it explain what kind of signals are returned or how the score is computed. The phrase 'list the signals' is vague about the content and format. This is a significant gap for a tool with no annotation support.
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?
The description is concise, one sentence with a purposeful start ('Score a single pair'). It efficiently communicates the core action and output. It could be slightly more informative without becoming verbose, but as is, it is appropriately sized and front-loaded.
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 has no output schema, no annotations, and limited schema coverage. The description only provides the high-level purpose and a vague reference to signals. It does not explain the return format beyond a 0-1 score, nor does it clarify parameter semantics or any edge cases (e.g., missing fields, mismatched field names). An agent trying to call this tool correctly would likely need additional documentation.
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?
The input schema has low description coverage (33%) – only parameter 'a' is described, while 'b' and 'fields' lack descriptions. The tool description does not mention any parameters or explain their roles. It only says 'Score a single pair', which implicitly refers to a and b, but does not clarify what 'fields' does or how it affects scoring. Given the low schema coverage, the description should compensate, but it does not.
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 states a specific verb (score) and a resource (a single pair) and clarifies the output (0-1 score plus signals). This clearly distinguishes it from sibling tools like find_duplicates (which scans many records) and dedupe_csv (which performs deduplication). An agent can immediately understand what the tool does and how it differs from alternatives.
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 mentions a concrete use case: 'useful for tuning the threshold'. This gives context for when to use the tool. However, it does not explicitly mention alternatives or state when not to use it. The sibling names imply other tools for bulk operations, but the description itself does not draw that contrast. Still, the stated purpose is clear enough for an agent to infer its role.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
dedupe_csvDeduplicate a CSVB
Merge duplicate groups into one row each and write a cleaned CSV. Conflicting values are reported, never dropped silently.
| Name | Required | Description | Default |
|---|---|---|---|
| out | No | Output path; defaults to <name>.deduped.csv | |
| file | Yes | ||
| fields | No | ||
| dry_run | No | ||
| threshold | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral disclosure burden and does add one useful trait: conflicting values are reported, never silently dropped. However, it does not clarify dry_run behavior, threshold semantics, overwrite behavior, or what 'reported' means, so significant behavior remains undisclosed.
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 sentences with no filler: the primary action is front-loaded and the conflict-handling guarantee is stated separately. Every phrase 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?
The tool has five parameters, a nested fields object, no output schema, and no annotations, so the description must carry more context. It explains the core output and conflict safety but omits threshold meaning, dry_run effects, field mapping, and required input details, making it insufficient for correct invocation without additional inference.
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 only 20% (only 'out' has a description), so the description must compensate for file, fields, dry_run, and threshold. It does not explain any of these parameters or how fields/threshold control deduplication, leaving key invocation details undocumented.
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 states a specific verb and resource: merge duplicate groups into one row each and write a cleaned CSV. It is clear enough to distinguish from find_duplicates, which likely only locates duplicates, though it never explicitly names that sibling or states the contrast.
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 profile_csv, find_duplicates, or compare_records. The description implies a deduplication workflow but provides no conditions, exclusions, or alternative tool routing, leaving the agent to infer applicability.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
find_duplicatesFind duplicate groupsB
Group rows that look like the same person and explain why, without changing the file.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | ||
| limit | No | ||
| fields | No | ||
| threshold | No | 0-1; lower finds more, with more false positives |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It does disclose the key read-only behavior ('without changing the file') and hints at the reasoning output ('explain why'), but it omits other behaviors such as fuzzy matching sensitivity, threshold effect, or how the limit applies. This is a minimal disclosure, though not contradictory.
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?
The description is a single efficient sentence that front-loads the core purpose and key constraint. No redundant words or filler.
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?
With no output schema and four parameters, the description is incomplete. It does not describe the output format (beyond 'explain why'), nor does it clarify how to specify fields, the meaning of limit, or how threshold works beyond the schema's minimal note. An agent would need to infer too much.
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 only 25% (only 'threshold' has a description). The description adds no parameter-level detail, failing to explain 'file', 'limit', or the 'fields' object. Since the schema is sparse, the description should compensate but does not.
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 clearly states the tool groups rows that look like the same person and explains why, while explicitly noting it does not change the file. This distinguishes it from a modification tool like dedupe_csv, though it does not name sibling tools directly. The verb 'Group' is specific enough.
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 phrase 'without changing the file' implies this is for analysis rather than modification, but there is no explicit guidance on when to choose this over siblings like dedupe_csv or compare_records. The context is clear but exclusions and alternatives are not spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
profile_csvProfile a CSVA
Row count, columns, fill rate per column and the detected name/email/phone/company mapping.
| Name | Required | Description | Default |
|---|---|---|---|
| file | Yes | Path to the CSV file |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It implies a read-only analysis operation by listing computed metrics, but does not explicitly state that the file is not modified, nor does it disclose any limitations (e.g., encoding assumptions, large-file performance, or the heuristic nature of the mapping detection). This is adequate but not comprehensive.
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?
The description is a single, compact sentence that front-loads the core outputs and contains no filler. It conveys all essential information about what the tool returns in a highly efficient manner.
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?
Given there is no output schema, the description enumerates the return values (row count, columns, fill rate, mapping), which is sufficient for an agent to understand what to expect. The main omission is any mention of error scenarios or assumptions about the input file format, but these are secondary for a straightforward profiling tool.
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?
The schema covers the single `file` parameter with a description ('Path to the CSV file'), so schema coverage is 100%. The tool description does not add any additional meaning about the parameter beyond what the schema provides, 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?
The description states a specific action ('Profile a CSV') and enumerates the exact outputs: row count, columns, fill rate, and detected name/email/phone/company mapping. This clearly distinguishes it from siblings like dedupe_csv or compare_records, which focus on data cleaning or comparison rather than structural analysis.
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 gives no guidance on when to use this tool versus find_duplicates, dedupe_csv, or compare_records. It does not mention context, prerequisites, or situations where a sibling would be more appropriate, leaving the agent to infer usage from the tool name and description alone.
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.
4 tool updates
v1.0.0- First observed
compare_records - First observed
dedupe_csv - First observed
find_duplicates - First observed
profile_csv
TDQS
Scored across 4 tools
Each tool has a clearly distinct role: profiling the CSV, finding duplicate groups, performing the deduplication, and comparing individual pairs. No overlap in purpose or output.
All tool names follow a consistent verb_noun pattern in snake_case: profile_csv, find_duplicates, dedupe_csv, compare_records. The style is uniform and predictable.
Four tools is exactly right for a focused deduplication workflow. Each tool serves a distinct step in the process without unnecessary bloat or missing core functionality.
The workflow is complete: profile to understand data, identify duplicates, execute deduplication, and fine-tune via pair scoring. No obvious dead ends or required operations that agents cannot perform.
Maintenance
Related MCP Connectors
Dedupe, flatten and clean messy JSON rows (emails, phones, URLs, HTML) in one call, as JSON or CSV.
Fuzzy entity resolution and dedupe for names, addresses, and company records. $0.02/call via x402.
Query, join, profile, clean and convert CSV/JSON/Parquet with server-side DuckDB over MCP.
Find duplicate records in 30 seconds. Zero-config entity resolution, 97.2% F1 out of the box.
Related MCP Servers
- AlicenseBqualityDmaintenanceComprehensive CSV processing MCP server with 40+ operations for data manipulation, analysis, and validation. Features auto-save, undo/redo, and handles GB+ files3925MIT
- FlicenseNot gradedqualityBmaintenanceEnables reading, normalizing, validating, merging, and exporting data from Excel, CSV, JSON, and SQLite sources into a unified schema, with tools exposed via FastMCP.1-
- FlicenseNot gradedqualityBmaintenanceEnables MCP-compatible AI clients to validate healthcare claims data quality by running completeness, integrity, and temporal checks on CSV files via five callable tools, including profiling and full scans.-
- FlicenseNot gradedqualityBmaintenanceEnables compliance cleansing of marketing lists against the NCC opt-out registry, checking and optionally updating spreadsheets to filter out pre-emptive blocks.-