At a glance
| Endpoint | https://chorus.host/mcp |
| Transport | Streamable HTTP, stateless |
| Auth | None. Optional Authorization: Bearer chk_... publishes into your account |
| Tools | publish_site, get_site, get_docs |
| Per call | 4 MB of files without a key, 10 MB with one; up to 1,000 files |
| Sites without an account | Live for 24 hours; a claim link keeps them |
| Publishes per hour | 5 per IP address without a key, 60 per account with one |
| Official MCP Registry name | host.chorus/mcp |
| Price | Free |
Add it to your client
Checked 1 October 2026. The Claude Code and Codex commands were run against this server that day; the Cursor and VS Code entries follow each client's documented config format and were not run by us.
Claude Code
claude mcp add --transport http chorus https://chorus.host/mcp
claude mcp list should show chorus: https://chorus.host/mcp (HTTP) - ✔ Connected.
Codex CLI
codex mcp add chorus --url https://chorus.host/mcp
This writes an [mcp_servers.chorus] entry with the URL to ~/.codex/config.toml. Codex's default workspace-write sandbox has no network, so approve the network request when Codex asks, or see the Codex section of the Claude Code and Codex guide.
opencode
In opencode.json:
{ "mcp": { "chorus": { "type": "remote", "url": "https://chorus.host/mcp" } } }
Cursor
In ~/.cursor/mcp.json (all projects) or .cursor/mcp.json (one project):
{ "mcpServers": { "chorus": { "url": "https://chorus.host/mcp" } } }
VS Code
In .vscode/mcp.json:
{ "servers": { "chorus": { "type": "http", "url": "https://chorus.host/mcp" } } }
claude.ai and Claude Desktop
Customize, then Connectors, then + and Add custom connector. Name it chorus.host and paste https://chorus.host/mcp as the URL. There's no OAuth step. The Free plan allows one custom connector.
ChatGPT
ChatGPT can only use MCP tools that write (publishing is a write) in Business and Enterprise or Edu workspaces, on the web, through developer mode (Settings, Apps, Advanced settings). On Pro, developer mode connectors can read and fetch but not write, according to OpenAI's help center on 1 October 2026. The article doesn't mention Plus, so expect the same there unless you test otherwise. On Pro or Plus, download the HTML ChatGPT made and drop it on chorus.host/html-to-url instead.
A note on shared addresses: claude.ai and ChatGPT call MCP servers from their own servers, so their requests share a small number of IP addresses. Publishing without a key is limited to 5 per hour per IP address, and that budget can run out on a shared address. If you see a rate-limit error there, add your API key as an Authorization: Bearer chk_... header (60 an hour per account).
What your agent gets
This reference is generated from the tool definitions the server registers, so it matches what tools/list returns.
publish_site: Publish website
Publish a website or any file (PDF, image, HTML, CSS/JS) to a live public HTTPS URL at <slug>.chorus.host in one call. Files keep their content type, so PDFs and images open in the browser.
| Argument | Type | Required | What it is |
|---|---|---|---|
claim_token | string | no | The claim_token (ctk_...) returned when the site was first published. Required to update an anonymous site. |
expires_at | string | no | Optional. When the site should be deleted: RFC 3339 (2026-10-08T00:00:00Z) or a duration from now (90m, 2h, 7d). |
files | array of object | yes | Every file of the site. Each call makes a new version with exactly these files; earlier versions are kept. |
password | object | no | Optional. Put the site behind a browser login prompt (HTTP Basic Auth). |
slug | string | no | Optional. Subdomain to publish to (3-63 lowercase letters, digits and hyphens). |
title | string | no | Optional human-readable title saved with the site. |
Returns: anonymous, claim_token, claim_url, expires_at, file_count, file_url, next_steps, page_url, password_protected, slug, tell_the_user, total_bytes, updated, url, version_id, warnings.
Annotations: not destructive (earlier versions are kept).
get_site: Check site status
Check a chorus.host site: whether it is live, its URL, whether it has a password, and when it expires. With the site's claim_token (or an API key that owns the site) it also returns the file list, total size, live version and claim link.
| Argument | Type | Required | What it is |
|---|---|---|---|
claim_token | string | no | Optional claim_token (ctk_...) of the site. Unlocks the file list and other details. |
slug | string | yes | The site's slug, i.e. the subdomain in <slug>.chorus.host. |
Returns: can_manage, claim_url, claimed, created_at, current_version_id, expires_at, file_count, files, files_truncated, password_protected, slug, status, summary, title, total_bytes, updated_at, url.
Annotations: read-only.
get_docs: Read chorus.host docs
Return the full chorus.host documentation as Markdown (the same text as https://chorus.host/skill.md): the REST API, the beacon CLI, accounts and API keys, claiming sites, password protection, and Workers, which run server-side JavaScript at <slug>.worker.chorus.host for APIs and webhook receivers (GitHub, Stripe), including Hono apps, with no Cloudflare account needed. Read it before building a backend, when the user asks about accounts or limits, or when a task needs something publish_site can't do.
Annotations: read-only.
Try it without a client
MCP is JSON over HTTP, so curl works. This publishes one page and prints the live URL:
jq -n --rawfile html index.html \
'{jsonrpc:"2.0",id:1,method:"tools/call",params:{name:"publish_site",arguments:{files:[{path:"index.html",content:$html}]}}}' \
| curl -sS https://chorus.host/mcp -H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' -d @- \
| jq -r .result.structuredContent.url
The full result has url, page_url, file_url, claim_url, claim_token, expires_at and a tell_the_user message. If you only want curl, the plain HTTP endpoint is shorter: curl -sS https://chorus.host/v1/publish -F file=@index.html.
Keep it, update it, lock it
- Keep it. Give the person the
claim_url. They open it, enter their email and the 6-digit code they get, and the site is theirs with no expiry. - Same URL, new content. Call
publish_siteagain with the sameslugand theclaim_tokenfrom the first call. Each call makes a new version live with exactly the files you send; earlier versions are kept and can be rolled back over the REST API. - Password. Pass
password: {username, password}and visitors get the browser's login prompt. It works without an account. See password-protect an HTML page. - Expiry. Pass
expires_at(2h,7dor an RFC 3339 time). Without a key it can only be sooner than 24 hours. See temporary website hosting. - Publish into your account. Send your API key as a header. Claude Code:
claude mcp add --transport http chorus https://chorus.host/mcp --header "Authorization: Bearer chk_...". Codex:codex mcp add chorus --url https://chorus.host/mcp --bearer-token-env-var CHORUS_API_KEY. - More than 4 MB. Use publish.py or the beacon CLI, which upload straight to storage (250 MB per file without an account).
- A backend. APIs and webhook receivers run as chorus.host Workers. They are deployed over the REST API or the CLI with a free account, not through an MCP tool today;
get_docsreturns the instructions.
Which MCP server should you use?
Checked 1 October 2026 from each server's tools/list and public docs. Blank cells mean we couldn't confirm the answer, not that the feature is missing.
| chorus.host | ShipStatic | Just Publish | |
|---|---|---|---|
| Publish with only the URL configured | Yes | Yes | The deploy tool asks for an email address |
| Lifetime without an account | 24 hours | 3 days | |
| Password from the tool | Yes | Yes | |
| Sign in from cloud clients | API key header | OAuth | |
| Custom domains | No | Yes | |
| Change one file without resending the site | No, full replace | Yes (update_site_file) | |
| Pick the subdomain | Yes | ||
| Server-side code | Workers, over REST or CLI |
Where they're better: ShipStatic keeps anonymous sites for 3 days instead of 24 hours, signs in over OAuth and supports custom domains. Just Publish can edit one file of a live site without sending the rest. here.now has no public MCP server; its agent card says MCP isn't supported.
Want to host your own MCP server?
This page is about an MCP server that publishes websites. If you want to run your own MCP server on the web, Cloudflare's guide to remote MCP servers on Workers is the place to start.
Questions
Is there an MCP server that publishes a website and returns a public URL?
Yes. Add https://chorus.host/mcp to your MCP client. Its publish_site tool takes the files and returns a live https://<name>.chorus.host URL, plus a claim link so a person can keep the site.
Do I need an account or an API key?
No. Without one, sites stay up for 24 hours and come with a claim link. With an API key in the Authorization header, sites go into your account and don't expire.
Does it work in ChatGPT?
Publishing needs a ChatGPT Business, Enterprise or Edu workspace with developer mode, on the web. On Pro, developer mode connectors are read and fetch only (OpenAI's help center doesn't cover Plus), so on Pro or Plus drag the HTML file onto chorus.host/html-to-url instead.
How long do sites stay up?
24 hours without an account, unless someone opens the claim link and signs in. Sites in an account stay up until you delete them, or until an expires_at you set.
How big can the site be?
4 MB of files per call without a key and 10 MB with one, up to 1,000 files. Bigger sites go through publish.py, the beacon CLI or the REST API: 250 MB per file without an account, 5 GB with one.
Can the agent update the same URL later?
Yes. Call publish_site again with the same slug and the claim_token it got the first time (or with your API key for sites in your account). The URL stays the same and the old version is kept.