MCP Server

Last updated: 2026-09-08

hdply ships a built-in MCP server. Any MCP client — Claude Code, Claude Desktop, or your own agent — can list your sites, create one, read the HTML that is live, publish a new version, and inspect the deploy history. Five tools, one API key, nothing to run locally.

Safe to hand to an agent

There is no delete tool. Removing a site is web-console only, by design. An agent with full deploy rights can publish a bad version, but it cannot destroy your work.

Every deploy — human or agent — is versioned. A wrong deploy is one click away from being restored in the console, and get_deploy_history shows exactly which deploys came through MCP ("source": "mcp"). That is the difference from a general-purpose deployment MCP: hdply is scoped to one HTML file per site, so the worst case is a page that looks wrong for a minute.

The main use case

Claude writes you a page — a proposal, a dashboard, a mockup — as an HTML artifact. Instead of saving the file and uploading it somewhere, you say "publish this" and the same conversation ends with a public URL you can send. Later, "change the heading and republish" is another single turn.

Connect

Claude Code, one command:

claude mcp add --transport http hdply https://api.app.hdply.com/mcp \
  --header "Authorization: Bearer hdply_sk_…"

Claude Desktop, in claude_desktop_config.json (through mcp-remote, since Desktop only launches local commands):

{
  "mcpServers": {
    "hdply": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://api.app.hdply.com/mcp",
               "--header", "Authorization: Bearer hdply_sk_…"]
    }
  }
}

Any other client: it is a stateless Streamable HTTP endpoint. Send JSON-RPC to the URL below with the same bearer header.

POST https://api.app.hdply.com/mcp
Authorization: Bearer hdply_sk_…
Content-Type: application/json

{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}

The key comes from the console dashboard ("API key" card). It is shown once, and it grants access to every site on the account — treat it like a password.

Tools

Each tool takes a JSON object and returns text content. Errors come back as text with isError: true, never as a transport failure, so an agent can read the reason and try again.

list_sites

Every site you can manage, personal and team, with its live URL and whether anything is deployed yet. No arguments.

Example call

{ "name": "list_sites", "arguments": {} }

Result

[
  {
    "id": 42,
    "name": "Q3 proposal",
    "subroute": "k3v9x2m7q1",
    "url": "https://k3v9x2m7q1.hdply.com",
    "live": true
  },
  {
    "id": 43,
    "name": "Launch page",
    "subroute": "launch",
    "url": "https://launch.hdply.com",
    "live": false,
    "team_id": 7,
    "team_name": "Design"
  }
]

create_site

Create a site. With html it is live the moment the call returns, at a random subdomain the server assigns; without it, the site exists empty until deploy_site.

Input

{
  "html":    string   // optional — full HTML document, max 1 MB; live immediately when given
  "name":    string   // optional — falls back to the HTML <title>
  "team_id": number   // optional — create inside a team (0 = personal)
}

Example call

{
  "name": "create_site",
  "arguments": {
    "html": "<!doctype html><html><head><title>Q3 proposal</title></head><body><h1>Q3 proposal</h1></body></html>"
  }
}

Result

Site "Q3 proposal" live at https://k3v9x2m7q1.hdply.com (id 42, subroute k3v9x2m7q1)

get_site_html

The HTML that visitors currently get. Use it before an edit so the agent changes what is actually live, not what it remembers.

Input

{
  "site": string   // required — numeric project id ("42") or subdomain ("k3v9x2m7q1")
}

Example call

{ "name": "get_site_html", "arguments": { "site": "k3v9x2m7q1" } }

Result

<!doctype html><html><head><title>Q3 proposal</title>…

deploy_site

Publish new HTML to an existing site. Live when the call returns, versioned like every other deploy, tagged mcp in the history.

Input

{
  "site": string   // required — numeric project id or subdomain
  "html": string   // required — full HTML document, max 1 MB
}

Example call

{
  "name": "deploy_site",
  "arguments": {
    "site": "k3v9x2m7q1",
    "html": "<!doctype html>…"
  }
}

Result

Deployed. Live at https://k3v9x2m7q1.hdply.com

get_deploy_history

The deploy history: who, when, how big, and through which path (web, api, mcp, restore). Newest first.

Input

{
  "site": string   // required — numeric project id ("42") or subdomain ("k3v9x2m7q1")
}

Example call

{ "name": "get_deploy_history", "arguments": { "site": "k3v9x2m7q1" } }

Result

[
  {
    "id": 918,
    "size": 4812,
    "hash": "3f9c1a7b2d4e6f80",
    "source": "mcp",
    "actor_email": "you@example.com",
    "created_at": "2026-09-08T09:41:12Z"
  },
  {
    "id": 902,
    "size": 4790,
    "hash": "b81e0c5d9a2f4711",
    "source": "web",
    "actor_email": "you@example.com",
    "created_at": "2026-09-07T18:02:55Z"
  }
]

Errors

Tool errors are ordinary results with isError: true. The text starts with a stable code where one exists: file_too_large (over 1 MB), project_limit (plan allowance reached), site not found. Authentication failures are the only HTTP-level errors (401).

{ "content": [{ "type": "text", "text": "file_too_large: html exceeds the 1MB size limit" }], "isError": true }

Limits

Discovery

The server describes itself at two unauthenticated URLs: a server card with the live tool list and schemas, and the manifest used for MCP directory listings.

https://api.app.hdply.com/.well-known/mcp/server-card.json   # tools + schemas, live
https://api.app.hdply.com/.well-known/mcp/server.json        # registry manifest (com.hdply/hdply)

Prefer plain HTTP? The same operations exist as a REST API, and hdply.com/llms.txt summarizes both for agents.