Skip to main content
Glama
porkbun-mcp-server

porkbun-mcp-server

by Avicennasis

porkbun-mcp-server

CI codecov OpenSSF Scorecard PyPI Release License: MIT Python 3.11+ pre-commit PRs welcome

Model Context Protocol server for Porkbun's API v3 — full coverage of domains, DNS records, DNSSEC, SSL bundle retrieval, glue records, URL forwarding, labels, domain registration/renewal/transfers, marketplace, account management, email hosting, and API key management.

Every mutation tool requires a reason argument and emits an audit row via a pluggable handler, so DNS changes are always traceable.

Install

pip install porkbun-mcp-server

Or from source:

git clone https://github.com/Avicennasis/porkbun-mcp-server.git
cd porkbun-mcp-server
pip install -e ".[dev]"

Related MCP server: porkbun-mcp

Register with Claude Code

claude mcp add porkbun -- porkbun-mcp

Or for other MCP clients, add to your configuration:

{
  "mcpServers": {
    "porkbun": {
      "command": "porkbun-mcp",
      "env": {
        "PORKBUN_API_KEY": "pk1_...",
        "PORKBUN_SECRET_KEY": "sk1_..."
      }
    }
  }
}

Configure

Variable

Required

Description

PORKBUN_API_KEY

Yes

Your Porkbun API key (pk1_...)

PORKBUN_SECRET_KEY

Yes

Your Porkbun secret key (sk1_...)

PORKBUN_MCP_AUDIT_ENABLED

No

Set false to disable audit logging

PORKBUN_MCP_AUDIT_HANDLER

No

Audit handler — see Audit Handler

PORKBUN_PRICING_CACHE_TTL

No

Pricing cache TTL in seconds (default: 86400, 0 = no cache)

Get your API keys at porkbun.com/account/api. Ensure API access is enabled for the domains you want to manage.

Tools (48)

DNS Records

list_dns_records create_dns_record bulk_create_dns_records get_dns_record get_dns_records_by_name_type edit_dns_record edit_dns_records_by_name_type delete_dns_record delete_dns_records_by_name_type

DNSSEC

get_dnssec_records create_dnssec_record delete_dnssec_record

Domains

list_domains get_domain check_availability check_bulk_availability register_domain renew_domain transfer_domain get_transfer_status list_transfers update_auto_renew list_labels add_label remove_label create_glue update_glue get_glue delete_glue create_invite get_invite_status

Nameservers

get_name_servers update_name_servers

SSL

get_ssl_bundle

URL Forwarding

get_url_forwarding add_url_forward delete_url_forward

Account & Pricing

ping get_ip get_account_balance get_api_settings get_pricing get_pricing_for_tld list_supported_tlds request_api_key retrieve_api_key

Email & Marketplace

set_email_password get_marketplace

Audit Handler

Every mutation tool emits an audit row. The handler is configured via PORKBUN_MCP_AUDIT_HANDLER:

Value

Behavior

unset or jsonl

Append JSONL to ~/.local/share/porkbun-mcp/audit.jsonl (default)

Absolute path

Shell out to the binary with --source, --category, --action, --service, --reason, --target, --payload flags

none

Disable audit (not recommended)

Audit failures are always swallowed — mutations are never blocked by logging issues.

JSONL format

{"ts": "2026-06-12T18:00:00+00:00", "source": "porkbun-mcp", "category": "dns", "action": "POST", "service": "example.com", "target": "A `www`", "reason": "point www to new server"}

Pricing Cache

get_pricing, get_pricing_for_tld, and list_supported_tlds are served from a disk cache at $XDG_CACHE_HOME/porkbun-mcp/pricing.json (default ~/.cache/porkbun-mcp/pricing.json). TTL defaults to 24 hours; override with PORKBUN_PRICING_CACHE_TTL. Pass force_refresh=true to bypass the cache. Mutable data (DNS records, domain inventory) is never cached.

Development

git clone https://github.com/Avicennasis/porkbun-mcp-server.git
cd porkbun-mcp-server
pip install -e ".[dev]"
pytest -v

License

MIT — see LICENSE.

Available Tools

48 tools
add_labelA

Create a Porkbun label and attach it to domain. color is a Porkbun-defined color name (orange, red, blue, ...). Returns {"status": "SUCCESS", "id": <int>}. action=LABEL_ADD.

Inputs: color (required), domain (required), reason (required), label_name (required).

add_url_forwardB

Add a URL forward. type is 'permanent' (301) or 'temporary' (302). include_path and wildcard are 'yes' / 'no' Porkbun flags. subdomain="" forwards the apex. action=URLFWD_ADD.

Inputs: domain (required), reason (required), location (required), subdomain (required), +3 more.

bulk_create_dns_recordsA

