MCP Server
The IQX Lookup MCP Server lets AI assistants (Claude, Cursor, Windsurf, Codex, etc.) call all 12 validation tools natively via the Model Context Protocol. One npx command — no build step, no HTTP client code, no JSON parsing.
Why MCP?
Traditional API integration requires HTTP client setup, authentication headers, JSON serialization, and error handling. With MCP, the AI assistant calls validation tools the same way it reads files or searches the web — natively. You describe what you need in natural language, and the assistant handles the rest.
Setup
Prerequisites
- Node.js 18+
- An API key from the dashboard
OpenCode
See here.
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"iqx-lookup": {
"type": "local",
"command": ["npx", "-y", "@neivi/iqx-lookup-mcp-server"],
"enabled": true,
"environment": {
"LOOKUP_API_KEY": "YOUR_API_KEY",
},
},
},
}
Claude Desktop / Claude Code
Add to your MCP configuration (claude_desktop_config.json or .claude.json):
{
"mcpServers": {
"iqx-lookup": {
"command": "npx",
"args": ["-y", "@neivi/iqx-lookup-mcp-server@latest"],
"env": {
"LOOKUP_API_KEY": "YOUR_API_KEY"
}
}
}
}
Cursor / Windsurf
Use the same configuration block in your editor's MCP settings file (.cursor/mcp.json or equivalent).
Codex
Codex uses config.toml for MCP server configuration, not a JSON mcpServers block. You can configure MCP servers globally in ~/.codex/config.toml or per project in .codex/config.toml (trusted projects only). The Codex CLI and IDE extension share the same configuration. See the official docs.
[mcp_servers.iqx_lookup]
command = "npx"
args = ["-y", "@neivi/iqx-lookup-mcp-server@latest"]
[mcp_servers.iqx_lookup.env]
LOOKUP_API_KEY = "YOUR_API_KEY"
Or add it from the CLI:
codex mcp add iqx_lookup --env LOOKUP_API_KEY=YOUR_API_KEY -- npx -y @neivi/iqx-lookup-mcp-server@latest
Verify it works
After configuration, ask your assistant:
"Validate the email test@example.com"
You should see a tool call to validate_email with the validation result.
Self-hosted / On-premises
By default, the MCP server connects to https://api.iqxlookup.neivi.es. To point it at a self-hosted IQX Lookup instance, set the LOOKUP_BASE_URL environment variable:
{
"mcpServers": {
"iqx-lookup": {
"command": "npx",
"args": ["-y", "@neivi/iqx-lookup-mcp-server@latest"],
"env": {
"LOOKUP_API_KEY": "YOUR_API_KEY",
"LOOKUP_BASE_URL": "http://localhost:8081"
}
}
}
}
For Codex, add LOOKUP_BASE_URL to the environment block:
[mcp_servers.iqx_lookup]
command = "npx"
args = ["-y", "@neivi/iqx-lookup-mcp-server@latest"]
[mcp_servers.iqx_lookup.env]
LOOKUP_API_KEY = "YOUR_API_KEY"
LOOKUP_BASE_URL = "http://localhost:8081"
Your data never leaves your network when using a local instance.
Available Tools
validate_email
Validates an email address — syntax, DNS MX/A records, disposable provider detection, role address detection, and free email provider identification.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
address | string | Yes | Email address to validate (e.g., user@company.com) |
Example response:
{
"email": "admin@gmail.com",
"user": "admin",
"domain": "gmail.com",
"validFormat": true,
"mxRecord": true,
"aRecord": true,
"roleAddress": true,
"disposableEmail": false,
"freeEmailProvider": true
}
validate_phone
Validates and parses a phone number — carrier, line type (mobile/landline/VoIP), E.164 format, location, and timezone.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
number | string | Yes | Phone number in E.164 (+34612345678) or local format (612345678) |
countryCode | string | No | ISO 3166-1 alpha-2 code (e.g., US, ES). Required for local numbers. |
Example response:
{
"number": "+34612345678",
"valid": true,
"validE164": true,
"e164Format": "+34612345678",
"internationalFormat": "+34 612 34 56 78",
"nationalFormat": "612 34 56 78",
"countryCode": "ES",
"countryName": "Spain",
"eu": true,
"carrier": "Movistar",
"phoneType": "mobile",
"location": "Spain",
"timezones": ["Europe/Madrid"]
}
geolocate_ip
Geolocates an IP address — country, city, coordinates, ASN, timezone, and EU membership status.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ip | string | Yes | IPv4 or IPv6 address (e.g., 8.8.8.8 or 2001:4860:4860::8888) |
Example response:
{
"ip": "8.8.8.8",
"ipType": "IPV4",
"countryCode": "US",
"countryName": "United States",
"regionName": "California",
"regionCode": "CA",
"cityName": "Mountain View",
"continentCode": "NA",
"continentName": "North America",
"lat": 37.386,
"lng": -122.0838,
"zipCode": "94035",
"timezone": "America/Los_Angeles",
"isEU": false,
"asn": 15169,
"asnOrganization": "Google LLC"
}
geolocate_my_ip
Geolocates the server's own public IP address. Returns the same fields as geolocate_ip. No parameters required.
validate_vat
Validates a European VAT number against the EU VIES service. Returns company name and address when available.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
countryCode | string | Yes | Two-letter EU country code (e.g., DE, FR, ES) |
number | string | Yes | VAT number without country prefix (e.g., for ESB87387775 pass B87387775) |
Example response:
{
"valid": true,
"countryCode": "ES",
"vatNumber": "B87387775",
"name": "NEIVI IT SOCIEDAD LIMITADA",
"address": "CL EXAMPLE 1\n28001 MADRID"
}
parse_useragent
Parses a User-Agent string — browser, OS, device type, brand/model, and bot detection.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
ua | string | Yes | Raw User-Agent header string |
Example response:
{
"userAgentString": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...",
"browserFamily": "Chrome",
"browserMajor": "125",
"browserMinor": "0",
"browserPatch": "0",
"osFamily": "Mac OS X",
"osMajor": "14",
"osMinor": "5",
"osPatch": "0",
"deviceFamily": "Mac",
"deviceBrand": "Apple",
"deviceModel": "Mac"
}
validate_iban
Validates an IBAN — structure (length per country), MOD 97-10 checksum, and bank/branch identifiers.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
iban | string | Yes | IBAN with or without spaces (e.g., DE89 3704 0044 0532 0130 00) |
Example response:
{
"iban": "DE89370400440532013000",
"valid": true,
"countryCode": "DE",
"bankCode": "37040044",
"branchCode": "",
"checkDigit": "89",
"accountNumber": "0532013000",
"bic": "COBADEFFXXX",
"bicValid": true
}
validate_bic
Validates a BIC/SWIFT code — format, country, location, and branch info.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
bic | string | Yes | BIC/SWIFT code, 8 or 11 characters (e.g., COBADEFFXXX) |
Example response:
{
"bic": "COBADEFFXXX",
"valid": true,
"bankCode": "COBA",
"countryCode": "DE",
"locationCode": "FF",
"branchCode": "XXX"
}
lookup_dns
Looks up DNS records for a domain. Also performs email security analysis: SPF, DKIM, and DMARC.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | Domain name (e.g., example.com, without protocol) |
types | string | No | Comma-separated record types: A, AAAA, MX, TXT, CNAME, NS, SOA. Omit for all. |
Example response:
{
"domain": "example.com",
"records": [
{ "type": "A", "name": "example.com", "value": "93.184.216.34", "ttl": 3600, "priority": null },
{ "type": "MX", "name": "example.com", "value": "mail.example.com", "ttl": 3600, "priority": 10 }
],
"queryTimeMs": 45,
"security": {
"spf": { "present": true, "rawRecord": "v=spf1 -all", "qualifier": "-all", "mechanisms": [] },
"dkimFound": false,
"dmarc": { "present": true, "rawRecord": "v=DMARC1; p=reject; rua=mailto:dmarc@example.com", "policy": "reject", "subdomainPolicy": "", "reportingEmail": "dmarc@example.com" }
}
}
check_password_strength
Analyzes password strength (zxcvbn) and checks against known breaches via Have I Been Pwned using k-anonymity — the full password is never sent over the network, logged, or stored.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
password | string | Yes | Password to analyze (never logged or stored) |
Example response:
{
"score": 3,
"crackTimeDisplay": "centuries",
"crackTimeSeconds": 3.15e+15,
"guesses": 1.0e+13,
"warning": "",
"suggestions": ["Add another word or two. Uncommon words are better."],
"breached": false,
"breachCount": 0
}
check_ssl_certificate
Inspects the SSL/TLS certificate for a domain — certificate chain, validity dates, SANs, protocol, cipher suite, and assigns a grade (A+ to F).
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
domain | string | Yes | Domain name (e.g., github.com). Do not include https://. |
Example response:
{
"domain": "example.com",
"valid": true,
"issuer": "CN=R3, O=Let's Encrypt, C=US",
"subject": "CN=example.com",
"serialNumber": "04:AB:CD:...",
"validFrom": "2025-01-01T00:00:00Z",
"validTo": "2025-04-01T00:00:00Z",
"daysUntilExpiry": 78,
"signatureAlgorithm": "SHA256withRSA",
"subjectAlternativeNames": ["example.com", "www.example.com"],
"protocol": "TLSv1.3",
"cipherSuite": "TLS_AES_256_GCM_SHA384",
"chainLength": 3,
"errorMessage": null,
"grade": "A+",
"warnings": []
}
validate_credit_card
Validates a credit card number — Luhn algorithm, card network identification, BIN lookup. Structural validation only — does not process payments. The full card number is never returned in the response.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
cardNumber | string | Yes | Card number with optional spaces/dashes (e.g., 4111 1111 1111 1111) |
Example response:
{
"valid": true,
"luhnValid": true,
"cardBrand": "Visa",
"lastFourDigits": "1111",
"cardType": "CREDIT",
"issuingBank": "Example Bank",
"cardCountry": "US",
"cardCategory": null
}
Multi-tool Workflow Examples
AI assistants can chain multiple tools in a single conversation. Here are common workflows:
Lead Qualification
"Validate these emails and tell me which are real: sales@acme.com, info@temp-mail.org, john@bigcorp.io"
The assistant calls validate_email three times, then summarizes: which are valid, which are disposable, which are role addresses.
Domain Security Audit
"Run a security check on example.com — SSL certificate and DNS email security"
The assistant calls check_ssl_certificate + lookup_dns, then synthesizes a report covering certificate grade, expiry, SPF/DKIM/DMARC policies.
KYC Verification
"Verify this company: VAT ES-B87387775, IBAN ES91 2100 0418 4502 0005 1332, phone +34 912 345 678"
The assistant calls validate_vat + validate_iban + validate_phone, cross-references the country codes, and reports consistency.
Password Policy Evaluation
"Test these passwords against our policy: Welcome1, Tr0ub4dor&3, correct-horse-battery-staple"
The assistant calls check_password_strength three times, compares scores, breach status, and crack times, then recommends which meet your requirements.
Best Practices
- Batch related validations together — describe all the data you want validated in a single message. The assistant will call multiple tools efficiently.
- VAT numbers — always strip the country prefix before calling. Pass
ESascountryCodeandB87387775asnumber, notESB87387775. - DNS comprehensive view — use
types=A,MX,TXTfor a focused lookup, or omittypesto get all record types. - Rate limits — every tool response includes remaining rate limit info. The AI can self-pace when approaching limits.
- Privacy — passwords and credit card numbers are never logged or stored. Password breach checks use k-anonymity (only a hash prefix is sent to HIBP). Credit card responses never include the full number.
Error Handling
When a tool call fails, the MCP server returns a structured error. Common error codes:
| Code | Error | Meaning |
|---|---|---|
401 | UNAUTHORIZED | Missing or invalid API key |
429 | RATE_LIMIT_EXCEEDED | Too many requests per minute |
429 | QUOTA_EXCEEDED | Monthly request quota exhausted |
503 | UPSTREAM_UNAVAILABLE | External service (VIES, HIBP, etc.) temporarily down |
Example error response:
{
"error": "Rate limit exceeded",
"retryAfter": 42,
"status": 429
}
The AI assistant will typically wait and retry automatically, or inform you that the rate limit has been reached.