spaceship-mcp
# spaceship-mcp
[](https://opensource.org/licenses/MIT)
[](https://nodejs.org/)
[](https://github.com/bearded-giant/spaceship-mcp/actions/workflows/ci.yml)
[](https://modelcontextprotocol.io)
A community-built [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server for the [Spaceship](https://spaceship.com) API. Manage domains, DNS records, contacts, marketplace listings, and more — all through natural language via any MCP-compatible AI client.
> **Note:** This is an unofficial, community-maintained project and is not affiliated with or endorsed by Spaceship.
This repo started from [BartWaardenburg/spaceship-mcp](https://github.com/BartWaardenburg/spaceship-mcp) (MIT) and isn't published to npm. The `npx -y spaceship-mcp` commands further down install the upstream package, which doesn't have the changes below, so run this one from source instead (see [Run From Source](#run-from-source)).
| Change from upstream | Why |
|---|---|
| `create_txt_record` adds the value next to existing TXT records at that name and skips an exact duplicate | Upstream replaced every TXT at the name, so adding a second Vercel `_vercel` verification deleted the first one |
| A save that the API rejects after the old records were deleted puts those records back | Upstream left the name empty when the write failed |
| `SPACESHIP_API_KEY` and `SPACESHIP_API_SECRET` accept `op://` 1Password references, read on the first API call | Keeps the key out of client config files, and the server still starts without a 1Password prompt |
| No npm update check at startup | The check pointed at the upstream package |
## Run From Source
```bash
git clone https://github.com/bearded-giant/spaceship-mcp.git
cd spaceship-mcp
pnpm install
pnpm build
```
Then register it with your client. For Claude Code, with the key stored in 1Password and only the DNS tools turned on:
```bash
claude mcp add -s user spaceship \
-e SPACESHIP_API_KEY=op://<vault>/spaceship-api/username \
-e SPACESHIP_API_SECRET=op://<vault>/spaceship-api/credential \
-e SPACESHIP_TOOLSETS=dns \
-- node <repo-root>/dist/index.js
```
Plain key values work too if you don't use 1Password.
## Add To Your Editor
CLI one-liners — the fastest way to get started. Pick your tool:
### Claude Code
```bash
claude mcp add --scope user spaceship-mcp \
--env SPACESHIP_API_KEY=your-key \
--env SPACESHIP_API_SECRET=your-secret \
-- npx -y spaceship-mcp
```
### Codex CLI (OpenAI)
```bash
codex mcp add spaceship-mcp \
--env SPACESHIP_API_KEY=your-key \
--env SPACESHIP_API_SECRET=your-secret \
-- npx -y spaceship-mcp
```
### Gemini CLI (Google)
```bash
gemini mcp add spaceship-mcp -- npx -y spaceship-mcp
```
Set environment variables `SPACESHIP_API_KEY` and `SPACESHIP_API_SECRET` separately via `~/.gemini/settings.json`.
### VS Code (Copilot)
Open the Command Palette (`Cmd+Shift+P` / `Ctrl+Shift+P`) > `MCP: Add Server` > select **Command (stdio)**.
Or add to `.vscode/mcp.json` in your project directory:
```json
{
"servers": {
"spaceship-mcp": {
"type": "stdio",
"command": "npx",
"args": ["-y", "spaceship-mcp"],
"env": {
"SPACESHIP_API_KEY": "your-key",
"SPACESHIP_API_SECRET": "your-secret"
}
}
}
}
```
### Cursor
Add to `.cursor/mcp.json` (project-level) or `~/.cursor/mcp.json` (global):
```json
{
"mcpServers": {
"spaceship-mcp": {
"command": "npx",
"args": ["-y", "spaceship-mcp"],
"env": {
"SPACESHIP_API_KEY": "your-key",
"SPACESHIP_API_SECRET": "your-secret"
}
}
}
}
```
## Supported Clients
This MCP server works with any client that supports the Model Context Protocol, including:
| Client | Easiest install |
|---|---|
| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | One-liner: `claude mcp add` |
| [Codex CLI](https://github.com/openai/codex) (OpenAI) | One-liner: `codex mcp add` |
| [Gemini CLI](https://github.com/google-gemini/gemini-cli) (Google) | One-liner: `gemini mcp add` |
| [VS Code](https://code.visualstudio.com/) (Copilot) | Command Palette: `MCP: Add Server` |
| [Claude Desktop](https://claude.ai/download) | JSON config file |
| [Cursor](https://cursor.com) | JSON config file |
| [Windsurf](https://codeium.com/windsurf) | JSON config file |
| [Cline](https://github.com/cline/cline) | UI settings |
| [Zed](https://zed.dev) | JSON settings file |
<details>
<summary><strong>Claude Desktop, Cowork & other GUI clients (expand)</strong></summary>
### Claude Desktop / Cowork
Cowork runs inside Claude Desktop and uses the same connected MCP servers and permissions. Configure once in Claude Desktop, then the server is available in Cowork.
Add the following to your Claude Desktop config file:
| Platform | Config file |
|---|---|
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
```json
{
"mcpServers": {
"spaceship-mcp": {
"command": "npx",
"args": ["-y", "spaceship-mcp"],
"env": {
"SPACESHIP_API_KEY": "your-key",
"SPACESHIP_API_SECRET": "your-secret"
}
}
}
}
```
### Windsurf / Cline / Zed
**Windsurf** — add to `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"spaceship-mcp": {
"command": "npx",
"args": ["-y", "spaceship-mcp"],
"env": {
"SPACESHIP_API_KEY": "your-key",
"SPACESHIP_API_SECRET": "your-secret"
}
}
}
}
```
**Cline** — open Settings > MCP Servers > Edit, then add the same `mcpServers` block shown above.
**Zed** — add to your Zed settings (`~/.zed/settings.json` on macOS, `~/.config/zed/settings.json` on Linux):
```json
{
"context_servers": {
"spaceship-mcp": {
"command": "npx",
"args": ["-y", "spaceship-mcp"],
"env": {
"SPACESHIP_API_KEY": "your-key",
"SPACESHIP_API_SECRET": "your-secret"
}
}
}
}
```
### Docker
```bash
docker build -t spaceship-mcp .
docker run -i --rm \
-e SPACESHIP_API_KEY=your-key \
-e SPACESHIP_API_SECRET=your-secret \
spaceship-mcp
```
`op://` references don't resolve inside the container, since it has no 1Password CLI, so pass plain values here.
### Generic MCP Server Config
Use this as the baseline in any host:
- **Command:** `npx`
- **Args:** `["-y", "spaceship-mcp"]`
- **Required env vars:** `SPACESHIP_API_KEY`, `SPACESHIP_API_SECRET`
- **Optional env vars:** `SPACESHIP_CACHE_TTL`, `SPACESHIP_MAX_RETRIES`, `SPACESHIP_TOOLSETS` (see [Configuration](#configuration))
Host key mapping:
| Host | Top-level key | Notes |
|---|---|---|
| VS Code | `servers` | Add `"type": "stdio"` on the server object |
| Claude Desktop / Cursor / Windsurf / Cline | `mcpServers` | Same command/args/env block |
| Zed | `context_servers` | Same command/args/env block |
| Codex CLI (TOML) | `mcp_servers` | Uses TOML, shown below |
### Codex CLI (TOML config alternative)
If you prefer editing `~/.codex/config.toml` directly:
```toml
[mcp_servers.spaceship-mcp]
command = "npx"
args = ["-y", "spaceship-mcp"]
env = { "SPACESHIP_API_KEY" = "your-key", "SPACESHIP_API_SECRET" = "your-secret" }
```
### Other MCP Clients
For any MCP-compatible client, use this server configuration:
- **Command:** `npx`
- **Args:** `["-y", "spaceship-mcp"]`
- **Environment variables:** `SPACESHIP_API_KEY` and `SPACESHIP_API_SECRET`
### Claude Ecosystem Notes
Claude currently has multiple MCP-related concepts that are easy to mix up:
- **Local MCP servers (Claude Desktop):** defined in `claude_desktop_config.json` and started on your machine ([docs](https://support.claude.com/en/articles/10949351-getting-started-with-local-mcp-servers-on-claude-desktop)).
- **Cowork:** reuses the MCP servers connected in Claude Desktop ([docs](https://support.claude.com/en/articles/13345190-get-started-with-cowork)).
- **Connectors:** remote MCP integrations managed in Claude ([docs](https://support.claude.com/en/articles/11176164-use-connectors-to-extend-claude-s-capabilities)).
- **Cowork plugins:** Claude-specific workflow packaging (instructions + tools/data integrations) ([docs](https://support.claude.com/en/articles/13837440-use-plugins-in-cowork)). Useful in Claude, but not portable as a generic MCP server config for other agent clients.
Verified against vendor docs on **2026-03-05**.
### Terminology
What is portable across hosts:
- MCP server runtime settings (`command`, `args`, `env`)
- Transport model (`stdio` command server)
- Tool names and tool schemas exposed by this server
What is host/vendor-specific (not portable as-is):
- Host config key names (`servers`, `mcpServers`, `context_servers`, `mcp_servers`)
- Host UX/workflows for adding servers (CLI commands, UI menus, settings paths)
- Anthropic-specific concepts such as [Claude Desktop local MCP servers](https://docs.anthropic.com/en/docs/claude-desktop/mcp), [Claude Connectors via remote MCP](https://docs.anthropic.com/en/docs/agents-and-tools/remote-mcp-servers), and [Claude Code plugins](https://docs.anthropic.com/en/docs/claude-code/plugins) used in Cowork workflows
</details>
## Features
- **48 tools** across 8 categories covering the full Spaceship API
- **13 DNS record types** with dedicated, type-safe creation tools (A, AAAA, ALIAS, CAA, CNAME, HTTPS, MX, NS, PTR, SRV, SVCB, TLSA, TXT)
- **Complete domain lifecycle** — register, renew, transfer, and restore domains
- **SellerHub integration** — list domains for sale and generate checkout links
- **DNS alignment analysis** — compare expected vs actual records to catch misconfigurations
- **WHOIS privacy and contact management** with TLD-specific attribute support
- **Input validation** via Zod schemas on every tool for safe, predictable operations
- **8 MCP Prompts** — 5 guided workflows and 3 with argument auto-complete
- **Response caching** with configurable TTL and automatic invalidation on writes
- **Rate limit handling** with exponential backoff and `Retry-After` header support
- **Toolset filtering** to expose only the tool categories you need
- **Actionable error messages** with context-aware recovery suggestions
- **Docker support** for containerized deployment
- **Unit tests** covering the API client and every tool
## Configuration
### Required
| Variable | Description |
|---|---|
| `SPACESHIP_API_KEY` | Your Spaceship API key, or a 1Password reference like `op://Private/spaceship-api/username` |
| `SPACESHIP_API_SECRET` | Your Spaceship API secret, or a 1Password reference like `op://Private/spaceship-api/credential` |
Generate your credentials in the [Spaceship API Manager](https://www.spaceship.com/application/api-manager/).
Values starting with `op://` are read through the 1Password CLI (`op read`) on the first API call, not at startup, so the server starts without a 1Password prompt and only asks once a tool actually hits the API. You need `op` installed and signed in.
### Optional
| Variable | Description | Default |
|---|---|---|
| `SPACESHIP_CACHE_TTL` | Response cache lifetime in seconds, applied to every cached endpoint. Set to `0` to disable caching. | `120` for DNS records, domain details, and SellerHub listings; `300` for the domain list and contacts |
| `SPACESHIP_MAX_RETRIES` | Maximum retry attempts for rate-limited (429) requests with exponential backoff. | `3` |
| `SPACESHIP_TOOLSETS` | Comma-separated list of tool categories to enable (see [Toolset Filtering](#toolset-filtering)). | All toolsets |
## API Key Setup
### Creating Your API Key
1. Log in to your [Spaceship account](https://www.spaceship.com)
2. Navigate to **API Manager** ([direct link](https://www.spaceship.com/application/api-manager/))
3. Click **New API key**
4. Give the key a descriptive name (e.g. "MCP Server")
5. Select the scopes you need (see below)
6. Copy both the **API key** and **API secret** — the secret is only shown once
### Available Scopes
Each scope controls access to a specific part of the Spaceship API. When creating your key, enable only the scopes you need.
| Scope | Access |
|---|---|
| `domains:read` | List domains, check availability, view domain details and settings |
| `domains:write` | Modify domain settings (nameservers, auto-renew, contacts, privacy) |
| `domains:billing` | Register, renew, restore, and transfer domains (financial operations) |
| `domains:transfer` | Transfer lock, auth codes, and transfer status |
| `contacts:read` | Read saved contact profiles and attributes |
| `contacts:write` | Create and update contact profiles and attributes |
| `dnsrecords:read` | List DNS records for your domains |
| `dnsrecords:write` | Create, update, and delete DNS records |
| `sellerhub:read` | View marketplace listings and verification records |
| `sellerhub:write` | List/delist domains for sale, update pricing, generate checkout links |
| `asyncoperations:read` | Poll status of async operations (registration, renewal, transfer) |
### Scopes Per Feature
The table below shows which scopes are required for each group of tools.
| Feature | Tools | Required scopes |
|---|---|---|
| **DNS Records** | `list_dns_records` | `dnsrecords:read` |
| | `save_dns_records`, `delete_dns_records`, all `create_*_record` tools | `dnsrecords:read` `dnsrecords:write` |
| **Domain Info** | `list_domains`, `get_domain`, `check_domain_availability` | `domains:read` |
| **Domain Settings** | `update_nameservers`, `set_auto_renew`, `set_privacy_level`, `set_email_protection`, `update_domain_contacts` | `domains:write` |
| **Domain Lifecycle** | `register_domain`, `renew_domain`, `restore_domain`, `transfer_domain` | `domains:billing` |
| **Transfer** | `set_transfer_lock`, `get_auth_code`, `get_transfer_status` | `domains:transfer` |
| **Contacts** | `get_contact`, `get_contact_attributes` | `contacts:read` |
| | `save_contact`, `save_contact_attributes` | `contacts:write` |
| **Personal NS** | `list_personal_nameservers`, `get_personal_nameserver` | `domains:read` |
| | `update_personal_nameserver`, `delete_personal_nameserver` | `domains:write` |
| **SellerHub** | `list_sellerhub_domains`, `get_sellerhub_domain`, `get_verification_records` | `sellerhub:read` |
| | `create_sellerhub_domain`, `update_sellerhub_domain`, `delete_sellerhub_domain`, `create_checkout_link` | `sellerhub:write` |
| **Async Operations** | `get_async_operation` | `asyncoperations:read` |
| **Analysis** | `check_dns_alignment` | `dnsrecords:read` |
### Recommended Scope Presets
**Full access** — enable everything for unrestricted use:
```
domains:read domains:write domains:billing domains:transfer
contacts:read contacts:write
dnsrecords:read dnsrecords:write
sellerhub:read sellerhub:write
asyncoperations:read
```
**DNS management only** — just read/write DNS records:
```
dnsrecords:read dnsrecords:write
```
**Read-only** — browse domains and records without making changes:
```
domains:read contacts:read dnsrecords:read sellerhub:read asyncoperations:read
```
## Available Tools
### DNS Records
| Tool | Description |
|---|---|
| `list_dns_records` | List all DNS records for a domain with pagination |
| `save_dns_records` | Save (upsert) DNS records — replaces records with the same name and type |
| `delete_dns_records` | Delete DNS records by name and type |
### Type-Specific Record Creation
Each DNS record type has a dedicated tool with type-safe parameters and validation.
| Tool | Description |
|---|---|
| `create_a_record` | Create an A record (IPv4 address) |
| `create_aaaa_record` | Create an AAAA record (IPv6 address) |
| `create_alias_record` | Create an ALIAS record (CNAME flattening at zone apex) |
| `create_caa_record` | Create a CAA record (Certificate Authority Authorization) |
| `create_cname_record` | Create a CNAME record (canonical name) |
| `create_https_record` | Create an HTTPS record (SVCB-compatible) |
| `create_mx_record` | Create an MX record (mail exchange) |
| `create_ns_record` | Create an NS record (nameserver delegation) |
| `create_ptr_record` | Create a PTR record (reverse DNS) |
| `create_srv_record` | Create an SRV record (service locator) |
| `create_svcb_record` | Create an SVCB record (general service binding) |
| `create_tlsa_record` | Create a TLSA record (DANE/TLS certificate association) |
| `create_txt_record` | Create a TXT record (text data) |
### Domain Management
| Tool | Description |
|---|---|
| `list_domains` | List all domains in the account with pagination |
| `get_domain` | Get detailed domain information |
| `check_domain_availability` | Check availability for up to 20 domains at once |
| `update_nameservers` | Update nameservers for a domain |
| `set_auto_renew` | Toggle auto-renewal for a domain |
| `set_transfer_lock` | Toggle transfer lock for a domain |
| `get_auth_code` | Get the transfer auth/EPP code |
### Domain Lifecycle
| Tool | Description |
|---|---|
| `register_domain` | Register a new domain (financial operation, async) |
| `renew_domain` | Renew a domain registration (financial operation, async) |
| `restore_domain` | Restore a domain from redemption grace period (financial operation, async) |
| `transfer_domain` | Transfer a domain to Spaceship (financial operation, async) |
| `get_transfer_status` | Check the status of a domain transfer |
| `get_async_operation` | Poll the status of an async operation by its operation ID |
### Contacts & Privacy
| Tool | Description |
|---|---|
| `save_contact` | Create or update a reusable contact profile |
| `get_contact` | Retrieve a saved contact by ID |
| `save_contact_attributes` | Save TLD-specific contact attributes (e.g. tax IDs) |
| `get_contact_attributes` | Retrieve all stored contact attributes |
| `update_domain_contacts` | Update domain contacts (registrant, admin, tech, billing) |
| `set_privacy_level` | Set WHOIS privacy level (high or public) |
| `set_email_protection` | Toggle contact form display in WHOIS |
### Personal Nameservers
| Tool | Description |
|---|---|
| `list_personal_nameservers` | List vanity/glue nameservers for a domain |
| `get_personal_nameserver` | Get details of a personal nameserver by hostname |
| `update_personal_nameserver` | Create or update a personal nameserver (glue record) |
| `delete_personal_nameserver` | Delete a personal nameserver |
### SellerHub
| Tool | Description |
|---|---|
| `list_sellerhub_domains` | List domains for sale on the marketplace |
| `create_sellerhub_domain` | List a domain for sale with pricing |
| `get_sellerhub_domain` | Get listing details |
| `update_sellerhub_domain` | Update listing display name, description, and pricing |
| `delete_sellerhub_domain` | Remove a listing from the marketplace |
| `create_checkout_link` | Generate a buy-now checkout link for a listing |
| `get_verification_records` | Get DNS verification records for a listing |
### Analysis
| Tool | Description |
|---|---|
| `check_dns_alignment` | Compare expected vs actual DNS records to detect missing or unexpected entries |
## MCP Prompts
Prompts provide guided workflows that clients can present as slash commands or quick actions.
### Guided Workflows
| Prompt | Description |
|---|---|
| `setup-domain` | Register and configure a new domain (availability check, registration, DNS, privacy) |
| `audit-domain` | Health check for an existing domain (status, DNS, privacy, auto-renew, contacts) |
| `setup-email` | Configure email DNS records for Google Workspace, Microsoft 365, Fastmail, or a custom provider |
| `migrate-dns` | Step-by-step guide to migrate DNS records to Spaceship |
| `list-for-sale` | List a domain on the SellerHub marketplace with pricing and checkout link |
### Auto-Complete Prompts
These prompts support argument auto-complete for domain names and common values:
| Prompt | Description |
|---|---|
| `dns-records` | List DNS records with domain and record type auto-complete |
| `set-privacy` | Set WHOIS privacy with domain and level auto-complete |
| `update-nameservers` | Update nameservers with domain and provider auto-complete |
## Toolset Filtering
Reduce context window usage by enabling only the tool categories you need. Set the `SPACESHIP_TOOLSETS` environment variable to a comma-separated list:
```bash
SPACESHIP_TOOLSETS=dns,domains
```
| Toolset | Tools included |
|---|---|
| `domains` | Domain management and lifecycle tools |
| `dns` | DNS records, record creators, and analysis |
| `contacts` | Contact and privacy management |
| `privacy` | Privacy management (same tools as `contacts`) |
| `nameservers` | Personal nameserver management |
| `sellerhub` | SellerHub marketplace tools |
| `availability` | Domain availability checking |
When not set, all toolsets are enabled. Invalid names are ignored; if all names are invalid, all toolsets are enabled as a fallback.
## Security Notes
- **Trust model:** Any prompt or agent allowed to call this MCP server can execute Spaceship API actions with the configured credentials.
- **Least-privilege credentials:** Use separate Spaceship API keys per environment/team/use case and enable only the scopes you need (see [Available Scopes](#available-scopes)).
- **Write-action approvals:** Enable host-side approvals for mutating tools (`register_domain`, `create_*`, `update_*`, `delete_*`, `save_*`, `set_*`, and lifecycle operations).
- **Team config governance:** Keep shared MCP config in version control, require review for changes to command/args/env/toolset filtering, and keep secrets in a vault or host secret manager (not in plain-text repo files).
## Example Usage
Once connected, you can interact with the Spaceship API using natural language:
- "List all my domains"
- "Check if example.com is available for registration"
- "Create an A record for api.example.com pointing to 203.0.113.10"
- "Set up MX records for example.com to use Google Workspace"
- "Enable WHOIS privacy on example.com"
- "Check if my DNS records for example.com match what I expect"
- "List my domains for sale on SellerHub"
- "Transfer example.com to Spaceship"
## Community
- Support: [SUPPORT.md](SUPPORT.md)
- Security reporting: [SECURITY.md](SECURITY.md)
- Contributing guidelines: [CONTRIBUTING.md](CONTRIBUTING.md)
- Bug reports and feature requests: [Issues](https://github.com/bearded-giant/spaceship-mcp/issues)
## Development
```bash
# Install dependencies
pnpm install
# Run in development mode
pnpm dev
# Build for production
pnpm build
# Run tests
pnpm test
# Type check
pnpm typecheck
```
### Project Structure
```
src/
index.ts # Entry point (stdio transport)
server.ts # MCP server setup, toolset filtering, feature registration
spaceship-client.ts # Spaceship API HTTP client with caching and retry
cache.ts # TTL-based in-memory response cache
schemas.ts # Shared Zod validation schemas
types.ts # TypeScript interfaces
tool-result.ts # Error formatting with recovery suggestions
prompts.ts # MCP Prompts (8 prompts, with argument auto-complete)
credentials.ts # Resolves op:// credential references via the 1Password CLI
dns-utils.ts # DNS record formatting utilities
tools/
dns-records.ts # List, save, delete DNS records
dns-record-creators.ts # 13 type-specific DNS record creation tools
domain-management.ts # Domain listing, settings, nameservers
domain-lifecycle.ts # Registration, renewal, transfer, restore
contacts-privacy.ts # Contact profiles and WHOIS privacy
personal-nameservers.ts # Vanity/glue nameserver management
sellerhub.ts # Marketplace listing and checkout tools
analysis.ts # DNS alignment analysis
```
## Requirements
- Node.js >= 20
- A [Spaceship](https://spaceship.com) account with API credentials
## License
MIT - see [LICENSE](LICENSE) for details.
TDQS
Scored across 48 tools
Most tools have clearly distinct resource/action boundaries, and the many DNS record creation tools are differentiated by record type. There is some overlap between save_dns_records and the type-specific create_*_record tools, but the descriptions explain when to use each.
Names generally follow a predictable snake_case verb_noun pattern such as list_domains, get_domain, create_a_record, and delete_sellerhub_domain. A few names omit the resource or use slightly different phrasing, such as update_nameservers, but the convention remains readable and consistent overall.
With 48 tools, the surface is very large for a single MCP server. Much of the count comes from separate DNS record-type creation tools, which could likely be consolidated or parameterized to reduce the tool burden.
The server covers most domain lifecycle, DNS, contact, nameserver, and SellerHub marketplace operations, including registration, renewal, transfer, restore, and async polling. Minor gaps exist, such as listing/deleting saved contacts or explicit domain deletion, but core workflows are well covered.