#!/usr/bin/env python3 """ Namecheap MCP Server """ import os from dotenv import load_dotenv from mcp.server.fastmcp import FastMCP from namecheap import NamecheapAPI, NamecheapConfig, RegistrantInfo load_dotenv() # Initialize MCP server mcp = FastMCP("namecheap") # Initialize Namecheap API config = NamecheapConfig( api_user=os.getenv("NAMECHEAP_API_USER", ""), api_key=os.getenv("NAMECHEAP_API_KEY", ""), username=os.getenv("NAMECHEAP_USERNAME", ""), client_ip=os.getenv("NAMECHEAP_CLIENT_IP", ""), sandbox=os.getenv("NAMECHEAP_SANDBOX", "false").lower() == "true", ) api = NamecheapAPI(config) # ===== Domain Tools ===== @mcp.tool() def domains_check(domains: str) -> dict: """ Check domain availability. Args: domains: Comma-separated domain names (e.g., "example.com,example.net") """ domain_list = [d.strip() for d in domains.split(",")] return api.domains_check(domain_list) @mcp.tool() def domains_list(page: int = 1, page_size: int = 20) -> list[dict]: """ Get list of domains in account. Args: page: Page number (default: 1) page_size: Number of domains per page (default: 20) """ return api.domains_get_list(page=page, page_size=page_size) @mcp.tool() def domains_info(domain: str) -> dict: """ Get detailed info about a domain. Args: domain: Domain name (e.g., "example.com") """ return api.domains_get_info(domain) @mcp.tool() def domains_renew(domain: str, years: int = 1) -> dict: """ Renew a domain. WARNING: This will charge your account. Args: domain: Domain name to renew years: Number of years (1-10) """ return api.domains_renew(domain, years=years) @mcp.tool() def domains_get_contacts(domain: str) -> dict: """ Get domain contact information. Args: domain: Domain name (e.g., "example.com") """ return api.domains_get_contacts(domain) # ===== DNS Tools ===== @mcp.tool() def dns_get_nameservers(domain: str) -> dict: """ Get nameserver information for a domain. Args: domain: Domain name (e.g., "example.com" or "sub.it.com") """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return {"error": "Invalid domain format"} return api.dns_get_list(sld, tld) @mcp.tool() def dns_set_nameservers(domain: str, nameservers: str) -> dict: """ Set custom nameservers for a domain. Args: domain: Domain name (e.g., "example.com") nameservers: Comma-separated nameservers (e.g., "ns1.cloudflare.com,ns2.cloudflare.com") """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return {"error": "Invalid domain format"} ns_list = [ns.strip() for ns in nameservers.split(",")] success = api.dns_set_custom(sld, tld, ns_list) return {"success": success, "domain": domain, "nameservers": ns_list} @mcp.tool() def dns_set_default(domain: str) -> dict: """ Set default Namecheap nameservers for a domain. Args: domain: Domain name (e.g., "example.com") """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return {"error": "Invalid domain format"} success = api.dns_set_default(sld, tld) return {"success": success, "domain": domain} @mcp.tool() def dns_get_records(domain: str) -> list[dict]: """ Get DNS records for a domain. Only works if using Namecheap DNS. Args: domain: Domain name (e.g., "example.com") """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return [{"error": "Invalid domain format"}] return api.dns_get_hosts(sld, tld) # ===== Glue Record (Child Nameserver) Tools ===== @mcp.tool() def glue_create(domain: str, nameserver: str, ip: str) -> dict: """ Create a glue record (child nameserver) for a domain. Use this when you want to use your own domain as a nameserver (e.g., ns1.example.com for example.com). Args: domain: Domain name (e.g., "example.com") nameserver: Full nameserver hostname (e.g., "ns1.example.com") ip: IP address for the nameserver """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return {"error": "Invalid domain format"} return api.ns_create(sld, tld, nameserver, ip) @mcp.tool() def glue_get(domain: str, nameserver: str) -> dict: """ Get info about a glue record (child nameserver). Args: domain: Domain name (e.g., "example.com") nameserver: Full nameserver hostname (e.g., "ns1.example.com") """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return {"error": "Invalid domain format"} return api.ns_get_info(sld, tld, nameserver) @mcp.tool() def glue_update(domain: str, nameserver: str, old_ip: str, ip: str) -> dict: """ Update a glue record (child nameserver) IP address. Args: domain: Domain name (e.g., "example.com") nameserver: Full nameserver hostname (e.g., "ns1.example.com") old_ip: Current IP address ip: New IP address """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return {"error": "Invalid domain format"} return api.ns_update(sld, tld, nameserver, old_ip, ip) @mcp.tool() def glue_delete(domain: str, nameserver: str) -> dict: """ Delete a glue record (child nameserver). Args: domain: Domain name (e.g., "example.com") nameserver: Full nameserver hostname to delete (e.g., "ns1.example.com") """ parts = domain.rsplit(".", 1) if len(parts) == 2: sld, tld = parts else: return {"error": "Invalid domain format"} return api.ns_delete(sld, tld, nameserver) # ===== Account Tools ===== @mcp.tool() def account_balance() -> dict: """Get account balance.""" return api.users_get_balances() @mcp.tool() def price_check(tld: str) -> dict: """ Get registration price for a TLD. Args: tld: TLD to check (e.g., "com", "net", "io") """ from db import get_prices, init_db init_db() prices = get_prices() for p in prices: if p["tld"] == tld: return {"tld": tld, "usd": p["usd"], "krw": p["krw"]} return {"error": f"TLD '{tld}' not found"} if __name__ == "__main__": mcp.run()