Deploy static websites from AI agents. Free at mcp.shipstatic.com — no install, no signup.
ShipStatic MCP (com.shipstatic/mcp)
ShipStatic MCP deploys static websites from AI agents. It is available both as a free hosted service at https://mcp.shipstatic.com and as a local alternative package (com.shipstatic/mcp). The server provides a fixed set of tools and is intended for agent-driven publishing without installing Node.js or requiring an API key for the hosted option.
🛠️ Key Features
Deploy static websites from AI agents
Hosted at https://mcp.shipstatic.com with one URL
Local alternative package: com.shipstatic/mcp
15 tools
🚀 Use Cases
Publish a website in an agent’s next message via an MCP client
Deploy a folder on your own machine using the local alternative
Prefer token configuration over signing in when needed
⚡ Developer Benefits
“No install, no Node.js, no signup, no API key” for the hosted server
Same fifteen tools available via hosted and local setup
Works when a client does not speak OAuth (via local alternative)
⚠️ Limitations
Focuses on deploying static sites (not described for dynamic hosting)
Hosted usage described as “no signup,” but local setup implies token/configuration needs
Deploy a static site to a live URL: free, no account or API key required.
**File content is plain text by default.** Pass HTML/CSS/JS/JSON/SVG/etc. directly in each file's `content` as a regular string. Only set `encoding: "base64"` per-file for binary content (images, fonts) — do not base64-encode text.
Returns the live URL. Without a connected account, the response also includes a one-time claim URL, and the site expires in 3 days unless claimed. Pass `password` to make the site private.
Parameters5
files
array
required
Files that make up the site. The site root is implied by these paths.
labels
array
optional
Labels for organizing deployments (e.g. ["production", "v1.2"]). Lowercase, 3-25 chars, allows . _ - separators. Up to 10.
password
string
optional
Optional password to gate the deployment behind an unlock prompt (6–128 characters; whitespace significant). Visitors must enter this password before viewing the site, including on any custom domains pointing at it.
idempotencyKey
string
optional
Makes this deploy replayable instead of repeatable. A deploy is not naturally idempotent: if a call times out you cannot tell "it never landed" from "it landed and the response was lost", and retrying creates a second deployment. Send the same key on the retry and the original deployment is replayed instead (within 24 hours). Key the ATTEMPT — a run id, a commit sha, a uuid minted before the first try — never one minted fresh on each retry, which would defeat the point.
ttl
number
optional
Seconds until this deployment expires and the platform reclaims it; omit for one that never does. Only for authenticated deploys — an anonymous deployment already expires on the platform's schedule, and a requested ttl on one is refused. A deployment carrying a ttl cannot be linked to a custom domain: deploy without one if the site needs a domain.
Raw schema
{
"type": "object",
"properties": {
"files": {
"type": "array",
"items": {
"type": "object",
"properties": {
"path": {
"type": "string",
"description": "Relative path within the site (e.g. \"index.html\", \"assets/app.css\"). No leading slash; no parent-folder wrapping."
},
"content": {
"type": "string",
"description": "File content as a plain text string. For HTML, CSS, JS, JSON, SVG, plain text — pass directly with no encoding step. For binary files (images, fonts) ONLY, set this entry's `encoding: \"base64\"` and pass base64-encoded bytes."
},
"encoding": {
"description": "Defaults to `\"utf-8\"` (raw text). Set to `\"base64\"` ONLY for binary files. Never base64-encode text content — pass it as a plain string.",
"type": "string",
"enum": [
"utf-8",
"base64"
]
}
},
"required": [
"path",
"content"
]
},
"description": "Files that make up the site. The site root is implied by these paths."
},
"labels": {
"description": "Labels for organizing deployments (e.g. [\"production\", \"v1.2\"]). Lowercase, 3-25 chars, allows . _ - separators. Up to 10.",
"type": "array",
"items": {
"type": "string"
}
},
"password": {
"description": "Optional password to gate the deployment behind an unlock prompt (6–128 characters; whitespace significant). Visitors must enter this password before viewing the site, including on any custom domains pointing at it.",
"type": "string"
},
"idempotencyKey": {
"description": "Makes this deploy replayable instead of repeatable. A deploy is not naturally idempotent: if a call times out you cannot tell \"it never landed\" from \"it landed and the response was lost\", and retrying creates a second deployment. Send the same key on the retry and the original deployment is replayed instead (within 24 hours). Key the ATTEMPT — a run id, a commit sha, a uuid minted before the first try — never one minted fresh on each retry, which would defeat the point.",
"type": "string"
},
"ttl": {
"description": "Seconds until this deployment expires and the platform reclaims it; omit for one that never does. Only for authenticated deploys — an anonymous deployment already expires on the platform's schedule, and a requested ttl on one is refused. A deployment carrying a ttl cannot be linked to a custom domain: deploy without one if the site needs a domain.",
"type": "number"
}
},
"required": [
"files"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
deployments_list
List all deployments with their URLs, status, labels, and password protection state. The response's `cursor` is null on the last page; pass it back as `cursor` to fetch the next.
Parameters2
limit
integer
optional
Maximum number of items to return in one page. Omit for the server default.
cursor
string
optional
Opaque position from the previous response's `cursor` field; omit for the first page.
Raw schema
{
"type": "object",
"properties": {
"limit": {
"description": "Maximum number of items to return in one page. Omit for the server default.",
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"cursor": {
"description": "Opaque position from the previous response's `cursor` field; omit for the first page.",
"type": "string"
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
deployments_get
Get deployment details including URL, status, file count, size, labels, and password protection state.
Parameters1
deployment
string
required
Deployment hostname (e.g. "happy-cat-abc1234.shipstatic.com"). Returned by deployments_upload or deployments_list.
Raw schema
{
"type": "object",
"properties": {
"deployment": {
"type": "string",
"description": "Deployment hostname (e.g. \"happy-cat-abc1234.shipstatic.com\"). Returned by deployments_upload or deployments_list."
}
},
"required": [
"deployment"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
deployments_set
Update deployment labels. Replaces all existing labels.
Parameters2
deployment
string
required
Deployment hostname (e.g. "happy-cat-abc1234.shipstatic.com"). Use deployments_list to find deployments.
labels
array
required
Labels to set. Replaces all existing labels. Pass empty array to clear.
Create or update a custom domain. Can reserve a name (omit deployment), link it to a deployment, switch deployments, or update labels. domains_records then returns the DNS records to configure.
Parameters3
domain
string
required
Domain name (e.g. "www.example.com" or "blog.example.com")
deployment
string
optional
Deployment to serve on this domain (e.g. "happy-cat-abc1234.shipstatic.com"). Omit to reserve the domain without linking.
labels
array
optional
Labels for organizing domains (e.g. ["production"]).
Raw schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "Domain name (e.g. \"www.example.com\" or \"blog.example.com\")"
},
"deployment": {
"description": "Deployment to serve on this domain (e.g. \"happy-cat-abc1234.shipstatic.com\"). Omit to reserve the domain without linking.",
"type": "string"
},
"labels": {
"description": "Labels for organizing domains (e.g. [\"production\"]).",
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"domain"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
domains_list
List all domains with their URLs, linked deployment, and verification status. The response's `cursor` is null on the last page; pass it back as `cursor` to fetch the next.
Parameters2
limit
integer
optional
Maximum number of items to return in one page. Omit for the server default.
cursor
string
optional
Opaque position from the previous response's `cursor` field; omit for the first page.
Raw schema
{
"type": "object",
"properties": {
"limit": {
"description": "Maximum number of items to return in one page. Omit for the server default.",
"type": "integer",
"minimum": 1,
"maximum": 9007199254740991
},
"cursor": {
"description": "Opaque position from the previous response's `cursor` field; omit for the first page.",
"type": "string"
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
domains_get
Get domain details including URL, linked deployment, verification status, and labels.
Parameters1
domain
string
required
Domain name (e.g. "www.example.com"). Use domains_list to find names.
Raw schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "Domain name (e.g. \"www.example.com\"). Use domains_list to find names."
}
},
"required": [
"domain"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
domains_records
Returns the DNS records to configure at the domain's DNS provider. Call after domains_set.
Parameters1
domain
string
required
Domain name. Must be a domain previously created with domains_set.
Raw schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "Domain name. Must be a domain previously created with domains_set."
}
},
"required": [
"domain"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
domains_dns
Returns the DNS provider recorded for the domain, if known (e.g. Cloudflare, Namecheap): where its DNS records are configured.
Parameters1
domain
string
required
Domain name (e.g. "www.example.com"). Must be a domain previously created with domains_set.
Raw schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "Domain name (e.g. \"www.example.com\"). Must be a domain previously created with domains_set."
}
},
"required": [
"domain"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
domains_share
Returns a shareable DNS setup URL that needs no API key, for whoever manages the domain's DNS.
Parameters1
domain
string
required
Domain name to generate a share link for. Must be a domain previously created with domains_set.
Raw schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "Domain name to generate a share link for. Must be a domain previously created with domains_set."
}
},
"required": [
"domain"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
domains_validate
Check if a domain name is valid and available before creating it. Returns the normalized form and availability.
Parameters1
domain
string
required
Domain name to check (e.g. "www.example.com"). Call before domains_set to check availability.
Raw schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "Domain name to check (e.g. \"www.example.com\"). Call before domains_set to check availability."
}
},
"required": [
"domain"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
domains_verify
Trigger DNS verification for a custom domain. Call after the user has configured DNS records from domains_records. Verification is asynchronous — the domain status updates once DNS propagates.
Parameters1
domain
string
required
Domain name to verify DNS for. Must be a domain previously created with domains_set.
Raw schema
{
"type": "object",
"properties": {
"domain": {
"type": "string",
"description": "Domain name to verify DNS for. Must be a domain previously created with domains_set."
}
},
"required": [
"domain"
],
"$schema": "http://json-schema.org/draft-07/schema#"
}
⚡ You probably don't need to install this. The same server is hosted at https://mcp.shipstatic.com — drop that URL into any MCP client and your agent can publish a website in its next message. No install, no Node.js, no signup, no API key.
This package is the local alternative. Install it when your agent needs to deploy a folder on your own machine, when you'd rather configure a token once than sign in, or when your client doesn't speak OAuth yet — the same fifteen tools, reached the other way. Local setup ↓
Deploy static websites, landing pages, and prototypes instantly from AI agents. Ask yours to put your site online and get back a real, shareable link in seconds.
Your agent publishes the files and answers with two links:
The live site — a real URL you can share right away.
A claim link — the site stays live for 3 days; open the claim link to keep it forever. A free account is all it takes.
Want the site private? Ask for a password — visitors must enter it before they can see anything.
Then connect, if you want more
Everything above works with no account at all. Connect one when your client offers to sign you in, and the same URL answers with the rest: everything you've shipped, your own domains, and sites that stay up permanently. Nothing to install, no key to paste — your client starts the sign-in itself.
Local: the same tools, from your own machine
Install this package when your agent needs to deploy a folder on your own machine — the hosted endpoint takes files inline, so it has no path to read from — when you'd rather configure a token once than sign in, or when your MCP client doesn't speak OAuth yet.
The config asks for one thing: SHIP_TOKEN. Its value is your API key — one credential, two names. The console mints it as an API key (it starts with ship-), and the setting that carries it is called the token. Get yours free at my.shipstatic.com/api-key, paste it where the snippets below show ship-your-api-key, and every site you publish lands in your account and never expires, with a rate limit of your own instead of the shared anonymous pools.
The key is optional: leave it out and the local server behaves exactly like the hosted endpoint with no account connected — public sites, claim links, live for 3 days.
The server runs with npx, which ships with Node.js (20.19 or newer).
Claude Code
bash
claude mcp add shipstatic -e SHIP_TOKEN=ship-your-api-key -- npx -y @shipstatic/mcp
Same config shape — npx -y @shipstatic/mcp, with SHIP_TOKEN in env. Works with any MCP-compatible client.
Tools
All fifteen tools are on both doors. What changes is not which tools exist, but which ones answer: deployments_upload is the one that needs no account, and the other fourteen answer once you have connected one (hosted) or set SHIP_TOKEN (local).
Publishing — no account needed
Tool
Description
deployments_upload
Publish files and get a live URL instantly, optionally protected by a password
Deployments — with an account
Tool
Description
deployments_list
List all deployments with their URLs, status, labels, and password protection state. Pages with limit and cursor
deployments_get
Get deployment details including URL, status, file count, size, labels, and password protection state
deployments_set
Update the labels on a deployment for organization and filtering
deployments_delete
Permanently delete a deployment and all its files
Domains — with an account
Tool
Description
domains_set
Connect a custom domain to your site, switch deployments, or update labels
domains_list
List all domains with their linked deployment and verification status. Pages with limit and cursor
domains_get
Get domain details including linked deployment, verification status, and labels
domains_records
Get the DNS records you need to configure at your DNS provider
domains_dns
The DNS provider recorded for a domain, if known (e.g. Cloudflare, Namecheap)
domains_share
Get a shareable link so someone else can see the required DNS records
domains_validate
Check if a domain name is valid and available before connecting it
domains_verify
Check if DNS is configured correctly after you set up the records
domains_delete
Permanently disconnect and delete a custom domain
Account — with an account
Tool
Description
whoami
Your account's email, name, plan, current usage and plan caps
Paging long lists
deployments_list and domains_list accept limit and cursor. Each response carries a cursor — pass it back to fetch the next page; null means you are on the last one.
Retrying a deploy safely
deployments_upload accepts an idempotencyKey. If a deploy times out you cannot tell "it never landed" from "it landed and the response was lost", and retrying without a key creates a second site. Send the same key on the retry and the original deployment is returned instead.
Key the attempt, not the try — a run id, a commit sha, or a uuid generated before the first call. A key that changes on every retry does nothing.
Deployments that clean themselves up
deployments_upload accepts a ttl in seconds. The deployment expires when the time is up and the platform reclaims it — handy for previews and throwaway iterations you would otherwise have to remember to delete.
json
{"path":"/path/to/dist","ttl":3600}
It needs an account — SHIP_TOKEN here, a connected account on the hosted endpoint: a deploy with no account already expires on the platform's schedule, so a ttl on one is refused rather than ignored. A deployment carrying a ttl cannot be linked to a custom domain — deploy without one when the site needs a domain.
Registry
Published to the MCP Registry as com.shipstatic/mcp. Registry-aware clients see both the hosted endpoint and the local install and pick whichever fits their environment.
Your API key — one credential, two names: the console mints it as an API key (ship-...), and this setting carries it as the token. Free at https://my.shipstatic.com/api-key. Optional: without it, deploys behave like the hosted endpoint (public, claim URL, 3-day expiry). With it, deployments are permanent, the full toolset (custom domains, listing, account-tied ops) unlocks, and rate limits are your own instead of the shared anonymous pools.