contact-check
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-checkValidate these phone numbers and emails"
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 Check
Agents fill forms, clean CRM exports and write shipping labels, and they check contact data by
eye: a UK number written without its country code, jane@gmial.com, a ZIP code with four digits,
a German address "missing" the state it does not need. Contact Check validates and normalises
contact data with the rules that production systems use:
Phone numbers with Google's libphonenumber data (offline): valid for their country or why not, the type (mobile, fixed line, toll free, VoIP...), E.164, international and national forms. North American numbers in the range reserved for fiction are noted.
Email addresses without sending anything: syntax, whether the domain accepts mail (MX records, a null MX that refuses all mail, or none at all), disposable providers, role accounts, and likely typos of the big providers (gmial.com, outlook.con).
Postal addresses against each country's rules from Google's address data (what Chrome and Android forms use): required fields, postcode pattern, states and provinces by code or name, and the address written as the country formats it.
Up to 100 phone numbers or emails, or 50 addresses, per call. No key needed.
Built and maintained by Arhan Canli.
Install
Needs Node.js 20 or newer. No account or key.
Claude Code
claude mcp add contact-check -- npx -y contact-check-mcpClaude Desktop: download contact-check-mcp-<version>.mcpb from the latest release and open it. The bundle is signed; verify it with gh attestation verify <file> --repo arhancanli/contact-check-mcp.
Any other client (Windsurf, Zed, Cline, Continue and others), in its MCP config file:
{
"mcpServers": {
"contact-check": {
"command": "npx",
"args": [
"-y",
"contact-check-mcp"
]
}
}
}Docker
docker build -t contact-check-mcp https://github.com/arhancanli/contact-check-mcp.git && docker run -i --rm contact-check-mcpHosted (Streamable HTTP): node src/server.mjs --http serves stateless MCP at POST /mcp (port from PORT, default 3000).
Related MCP server: USPS Address Validation and Standardization MCP Server
Example
An agent calls check_phones with:
{
"numbers": [
"+44 20 7946 0958",
"020 7946 0958",
"+1 202-555-0143",
"+971 50 123 4567",
"+1 800 555 0199",
"12345",
"+44 20 794"
],
"country": "GB"
}and gets back (recorded from the live server on 2026-09-26):
{
"valid": 5,
"results": [
{
"input": "+44 20 7946 0958",
"valid": true,
"e164": "+442079460958",
"international": "+44 20 7946 0958",
"national": "020 7946 0958",
"country": "GB",
"calling_code": "+44",
"type": "fixed_line"
},
{
"input": "020 7946 0958",
"valid": true,
"e164": "+442079460958",
"international": "+44 20 7946 0958",
"national": "020 7946 0958",
"country": "GB",
"calling_code": "+44",
"type": "fixed_line"
},
{
"input": "+1 202-555-0143",
"valid": true,
"e164": "+12025550143",
"international": "+1 202 555 0143",
"national": "(202) 555-0143",
"country": "US",
"calling_code": "+1",
"type": "fixed_line_or_mobile",
"note": "a number reserved for fiction (555-0100 to 555-0199)"
},
{
"input": "+971 50 123 4567",
"valid": true,
"e164": "+971501234567",
"international": "+971 50 123 4567",
"national": "050 123 4567",
"country": "AE",
"calling_code": "+971",
"type": "mobile"
},
{
"input": "+1 800 555 0199",
"valid": true,
"e164": "+18005550199",
"international": "+1 800 555 0199",
"national": "(800) 555-0199",
"country": "US",
"calling_code": "+1",
"type": "toll_free",
"note": "a number reserved for fiction (555-0100 to 555-0199)"
},
{
"input": "12345",
"valid": false,
"reason": "too short for its country",
"country": "GB"
... (8 more lines)Tools
Tool | What it does |
| Checks up to 50 postal addresses against each country's rules (Google's address data): required fields, postcode pattern, state or province, and writes each as the country formats it. Without street and city, returns the country's rules and regions. |
| Checks up to 100 email addresses without sending mail: syntax, whether the domain exists and accepts mail (MX), disposable providers, role accounts (info@, support@), and likely typos of big providers (gmial.com). Gives the reason when invalid. |
| Validates up to 100 phone numbers with Google's libphonenumber data: valid for their country or why not, type (mobile, fixed line, toll free, VoIP...), and E.164, international and national forms. country (ISO code) for numbers written without +. |
How it behaves
Read-only: no tool changes anything outside this process.
Network: HTTPS only, to the hosts listed in
package.jsonunderfactory.allowHosts, with a deadline, a size cap and bounded retries. Nothing else is contacted, and nothing is logged except unexpected failures (to stderr, without your inputs).Phone checks run offline. Email checks ask Cloudflare's DNS-over-HTTPS resolver about the domain only (the address itself is never sent anywhere, and no mail is sent). Address rules come from Google's address data service, one small file per country, cached for 30 minutes.
A valid email means the domain accepts mail; whether the mailbox exists cannot be known without sending, which this server never does.
Results are compact JSON with a matching output schema.
Benchmark
Measured 2026-09-26 with gpt-5.4-mini, 10 fixed tasks graded by fixed checks (bench/tasks.json, raw results in bench/results/).
Server | Correct | Input tokens | Output tokens | Tool calls | Median time |
This server | 10/10 | 10735 | 285 | 8 | 2.3 s |
mcp-server-fetch (no open contact-validation server exists; this is what agents use today) | 9/10 | 10584 | 310 | 7 | 2.0 s |
Performance
Measured 2026-09-26 from Dubai, home connection against the live upstream, Node 24.19.0 (bench/perf.json, scripts/perf.mjs in the factory).
Call | First call | Repeat | Result size |
check_phones: 7 numbers (UK, US, UAE, toll free, fictional, too short) | 5 ms | 0.5 ms | 1,216 chars |
check_emails: 9 addresses (typos, disposable, role, null MX, no domain) | 1090 ms | 0.6 ms | 1,730 chars |
check_addresses: 5 addresses (US, UK, bad state and ZIP, UAE, rules only) | 281 ms | 0.6 ms | 681 chars |
First call: a fresh server process, including the TLS connection and the upstream's own time. Repeat: the same call again, answered from the in-process cache, so it shows this server's own overhead.
Tool definitions the model reads on every turn (name, description, input schema): 1,920 characters, against 1,105 for mcp-server-fetch (no open contact-validation server exists; this is what agents use today). The full tool list, with the output schemas and annotations clients use to validate results, is 3,109 characters (1,104 for the alternative).
Data sources
libphonenumber-js (MIT), Google's libphonenumber metadata.
Google address data (Apache 2.0), as served for Chrome's autofill.
disposable-email-domains (CC0).
DNS over HTTPS from Cloudflare.
More MCP servers by Arhan Canli
Actions Check: Checks GitHub Actions workflows: outdated actions, old Node runtimes, retired runners, injection.
Citation Check: Verifies citations: finds fabricated or mismatched references and retractions, returns clean BibTeX.
Cron Check: Explains cron expressions, lists next run times in any time zone, converts between cron dialects.
Domain Health: Email and domain checks: SPF lookup limits, DKIM keys, DMARC, DNS records, registration expiry.
Drug Label: FDA drug label answers with section citations, RxNorm name resolution, recalls and shortages.
End of Life: Is this version still supported? EOL dates, latest patch and upgrade target for 470+ products.
Internet Standards: RFC sections, status, obsoleted-by chains, errata and IANA registries for coding agents.
License Check: Open source license answers: SPDX ids, copyleft, and whether a dependency's license fits yours.
The whole collection, 7 more
License
MIT, Copyright (c) 2026 Arhan Canli.
Available Tools
3 toolscheck_addressesValidate postal addressesARead-onlyIdempotent
Checks up to 50 postal addresses against each country's rules (Google's address data): required fields, postcode pattern, state or province, and writes each as the country formats it. Without street and city, returns the country's rules and regions.
| Name | Required | Description | Default |
|---|---|---|---|
| addresses | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover read-only, idempotent, and non-destructive behavior. The description adds valuable behavioral context: the source (Google's address data), the validation criteria, the formatting behavior, and the fallback action when street/city are absent. This goes beyond the annotations without contradicting them.
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 redundancy. The main function is front-loaded, and the conditional behavior is stated succinctly at the end. Every clause earns its place, keeping the description lean yet informative.
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 the complexity of an array of address objects and the existence of an output schema, the description covers the core purpose, key behavioral rules, and a conditional branch. Annotations cover safety and idempotency, so the agent has enough to decide invocation. Minor gaps like explicit error handling or output format details are complemented by the output schema.
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 0%, so the description must compensate. It mentions required fields, postcode pattern, state/province, and street/city, providing context for those properties. However, it does not explicitly explain all parameters (e.g., 'name', 'organization'), and some properties like 'region' and 'country' have schema descriptions while others don't. The description adds partial value but leaves field-level semantics incomplete.
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 it checks addresses against country rules, validating required fields, postcode pattern, and state/province, and formats them. It distinguishes from sibling tools (check_emails, check_phones) by explicitly targeting postal addresses. The verb 'checks' and resource 'addresses' make the purpose 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?
Usage is implied by the domain (address validation vs email/phone), but the description does not explicitly reference alternatives or exclusionary conditions. It does provide a conditional hint ('Without street and city, returns...'), which aids usage but stops short of naming when not to use this tool. No explicit differentiation from siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_emailsValidate email addressesARead-onlyIdempotent
Checks up to 100 email addresses without sending mail: syntax, whether the domain exists and accepts mail (MX), disposable providers, role accounts (info@, support@), and likely typos of big providers (gmial.com). Gives the reason when invalid.
| Name | Required | Description | Default |
|---|---|---|---|
| emails | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| valid | Yes | |
| results | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint false, so the safety profile is covered. The description adds meaningful behavioral context: it performs multiple checks, returns a reason when invalid, and is limited to 100 addresses. It does not contradict the annotations and provides value beyond them.
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, well-structured sentence that front-loads the core action and scope ('Checks up to 100 email addresses without sending mail') before enumerating specific checks. Every word adds value, and there is no redundancy or padding.
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 the tool has an output schema (which handles return values) and only one parameter with clear semantics, the description covers all necessary context for an agent to decide when to use it and what to expect. It mentions the validation types and the reason-on-invalid behavior, making it complete for this simple 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 has no description for the single 'emails' parameter (0% coverage), so the description carries the burden. It explains that the tool checks up to 100 addresses and what those checks are, which clarifies the expected input format (array of email strings) and behavior. This compensates well for the missing schema description.
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 uses a specific verb ('Checks') and resource ('email addresses'), and enumerates the exact validation dimensions: syntax, MX, disposable providers, role accounts, and typos. This clearly distinguishes it from sibling tools check_addresses and check_phones, making its purpose 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?
The description explicitly states it checks without sending mail, which signals it is a validation-only tool and not for deliverability testing. It doesn't name alternatives or exclusion criteria, but the sibling names make it clear when to use this over check_addresses/check_phones, so the context is adequate.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
check_phonesValidate phone numbersARead-onlyIdempotent
Validates up to 100 phone numbers with Google's libphonenumber data: valid for their country or why not, type (mobile, fixed line, toll free, VoIP...), and E.164, international and national forms. country (ISO code) for numbers written without +.
| Name | Required | Description | Default |
|---|---|---|---|
| country | No | default country, e.g. GB | |
| numbers | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| valid | Yes | |
| results | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already signal read-only/idempotent/safe; the description adds non-redundant details: batch limit, libphonenumber data, validity/type/form outputs, and the country fallback for numbers without '+'. It does not repeat annotation flags or contradict them.
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 dense sentences with no filler; the first sentence front-loads scope and capability. The second is a fragment but communicates country semantics efficiently. Slightly run-on structure prevents a 5.
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 validation tool with an output schema and annotations, the description covers input limits, optional country semantics, and result categories. It does not need to explain return values because an output schema exists; minor omissions such as exact error behavior keep it from a 5.
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 documents country as 'default country, e.g. GB' but the description enriches it with 'ISO code' and the key condition 'for numbers written without +'. The numbers array is left implicit but is self-evident from the description; more direct parameter-level detail for numbers would be ideal, yet coverage is adequate.
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 ('validates'), exact resource (phone numbers), a hard limit (up to 100) and data source (Google's libphonenumber). It also enumerates output dimensions, making it easy to distinguish from sibling check_addresses/check_emails.
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 or alternative routing is given; usage must be inferred from the tool name and resource type. The description does provide sufficient context that a phone-number validation request should be routed here, but it never states exclusions or how this differs from check_addresses/check_emails.
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.
3 tool updates
v0.1.0- First observed
check_addresses - First observed
check_emails - First observed
check_phones
TDQS
Scored across 3 tools
Each tool targets a completely distinct contact channel: addresses, emails, and phone numbers. There is no overlap in purpose or output, so an agent can reliably select the right tool based on the input type.
All three tool names follow the exact same check_<plural noun> pattern using snake_case. The naming is uniform and predictable, making the set easy to navigate.
Three tools is well-scoped for a contact-checking server. Each tool covers one major contact method without unnecessary bloat or redundancy.
The server covers the three core contact data types—address, email, and phone—with validation and formatting details. Minor gaps exist, such as lacking a batch/combined contact check or support for other contact identifiers, but the surface is coherent and practical for its stated purpose.
Maintenance
Related MCP Connectors
Verify addresses, email addresses, and phone numbers with confidence scores.
Address validation & geocoding for AI agents: 240+ countries, UK PAF, free US/CA enrichment
- SnipgetOAuthai.snipget
300+ deterministic data utilities for AI agents: validate, normalize, parse, match, redact.
Verify emails and domains for routing, disposable providers, role accounts, and SMTP risk.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceEnables AI-driven data quality operations such as validation, enrichment, and deduplication for customer data fields including email, address, phone, and LinkedIn profiles through natural language interactions.2MIT
- FlicenseAqualityDmaintenanceEnables AI assistants to validate and standardize US addresses using the official USPS Address Validation API with secure OAuth2 authentication.1-
- AlicenseNot gradedqualityBmaintenanceValidates phone numbers and provides country calling codes, enabling AI agents to look up international dialing codes and filter by country name, ISO code, or calling code.4 npmMIT
- FlicenseAqualityCmaintenanceEnables agents to verify postal addresses, email addresses, and phone numbers against Melissa's Global Verification APIs before acting on the data, including batch verification and a per-session call budget to prevent runaway costs.4-