Cheldrop MCP Server — Plan & Build Brief
Status: shipped 14 August 2026 (build plan Phase 7). The transport, auth, guardrails, upgrade nudges, error format and Settings UI below are what was built. The tool list is superseded by the build plan's Phase 7 list:
get_settings,list_sites,create_site,adopt_folder,publish_now,set_password,delete_site.publish_filesandpublish_folderwere deliberately not built — with Live site folders, writing files into the folder is the publish interface, and a second path to it would be a second set of rules about what a publish means. The docs page shipped with the feature; the landing-page section is still pending, per "What to add when this ships".
What this is
A local MCP (Model Context Protocol) server that Cheldrop exposes, allowing Claude Desktop to publish files and folders on behalf of the user. The user configures it once, and can then prompt Claude naturally — "publish ~/Projects/mockup to preview.myclient.com" — and Claude does the work through Cheldrop's existing publish pipeline.
This is a free feature, shipping in the version after the current one.
Files to create / modify
| File | Action | Notes |
|---|---|---|
main/mcp-server.js |
Create | The MCP server — tools, safety guards, upgrade nudges |
main/ipc.js |
Modify | Start/stop the MCP server with the app |
| Settings UI | Modify | Add MCP secret display + copy button |
Do not touch landing/ or docs/ until the MCP feature is built and working.
Architecture
- HTTP server on
localhost:3847(or similar fixed port), started by Electron on app launch - Requires a shared secret in each request header:
x-cheldrop-mcp-secret - Secret is generated on first launch, stored in electron-store, shown in Settings UI with a copy button
- Claude Desktop connects via
claude_desktop_config.json(user sets up once) - Server calls the existing
publish()anddeleteSite()functions fromcloudflare.jsdirectly — no duplication of logic
Tools exposed
list_sites
Returns all published sites from the local DB. Read-only, no guards needed.
Response fields: id, subdomain, domain, backend, publishMode, liveUrl, publishedAt, fileCount
get_settings
Returns whether the app is configured and ready. Read-only.
Response fields: configured (bool), available_domains (string[]), license_status (free | active)
Note: never expose the raw API token.
publish_files
Publishes a list of file paths to a subdomain/domain.
Parameters:
files: string[] — absolute filesystem pathssubdomain: stringdomain: string — must be in user's Cloudflare accountbackend:workers|r2(optional, defaults toworkers)show_toc: bool (optional, default true)show_toolbar: bool (optional, default true)confirm_overwrite: bool (optional, default false)
Safety logic:
- Validate domain is in stored zones — error if not, list available domains
- Validate all file paths exist on disk
- Check if site already exists in DB
- If site exists and
confirm_overwriteis nottrue→ returnstatus: "site_exists"with site details andrequires_confirmation: true. Do NOT publish. - If
confirm_overwrite: true→ publish - Check license for R2 or site limit — return upgrade nudge if blocked
publish_folder
Publishes a folder path to a subdomain/domain.
Parameters:
folder: string — absolute filesystem path to foldersubdomain: stringdomain: stringbackend:workers|r2(optional)confirm_overwrite: bool (optional, default false)
Safety logic: same as publish_files above. Also validates the folder path exists and is a directory.
delete_site
Deletes a site from Cloudflare and the local DB.
Parameters:
id: string — site ID in formatsubdomain.domainconfirmed: bool (optional, default false)
Safety logic:
- First call without
confirmed: true→ return site details + warning, do nothing - Second call with
confirmed: true→ delete
Upgrade nudges
The server checks license status before publish operations. When a free-tier limit is hit, the response includes an upgrade field alongside the error:
{
"ok": false,
"error": "Free tier is limited to 1 site.",
"upgrade": {
"reason": "Unlimited sites",
"cta": "Upgrade to Business Class — $49 one-time, no subscription.",
"url": "https://cheldrop.com/#pricing"
}
}
Triggers:
- Site limit hit (free tier, trying to publish a new subdomain when 1 already exists)
- Password protection requested (free tier)
- R2 backend requested (free tier)
- File over 25 MB detected (any tier — inform about R2 as the solution, nudge upgrade if free)
Never show upgrade nudge on: list_sites, get_settings, or any successful operation.
Error response format
All errors should be human-readable and actionable — Claude will relay them verbatim to the user.
{
"ok": false,
"error": "Domain example.com is not in your Cloudflare account. Available domains: mydomain.com, otherdomain.com"
}
{
"ok": false,
"error": "No API token configured. Open Cheldrop → Settings to add your Cloudflare token."
}
{
"status": "site_exists",
"requires_confirmation": true,
"site": {
"id": "preview.myclient.com",
"live_url": "https://preview.myclient.com",
"last_published": "2025-03-20T14:32:00Z",
"file_count": 6,
"backend": "workers"
},
"message": "This will replace everything currently live on the site. Call again with confirm_overwrite: true to proceed."
}
Settings UI addition
In the Settings page, add a new section (below API token, above license):
- Label: MCP Server
- Show the port (
localhost:3847) and the secret key (masked by default, reveal on click) - Copy button for the full config snippet users need for
claude_desktop_config.json - Status indicator: running / not running
What to add when this ships (not before)
Docs page
A new page in the app's docs (or at cheldrop.com/docs/mcp):
- One-time setup: where to find the secret, what to paste into
claude_desktop_config.json - What Claude can do (publish files, publish folder, list sites, delete with confirmation)
- What Claude can't do (operate without the app running, bypass confirmations)
- 3–4 example prompts
Landing page section
New section between Features and Pricing:
- Heading: "Works with Claude"
- Angle: the only file publishing tool Claude can operate directly
- Short: 2–3 sentences + one example prompt + link to docs
- Do not add until MCP is built and working
Prompt for a new Claude conversation
Paste this at the start of a new conversation, with this file and the brand skill attached:
I'm building a local MCP server for Cheldrop — a Mac/Windows Electron desktop app (React, Vite, electron-store, lowdb) that publishes files to Cloudflare Workers static assets and R2 via a custom API pipeline.
Read the attached plan document (mcp-plan.md) in full before writing any code.
Key files in the project (read these first):
main/ipc.js— Electron IPC handlers, store and DB access patternsmain/cloudflare.js—publish()anddeleteSite()functions you'll be callingmain/renderer.js— file rendering pipeline (reference only)
Project folder: /Users/christian/Developer/Cheldrop/app
Brand skill: /Users/christian/Documents/Prosjekter/Cheldrop/docs/cheldrop-brand-skill.md
Build in this order:
main/mcp-server.js— the full MCP server per the plan- Wire it into app startup in
main/ipc.js(or wherever the app initialises) - Add the Settings UI section (secret display + copy button)
Start by reading main/ipc.js and main/cloudflare.js.