shiply
A remote MCP server that hosts your site, not just the MCP.
What it can do
- Publish Site: Publish files to the web → live URL at <slug>.shiply.now. UPDATING: never create a new site for changes — re-call with claimToken (anonymous sites) or slug (sites you own with a Bearer k
- Site Status: Check any shiply slug or custom hostname: TLS certificate (issuer, days left) + HTTPS probe. ready=true means live.
- Verify Site: Edge-check a shiply slug or custom hostname and return a structured readiness report: status (LIVE/PENDING), SSL details (valid, issuer, daysLeft), HTTP probe, and a presigned thumbnail U
What data it sees
Do you need an account
No: the server works without sign-in
A remote MCP server that hosts your site, not just the MCP. Publish a static site from Claude Code, Cursor, or any AI agent in one call — no account, no CLI, no GitHub, a live URL. Add custom domains, SSL, databases, and edge functions, or sell the site you built. Flat price, no usage meter.
How to connect
How to connect shiply to Claude
The server address to paste into Claude settings:
https://shiply--stevejford1.run.tools
- Open Claude (claude.ai or the desktop app).
- Go to Settings → Connectors.
- Click Add custom connector.
- Paste the server address copied below into Remote MCP server URL and click Add.
- In a chat, click + → Connectors and switch the new connector on.
Custom connectors are available on Free, Pro, Max, Team and Enterprise plans (Free is limited to one). On Team and Enterprise an organization Owner adds the connector first under Organization settings → Connectors.
Authorization
After you click Add, a sign-in window for the service opens. Sign in with your own account and approve access. Claude never sees your password.
How to connect shiply to ChatGPT
The server address to paste into ChatGPT settings:
https://shiply--stevejford1.run.tools
- Open ChatGPT in a browser (chatgpt.com). A Plus, Pro, Business, Enterprise or Edu plan is required.
- Turn on developer mode once: Settings → Apps → Advanced settings → Developer mode.
- Open Settings → Connectors and click Create.
- Fill in the form: Name (anything), Description (one line about what the service does), MCP server URL (copy it below).
- Under Authentication choose OAuth if the service requires sign-in, otherwise None. Click Create.
- In a new chat open + → Apps/Connectors and enable the connector.
OpenAI has renamed this section before (Connectors → Apps/Plugins). If the label differs, search settings for "developer mode". On Business/Enterprise workspaces an admin must allow custom connectors first.
Authorization
On first use ChatGPT opens the service's sign-in window. Sign in and approve access.
How to connect shiply to Cursor
The server address to paste into Cursor settings:
https://shiply--stevejford1.run.tools
Fastest: click Open in Cursor below and confirm the prompt.
Manually:
- In Cursor open Settings → Cursor Settings → MCP and click Add new global MCP server.
- Paste the JSON copied below into
~/.cursor/mcp.json(per project:.cursor/mcp.jsonin the repo root). - Save the file. The server appears in the MCP list; authorize it there if asked.
Authorization
If the service needs sign-in, an authorize button appears next to the server in the MCP list.
Server tool list (60)
Raw names from tools/list. Only developers need these.
| publish_site | Publish files to the web → live URL at <slug>.shiply.now. UPDATING: never create a new site for changes — re-call with claimToken (anonymous sites) or slug (sites you own with a Bearer key) and the SAME URL gets the new version (unchanged files are hash-skipped). Works WITHOUT auth (anonymous: 24h lifetime, returns claimToken/claimUrl — SAVE THEM). With a Bearer shp_ key sites are permanent. ≤50 files / 2 MB inline; bigger: REST flow per https://shiply.now/llms.txt. index.html serves at /. spaMode for client-side routing. |
| site_status | Check any shiply slug or custom hostname: TLS certificate (issuer, days left) + HTTPS probe. ready=true means live. |
| verify_site | Edge-check a shiply slug or custom hostname and return a structured readiness report: status (LIVE/PENDING), SSL details (valid, issuer, daysLeft), HTTP probe, and a presigned thumbnail URL when available. Use this after publishing to confirm the site is reachable. |
| list_sites | List the sites owned by this API key. |
| get_site | Site settings + version history for one of my sites. |
| delete_site | PERMANENTLY delete a site and all stored files. Irreversible — confirm with the user first. |
| rollback_site | Re-point a site to any finalized version (rollback or roll-forward). Get version ids from get_site. Serving updates immediately. |
| set_handle | Rename a site to <handle>.shiply.now (3-30 chars, a-z 0-9 -). The old address 301-redirects for 30 days. |
| duplicate_site | Server-side copy of an owned site under a new slug — instantly live. Copies files + title; does NOT copy access settings, domains, or data. Great for iterating on variants. |
| promote_site | Copy the EXACT live bytes of one owned site (srcSlug — your preview) into another owned site (destSlug — your production site / custom domain), no rebuild. Dest keeps its slug, domains, and access settings; only the served bytes change. |
| set_link | Path-mounting: serve an owned target site at a path on an owned host site (host/docs -> target). location is a path like "docs", or "__root__" for the host root. Both sites must be owned by you. Pass remove=true to unmount. |
| set_site_access | Protect an owned site (paid plans). mode 'public' (anyone), 'password' (supply password), or 'restricted' (supply allowedEmails and/or allowedDomains — only those can request a login code). Changing any setting signs out existing visitors. |
| export_account | Return a JSON bundle of the user's profile, sites, Site Data, drives, and metadata (secrets excluded). Data portability. |
| whoami | Who am I? Returns the signed-in account: email, @handle, plan + limits, counts of sites/domains/drives, and connected DNS providers. Call this first to orient before managing sites or domains. |
| get_account_status | Get the signed-in account's plan, capabilities, and upgrade URL. Call this FIRST when figuring out what features you have access to — it tells you exactly what's available and what's blocked. The upgrade_url is human-clickable; show it in chat when a feature requires a higher plan. Returns plan id + name + subscription status, hard limits (sites, databases, custom domains, drives), and a capability matrix listing every gated feature (workers_lite, databases_neon_postgres, custom_domains, etc.) with whether you have access and the minimum plan needed. |
| list_drives | List the user's private cloud Drives (id, name). |
| create_drive | Create a private cloud Drive (plan-limited). |
| drive_list_files | List files in a Drive (driveId = drv_…, or "default"). Optional prefix filter. |
| drive_put_file | Write a file into a Drive (driveId = drv_… or "default"). content is utf8 or base64. Use for agent memory, notes, context, assets. |
| drive_delete_file | Delete a file from a Drive. |
| publish_from_drive | Snapshot a Drive (or a prefix of it) into a new live site at <slug>.shiply.now. Files copied server-side. |
| set_profile | Create or update the user's public portfolio at <handle>.shiply.now (handle 3-30 chars a-z0-9-). enable shows the profile; autoAdd auto-lists new sites. Use after publishing to give the user a shareable portfolio. |
| feature_site | Toggle whether an owned, public site appears in the public shiply Explore gallery (https://shiply.now/explore). Only public-access sites are eligible. |
| set_variable | Upsert a key/value in the user's encrypted variable store (UPPER_SNAKE name, ≤8 KiB value). Use for API keys the user's sites/agents need, e.g. SUPABASE_URL. |
| list_variables | List the encrypted variables. Values are masked unless reveal=true. |
| delete_variable | Remove one variable by name. |
| data_list_collections | List collections declared in an owned site's .shiply/data.json with current record counts. Empty list means the site has no manifest yet — scaffold one with `shiply data init`. |
| data_query | Page records from an owned site's collection, newest-first. limit ≤ 200 (default 50). cursor from a previous response's nextCursor. |
| data_insert | Insert one record into a collection. Goes through the same public visitor endpoint a browser would use — manifest access.insert decides whether it is allowed. Use to seed waitlist data, test forms end-to-end, etc. |
| data_export_collection | Return up to `limit` records (default 1000, max 5000) from a collection — for snapshotting into agent context. For larger sets use the CLI: `shiply data export <slug> <collection>`. |
| add_domain | Serve a site on a domain the user owns. Returns the CNAME to add (hostname → cname.shiply.now); the certificate issues automatically once DNS resolves. Poll with check_domain. |
| add_custom_domain | Register a registrable domain (e.g. example.com) the user owns and detect its DNS provider. Returns the provider and whether one-click connect is available. Then attach sites with add_subdomain. |
| add_subdomain | Serve an owned site at <subdomain>.<domain> (use subdomain "@" or "" for the apex — apex needs a provider with CNAME flattening/ALIAS, e.g. Cloudflare). Auto-registers the parent domain. Returns the CNAME record to add (host -> cname.shiply.now); the certificate issues automatically once DNS resolves. Poll with check_domain. |
| set_primary_subdomain | Mark a hostname as the primary (canonical) URL for its site. Sibling hostnames (apex + www both pointed at the same site) start 301-redirecting to it, preserving path + query. The host-side fix for the duplicate-content SEO problem. The first subdomain you add for a site is primary by default; call this only when you need to switch. |
| list_custom_domains | List registered custom domains grouped with their subdomains, each subdomain's site and status, and the detected provider. |
| connect_provider | Start one-click DNS connect for a registered custom domain. For Cloudflare-hosted domains this returns an authorize URL — SHOW THE USER the url as a clickable link; after they authorize, records are written automatically. For other providers, add the records manually. |
| sync_dns | For a connected custom domain, (re)write the CNAME records for all its subdomains automatically and report what changed. For unconnected domains, returns the records to add manually. |
| check_custom_domain | Check whether a custom domain's subdomains are live: re-polls Cloudflare cert status + probes DNS/TLS/HTTPS on each subdomain. Poll this after connect_provider / add_subdomain to confirm the domain is serving. Returns per-subdomain status + tls + http + ready. |
| remove_custom_domain | Remove a registered custom domain and all its subdomains; they stop serving immediately. |
| list_domains | List connected custom domains with status. |
| check_domain | Refresh certificate status + live TLS/HTTPS probe for a connected domain (by id from list_domains). |
| remove_domain | Remove a connected domain (by id). It stops serving immediately. |
| get_analytics | Daily page views per site for the last 30 days. |
| create_test | Provision a demand test in one call: deploys a landing page with a native email-capture form and creates a confirmed-subscriber segment. Returns testId + live siteUrl. Share the siteUrl to collect signups; each signup gets a double-opt-in confirmation. Read progress with get_test_status. |
| list_tests | List your demand tests with signups + confirmed counts. |
| get_test_status | ONE consolidated object: page funnel (views, signups, confirmed, conversion) ⊕ email events (delivered/opened/clicked/bounced) ⊕ a computed verdict. The single place to check progress — never query email separately. |
| send_broadcast | Send a campaign to this test's confirmed (double-opt-in) subscribers — the "we're live" email. An unsubscribe link is added automatically. Fails if there are no confirmed subscribers yet. |
| resend_confirmation | Re-send the double-opt-in confirmation to a signup that has not confirmed yet. |
| verify_claim | Confirm a pairing code shown in the user's browser at https://shiply.now/claim/<slug>?pair=1. Use ONLY in the agent session that originally published the site — it reads the claimToken from .shiply.json in the current working directory and proves to Shiply that this agent session is authorised to claim the site. After verification the user is auto-redirected to /welcome and the site binds to their account. |
| list_inbox | List the user's email inbox threads (outbound demand-test sends + inbound replies / unsubscribes / complaints / bounces). Filter by tag. |
| read_thread | Return the thread metadata + all messages in chronological order. Use list_inbox first to get a threadId. |
| summarize_thread | One-paragraph summary of the thread, oriented to the most actionable signal (interest, complaint, question, unsubscribe). |
| reply_to_thread | Send an email reply on an existing thread. Goes FROM the original recipient address (the <slug>@shiply.now alias the sender used) and TO the original sender. Threaded via RFC 5322 In-Reply-To so Gmail/Outlook group it with the original. Subject defaults to 'Re: <original>' when omitted. Cap at 20,000 chars. Use after read_thread to make sure you're replying to the right conversation. |
| mark_thread_read | Zero the unread counter for a thread. Useful after the agent has read but not acted. read_thread already calls this implicitly; use this explicitly when you want to clear unread without re-fetching the thread body. |
| archive_thread | Soft-archive the thread (sets archivedAt). Hidden from the default inbox view; surface again with list_inbox filter=archived. Reverse with unarchive_thread. |
| unarchive_thread | Restore an archived thread (clears archivedAt). It reappears in the default inbox list. Pair with list_inbox filter=archived to find archived threadIds first. |
| forward_thread | Forward a message from a thread (default: the most recent message) to a NEW recipient with an optional intro note. Body is composed as note + standard '---------- Forwarded message ----------' quote of the original. Goes from the thread's existing shiply alias so replies still route through the inbox. Subject defaults to 'Fwd: <original>'. |
| list_test_inbox_addresses | Return every active demand test's reply / inbound address (<slug>@<sitesDomain>). Use this when you need to TELL someone where to email — e.g. drafting a reply or sharing a test's contact address. Mail sent to these aliases lands in /dashboard/inbox tied to the test. |
| list_unsubscribes | Shortcut for list_inbox with filter=unsubscribes — shows every thread tagged as an opt-out request. |
| list_suppressions | Return the user's suppression list — addresses (and full domains) that shiply skips when sending. Bounces, complaints, manual user adds, and AI-detected unsubscribes all land here. |