npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

mcp-domain-purchaser

v0.1.0-draft.1770992906137

Published

MCP server for domain purchase across multiple registrars

Downloads

79

Readme

MCP Domain Purchaser

An MCP (Model Context Protocol) server for domain purchase operations across multiple registrars with a clean adapter-based architecture.

Features

  • Multi-Registrar Support: Unified interface for multiple domain registrars (Porkbun, Namecheap, GoDaddy, Gandi)
  • Adapter Pattern: Easy to add new registrars by implementing the RegistrarAdapter interface
  • IPv4-Safe Networking: Works reliably in Docker/WSL2 environments with IPv6 issues
  • Type-Safe: Full TypeScript with Zod schemas for runtime validation
  • MCP Standard: Implements the Model Context Protocol for AI assistant integration

Supported Registrars

| Registrar | Availability | Pricing | DNS | Balance | Sandbox | |-----------|--------------|---------|-----|---------|---------| | Porkbun | Yes | Yes | Yes | Yes | No | | name.com | Yes | Yes | Yes | No | Yes | | GoDaddy | Yes | Yes | Yes | No | Yes (OTE) | | Gandi | Yes | Yes | Yes | Yes | Yes | | Namecheap | Yes | Premium only* | Yes | Yes | Yes |

* Namecheap only returns pricing for premium domains via API. Standard domain pricing must be checked at namecheap.com.

name.com Setup

export NAME_USERNAME=your_namecom_username
export NAME_TOKEN=your_api_token
export NAME_USE_SANDBOX=true  # Optional: use sandbox for testing

Getting API Access:

  1. Log in to your name.com account
  2. Go to Account Settings -> API Settings
  3. Create an API token
  4. Important: Disable 2FA for API access (required by name.com)

Sandbox Environment:

  • Uses https://api.dev.name.com/v4 endpoint
  • Username automatically gets -test suffix in sandbox mode
  • Same token works for both production and sandbox

Namecheap Setup

export NAMECHEAP_API_USER=your_api_username
export NAMECHEAP_API_KEY=your_api_key
export NAMECHEAP_USERNAME=your_username
export NAMECHEAP_CLIENT_IP=your_whitelisted_ip  # REQUIRED!
export NAMECHEAP_USE_SANDBOX=true  # Optional: use sandbox for testing

Important: Namecheap requires:

  1. API access enabled (requires $50 balance, 20+ domains, OR $50 spent in 2 years)
  2. Your IP address whitelisted in your Namecheap account

See Namecheap Adapter Documentation for detailed setup instructions.

Gandi Setup

export GANDI_PAT=your_personal_access_token
export GANDI_USE_SANDBOX=true  # Optional: use sandbox for testing

See Gandi Adapter Documentation for detailed setup instructions.

Installation

npm install mcp-domain-purchaser

Available Tools

The MCP server provides the following tools:

| Tool | Description | |------|-------------| | check_availability | Check domain availability across all configured registrars | | compare_prices | Compare registration and renewal prices across registrars | | get_balance | Get account balance from prepaid registrars | | list_domains | List all domains owned across all registrars |

Usage

As an MCP Server

Add to your Claude Code MCP configuration:

{
  "mcpServers": {
    "domain-purchaser": {
      "command": "npx",
      "args": ["mcp-domain-purchaser"],
      "env": {
        "MAX_DOMAIN_PRICE": "50",
        "CONFIRMATION_TIMEOUT_MINUTES": "5"
      }
    }
  }
}

Programmatic Usage

import {
  DomainPurchaserServer,
  BaseRegistrarAdapter,
  type RegistrarCapabilities,
} from 'mcp-domain-purchaser';

// Create server with configuration
const server = new DomainPurchaserServer({
  maxDomainPrice: 50,
  confirmationTimeoutMinutes: 5,
  auditLogPath: '~/.domain-purchaser/audit.log',
});

// Register your adapter(s)
// server.registerAdapter(new MyRegistrarAdapter(...));

// Start the server
await server.start();

Creating a Custom Adapter

To add support for a new registrar, extend BaseRegistrarAdapter:

