Initial commit: Namecheap API library with REST/MCP servers
Features: - Domain management (check, register, renew, contacts) - DNS management (nameservers, records) - Glue records (child nameserver) support - TLD price tracking with KRW conversion - FastAPI REST server with OpenAI schema - MCP server for Claude integration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
270
mcp_server.py
Normal file
270
mcp_server.py
Normal file
@@ -0,0 +1,270 @@
|
||||
#!/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()
|
||||
Reference in New Issue
Block a user