spaceship-mcp

spaceship-mcp

MCP server for reading and changing DNS records via the Spaceship API, with reviewable two-step confirmation and safety restrictions. It exposes only safe DNS operations, using domain allowlisting and failing closed when not configured.

Category
访问服务器

README

spaceship-mcp

An MCP server over the Spaceship.dev API, scoped to DNS record management.

Lets an AI agent read and change DNS records through reviewable tool calls with a preview step — instead of clicking around a registrar console.


Why the surface is deliberately small

The Spaceship API exposes around 50 operations. A server that surfaced all of them would hand a connected agent the ability to:

Operation Effect
DELETE /v1/domains/{domain} delete a domain
GET /v1/domains/{domain}/transfer/auth-code return the EPP auth code — whoever holds it can transfer the domain away
PUT /v1/domains/{domain}/transfer/lock unlock a domain for transfer
PUT /v1/domains/{domain}/nameservers repoint the entire domain
POST /v1/domains/{domain}, /renew, /restore spend money
/v1/sellerhub/* list your domains for sale
/v1/hyperlift/* scale, restart and rewrite app environment variables

None of that is exposed here. Six tools ship, and there is no code path from this server to the destructive half of the API. If you need those operations, use the console — the blast radius is too large to sit behind a tool call.

Tools

Tool Writes? Notes
list_domains no paginated
get_domain no status, expiry, nameservers
list_dns_records no not gated by the allowlist — reading is safe
add_dns_records yes allowlisted domains only, two-step confirm
delete_dns_records yes deletes exactly the records passed, never a zone
get_async_operation no poll a long-running change

Safety model

Four independent layers, strongest first. Note that the strongest one is not code:

1. Scope the API key. Spaceship lets you choose scopes when minting a key. Create this one with DNS scopes only. If the key cannot delete a domain, no bug in this server can either. Nothing below substitutes for this.

2. Domain allowlist. SPACESHIP_ALLOWED_DOMAINS is checked on every write. Unset means writes are disabled entirely — failing closed is the right default for something that can take a site offline.

3. Two-step confirm. Write tools called without confirm: true change nothing. They return a preview:

  • the exact payload that would be sent
  • which sensitive record types it touches (MX, NS, CAA, TXT, SOA — the ones that silently break mail or certificate issuance)
  • the current zone, for comparison

4. force is never sent. The API documents this flag as "turn-off conflicts resolution checker and force zone update" — it disables the server-side check that stops a malformed payload clobbering a live zone. There is no code path here that sets it.

Access to the server itself is separate and also fails closed: with MCP_AUTH_TOKEN unset, every request is rejected rather than serving DNS write tools openly. The bearer comparison is constant-time.

Why HTTP, not stdio

A stdio MCP server only helps a client that can already reach spaceship.dev from its own network. Sandboxed agent environments frequently cannot — egress is often restricted to an allowlist, and the connection fails at the proxy before it reaches the API.

Hosting this over HTTP and registering it as a remote MCP connector means the connection is brokered by the MCP host rather than the agent's sandbox, which is what makes it usable from a restricted environment at all.

Configuration

cp .env.example .env
Variable Required Notes
SPACESHIP_API_KEY yes mint with DNS scopes only
SPACESHIP_API_SECRET yes paired with the key
MCP_AUTH_TOKEN yes bearer token clients present; unset = reject all
SPACESHIP_ALLOWED_DOMAINS for writes comma-separated; unset = writes disabled
PORT no default 8080
SPACESHIP_BASE_URL no default https://spaceship.dev/api

Running

npm install
npm run build
npm start

Or containerised:

docker build -t spaceship-mcp .
docker run --rm -p 8080:8080 --env-file .env spaceship-mcp

Health check — reports whether writes are enabled without revealing configuration:

curl -s localhost:8080/health
# {"status":"ok","server":{...},"protocolVersions":[...],"writesEnabled":true}

Usage

Always preview first:

// tools/call → add_dns_records   (no confirm)
{
  "domain": "example.com",
  "records": [
    { "type": "A", "name": "api", "address": "203.0.113.10", "ttl": 3600 }
  ]
}
// → returns, without changing anything
{
  "status": "preview",
  "wouldWrite": [ ... ],
  "sensitiveTypesIncluded": [],
  "currentZone": [ ... ],
  "next": "Re-run with confirm=true to apply."
}

Re-send with "confirm": true to apply.

Record shapes

Records follow the API's discriminated union on type:

Type Value field
A address (IPv4)
AAAA address (IPv6)
CNAME cname
MX exchange + preference
TXT value
NS nameserver

name is the host part only — "@" for the apex. ttl is optional, 60–3600.

Protocol

Streamable HTTP MCP, JSON-RPC 2.0 over POST /. Supported protocol versions: 2025-06-18, 2025-03-26, 2024-11-05 — the client's requested version is echoed back when supported. Old versions are kept deliberately; removing one silently breaks any client pinned to it.

Implemented methods: initialize, notifications/initialized, ping, tools/list, tools/call. Batch requests are rejected explicitly rather than half-supported.

Verified behaviour

Exercised against a locally running instance:

  • initialize echoes the client's requested protocol version when supported
  • unauthenticated POST → 401
  • write to a non-allowlisted domain → refused, naming the allowlist
  • ttl: 99999 → refused, quoting the offending value
  • allowlist unset → writesEnabled: false, writes refused

Not verified: any live call against Spaceship. That needs real credentials. Two things a first real call should confirm:

  • DELETE body shape. The spec sends the record array bare for delete but wrapped as { items: [...] } for save. That asymmetry is implemented as specified, but is the kind of detail that stays wrong until a real request proves otherwise.
  • Validation depth. type, name and ttl are validated locally; type-specific value fields are not, so an A record missing address fails at the API rather than here.

Neither is a safety hole — the allowlist, confirm step and force omission all sit in front of them.

Licence

MIT

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选