Create multiple DNS records on domain. Porkbun has no native bulk endpoint — this fans out one create per record with continue-and-report semantics: failures collect in failed, successes in created. Each entry needs type / name / content; ttl / prio / notes are optional. reason is required and tags every per-record audit row.

Inputs: domain (required), reason (required), records (required).

check_availabilityA

Check whether domain (e.g. 'example.com') is available for registration.

Inputs: domain (required).

check_bulk_availabilityA

Check availability for multiple domains. Client-side fan-out — one API call per domain. Per-domain errors surface in the results map without aborting the batch.

Inputs: domains (required).

create_dns_recordC

Create a DNS record on domain. name is the subdomain ("" for apex). reason is required and goes into the audit row. Returns {"status": "SUCCESS", "id": <int>} on success.

Inputs: name (required), type (required), domain (required), reason (required), +4 more.

create_dnssec_recordA

Publish a DNSSEC DS record at the registrar. Required: key_tag, alg, digest_type, digest. Optional key_data_* fields apply only when you're also publishing the DNSKEY-derived form. reason is required and tags the audit row as action=DNSSEC_ADD.

Inputs: alg (required), digest (required), domain (required), reason (required), +7 more.

create_glueA

Create a glue record (host A/AAAA records served by the registrar). Required for custom nameservers like ns1.example.com that point at IPs you control. reason is required; audit row action=GLUE_CREATE.

Inputs: ips (required), host (required), domain (required), reason (required).

create_inviteA

Create a one-time account registration invite. The invite expires in 48 hours. email pre-fills the registration form. return_url redirects the user after registration.

Inputs: email, return_url.

delete_dns_recordC

Delete a DNS record by Porkbun's record id. reason is required.

Inputs: domain (required), reason (required), record_id (required).

delete_dns_records_by_name_typeA

Bulk-delete every record matching (type, subdomain) on domain. subdomain="" → apex. reason`` is required.

Inputs: type (required), domain (required), reason (required), subdomain (required).

delete_dnssec_recordA

Remove a DNSSEC DS record by key tag. reason is required; audit row action=DNSSEC_DELETE.

Inputs: domain (required), reason (required), key_tag (required).

delete_glueC

Remove a glue record by host name. action=GLUE_DELETE.

Inputs: host (required), domain (required), reason (required).

delete_url_forwardA

Remove a URL forward by record id (from get_url_forwarding). action=URLFWD_DELETE.

Inputs: domain (required), reason (required), record_id (required).

edit_dns_recordA

Edit an existing DNS record by Porkbun's record id. Porkbun's edit is a full replace — pass every field. reason is required.

Inputs: name (required), type (required), domain (required), reason (required), +5 more.

edit_dns_records_by_name_typeB

Bulk-edit every record matching (type, subdomain) on domain. subdomain="" → apex. reason`` is required.

Inputs: type (required), domain (required), reason (required), content (required), +4 more.

get_account_balanceA

Current Porkbun account credit balance.

Inputs: no named parameters.

get_api_settingsA

Get the account's API spend control settings and current month's spend total. All amounts are in cents.

Inputs: no named parameters.

get_dns_recordB

Fetch a single DNS record by Porkbun's record id.

Inputs: domain (required), record_id (required).

get_dns_records_by_name_typeA

Filter DNS records by type ('A','TXT','MX',...) and subdomain (empty string for apex). Useful for checking whether a specific record exists without scanning the full zone.

Inputs: type (required), domain (required), subdomain.

get_dnssec_recordsA

List the DS records Porkbun publishes for domain. Empty if DNSSEC is not enabled for the zone.

Inputs: domain (required).

get_domainA

Get detailed info for a single domain — expiry date, status, auto-renew setting, creation date, lock state, etc.

Inputs: domain (required).

get_glueA

List glue records (host A/AAAA records at the registrar) for domain. Returns an empty list if no glue records exist.

Inputs: domain (required).

get_invite_statusC

Check the status of a registration invite. Returns PENDING, ACCEPTED (with newAccountId), or EXPIRED.

Inputs: token (required).

get_ipA

Get the caller's public IP address. No authentication required (though our client always sends credentials, which is harmless). Similar to ping but without credential verification.

Inputs: no named parameters.

get_marketplaceA

Browse domains listed for sale on the Porkbun marketplace. Supports pagination (start/limit), search (query), TLD filtering, SLD length filtering, and sorting.

Inputs: tlds, limit, query, start, +4 more.

get_name_serversC

Get the active nameservers for domain.

Inputs: domain (required).

get_pricingA

Public TLD pricing table from Porkbun. Served from a disk cache (~/.cache/porkbun-mcp/pricing.json, XDG-aware) with a 24h TTL (override via PORKBUN_PRICING_CACHE_TTL, seconds). force_refresh=True bypasses the cache and refetches live.

