What SandyWP is
SandyWP creates disposable WordPress sandboxes for plugin and theme makers. Each sandbox is a real, isolated WordPress install with its own database, files, and public URL, and it is safe to throw away. A user asks Muse to list sandboxes, check status, openwp-admin, or create a test site. The connector does not take payment and never sees card details.
Billing stays on sandywp.com through Polar.
Connection details
Fetch https://sandywp.com/agents before connecting. Do not guess the MCP URL from the marketing homepage.
Transport notes
- Send
POSTwithContent-Type: application/jsonandAccept: application/json, text/event-stream. A JSON-onlyAcceptalso works. - Unauthenticated
GET /mcpreturns HTTP 401 plus a JSON probe andWWW-Authenticatepointing at protected-resource metadata. That means the host is up and OAuth is required, so do not treat 401 as a dead server. - Authenticated
GET /mcpreturns HTTP 200 with the same probe shape.DELETE /mcpreturns 405 and sessions need no teardown. initialize,ping, andtools/listmay run without a token so a client can import tool metadata.tools/callwithout a bearer access token returns HTTP 401.- After
initialize, sendMCP-Protocol-Versionon later requests. An unknown value returns HTTP 400. - Tool results are
content[0].text. Objects are pretty-printed JSON in that text field, so read it and do not expect a separatestructuredContentobject.
initialize (metadata only, no token):
2025-03-26 or 2024-11-05, the server echoes that version. If it proposes anything else, the server answers 2025-06-18 and you continue with the version it returned.
After OAuth, send Authorization: Bearer <access_token> on every tools/call.
OAuth with PKCE
SandyWP is both the authorization server and the resource server onhttps://app.sandywp.com. Public MCP clients register dynamically and complete an authorization-code grant with S256 PKCE.
There is no client secret and no refresh-token grant.
Discovery documents (no auth):
High-level flow:
- An unauthenticated
tools/call(orGET /mcp) returns HTTP 401 withWWW-Authenticatepointing at protected-resource metadata. - The client reads authorization-server metadata, then registers itself at
POST /api/connect/registerwith its own redirect URIs (RFC 7591). Use the URIs the client actually redirects to, and do not invent or substitute them. - The browser opens
/connect/authorizewithclient_id, an exact registeredredirect_uri, S256code_challenge, requested scopes, andresource=https://app.sandywp.com/mcp. - If the account holder is not signed in, SandyWP sends them through login on
https://app.sandywp.com, then back to consent. - The account holder chooses Approve. The browser returns a short-lived, single-use authorization code to the registered redirect URI.
- The client POSTs the code,
client_id,redirect_uri, and matchingcode_verifierto/api/connect/tokenwithgrant_type=authorization_code. - The response is a bearer
access_token(swp_…) and the grantedscope. Send that token on later POSTs to/mcp.
Access and usage
A SandyWP account is required. Free, Plus, Pro, Max, and Workspace plans all work. Guest-only sandboxes are not an MCP login. Rate limits and sandbox quotas follow the connected account’s plan. Creating a sandbox counts against the active-sandbox limit. MCP calls are also rate-limited per token. See Plans and limits. Billing, plan changes, and payment methods stay on sandywp.com through Polar. Never collect card details in chat.Meta E2E review
Use this account for Meta’s end-to-end connector review. Do not ask for or store a password.
If login or consent fails, stop and report the tool or HTTP error. Do not guess a workaround.
Core recipes
Call tools only after OAuth. Use theid and publicUrl values the server returned. Never invent them.
A. List sites and check status
sandywp_list_siteswith{}.- Each item includes
id,slug,status, andpublicUrlwhen the server has them. - For one site,
sandywp_site_statuswith{ "siteId": "<id from the list>" }. site.statusis one ofcreating,ready,expired,failed,pending_delete,deleted,cleanup_failed. Report the returned status. Do not infer ready from a URL you made up.
B. Magic login link
- Confirm the sandbox
statusisreadywithsandywp_site_status. sandywp_magic_loginwith{ "siteId": "<id>" }.- Give the user the returned
urlandexpiresAtexactly. The link is a reusable bearer credential until it expires, and anyone who has it can enterwp-admin. - Never construct a login URL. If the tool errors, say so.
C. Create a sandbox
sandywp_create_sitewith optional{ "siteName": "muse-review-test" }. All fields are optional.- By default the tool waits up to about 60 seconds. If
site.statusis stillcreating, pollsandywp_site_statuswith thatsiteIduntilreadyorfailed. - Pass
"background": trueonly when you will poll. Do not tell the user the site is live while status iscreating. - Optional create fields include
phpVersion(8.5,8.4,8.3,8.2,8.1,7.4; default8.3) andplugins(wordpress.org slugs, max 10).
D. Deploy a plugin (optional)
- Confirm the sandbox is
ready. sandywp_deploy_pluginwith{ "siteId": "<id>", "pluginSlug": "query-monitor" }. Provide exactly one ofpluginSlug,zipUrl, orartifactId.- The tool waits up to about 60 seconds. If it returns an in-flight job, poll
sandywp_get_jobwith{ "siteId": "<id>", "jobId": "<jobId>" }. - This remote server cannot read local files. For a local ZIP, the user runs
npx @sandywp/cli deploy <site> <plugin.zip>.
E. Preview a GitHub pull request (optional)
sandywp_preview_github_prwith{ "repository": "owner/repo", "destination": "plugin", "folderName": "my-plugin" }.pullNumberis optional when the repository URL already includes/pull/N.- This uses the account GitHub App. It does not mint per-sandbox SSH deploy keys.
- If GitHub is not connected, the tool returns
needs_github_connectand a dashboard URL. Send the human to that URL. Do not invent a deploy key. - Poll
sandywp_site_statusuntilready, thensandywp_magic_loginif the user needswp-admin.
sandywp_whoami confirms which account is connected. sandywp_usage reports plan and active-sandbox count.
Rules
- Quote only what the server returned. Never invent a site URL, slug, status, job result, or login link; if a tool did not return it, you do not know it.
- Never ask for card numbers, security codes, passwords, or one-time codes in chat. Payment and plan changes happen on sandywp.com through Polar, with the user’s approval.
- Confirm with the user before calling a destructive tool. That includes
sandywp_delete_site,sandywp_reset_site,sandywp_delete_path,sandywp_rotate_demo_launch_webhook_secret, andsandywp_delete_demo_launch_webhook. sandywp_magic_loginmints a sensitive, reusablewp-adminURL. Show it to the user with its expiry. Do not store it in a public place.- Product MCP is
https://app.sandywp.com/mcp. Docs MCP ishttps://docs.sandywp.com/mcp. Do not call product tools against the docs MCP. - If a tool returns
isError: trueor HTTP 401, say so. A 401 means complete OAuth. Do not fill the gap with invented sandboxes. - Creates and deploys are jobs. Poll
sandywp_site_statusorsandywp_get_jobuntil a terminal state before claiming success.

