Skip to content

Latest commit

 

History

History
413 lines (318 loc) · 12.4 KB

File metadata and controls

413 lines (318 loc) · 12.4 KB

Domain Search MCP - Architecture

This document provides detailed architectural diagrams for the Domain Search MCP server.

Table of Contents


High-Level Overview

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
Loading

Transport Layer

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"]
Loading

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

HTTP Transport Details

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
Loading

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

Tool Execution Flow

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)"]
Loading

Data Source Waterfall

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}"]
Loading

Source Priority:

  1. RDAP - Fast, free, reliable availability data
  2. Pricing API - Live Porkbun quotes, corrects RDAP false positives
  3. WHOIS - Fallback when RDAP unavailable
  4. GoDaddy Public - Premium/auction signals for search_domain
  5. Sedo Feed - Aftermarket auction hints for taken domains

VPS Deployment

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
Loading

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 info
  • https://vmi3000318.contaboserver.net/mcp - MCP protocol
  • https://vmi3000318.contaboserver.net/openapi.json - OpenAPI spec
  • https://vmi3000318.contaboserver.net/health - Health check
  • https://vmi3000318.contaboserver.net/metrics - Prometheus metrics

AI Suggestion Flow

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
Loading

MCP Session Lifecycle

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
Loading

Directory Structure

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

Key Design Decisions

  1. Dual Transport Architecture: Same tool code serves both stdio and HTTP clients - no code duplication.

  2. Waterfall Data Sources: RDAP → Pricing API → WHOIS chain ensures fast results with pricing enrichment.

  3. Session-based HTTP: Each HTTP client gets isolated session with automatic cleanup on disconnect.

  4. Rate Limiting Strategy: Global HTTP rate limiting (100/min) protects against abuse while per-registrar limits protect API quotas.

  5. OpenAPI Auto-generation: Schemas defined once in Zod, automatically converted to OpenAPI 3.1 for ChatGPT Actions compatibility.

  6. Hybrid Caching: Redis as primary cache with automatic fallback to in-memory. Circuit breaker pattern prevents Redis failures from affecting availability.

  7. Circuit Breaker Pattern: All external services (Redis, AI inference) protected by circuit breakers with exponential backoff and automatic recovery.

  8. Adaptive Concurrency: AI inference dynamically adjusts batch size and parallelism based on response latency percentiles.