import {
  BaseRegistrarAdapter,
  type RegistrarCapabilities,
  type AvailabilityResult,
  type PricingResult,
  type BalanceResult,
  type DomainListResult,
  type PendingTransaction,
  type PurchaseResult,
  type DnsRecord,
  type DnsResult,
} from 'mcp-domain-purchaser';

export class MyRegistrarAdapter extends BaseRegistrarAdapter {
  readonly name = 'myregistrar';
  readonly priority = 1;
  readonly capabilities: RegistrarCapabilities = {
    supportsAvailability: true,
    supportsPricing: true,
    supportsBalance: true,
    supportsListDomains: true,
    supportsPurchase: true,
    supportsDns: true,
    hasSandbox: false,
  };

  private readonly apiKey: string;

  constructor(apiKey: string, options?: { timeout?: number; debug?: boolean }) {
    super(options);
    this.apiKey = apiKey;
  }

  async checkAvailability(domain: string): Promise<AvailabilityResult> {
    const validDomain = this.validateDomainInput(domain);
    // Implement API call...
    return {
      domain: validDomain,
      available: true,
      status: 'available',
    };
  }

  async getPricing(domain: string): Promise<PricingResult> {
    // Implement...
  }

  async getBalance(): Promise<BalanceResult> {
    // Implement...
  }

  async listDomains(): Promise<DomainListResult> {
    // Implement...
  }

  async createPurchase(domain: string, years: number): Promise<PendingTransaction> {
    // Implement...
  }

  async executePurchase(transactionId: string): Promise<PurchaseResult> {
    // Implement...
  }

  async getDnsRecords(domain: string): Promise<DnsRecord[]> {
    // Implement...
  }

  async setDnsRecords(domain: string, records: DnsRecord[]): Promise<DnsResult> {
    // Implement...
  }

  isConfigured(): boolean {
    return Boolean(this.apiKey);
  }

  async validateCredentials(): Promise<boolean> {
    // Make a test API call to verify credentials
    return true;
  }
}

Safety Controls

The domain purchaser includes comprehensive safety controls to protect users from accidental or unauthorized purchases.

Price Limits

Purchases over the configured maximum price (default $50) are automatically rejected:

import { SafetyService } from 'mcp-domain-purchaser';

const safety = new SafetyService();
const check = safety.checkPriceLimit(1500);
// check.allowed === false
// check.reason includes instructions to increase MAX_DOMAIN_PRICE

Premium Domain Detection

Detects premium domains using multiple heuristics:

  • Known premium TLDs (.ai, .io, .co, .dev, etc.)
  • Short domain names (1-3 characters)
  • Pure numeric domains
  • High absolute price (>$100)
  • Price significantly above TLD average
const result = safety.detectPremiumDomain('ai.io', 5000);
// result.isPremium === true
// result.confidence === 'high'
// result.reasons includes all detected premium indicators

Two-Step Confirmation

All purchases require explicit confirmation within a timeout period (default 5 minutes):

import { PendingTransactionService } from 'mcp-domain-purchaser';

const txnService = new PendingTransactionService();

// Step 1: Create pending transaction
const txn = txnService.createTransaction('example.com', 'Porkbun', 9.99);

// Step 2: Confirm within 5 minutes
const confirmed = txnService.confirmTransaction(txn.transactionId);

// Expired transactions are automatically rejected

Audit Logging

All operations are logged to a JSON Lines file for accountability:

import { AuditLogger } from 'mcp-domain-purchaser';

const audit = new AuditLogger();
await audit.logPurchaseInitiated('example.com', 'Porkbun', 9.99, 'txn_abc123');

CRITICAL SECURITY: The audit logger NEVER logs API keys, secrets, or credentials. All sensitive data is automatically scrubbed before writing.

Environment Variables for Safety

| Variable | Description | Default | |----------|-------------|---------| | MAX_DOMAIN_PRICE | Maximum allowed domain price in USD | 50 | | CONFIRMATION_TIMEOUT_MINUTES | Minutes before pending transactions expire | 5 | | AUDIT_LOG_PATH | Path to audit log file | ~/.domain-purchaser/audit.log |

