Content
# DNSimple MCP Server
MCP server for DNSimple API interactions, providing tools for domain management, DNS configuration, pricing queries, and domain transfers.
## Features
- **Domain Management**: List domains, get pricing, check renewal costs
- **Nameserver Delegation**: Read and update registrar-level domain nameservers
- **DNS Configuration**: Create, update, list, and delete DNS records
- **Auto-Renewal Control**: Disable auto-renewal for domains
- **Domain Transfers**: Initiate domain transfers to DNSimple
- **Whois Privacy**: Check and enable whois privacy (domain privacy) for domains
## Installation
```bash
cd execution/mcp-servers/dnsimple
pip install -r requirements.txt
```
## Configuration
### Authentication
The server supports multiple authentication methods (checked in priority order):
1. **Environment Variable** (recommended, highest priority):
```bash
export DNSIMPLE_API_TOKEN="your-token-here"
```
2. **Config Directory `.env` File** (portable, user-specific):
- Location: `~/.config/dnsimple-mcp/.env`
- Format: `DNSIMPLE_API_TOKEN=your-token-here`
- The config directory is created automatically on first use
3. **1Password Integration** (optional, for backward compatibility):
- Only available if parent repository structure exists
- Configure 1Password item titled "DNSimple" or with URL "dnsimple.com"
- Add field: "access token", "api_token", or "token" with your DNSimple API token
- Get your API token from: https://dnsimple.com/user
**Note:** The MCP server is self-contained and portable. It does not require any specific repository structure and can be used in any project.
### Cursor Configuration
Add to your Cursor MCP settings (typically `~/.cursor/mcp.json` or Cursor settings):
**Option 1: Using environment variable (recommended):**
```json
{
"mcpServers": {
"dnsimple": {
"command": "python3",
"args": [
"/path/to/dnsimple_mcp_server.py"
],
"env": {
"DNSIMPLE_API_TOKEN": "your-token-here"
}
}
}
}
```
**Option 2: Using config directory (token in ~/.config/dnsimple-mcp/.env):**
```json
{
"mcpServers": {
"dnsimple": {
"command": "python3",
"args": [
"/path/to/dnsimple_mcp_server.py"
],
"env": {}
}
}
}
```
**Note:** Replace `/path/to/dnsimple_mcp_server.py` with the actual path to the server file. The server is portable and can be placed anywhere.
### Claude Desktop Configuration
Add to `claude_desktop_config.json` (typically `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"dnsimple": {
"command": "python3",
"args": [
"/path/to/dnsimple_mcp_server.py"
],
"env": {
"DNSIMPLE_API_TOKEN": "your-token-here"
}
}
}
}
```
**Note:** Replace `/path/to/dnsimple_mcp_server.py` with the actual path to the server file.
## Available Tools
### `list_domains`
List all domains in the DNSimple account.
**Parameters:** None
**Returns:**
- `account_id`: DNSimple account ID
- `count`: Number of domains
- `domains`: Array of domain objects with name, expires_at, auto_renew, etc.
**Example:**
```json
{
"account_id": "12345",
"count": 5,
"domains": [
{
"id": 123456,
"name": "example.com",
"expires_at": "2026-12-31",
"auto_renew": true,
"registrant_id": 789
}
]
}
```
### `get_domain_nameservers`
Get the current delegated nameservers set at the registrar for a domain.
**Parameters:**
- `domain_name` (required): Domain name (e.g., "example.com")
**Returns:**
- `domain`: Domain name
- `nameservers`: Current delegated nameservers
- `delegation`: Raw DNSimple delegation payload
**Example:**
```json
{
"domain_name": "example.com"
}
```
### `update_domain_nameservers`
Replace delegated nameservers for a domain at the registrar level.
**Parameters:**
- `domain_name` (required): Domain name (e.g., "example.com")
- `nameservers` (required): Array of nameserver hostnames (minimum 2)
**Returns:**
- `success`: Boolean indicating success
- `domain`: Domain name
- `nameservers`: Updated delegated nameservers
- `delegation`: Raw DNSimple delegation payload
**Example:**
```json
{
"domain_name": "example.com",
"nameservers": [
"kipp.ns.cloudflare.com",
"mona.ns.cloudflare.com"
]
}
```
### `get_domain_costs`
Get pricing information for domains. Returns registration and renewal costs.
**Parameters:**
- `domain_names` (optional): Array of domain names to get pricing for. If empty, returns pricing for all domains in account.
**Returns:**
- `account_id`: DNSimple account ID
- `domains`: Array of domain pricing objects
**Example:**
```json
{
"domain_names": ["example.com", "test.org"]
}
```
**Response:**
```json
{
"account_id": "12345",
"domains": [
{
"domain": "example.com",
"domain_info": {
"id": 123456,
"name": "example.com",
"expires_at": "2026-12-31"
},
"prices": [
{
"operation": "register",
"price": "15.00",
"currency": "USD"
},
{
"operation": "renew",
"price": "15.00",
"currency": "USD"
}
]
}
]
}
```
### `get_renewal_costs`
Get renewal costs for domains. Returns total annual renewal cost and per-domain breakdown.
**Parameters:**
- `domain_names` (optional): Array of domain names to get renewal costs for. If empty, returns costs for all domains in account.
**Returns:**
- `account_id`: DNSimple account ID
- `total_domains`: Number of domains
- `total_annual_renewal_cost`: Sum of all renewal costs
- `domains`: Array of domain renewal details
**Example:**
```json
{
"domain_names": ["example.com", "test.org"]
}
```
**Response:**
```json
{
"account_id": "12345",
"total_domains": 2,
"total_annual_renewal_cost": 30.00,
"domains": [
{
"domain": "example.com",
"expires_at": "2026-12-31",
"auto_renew": true,
"renewal_price": 15.00,
"currency": "USD"
},
{
"domain": "test.org",
"expires_at": "2026-06-15",
"auto_renew": false,
"renewal_price": 15.00,
"currency": "USD"
}
]
}
```
### `list_dns_records`
List DNS records for a domain.
**Parameters:**
- `domain_name` (required): Domain name (e.g., "example.com")
- `name` (optional): Filter by record name
- `type` (optional): Filter by record type (A, AAAA, CNAME, MX, TXT, NS, SRV, ALIAS)
**Returns:**
- `domain`: Domain name
- `count`: Number of records
- `records`: Array of DNS record objects
**Example:**
```json
{
"domain_name": "example.com",
"type": "A"
}
```
**Response:**
```json
{
"domain": "example.com",
"count": 2,
"records": [
{
"id": 123456,
"name": "www",
"type": "A",
"content": "192.0.2.1",
"ttl": 3600,
"priority": null
},
{
"id": 123457,
"name": "@",
"type": "A",
"content": "192.0.2.1",
"ttl": 3600,
"priority": null
}
]
}
```
### `configure_dns_record`
Create or update a DNS record. If a record with the same name and type exists, it will be updated.
**Parameters:**
- `domain_name` (required): Domain name (e.g., "example.com")
- `name` (required): Record name (e.g., "www" or "@" for root domain)
- `type` (required): DNS record type (A, AAAA, CNAME, MX, TXT, NS, SRV, ALIAS, URL). Use **URL** for DNSimple’s redirect (apex or subdomain → target URL).
- `content` (required): Record content (IP address for A/AAAA, hostname for CNAME, etc.)
- `ttl` (optional): TTL in seconds (default: 3600)
- `priority` (optional): Priority for MX records
**Returns:**
- `success`: Boolean indicating success
- `action`: "created" or "updated"
- `record`: DNS record object
**Example (Create A record):**
```json
{
"domain_name": "example.com",
"name": "www",
"type": "A",
"content": "192.0.2.1",
"ttl": 3600
}
```
**Example (Create MX record):**
```json
{
"domain_name": "example.com",
"name": "@",
"type": "MX",
"content": "mail.example.com",
"priority": 10,
"ttl": 3600
}
```
**Example (Create CNAME record):**
```json
{
"domain_name": "example.com",
"name": "blog",
"type": "CNAME",
"content": "example.github.io",
"ttl": 3600
}
```
**Example (URL redirect for apex domain):**
```json
{
"domain_name": "example.com",
"name": "",
"type": "URL",
"content": "https://github.com/username/repo",
"ttl": 3600
}
```
Use empty `name` for apex; DNSimple serves a 301 redirect to `content`. Requires DNSimple nameservers (not applicable if the zone is delegated elsewhere, e.g. Cloudflare).
### `delete_dns_record`
Delete a DNS record by ID.
**Parameters:**
- `domain_name` (required): Domain name (e.g., "example.com")
- `record_id` (required): DNS record ID to delete
**Returns:**
- `success`: Boolean indicating success
- `message`: Success message
**Example:**
```json
{
"domain_name": "example.com",
"record_id": "123456"
}
```
### `disable_autorenew`
Disable auto-renewal for one or more domains.
**Parameters:**
- `domain_names` (required): Array of domain names to disable auto-renewal for
**Returns:**
- `results`: Array of operation results
**Example:**
```json
{
"domain_names": ["example.com", "test.org"]
}
```
**Response:**
```json
{
"results": [
{
"domain": "example.com",
"status": "disabled",
"error": null
},
{
"domain": "test.org",
"status": "disabled",
"error": null
}
]
}
```
### `transfer_domain`
Initiate a domain transfer to DNSimple. Requires authorization code from current registrar.
**Parameters:**
- `domain_name` (required): Domain name to transfer
- `auth_code` (required): Authorization code (EPP code) from current registrar
- `registrant_id` (optional): Registrant ID (uses account default if not provided)
**Returns:**
- `success`: Boolean indicating success
- `transfer`: Transfer object with ID and status
**Example:**
```json
{
"domain_name": "example.com",
"auth_code": "ABC123XYZ789"
}
```
**Response:**
```json
{
"success": true,
"transfer": {
"id": 123456,
"domain_id": 789012,
"state": "new",
"auto_renew": false,
"whois_privacy": false
}
}
```
**Note:** Domain must be unlocked at current registrar before transfer can be initiated.
### `get_whois_privacy`
Get whois privacy (domain privacy) status for a domain.
**Parameters:**
- `domain_name` (required): Domain name (e.g., "example.com")
**Returns:**
- `domain`: Domain name
- `enabled`: Boolean indicating if whois privacy is enabled
- `whois_privacy`: Whois privacy object with details
- `expires_on`: Expiration date of whois privacy (if enabled)
**Example:**
```json
{
"domain_name": "example.com"
}
```
**Response:**
```json
{
"domain": "example.com",
"enabled": true,
"whois_privacy": {
"id": 123456,
"domain_id": 789012,
"enabled": true,
"expires_on": "2026-12-31"
},
"expires_on": "2026-12-31"
}
```
### `enable_whois_privacy`
Enable whois privacy (domain privacy) for a domain. This will purchase and enable whois privacy if not already enabled.
**Parameters:**
- `domain_name` (required): Domain name (e.g., "example.com")
**Returns:**
- `success`: Boolean indicating success
- `domain`: Domain name
- `status`: Status message ("already_enabled" or "enabled")
- `message`: Human-readable message
- `whois_privacy`: Whois privacy object with details
**Example:**
```json
{
"domain_name": "example.com"
}
```
**Response (already enabled):**
```json
{
"domain": "example.com",
"status": "already_enabled",
"message": "Whois privacy is already enabled for this domain",
"whois_privacy": {
"id": 123456,
"domain_id": 789012,
"enabled": true,
"expires_on": "2026-12-31"
}
}
```
**Response (newly enabled):**
```json
{
"success": true,
"domain": "example.com",
"status": "enabled",
"message": "Whois privacy has been enabled for this domain",
"whois_privacy": {
"id": 123456,
"domain_id": 789012,
"enabled": true,
"expires_on": "2026-12-31"
}
}
```
**Note:** Enabling whois privacy may incur a charge depending on your DNSimple plan and TLD.
## Error Handling
The server returns structured error messages in JSON format when operations fail. Common errors include:
- **Authentication errors**: Missing or invalid API token
- **Account errors**: No account found or account access issues
- **Domain errors**: Domain not found or not accessible
- **API errors**: DNSimple API errors with status codes and messages
**Example error response:**
```json
{
"error": "Failed to get account ID: Invalid API response: missing 'data' key"
}
```
## Security Notes
- API tokens are never logged or exposed in error messages
- Tokens can be stored in environment variables, `~/.config/dnsimple-mcp/.env`, or 1Password
- All API requests use HTTPS
- Config directory `.env` file has restricted permissions (owner read/write only)
- Environment variables are the most secure method (not persisted to disk)
## Troubleshooting
1. **Authentication Fails**
- Verify API token is correct
- Check token has not expired
- Ensure 1Password integration is configured correctly
- Get new token from: https://dnsimple.com/user
2. **Account Not Found**
- Verify account exists in DNSimple
- Check account permissions
- Ensure API token has account access
3. **Domain Not Found**
- Verify domain exists in DNSimple account
- Check domain spelling
- Ensure domain is registered through DNSimple (for registrar operations)
4. **DNS Record Operations Fail**
- Verify domain is using DNSimple nameservers
- Check record name and type are valid
- Ensure TTL is within valid range (60-604800 seconds)
## Notes
- The server automatically discovers the account ID from the DNSimple API
- DNS record updates will replace existing records with the same name and type
- Domain transfers require the domain to be unlocked at the current registrar
- All date fields are returned as ISO format strings
- The server runs in stdio mode for MCP communication
## License
MIT
## Support
- [GitHub Issues](https://github.com/markmhendrickson/mcp-server-dnsimple/issues)
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available