This document provides detailed architectural diagrams for the Domain Search MCP server.
- High-Level Overview
- Transport Layer
- HTTP Transport Details
- Tool Execution Flow
- Data Source Waterfall
- VPS Deployment
- AI Suggestion Flow
- MCP Session Lifecycle
- Directory Structure
flowchart TB
subgraph Clients["MCP Clients"]
subgraph STDIO["stdio Transport"]
CD[Claude Desktop]
CU[Cursor]
VS[VS Code]
PX[Perplexity]
end
subgraph HTTP["HTTP Transport"]
CG[ChatGPT]
LM[LM Studio]
WC[Web Clients]
end
end
subgraph Local["Local Execution"]
NPX["npx domain-search-mcp@latest"]
end
subgraph VPS["Production VPS"]
HTTPS["https://vmi3000318.contaboserver.net"]
end
CD & CU & VS & PX --> NPX
CG & LM & WC --> HTTPS
NPX --> SERVER
HTTPS --> SERVER
subgraph SERVER["Domain Search MCP Server (v1.9.6)"]
TOOLS[11 MCP Tools]
end
The server supports two transport modes, selected at runtime:
flowchart TD
START[server.ts] --> CONFIG["getTransportConfig()"]
CONFIG --> CHECK{config.type?}
CHECK -->|"stdio (default)"| STDIO["StdioServerTransport"]
CHECK -->|"http (--http flag)"| HTTP["createHttpTransport()"]
STDIO --> STDIN["stdin: JSON-RPC input"]
STDIO --> STDOUT["stdout: JSON-RPC output"]
HTTP --> EXPRESS["Express.js Server"]
EXPRESS --> PORT["Port 3001 (VPS)"]
EXPRESS --> RATE["Rate Limit: 100/min"]
EXPRESS --> CORS["CORS Enabled"]
EXPRESS --> SESSIONS["Session Management"]
Environment Variables:
| Variable | Default | Description |
|---|---|---|
MCP_TRANSPORT |
stdio |
Transport mode |
MCP_PORT |
3000 |
HTTP server port |
MCP_HOST |
0.0.0.0 |
HTTP server bind address |
CORS_ORIGINS |
* |
Allowed CORS origins |
flowchart TB
subgraph MW["Middleware Stack"]
direction LR
JSON["JSON Parser"] --> CORS["CORS"] --> RATE["Rate Limiter<br/>100/min/IP"]
end
REQ[Request] --> MW --> ROUTER
subgraph ROUTER["Express Router"]
ROOT["GET /"]
HEALTH["GET /health"]
OPENAPI["GET /openapi.json"]
METRICS["GET /metrics"]
MCP["ALL /mcp"]
API["POST /api/tools/*"]
end
ROOT --> INFO["Server info JSON"]
HEALTH --> STATUS["Status, uptime, sessions"]
OPENAPI --> SPEC["OpenAPI 3.1 Spec<br/>(auto-generated from Zod)"]
METRICS["/metrics"] --> PROM["Prometheus metrics<br/>(cache stats, latency)"]
MCP --> MCPCHECK{Method?}
MCPCHECK -->|POST| MESSAGES["JSON-RPC Messages"]
MCPCHECK -->|GET| SSE["SSE Stream"]
MESSAGES --> INIT{Has Session?}
INIT -->|No| CREATE["Create new session<br/>Generate UUID"]
INIT -->|Yes| LOOKUP["Lookup existing session"]
API --> REST["REST API<br/>(ChatGPT Actions)"]
subgraph SESSIONS["Session Store"]
S1["Session A<br/>uuid-1234"]
S2["Session B<br/>uuid-5678"]
S3["Session C<br/>uuid-9012"]
end
CREATE --> SESSIONS
LOOKUP --> SESSIONS
Endpoints:
| Method | Path | Description |
|---|---|---|
| GET | / |
Server info |
| GET | /health |
Health check (bypasses rate limit) |
| GET | /openapi.json |
OpenAPI 3.1 specification |
| GET | /metrics |
Prometheus-compatible metrics |
| POST | /mcp |
MCP JSON-RPC messages |
| GET | /mcp |
MCP SSE stream |
| POST | /api/tools/:name |
REST API for ChatGPT Actions |
flowchart TD
REQ["Client Request"] --> EXEC["executeToolCall()"]
EXEC --> SWITCH{"switch(toolName)"}
SWITCH -->|search_domain| SD["executeSearchDomain()"]
SWITCH -->|bulk_search| BS["executeBulkSearch()"]
SWITCH -->|suggest_domains| SG["executeSuggestDomains()"]
SWITCH -->|suggest_domains_smart| AI["executeSuggestDomainsSmart()"]
SWITCH -->|compare_registrars| CR["executeCompareRegistrars()"]
SWITCH -->|tld_info| TI["executeTldInfo()"]
SWITCH -->|check_socials| CS["executeCheckSocials()"]
SWITCH -->|whois_lookup| WH["executeWhoisLookup()"]
SWITCH -->|dns_lookup| DNS["executeDnsLookup()"]
SWITCH -->|get_premium_info| PI["executeGetPremiumInfo()"]
SD & BS & SG & AI & CR --> VALIDATE["1. Zod Schema Validation"]
VALIDATE --> SERVICE["2. Service Layer Call"]
SERVICE --> FORMAT["3. Response Formatting"]
FORMAT --> RESP["Response<br/>(Markdown table or JSON)"]
The system uses multiple data sources in a waterfall pattern:
flowchart TD
START["searchDomains(names, tlds)"] --> RDAP
subgraph PRIMARY["Primary: Availability"]
RDAP["RDAP<br/>(Public registry data)"]
end
RDAP --> AVAIL{Available?}
AVAIL -->|Yes| PRICING
AVAIL -->|No| AFTERMARKET
subgraph ENRICHMENT["Enrichment: Pricing"]
PRICING["Pricing API Backend<br/>(Porkbun via localhost:3000)"]
end
PRICING --> PRICEFAIL{Success?}
PRICEFAIL -->|Yes| RESULT
PRICEFAIL -->|No| FALLBACK
subgraph FALLBACK_SOURCES["Fallback"]
FALLBACK["WHOIS<br/>(If RDAP fails)"]
end
subgraph AFTERMARKET_SOURCES["Aftermarket Hints"]
AFTERMARKET["Sedo Feed + NS Lookup"]
GODADDY["GoDaddy Public<br/>(Premium/Auction signals)"]
end
AFTERMARKET --> RESULT
FALLBACK --> RESULT
RESULT["DomainResult<br/>{status, price, source, aftermarket}"]
Source Priority:
- RDAP - Fast, free, reliable availability data
- Pricing API - Live Porkbun quotes, corrects RDAP false positives
- WHOIS - Fallback when RDAP unavailable
- GoDaddy Public - Premium/auction signals for
search_domain - Sedo Feed - Aftermarket auction hints for taken domains
flowchart TB
subgraph INTERNET["Internet"]
CLIENT["Clients"]
end
CLIENT -->|HTTPS :443| NGINX
subgraph VPS["Contabo VPS (95.111.240.197)"]
subgraph NGINX_BLOCK["NGINX"]
NGINX["Reverse Proxy<br/>SSL Termination<br/>Let's Encrypt"]
end
NGINX -->|:3000| MCP_SERVICE
MCP_SERVICE -.->|:8000| LLAMA_SERVICE
MCP_SERVICE -.->|:6379| REDIS_SERVICE
subgraph SERVICES["systemd Services"]
MCP_SERVICE["domain-mcp.service<br/>/var/www/domain-mcp<br/>Port 3000"]
LLAMA_SERVICE["qwen-inference.service<br/>Qwen 7B DPO<br/>Port 8000<br/>(AI Inference)"]
REDIS_SERVICE["redis-server.service<br/>Port 6379<br/>(Distributed Cache)"]
end
end
Service Configuration:
| Service | Port | Purpose |
|---|---|---|
domain-mcp |
3000 | MCP HTTP server |
qwen-inference |
8000 | Qwen 7B AI inference |
redis-server |
6379 | Distributed cache |
Production URLs:
https://vmi3000318.contaboserver.net- Server infohttps://vmi3000318.contaboserver.net/mcp- MCP protocolhttps://vmi3000318.contaboserver.net/openapi.json- OpenAPI spechttps://vmi3000318.contaboserver.net/health- Health checkhttps://vmi3000318.contaboserver.net/metrics- Prometheus metrics
The suggest_domains_smart tool uses a fine-tuned Qwen 7B model:
sequenceDiagram
participant C as Client
participant M as MCP Server
participant Q as Qwen 7B (Port 8000)
participant R as RDAP
participant P as Pricing API
C->>M: suggest_domains_smart<br/>"AI coffee shop finder app"
M->>Q: POST /v1/chat/completions
Q-->>M: ["brewbot", "coffeewise", "beanfinder", ...]
par Parallel availability checks
M->>R: Check brewbot.com, .io
M->>R: Check coffeewise.com, .io
M->>R: Check beanfinder.com, .io
end
R-->>M: Availability results
loop For each available domain
M->>P: Get live price
P-->>M: Price quote
end
M-->>C: Markdown table with results
sequenceDiagram
participant C as Client
participant S as Server
participant SM as Session Map
Note over C,SM: 1. Initialize
C->>S: POST /mcp<br/>{"method": "initialize"}
S->>SM: Create new transport<br/>Generate UUID
S-->>C: Response<br/>Mcp-Session-Id: uuid-xxxx
Note over C,SM: 2. Tool Calls
C->>S: POST /mcp<br/>Mcp-Session-Id: uuid-xxxx<br/>{"method": "tools/call"}
S->>SM: Lookup session
SM-->>S: Transport instance
S-->>C: {"result": {...}}
Note over C,SM: 3. SSE Stream (Optional)
C->>S: GET /mcp<br/>Mcp-Session-Id: uuid-xxxx
S-->>C: SSE: event: message<br/>data: {...}
Note over C,SM: 4. Cleanup
C-xS: Disconnect
S->>SM: onclose() triggered
SM->>SM: Remove session<br/>Free resources
domain-search-mcp/
├── src/
│ ├── server.ts # Entry point, transport selection
│ │
│ ├── transports/
│ │ ├── index.ts # TransportConfig, getTransportConfig()
│ │ └── http.ts # Express server, session management
│ │
│ ├── tools/
│ │ ├── index.ts # Export all tools
│ │ ├── search-domain.ts # search_domain tool
│ │ ├── bulk-search.ts # bulk_search tool
│ │ ├── suggest-domains.ts # suggest_domains tool
│ │ ├── suggest-smart.ts # suggest_domains_smart (AI)
│ │ └── ... # Other tools
│ │
│ ├── services/
│ │ ├── domain-search.ts # Main orchestration layer
│ │ ├── pricing-api.ts # Backend API client
│ │ └── qwen-inference.ts # AI suggestion service
│ │
│ ├── registrars/
│ │ ├── base.ts # RegistrarAdapter base class
│ │ ├── porkbun.ts # Porkbun API adapter
│ │ ├── namecheap.ts # Namecheap API adapter
│ │ └── godaddy-public.ts # GoDaddy public endpoint
│ │
│ ├── fallbacks/
│ │ ├── rdap.ts # RDAP availability check
│ │ └── whois.ts # WHOIS fallback
│ │
│ ├── openapi/
│ │ ├── generator.ts # OpenAPI 3.1 spec generator
│ │ └── schemas.ts # Zod to OpenAPI registration
│ │
│ ├── api/
│ │ └── routes.ts # REST API router (/api/tools/*)
│ │
│ └── utils/
│ ├── cache.ts # TTL-based in-memory cache
│ ├── redis-cache.ts # Hybrid Redis + in-memory cache
│ ├── circuit-breaker.ts # Circuit breaker pattern
│ ├── adaptive-concurrency.ts # Dynamic batch sizing
│ ├── metrics.ts # Prometheus metrics
│ ├── errors.ts # Error types
│ └── validators.ts # Input validation
│
├── docs/
│ ├── ARCHITECTURE.md # This file
│ └── MULTI_PLATFORM_EXPANSION.md
│
└── package.json # v1.9.6
-
Dual Transport Architecture: Same tool code serves both stdio and HTTP clients - no code duplication.
-
Waterfall Data Sources: RDAP → Pricing API → WHOIS chain ensures fast results with pricing enrichment.
-
Session-based HTTP: Each HTTP client gets isolated session with automatic cleanup on disconnect.
-
Rate Limiting Strategy: Global HTTP rate limiting (100/min) protects against abuse while per-registrar limits protect API quotas.
-
OpenAPI Auto-generation: Schemas defined once in Zod, automatically converted to OpenAPI 3.1 for ChatGPT Actions compatibility.
-
Hybrid Caching: Redis as primary cache with automatic fallback to in-memory. Circuit breaker pattern prevents Redis failures from affecting availability.
-
Circuit Breaker Pattern: All external services (Redis, AI inference) protected by circuit breakers with exponential backoff and automatic recovery.
-
Adaptive Concurrency: AI inference dynamically adjusts batch size and parallelism based on response latency percentiles.