domain-search-mcp 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +52 -0
- package/Dockerfile +15 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/SECURITY.md +252 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +117 -0
- package/dist/config.js.map +1 -0
- package/dist/fallbacks/index.d.ts +6 -0
- package/dist/fallbacks/index.d.ts.map +1 -0
- package/dist/fallbacks/index.js +14 -0
- package/dist/fallbacks/index.js.map +1 -0
- package/dist/fallbacks/rdap.d.ts +18 -0
- package/dist/fallbacks/rdap.d.ts.map +1 -0
- package/dist/fallbacks/rdap.js +339 -0
- package/dist/fallbacks/rdap.js.map +1 -0
- package/dist/fallbacks/whois.d.ts +27 -0
- package/dist/fallbacks/whois.d.ts.map +1 -0
- package/dist/fallbacks/whois.js +219 -0
- package/dist/fallbacks/whois.js.map +1 -0
- package/dist/registrars/base.d.ts +89 -0
- package/dist/registrars/base.d.ts.map +1 -0
- package/dist/registrars/base.js +203 -0
- package/dist/registrars/base.js.map +1 -0
- package/dist/registrars/index.d.ts +7 -0
- package/dist/registrars/index.d.ts.map +1 -0
- package/dist/registrars/index.js +15 -0
- package/dist/registrars/index.js.map +1 -0
- package/dist/registrars/namecheap.d.ts +69 -0
- package/dist/registrars/namecheap.d.ts.map +1 -0
- package/dist/registrars/namecheap.js +307 -0
- package/dist/registrars/namecheap.js.map +1 -0
- package/dist/registrars/porkbun.d.ts +63 -0
- package/dist/registrars/porkbun.d.ts.map +1 -0
- package/dist/registrars/porkbun.js +299 -0
- package/dist/registrars/porkbun.js.map +1 -0
- package/dist/server.d.ts +19 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +209 -0
- package/dist/server.js.map +1 -0
- package/dist/services/domain-search.d.ts +40 -0
- package/dist/services/domain-search.d.ts.map +1 -0
- package/dist/services/domain-search.js +438 -0
- package/dist/services/domain-search.js.map +1 -0
- package/dist/services/index.d.ts +5 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +11 -0
- package/dist/services/index.js.map +1 -0
- package/dist/tools/bulk_search.d.ts +72 -0
- package/dist/tools/bulk_search.d.ts.map +1 -0
- package/dist/tools/bulk_search.js +108 -0
- package/dist/tools/bulk_search.js.map +1 -0
- package/dist/tools/check_socials.d.ts +71 -0
- package/dist/tools/check_socials.d.ts.map +1 -0
- package/dist/tools/check_socials.js +357 -0
- package/dist/tools/check_socials.js.map +1 -0
- package/dist/tools/compare_registrars.d.ts +80 -0
- package/dist/tools/compare_registrars.d.ts.map +1 -0
- package/dist/tools/compare_registrars.js +116 -0
- package/dist/tools/compare_registrars.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +31 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/search_domain.d.ts +61 -0
- package/dist/tools/search_domain.d.ts.map +1 -0
- package/dist/tools/search_domain.js +81 -0
- package/dist/tools/search_domain.js.map +1 -0
- package/dist/tools/suggest_domains.d.ts +82 -0
- package/dist/tools/suggest_domains.d.ts.map +1 -0
- package/dist/tools/suggest_domains.js +227 -0
- package/dist/tools/suggest_domains.js.map +1 -0
- package/dist/tools/tld_info.d.ts +56 -0
- package/dist/tools/tld_info.d.ts.map +1 -0
- package/dist/tools/tld_info.js +273 -0
- package/dist/tools/tld_info.js.map +1 -0
- package/dist/types.d.ts +193 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/cache.d.ts +81 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +192 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/errors.d.ts +87 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +191 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +24 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +27 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +132 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/premium-analyzer.d.ts +33 -0
- package/dist/utils/premium-analyzer.d.ts.map +1 -0
- package/dist/utils/premium-analyzer.js +273 -0
- package/dist/utils/premium-analyzer.js.map +1 -0
- package/dist/utils/validators.d.ts +53 -0
- package/dist/utils/validators.d.ts.map +1 -0
- package/dist/utils/validators.js +159 -0
- package/dist/utils/validators.js.map +1 -0
- package/docs/marketing/devto-post.md +135 -0
- package/docs/marketing/hackernews.md +42 -0
- package/docs/marketing/producthunt.md +109 -0
- package/docs/marketing/reddit-post.md +59 -0
- package/docs/marketing/twitter-thread.md +105 -0
- package/examples/bulk-search-50-domains.ts +131 -0
- package/examples/cli-interactive.ts +280 -0
- package/examples/compare-registrars.ts +78 -0
- package/examples/search-single-domain.ts +54 -0
- package/examples/suggest-names.ts +110 -0
- package/glama.json +6 -0
- package/jest.config.js +35 -0
- package/package.json +62 -0
- package/smithery.yaml +36 -0
- package/src/config.ts +121 -0
- package/src/fallbacks/index.ts +6 -0
- package/src/fallbacks/rdap.ts +407 -0
- package/src/fallbacks/whois.ts +250 -0
- package/src/registrars/base.ts +264 -0
- package/src/registrars/index.ts +7 -0
- package/src/registrars/namecheap.ts +378 -0
- package/src/registrars/porkbun.ts +380 -0
- package/src/server.ts +276 -0
- package/src/services/domain-search.ts +567 -0
- package/src/services/index.ts +9 -0
- package/src/tools/bulk_search.ts +142 -0
- package/src/tools/check_socials.ts +467 -0
- package/src/tools/compare_registrars.ts +162 -0
- package/src/tools/index.ts +45 -0
- package/src/tools/search_domain.ts +93 -0
- package/src/tools/suggest_domains.ts +284 -0
- package/src/tools/tld_info.ts +294 -0
- package/src/types.ts +289 -0
- package/src/utils/cache.ts +238 -0
- package/src/utils/errors.ts +262 -0
- package/src/utils/index.ts +8 -0
- package/src/utils/logger.ts +162 -0
- package/src/utils/premium-analyzer.ts +303 -0
- package/src/utils/validators.ts +193 -0
- package/tests/premium-analyzer.test.ts +310 -0
- package/tests/unit/cache.test.ts +123 -0
- package/tests/unit/errors.test.ts +190 -0
- package/tests/unit/tld-info.test.ts +62 -0
- package/tests/unit/tools.test.ts +200 -0
- package/tests/unit/validators.test.ts +146 -0
- package/tsconfig.json +25 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Domain Name Validators.
|
|
4
|
+
*
|
|
5
|
+
* Validates domain names, TLDs, and other inputs.
|
|
6
|
+
* Provides user-friendly error messages.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.validateDomainName = validateDomainName;
|
|
10
|
+
exports.validateTld = validateTld;
|
|
11
|
+
exports.parseDomain = parseDomain;
|
|
12
|
+
exports.validateTlds = validateTlds;
|
|
13
|
+
exports.isFullDomain = isFullDomain;
|
|
14
|
+
exports.buildDomain = buildDomain;
|
|
15
|
+
exports.validateRegistrar = validateRegistrar;
|
|
16
|
+
const config_js_1 = require("../config.js");
|
|
17
|
+
const errors_js_1 = require("./errors.js");
|
|
18
|
+
/**
|
|
19
|
+
* Valid domain name pattern (without TLD).
|
|
20
|
+
* - 1-63 characters per label
|
|
21
|
+
* - Alphanumeric and hyphens
|
|
22
|
+
* - Cannot start or end with hyphen
|
|
23
|
+
* - Cannot have consecutive hyphens (except for IDN: xn--)
|
|
24
|
+
*/
|
|
25
|
+
const DOMAIN_LABEL_PATTERN = /^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/i;
|
|
26
|
+
/**
|
|
27
|
+
* Valid TLD pattern.
|
|
28
|
+
* - 2-63 characters
|
|
29
|
+
* - Alphanumeric only (no hyphens in TLD)
|
|
30
|
+
*/
|
|
31
|
+
const TLD_PATTERN = /^[a-z]{2,63}$/i;
|
|
32
|
+
/**
|
|
33
|
+
* Characters that are definitely not allowed in domains.
|
|
34
|
+
*/
|
|
35
|
+
const INVALID_CHARS = /[^a-z0-9.-]/i;
|
|
36
|
+
/**
|
|
37
|
+
* Validate and normalize a domain name (without TLD).
|
|
38
|
+
*
|
|
39
|
+
* @param name - The domain name to validate
|
|
40
|
+
* @returns Normalized domain name (lowercase)
|
|
41
|
+
* @throws InvalidDomainError if invalid
|
|
42
|
+
*/
|
|
43
|
+
function validateDomainName(name) {
|
|
44
|
+
// Trim and lowercase
|
|
45
|
+
const normalized = name.trim().toLowerCase();
|
|
46
|
+
// Check for empty
|
|
47
|
+
if (!normalized) {
|
|
48
|
+
throw new errors_js_1.InvalidDomainError(name, 'Domain name cannot be empty');
|
|
49
|
+
}
|
|
50
|
+
// Check length
|
|
51
|
+
if (normalized.length > 63) {
|
|
52
|
+
throw new errors_js_1.InvalidDomainError(name, `Domain name too long (${normalized.length} chars, max 63)`);
|
|
53
|
+
}
|
|
54
|
+
// Check for invalid characters
|
|
55
|
+
if (INVALID_CHARS.test(normalized)) {
|
|
56
|
+
const invalidChar = normalized.match(INVALID_CHARS)?.[0];
|
|
57
|
+
throw new errors_js_1.InvalidDomainError(name, `Contains invalid character: "${invalidChar}"`);
|
|
58
|
+
}
|
|
59
|
+
// Check pattern
|
|
60
|
+
if (!DOMAIN_LABEL_PATTERN.test(normalized)) {
|
|
61
|
+
if (normalized.startsWith('-')) {
|
|
62
|
+
throw new errors_js_1.InvalidDomainError(name, 'Cannot start with a hyphen');
|
|
63
|
+
}
|
|
64
|
+
if (normalized.endsWith('-')) {
|
|
65
|
+
throw new errors_js_1.InvalidDomainError(name, 'Cannot end with a hyphen');
|
|
66
|
+
}
|
|
67
|
+
throw new errors_js_1.InvalidDomainError(name, 'Invalid format. Use only letters, numbers, and hyphens.');
|
|
68
|
+
}
|
|
69
|
+
return normalized;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Validate a TLD.
|
|
73
|
+
*
|
|
74
|
+
* @param tld - The TLD to validate (with or without leading dot)
|
|
75
|
+
* @returns Normalized TLD (lowercase, no dot)
|
|
76
|
+
* @throws UnsupportedTldError if invalid or not allowed
|
|
77
|
+
*/
|
|
78
|
+
function validateTld(tld) {
|
|
79
|
+
// Remove leading dot if present
|
|
80
|
+
const normalized = tld.replace(/^\./, '').trim().toLowerCase();
|
|
81
|
+
// Check for empty
|
|
82
|
+
if (!normalized) {
|
|
83
|
+
throw new errors_js_1.UnsupportedTldError(tld, config_js_1.config.allowedTlds);
|
|
84
|
+
}
|
|
85
|
+
// Check pattern
|
|
86
|
+
if (!TLD_PATTERN.test(normalized)) {
|
|
87
|
+
throw new errors_js_1.UnsupportedTldError(normalized, config_js_1.config.allowedTlds);
|
|
88
|
+
}
|
|
89
|
+
// Check against deny list
|
|
90
|
+
if (config_js_1.config.denyTlds.includes(normalized)) {
|
|
91
|
+
throw new errors_js_1.UnsupportedTldError(normalized, config_js_1.config.allowedTlds);
|
|
92
|
+
}
|
|
93
|
+
// Check against allow list (if not empty)
|
|
94
|
+
if (config_js_1.config.allowedTlds.length > 0 &&
|
|
95
|
+
!config_js_1.config.allowedTlds.includes(normalized)) {
|
|
96
|
+
throw new errors_js_1.UnsupportedTldError(normalized, config_js_1.config.allowedTlds);
|
|
97
|
+
}
|
|
98
|
+
return normalized;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Parse a full domain name into name and TLD.
|
|
102
|
+
*
|
|
103
|
+
* @param fullDomain - Full domain like "example.com" or "sub.example.co.uk"
|
|
104
|
+
* @returns Object with name and tld
|
|
105
|
+
* @throws InvalidDomainError if parsing fails
|
|
106
|
+
*/
|
|
107
|
+
function parseDomain(fullDomain) {
|
|
108
|
+
const normalized = fullDomain.trim().toLowerCase();
|
|
109
|
+
// Find the last dot
|
|
110
|
+
const lastDot = normalized.lastIndexOf('.');
|
|
111
|
+
if (lastDot === -1) {
|
|
112
|
+
throw new errors_js_1.InvalidDomainError(fullDomain, 'No TLD found. Include the extension (e.g., "example.com")');
|
|
113
|
+
}
|
|
114
|
+
const name = normalized.slice(0, lastDot);
|
|
115
|
+
const tld = normalized.slice(lastDot + 1);
|
|
116
|
+
// Handle multi-part TLDs (e.g., co.uk) - for simplicity, we don't support these yet
|
|
117
|
+
// In a full implementation, you'd use the Public Suffix List
|
|
118
|
+
return {
|
|
119
|
+
name: validateDomainName(name),
|
|
120
|
+
tld: validateTld(tld),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Validate an array of TLDs.
|
|
125
|
+
*
|
|
126
|
+
* @param tlds - Array of TLDs to validate
|
|
127
|
+
* @returns Array of normalized TLDs
|
|
128
|
+
*/
|
|
129
|
+
function validateTlds(tlds) {
|
|
130
|
+
if (!tlds || tlds.length === 0) {
|
|
131
|
+
// Return default TLDs
|
|
132
|
+
return ['com', 'io', 'dev'];
|
|
133
|
+
}
|
|
134
|
+
return tlds.map(validateTld);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check if a string looks like a full domain (has a dot).
|
|
138
|
+
*/
|
|
139
|
+
function isFullDomain(input) {
|
|
140
|
+
return input.includes('.');
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Build a full domain from name and TLD.
|
|
144
|
+
*/
|
|
145
|
+
function buildDomain(name, tld) {
|
|
146
|
+
return `${validateDomainName(name)}.${validateTld(tld)}`;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Validate registrar name.
|
|
150
|
+
*/
|
|
151
|
+
function validateRegistrar(registrar) {
|
|
152
|
+
const normalized = registrar.trim().toLowerCase();
|
|
153
|
+
const validRegistrars = ['porkbun', 'namecheap', 'godaddy'];
|
|
154
|
+
if (!validRegistrars.includes(normalized)) {
|
|
155
|
+
throw new Error(`Invalid registrar: "${registrar}". Valid options: ${validRegistrars.join(', ')}`);
|
|
156
|
+
}
|
|
157
|
+
return normalized;
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: I Built an MCP Server to Check Domain Availability from Claude
|
|
3
|
+
published: true
|
|
4
|
+
description: How I stopped context-switching between AI and domain registrars
|
|
5
|
+
tags: ai, typescript, opensource, webdev
|
|
6
|
+
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/placeholder.png
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# I Built an MCP Server to Check Domain Availability from Claude
|
|
10
|
+
|
|
11
|
+
Last week, I was brainstorming names for a new side project with Claude. Every time I came up with a name, I had to:
|
|
12
|
+
|
|
13
|
+
1. Leave Claude
|
|
14
|
+
2. Open Namecheap/Porkbun
|
|
15
|
+
3. Search the domain
|
|
16
|
+
4. Go back to Claude
|
|
17
|
+
5. Report the result
|
|
18
|
+
6. Repeat 50 times
|
|
19
|
+
|
|
20
|
+
This was frustrating. So I built a solution.
|
|
21
|
+
|
|
22
|
+
## Introducing Domain Search MCP
|
|
23
|
+
|
|
24
|
+
[Domain Search MCP](https://github.com/dorukardahan/domain-search-mcp) is an open-source MCP server that gives Claude the ability to check domain availability in real-time.
|
|
25
|
+
|
|
26
|
+
Now my workflow is:
|
|
27
|
+
|
|
28
|
+
> **Me:** "Is vibecoding.com available?"
|
|
29
|
+
> **Claude:** "โ
vibecoding.com is available at $9.73/year on Porkbun (includes free WHOIS privacy)"
|
|
30
|
+
|
|
31
|
+
## What is MCP?
|
|
32
|
+
|
|
33
|
+
[Model Context Protocol (MCP)](https://modelcontextprotocol.io) is Anthropic's open standard for connecting AI assistants to external tools and data sources. Think of it as USB-C for AI โ a universal way to plug in capabilities.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
### 1. Multi-Source Search
|
|
38
|
+
Checks domain availability across:
|
|
39
|
+
- **Porkbun** (with pricing)
|
|
40
|
+
- **Namecheap** (with pricing)
|
|
41
|
+
- **RDAP** (free, 50+ TLDs)
|
|
42
|
+
- **WHOIS** (fallback)
|
|
43
|
+
|
|
44
|
+
### 2. Sherlock-Style Social Check
|
|
45
|
+
```
|
|
46
|
+
check_socials("vibecoding")
|
|
47
|
+
```
|
|
48
|
+
Returns availability across 10 platforms:
|
|
49
|
+
- HIGH confidence: GitHub, npm, PyPI, Reddit
|
|
50
|
+
- MEDIUM confidence: Twitter, YouTube, ProductHunt
|
|
51
|
+
- LOW confidence: Instagram, LinkedIn, TikTok
|
|
52
|
+
|
|
53
|
+
### 3. Premium Domain Analysis
|
|
54
|
+
When a domain is premium, you get insights:
|
|
55
|
+
```
|
|
56
|
+
๐ ai.io is priced at $5000 (125x standard .io pricing)
|
|
57
|
+
Why premium: Two-character domain, Popular keyword "ai", High-demand .io extension
|
|
58
|
+
๐ก Try: getai.io, aihq.io, ai.dev
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### 4. Expiration Tracking
|
|
62
|
+
For taken domains, see when they expire:
|
|
63
|
+
```
|
|
64
|
+
๐ coolstartup.com expires in 23 days โ watch for availability
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Add to Claude Desktop
|
|
71
|
+
npx @anthropic/claude-code mcp add domain-search-mcp
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Or manually add to `claude_desktop_config.json`:
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"mcpServers": {
|
|
79
|
+
"domain-search": {
|
|
80
|
+
"command": "npx",
|
|
81
|
+
"args": ["-y", "domain-search-mcp"]
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Zero Config Mode
|
|
88
|
+
|
|
89
|
+
Works out of the box using public RDAP/WHOIS. Add registrar API keys for pricing:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
PORKBUN_API_KEY=pk1_xxx
|
|
93
|
+
PORKBUN_API_SECRET=sk1_xxx
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## Technical Highlights
|
|
97
|
+
|
|
98
|
+
- **TypeScript** with strict types
|
|
99
|
+
- **Zod validation** for all API responses
|
|
100
|
+
- **98 tests** passing
|
|
101
|
+
- **LRU cache** with TTL
|
|
102
|
+
- **Rate limiting** per registrar
|
|
103
|
+
- **Security audited** (see SECURITY.md)
|
|
104
|
+
|
|
105
|
+
## Architecture
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
109
|
+
โ MCP Protocol Layer โ
|
|
110
|
+
โ (Zod schema validation) โ
|
|
111
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
112
|
+
โ 6 Tools โ
|
|
113
|
+
โ search_domain, bulk_search, compare, โ
|
|
114
|
+
โ suggest, tld_info, check_socials โ
|
|
115
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
|
|
116
|
+
โ Registrar Adapters โ
|
|
117
|
+
โ Porkbun โ Namecheap โ RDAP โ WHOIS โ
|
|
118
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## What's Next?
|
|
122
|
+
|
|
123
|
+
I'm considering adding:
|
|
124
|
+
- DNS record checking
|
|
125
|
+
- SSL certificate info
|
|
126
|
+
- Trademark search integration
|
|
127
|
+
|
|
128
|
+
What features would you find useful? Drop a comment!
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
**GitHub:** https://github.com/dorukardahan/domain-search-mcp
|
|
133
|
+
**License:** MIT
|
|
134
|
+
|
|
135
|
+
If this helped you, consider giving it a โญ on GitHub!
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Hacker News - Show HN Post
|
|
2
|
+
|
|
3
|
+
## Title (80 char max):
|
|
4
|
+
```
|
|
5
|
+
Show HN: Domain Search MCP โ AI-powered domain availability checker for Claude
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
## URL:
|
|
9
|
+
```
|
|
10
|
+
https://github.com/dorukardahan/domain-search-mcp
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Text (optional, for self-posts):
|
|
14
|
+
```
|
|
15
|
+
I built an MCP (Model Context Protocol) server that lets Claude check domain availability in real-time.
|
|
16
|
+
|
|
17
|
+
Why? I was tired of context-switching between Claude and domain registrars while brainstorming project names. Now I just ask Claude "Is vibecoding.com available?" and it checks Porkbun, Namecheap, RDAP, and WHOIS in seconds.
|
|
18
|
+
|
|
19
|
+
Features:
|
|
20
|
+
- Check availability + pricing across multiple TLDs
|
|
21
|
+
- Compare prices between registrars
|
|
22
|
+
- Sherlock-style social handle checking (10 platforms)
|
|
23
|
+
- Premium domain detection with "why it's premium" insights
|
|
24
|
+
- Domain expiration tracking for taken domains
|
|
25
|
+
|
|
26
|
+
Works with zero config (uses public RDAP/WHOIS), or add registrar API keys for pricing.
|
|
27
|
+
|
|
28
|
+
Built with TypeScript, 98 tests, security audited. Open source, MIT license.
|
|
29
|
+
|
|
30
|
+
Would love feedback on the architecture or feature requests!
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Posting Tips:
|
|
36
|
+
- Post between 6-9 AM PT (best visibility)
|
|
37
|
+
- Monday-Thursday performs best
|
|
38
|
+
- Don't post on weekends
|
|
39
|
+
- Respond to comments quickly
|
|
40
|
+
|
|
41
|
+
## Suggested posting time:
|
|
42
|
+
- 6:00 AM PT = 4:00 PM Istanbul time
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Product Hunt Launch Preparation
|
|
2
|
+
|
|
3
|
+
## Basic Info
|
|
4
|
+
|
|
5
|
+
**Name:** Domain Search MCP
|
|
6
|
+
|
|
7
|
+
**Tagline (60 chars max):**
|
|
8
|
+
```
|
|
9
|
+
Check domain availability directly from Claude AI
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
**Description:**
|
|
13
|
+
```
|
|
14
|
+
Domain Search MCP is an open-source tool that gives Claude AI the ability to check domain availability in real-time.
|
|
15
|
+
|
|
16
|
+
Stop context-switching between your AI assistant and domain registrars. Just ask Claude "Is mybrand.com available?" and get instant results with pricing from multiple sources.
|
|
17
|
+
|
|
18
|
+
๐ What it does:
|
|
19
|
+
โข Check domain availability across Porkbun, Namecheap, RDAP, WHOIS
|
|
20
|
+
โข Compare prices between registrars instantly
|
|
21
|
+
โข Check social handle availability (GitHub, Twitter, npm, etc.)
|
|
22
|
+
โข Understand why premium domains are expensive
|
|
23
|
+
โข Track when taken domains will expire
|
|
24
|
+
|
|
25
|
+
โก Key features:
|
|
26
|
+
โข Works with zero configuration (uses public RDAP/WHOIS)
|
|
27
|
+
โข Add registrar API keys for real-time pricing
|
|
28
|
+
โข 50+ TLD support including .com, .io, .dev, .ai, and more
|
|
29
|
+
โข Sherlock-style social media username checking
|
|
30
|
+
โข Security audited, 98 tests passing
|
|
31
|
+
|
|
32
|
+
๐ Built with:
|
|
33
|
+
โข TypeScript + Zod validation
|
|
34
|
+
โข Model Context Protocol (MCP) by Anthropic
|
|
35
|
+
โข MIT License, fully open source
|
|
36
|
+
|
|
37
|
+
Perfect for:
|
|
38
|
+
โข Developers brainstorming project names
|
|
39
|
+
โข Startup founders checking brand availability
|
|
40
|
+
โข Anyone who uses Claude for ideation
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Topics/Categories:
|
|
46
|
+
- Developer Tools
|
|
47
|
+
- Artificial Intelligence
|
|
48
|
+
- Open Source
|
|
49
|
+
- Productivity
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## First Comment (Maker's Comment):
|
|
54
|
+
```
|
|
55
|
+
Hey Product Hunt! ๐
|
|
56
|
+
|
|
57
|
+
I'm the maker of Domain Search MCP.
|
|
58
|
+
|
|
59
|
+
The problem: I use Claude constantly for brainstorming. Every time I come up with a project name, I have to leave Claude, open a domain registrar, check if it's available, and then go back to report the result. This breaks my flow.
|
|
60
|
+
|
|
61
|
+
The solution: An MCP server that lets Claude check domains directly. Now I just ask "Is coolname.com available?" and Claude tells me instantly โ with pricing from multiple registrars.
|
|
62
|
+
|
|
63
|
+
This is open source (MIT license) and works with Claude Desktop. Would love your feedback!
|
|
64
|
+
|
|
65
|
+
Try it: npx @anthropic/claude-code mcp add domain-search-mcp
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Launch Checklist:
|
|
71
|
+
|
|
72
|
+
### Before Launch:
|
|
73
|
+
- [ ] Create Product Hunt account
|
|
74
|
+
- [ ] Verify email
|
|
75
|
+
- [ ] Complete profile with photo
|
|
76
|
+
- [ ] Have 5+ followers on PH
|
|
77
|
+
- [ ] Prepare 4-6 images/screenshots
|
|
78
|
+
- [ ] Write description
|
|
79
|
+
- [ ] Schedule for Monday 12:01 AM PT
|
|
80
|
+
|
|
81
|
+
### Launch Day (Monday):
|
|
82
|
+
- [ ] Post at 12:01 AM PT (10:01 AM Istanbul)
|
|
83
|
+
- [ ] Share on Twitter immediately
|
|
84
|
+
- [ ] Share on LinkedIn
|
|
85
|
+
- [ ] Reply to every comment within 1 hour
|
|
86
|
+
- [ ] Ask friends to upvote + comment (authentic)
|
|
87
|
+
|
|
88
|
+
### Images Needed:
|
|
89
|
+
1. Logo/Icon (240x240)
|
|
90
|
+
2. Gallery image 1: Hero screenshot
|
|
91
|
+
3. Gallery image 2: Example conversation
|
|
92
|
+
4. Gallery image 3: Feature overview
|
|
93
|
+
5. Gallery image 4: Social check feature
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Screenshot Ideas:
|
|
98
|
+
|
|
99
|
+
### Screenshot 1 - Hero:
|
|
100
|
+
Claude conversation showing domain search in action
|
|
101
|
+
|
|
102
|
+
### Screenshot 2 - Multi-TLD:
|
|
103
|
+
Checking .com, .io, .dev at once
|
|
104
|
+
|
|
105
|
+
### Screenshot 3 - Social Check:
|
|
106
|
+
Showing the 10-platform social handle check
|
|
107
|
+
|
|
108
|
+
### Screenshot 4 - Premium Analysis:
|
|
109
|
+
Premium domain with "why it's expensive" insight
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Reddit Post - r/ClaudeAI
|
|
2
|
+
|
|
3
|
+
## Title:
|
|
4
|
+
```
|
|
5
|
+
I built an MCP server that lets Claude check domain availability in real-time
|
|
6
|
+
```
|
|
7
|
+
|
|
8
|
+
## Body:
|
|
9
|
+
```
|
|
10
|
+
Hey everyone!
|
|
11
|
+
|
|
12
|
+
I got frustrated with constantly leaving Claude to check if domains were available while brainstorming project names. So I built an MCP server to solve this.
|
|
13
|
+
|
|
14
|
+
**What it does:**
|
|
15
|
+
|
|
16
|
+
- Check domain availability + pricing across Porkbun, Namecheap, RDAP, WHOIS
|
|
17
|
+
- Compare prices between registrars
|
|
18
|
+
- Check social handle availability (GitHub, Twitter, npm, etc.)
|
|
19
|
+
- Tell you WHY premium domains are expensive
|
|
20
|
+
- Show when taken domains expire
|
|
21
|
+
|
|
22
|
+
**Example conversation:**
|
|
23
|
+
|
|
24
|
+
> Me: "Is vibecoding.com available?"
|
|
25
|
+
>
|
|
26
|
+
> Claude: "โ
vibecoding.com is available!
|
|
27
|
+
> - Porkbun: $9.73/year (includes free WHOIS privacy)
|
|
28
|
+
> - .io also available at $39.99/year
|
|
29
|
+
> - .dev available at $12.00/year
|
|
30
|
+
>
|
|
31
|
+
> ๐ก .com is the classic, universal choice โ trusted worldwide"
|
|
32
|
+
|
|
33
|
+
**Install:**
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx @anthropic/claude-code mcp add domain-search-mcp
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Links:**
|
|
40
|
+
- GitHub: https://github.com/dorukardahan/domain-search-mcp
|
|
41
|
+
- MIT License, open source
|
|
42
|
+
- 98 tests, TypeScript, security audited
|
|
43
|
+
|
|
44
|
+
Would love to hear your feedback or feature requests!
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Subreddit options:
|
|
50
|
+
1. r/ClaudeAI (primary)
|
|
51
|
+
2. r/LocalLLaMA (if they allow MCP posts)
|
|
52
|
+
3. r/MachineLearning (Saturday thread)
|
|
53
|
+
4. r/SideProject
|
|
54
|
+
|
|
55
|
+
## Tips:
|
|
56
|
+
- Post during US working hours (9 AM - 5 PM EST)
|
|
57
|
+
- Respond to every comment
|
|
58
|
+
- Don't be too promotional
|
|
59
|
+
- Ask for feedback genuinely
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Twitter Thread
|
|
2
|
+
|
|
3
|
+
## Thread (copy each tweet separately):
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
**Tweet 1 (Hook):**
|
|
8
|
+
```
|
|
9
|
+
I got tired of leaving Claude every time I needed to check if a domain was available.
|
|
10
|
+
|
|
11
|
+
So I built an MCP server that does it for me.
|
|
12
|
+
|
|
13
|
+
Now I just ask: "Is vibecoding.com available?"
|
|
14
|
+
|
|
15
|
+
๐งต Here's what I built (open source):
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
**Tweet 2:**
|
|
21
|
+
```
|
|
22
|
+
Domain Search MCP connects Claude to:
|
|
23
|
+
|
|
24
|
+
โข Porkbun (with pricing)
|
|
25
|
+
โข Namecheap (with pricing)
|
|
26
|
+
โข RDAP (50+ TLDs)
|
|
27
|
+
โข WHOIS (fallback)
|
|
28
|
+
|
|
29
|
+
One question โ multiple sources checked in seconds.
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
**Tweet 3:**
|
|
35
|
+
```
|
|
36
|
+
But domains aren't enough.
|
|
37
|
+
|
|
38
|
+
I added Sherlock-style social handle checking.
|
|
39
|
+
|
|
40
|
+
One command checks 10 platforms:
|
|
41
|
+
โ
GitHub, npm, PyPI, Reddit (high confidence)
|
|
42
|
+
โ ๏ธ Twitter, YouTube, ProductHunt (medium)
|
|
43
|
+
๐ Instagram, LinkedIn, TikTok (verify manually)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
**Tweet 4:**
|
|
49
|
+
```
|
|
50
|
+
Premium domains now tell you WHY they're expensive:
|
|
51
|
+
|
|
52
|
+
๐ "ai.io is $5000 (125x standard pricing)"
|
|
53
|
+
|
|
54
|
+
"Why premium: Two-character domain, Popular keyword, High-demand TLD"
|
|
55
|
+
|
|
56
|
+
"Try instead: getai.io, aihq.io, ai.dev"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
**Tweet 5:**
|
|
62
|
+
```
|
|
63
|
+
For taken domains, it shows expiration dates:
|
|
64
|
+
|
|
65
|
+
๐ "coolstartup.com expires in 23 days"
|
|
66
|
+
|
|
67
|
+
Useful if you're watching a domain.
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
**Tweet 6:**
|
|
73
|
+
```
|
|
74
|
+
Technical details for the nerds:
|
|
75
|
+
|
|
76
|
+
โข TypeScript + Zod validation
|
|
77
|
+
โข 98 tests passing
|
|
78
|
+
โข LRU cache with TTL
|
|
79
|
+
โข Rate limiting per registrar
|
|
80
|
+
โข Security audited
|
|
81
|
+
|
|
82
|
+
MIT license, contributions welcome.
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
**Tweet 7 (CTA):**
|
|
88
|
+
```
|
|
89
|
+
Try it now:
|
|
90
|
+
|
|
91
|
+
npx @anthropic/claude-code mcp add domain-search-mcp
|
|
92
|
+
|
|
93
|
+
Or check GitHub for manual setup:
|
|
94
|
+
github.com/dorukardahan/domain-search-mcp
|
|
95
|
+
|
|
96
|
+
@AnthropicAI @ClaudeAI #MCP #AI #OpenSource
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Posting tips:
|
|
102
|
+
- Post between 9-11 AM or 1-3 PM (your local time)
|
|
103
|
+
- Use the thread feature (reply to yourself)
|
|
104
|
+
- Add a relevant image/GIF to Tweet 1
|
|
105
|
+
- Pin the thread after posting
|