Inputs: force_refresh.

get_pricing_for_tldA

Pricing for a single TLD (e.g. 'com'). Derived from the same cached pricing table as get_pricing — no separate API call. force_refresh=True bypasses the cache.

Inputs: tld (required), force_refresh.

get_ssl_bundleA

Retrieve Porkbun's free DV SSL certificate bundle for domain. Returns certificate chain, public key, and private key as PEM strings. The cert is auto-issued by Porkbun for zones using their nameservers.

Inputs: domain (required).

get_transfer_statusC

Get the most recent transfer record for domain.

Inputs: domain (required).

get_url_forwardingC

List URL-forwarding rules for domain.

Inputs: domain (required).

list_dns_recordsA

List ALL DNS records for domain from Porkbun's nameservers. Note: if the domain's NS is set to a non-Porkbun host, these records are not what resolvers see — they're what Porkbun has on file.

Inputs: domain (required).

list_domainsA

List all domains in the Porkbun account. start is a 0-indexed offset for pagination (Porkbun returns 1000 per page).

Inputs: start, include_labels.

list_labelsA

List all domain labels (Porkbun's tagging system).

Inputs: no named parameters.

list_supported_tldsA

All TLDs Porkbun supports for registration. Sorted alphabetically. Derived from the same cached pricing table as get_pricing. force_refresh=True bypasses the cache.

Inputs: force_refresh.

list_transfersA

List all active inbound domain transfers (excludes completed and canceled transfers).

Inputs: no named parameters.

pingA

Authenticated ping against Porkbun. Returns {"status", "yourIp"}. Useful as a readiness probe — confirms credentials work and your public IP is on Porkbun's allowlist (if you've enabled IP restriction).

Inputs: no named parameters.

register_domainA

Register a new domain using account credit. cost is in pennies (USD cents) and must exactly match the price from check_availability. agree_to_terms must be 'yes' or '1'. This is a financial operation — verify cost before calling. action=REGISTER.

Inputs: cost (required), domain (required), reason (required), agree_to_terms.

remove_labelC

Detach a label from domain by label id. action=LABEL_DELETE.

Inputs: domain (required), reason (required), label_id (required).

renew_domainA

Renew a domain using account credit. cost is in pennies (USD cents) and must exactly match the renewal price. Use check_availability with the domain to get the current price before renewing. This is a financial operation. action=RENEW.

Inputs: cost (required), domain (required), reason (required).

request_api_keyA

Initiate an API key authorization request. Returns a requestToken and authUrl for the account holder to approve. name is an optional human-readable label for the application.

Inputs: name.

retrieve_api_keyB

Poll to check whether an API key authorization request has been approved. Returns PENDING while awaiting approval, or the public API key on approval.

Inputs: request_token (required).

set_email_passwordB

Set the password for an email hosting account. email_address is the full address (e.g. user@example.com).

Inputs: password (required), email_address (required).

transfer_domainA

Initiate an inbound domain transfer. auth_code is the EPP authorization code from the current registrar. cost is in pennies and must match the transfer price. Transfers take 5–7 days. This is a financial operation. action=TRANSFER.

Inputs: cost (required), domain (required), reason (required), auth_code (required).

update_auto_renewA

Toggle auto-renewal for domain. auto_renew=True enables, False disables. reason is required; audit row action=AUTO_RENEW.

Inputs: domain (required), reason (required), auto_renew (required).

update_glueC

Replace the IPs on an existing glue record. action=GLUE_UPDATE.

Inputs: ips (required), host (required), domain (required), reason (required).

update_name_serversA

Replace domain's nameservers. ns is the new list of NS hostnames (typically 2-4). reason is required and tags the audit row (action='NS', new list goes in the payload column).

Inputs: ns (required), domain (required), reason (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 48 tools

    Disambiguation4/5

    Most tools have distinct purposes, but there is some overlap between 'list_dns_records' and 'get_dns_records_by_name_type', and between 'get_pricing' and 'get_pricing_for_tld'. Descriptions are clear enough to differentiate them, but an agent might occasionally misselect.

    Naming Consistency5/5

    Tool names consistently follow a verb_noun pattern in snake_case. Prefixes like 'bulk_' and 'check_' are used predictably. There are no mixed conventions or chaotic naming.

    Tool Count2/5

    With 48 tools, the server is quite heavy. While the domain is broad, many DNS operations could be consolidated into fewer, more parameterized tools. The count exceeds the typical well-scoped range and may overwhelm agents.

    Completeness5/5

    The tool set covers nearly every aspect of the Porkbun API: domain lifecycle, DNS management, DNSSEC, glue records, URL forwarding, pricing, account info, API keys, invites, SSL, email, and marketplace. No obvious gaps are present.

    Maintenance

    ActivityNo data
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers