loading…
Search for a command to run...
loading…
Production-grade MCP server for the Gandi v5 API, enabling domain, DNS, email, billing, organization, and certificate management through natural language with a
Production-grade MCP server for the Gandi v5 API, enabling domain, DNS, email, billing, organization, and certificate management through natural language with a three-tier safety model.
Production-grade Python MCP server for the Gandi v5 API.
Under active development — see CLAUDE.md for the architectural overview.
sharing_id scoping for reseller / multi-org accounts# Install from source
git clone https://github.com/millsmillsymills/gandi-mcp.git
cd gandi-mcp
uv sync --extra dev
# Configure
cp .env.example .env
# Edit .env — at minimum set GANDI_TOKEN
# Run
uv run gandi-mcp
To install gandi-mcp as a global binary on PATH (useful when wiring it into Claude Code without a per-project checkout):
# From the cloned repo
uv tool install /absolute/path/to/gandi-mcp
# Refresh after pulling new commits
uv tool upgrade --reinstall gandi-mcp
# Verify
gandi-mcp --help
See .env.example for every option.
| Variable | Default | Description |
|---|---|---|
GANDI_TOKEN |
— | Required. Personal Access Token from https://admin.gandi.net/ |
GANDI_SHARING_ID |
— | Optional organization UUID to scope all requests to |
GANDI_MODE |
readonly |
readonly hides all write tools; readwrite exposes them |
GANDI_ALLOW_PURCHASES |
false |
When true AND GANDI_MODE=readwrite, exposes tools that spend money |
GANDI_API_BASE_URL |
https://api.gandi.net |
Override only for testing |
GANDI_REQUEST_TIMEOUT |
30 |
Request timeout in seconds |
GANDI_MAX_RETRIES |
3 |
Retry attempts on connection errors |
Three tiers, two orthogonal gates:
| Mode | Purchases | Tools visible |
|---|---|---|
readonly (default) |
n/a | Read tools only |
readwrite |
false (default) |
Read + non-purchasing writes (DNS records, contacts, mailbox edits, cert revoke, …) |
readwrite |
true |
Everything including gandi_domain_register, gandi_domain_renew, gandi_domain_transfer_in, gandi_email_create_mailbox, gandi_email_create_slot, gandi_email_renew_mailbox, gandi_cert_issue, gandi_cert_renew |
Defense-in-depth: every write tool also checks the mode at handler time, and every purchase tool also checks the purchase flag, so a stale tool list cached by an MCP client can't slip a write through.
Register the server in ~/.claude.json (global) or .claude/settings.json (project).
With a global install (uv tool install, recommended for global config — no project directory required):
{
"mcpServers": {
"gandi": {
"command": "gandi-mcp",
"env": {
"GANDI_TOKEN": "your-bearer-pat-here",
"GANDI_MODE": "readonly",
"GANDI_ALLOW_PURCHASES": "false"
}
}
}
}
From a working copy (picks up local edits live):
{
"mcpServers": {
"gandi": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/gandi-mcp", "run", "gandi-mcp"]
}
}
}
In the working-copy form, environment variables are read from .env in the project directory. In the global-install form, set them under env in the JSON or via your shell environment.
Default the global config to GANDI_MODE=readonly until you actively need writes — every session inherits the mode you set here.
Gaps in Gandi's v5 REST API that this server cannot work around. Each requires manual action in the Gandi web UI:
clientTransferProhibited in gandi_domain_get_domain / gandi_domain_get_status responses but exposes no PATCH/PUT endpoint to set it. Unlock from Domains → <domain> → Transfer lock before initiating a registrar transfer-out.gandi_email_refund_slot only refunds an unused slot within the refund window — there is no v5 endpoint to stop a recurring email subscription. Cancel from Billing → Subscriptions.# Lint and format
uv run ruff check src/ tests/
uv run ruff format --check src/ tests/
# Type check
uv run ty check src/gandi_mcp/
# Unit tests
uv run pytest tests/unit/ -v
# Full suite with coverage (matches CI gate: >=85% total, >=70% tools/*.py, >=90% core)
uv run pytest -m "not live" --cov=gandi_mcp --cov-report=term-missing --cov-report=json
uv run python scripts/check_coverage_thresholds.py
# Pre-commit hooks
uv run pre-commit install
Apache-2.0 — see LICENSE.
Run in your terminal:
claude mcp add gandi-mcp -- npx Security
Low riskAutomated heuristic from public metadata — not a security guarantee.