Architecture

mcp-domain-purchaser/
  src/
    index.ts                    # Entry point + exports
    server.ts                   # DomainPurchaserServer class
    adapters/
      types.ts                  # RegistrarAdapter interface
      base.ts                   # BaseRegistrarAdapter abstract class
      gandi.ts                  # Gandi adapter (v5 API + LiveDNS)
      godaddy.ts                # GoDaddy adapter
      namecheap.ts              # Namecheap adapter (XML API)
      namecom.ts                # name.com adapter (v4 Core API)
      porkbun.ts                # Porkbun adapter
    config/
      limits.ts                 # Safety configuration loading
    services/
      safety.ts                 # SafetyService (price limits, premium detection)
      pending-transactions.ts   # PendingTransactionService (two-step confirmation)
      audit.ts                  # AuditLogger (JSON Lines logging, credential scrubbing)
    types/
      domain.ts                 # Domain types + zod schemas
      pricing.ts                # Pricing types + zod schemas
      transaction.ts            # Transaction types + zod schemas
      safety.ts                 # Safety types + zod schemas
    utils/
      fetch.ts                  # IPv4-safe fetch wrapper
      validation.ts             # Input validation utilities
      xml.ts                    # XML parsing utilities (for Namecheap)
  docs/
    adapters/
      gandi.md                  # Gandi adapter documentation
      namecheap.md              # Namecheap adapter documentation

Type Definitions

Domain Types

  • DomainStatus: 'available' | 'taken' | 'premium' | 'unknown' | 'error'
  • AvailabilityResult: Result of domain availability check
  • OwnedDomain: Domain owned by the user
  • DomainListResult: Result of listing owned domains

Pricing Types

  • PricingResult: Pricing information for a domain
  • BalanceResult: Account balance from a registrar
  • PriceComparison: Price comparison across registrars

Transaction Types

  • TransactionStatus: Status of a purchase transaction
  • PendingTransaction: A pending purchase awaiting confirmation
  • PurchaseResult: Result of an executed purchase
  • AuditLogEntry: Entry in the audit log

Environment Variables

General Configuration

| Variable | Description | Default | |----------|-------------|---------| | MAX_DOMAIN_PRICE | Maximum allowed domain price in USD | 50 | | CONFIRMATION_TIMEOUT_MINUTES | Minutes before pending transactions expire | 5 | | AUDIT_LOG_PATH | Path to audit log file | ~/.domain-purchaser/audit.log |

name.com

| Variable | Description | Required | |----------|-------------|----------| | NAME_USERNAME | name.com account username | Yes | | NAME_TOKEN | API token from name.com account settings | Yes | | NAME_USE_SANDBOX | Use sandbox environment (true/false) | No |

Sandbox Mode:

  • When NAME_USE_SANDBOX=true, requests go to api.dev.name.com
  • Username is automatically suffixed with -test for sandbox auth
  • Allows safe testing without real charges

Gandi

| Variable | Description | Required | |----------|-------------|----------| | GANDI_PAT | Personal Access Token | Yes | | GANDI_USE_SANDBOX | Use sandbox environment | No | | GANDI_SHARING_ID | Organization sharing ID | No |

Namecheap

| Variable | Description | Required | |----------|-------------|----------| | NAMECHEAP_API_USER | API username (usually same as account username) | Yes | | NAMECHEAP_API_KEY | API key from Namecheap account | Yes | | NAMECHEAP_USERNAME | Namecheap account username | Yes | | NAMECHEAP_CLIENT_IP | Whitelisted IP address for API access | Yes | | NAMECHEAP_USE_SANDBOX | Use sandbox environment for testing | No |

IPv4 Networking

This package includes an IPv4-safe fetch wrapper to handle networking issues common in Docker and WSL2 environments where IPv6 connections fail or timeout. The wrapper uses undici with explicit IPv4 configuration.

import { fetchIPv4, fetch } from 'mcp-domain-purchaser';

// Use just like native fetch, but with guaranteed IPv4
const response = await fetchIPv4('https://api.example.com/data');

License

MIT