MCP endpoint and headers

The address, authentication headers, protocol versions, sessions, rate limits and error shapes of the PowerWP AI MCP endpoint, for developers.

PowerWP AI exposes one MCP server on your site. Most people never touch it, because AI apps set themselves up from the Connections screen. This page is for developers who build or debug a client.

The endpoint#

https://your-store.com/wp-json/wpai/v1/mcp

With plain permalinks the address is https://your-store.com/?rest_route=/wpai/v1/mcp. Your exact address is shown under PowerWP AI › Help › Connection details.

  • Transport: Streamable HTTP. Send JSON-RPC messages with POST. Every answer is a single JSON object. There are no event streams, because long jobs such as backups run as jobs that the client polls.
  • GET answers 405. DELETE with an Mcp-Session-Id header ends that session.
  • Server: name wpai-mcp, title PowerWP AI, version of the plugin. It offers tools and prompts, and no resources.
  • Requests must use HTTPS. Local development sites are exempt, and Settings › Connection security › Trust X-Forwarded-Proto helps behind a proxy.
  • A request with an Origin header must come from your site's own address. Clients that are not browsers send none.

Authentication#

HeaderUse
X-WPAI-Token: <key>Recommended. It works on hosts that strip the Authorization header.
Authorization: Bearer <key>Also accepted.

Connection keys begin with wpai_. Apps that connect by signing in receive access tokens that begin with wpaio_. Management keys cannot be used on this endpoint: they get a 403 wrong_credential_type error. Keys are shown once when you create a connection.

Sign-in (OAuth)#

New in 1.6. Apps that support the MCP authorization specification can connect with just the endpoint address. A request without credentials gets a 401 with this header, which points the app to the sign-in:

WWW-Authenticate: Bearer realm="wpai-mcp", resource_metadata="https://your-store.com/wp-json/wpai/v1/oauth/protected-resource"

The site is its own authorization server. The app registers (POST /wp-json/wpai/v1/oauth/register), sends you to the approval screen in wp-admin, where you choose what it may do, and then exchanges the code at /wp-json/wpai/v1/oauth/token (PKCE S256 required). Access tokens last 1 hour, refresh tokens 60 days, and /wp-json/wpai/v1/oauth/revoke ends them. The approval creates a normal connection, with the same permissions, plan limits, change log and activity log.

Sign-in needs pretty permalinks, HTTPS on public sites, and the setting Sign-in for AI apps (on by default). See Sign-in for AI apps.

Protocol versions#

VersionStyle
2026-07-28Stateless. No initialize and no session.
2025-11-25, 2025-06-18, 2025-03-26, 2024-11-05Sessions, with an initialize handshake.

2026-07-28. Every request carries params._meta with io.modelcontextprotocol/protocolVersion and io.modelcontextprotocol/clientCapabilities, and optionally io.modelcontextprotocol/clientInfo. The headers MCP-Protocol-Version, Mcp-Method and, for tools/call and prompts/get, Mcp-Name must match the body. With Strict MCP headers on (the default), a missing header is an error too. Results carry resultType: "complete", and list results add ttlMs (300000) and cacheScope.

Older versions. initialize answers with an Mcp-Session-Id header. Send it back on later requests. A request without it still works, and the protocol is then taken from the MCP-Protocol-Version header, or assumed to be 2025-03-26. An unknown session gets a 404 and code -32001: initialize again. Idle session records are removed after 7 days. JSON-RPC batches of up to 50 messages are accepted for compatibility.

Methods: server/discover, initialize (older versions), ping and logging/setLevel (older versions only), tools/list, tools/call, prompts/list and prompts/get. Notifications get a 202 without a body.

Example for the stateless style:

curl -X POST "https://your-store.com/wp-json/wpai/v1/mcp" \
  -H "Content-Type: application/json" \
  -H "X-WPAI-Token: $WPAI_TOKEN" \
  -H "MCP-Protocol-Version: 2026-07-28" \
  -H "Mcp-Method: tools/call" \
  -H "Mcp-Name: site_overview" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"site_overview","arguments":{},"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientCapabilities":{}}}}'

Tools and prompts#

tools/list returns only the tools the connection's permissions allow. With read-only mode on, or on the Free plan, the write tools are not listed. There are 85 tools in 14 categories: see Tools. Each tool carries the annotations readOnlyHint, destructiveHint, idempotentHint and openWorldHint.

Results are text. A result is cut at 100,000 characters unless the tool allows more, with a note that says how to narrow the request. When a call records changes, the result ends with a line such as "Change journal: #12, #13 recorded (undo with changes_rollback)."

The recipes are the server's prompts. prompts/list returns them and prompts/get returns one with its arguments filled in. Claude Code shows them as slash commands, and apps without prompts use the tools recipes_list and recipe_get. See Recipes.

Rate limits and lockouts#

  • Rate limit per key: 240 requests a minute by default (10 to 5,000). Above it you get HTTP 429 and a Retry-After header.
  • Lockout: after 10 failed authentications from one IP address (3 to 1,000), that address is locked out for 15 minutes (1 to 1,440). A valid key is never counted as a failed attempt.

Both are set under Settings › Connection security.

Errors#

Authentication problems return an HTTP error with a JSON-RPC body. code is the HTTP status and data.reason says what happened:

{"jsonrpc":"2.0","error":{"code":401,"message":"Authentication required. Send your PowerWP AI token in the \"X-WPAI-Token\" header (or \"Authorization: Bearer <token>\").","data":{"reason":"missing_credentials"}}}
StatusreasonMeaning
401missing_credentials, invalid_token, token_revoked, token_expiredNo key, a wrong key, or a connection that was revoked or has expired.
403https_required, ip_not_allowed, wrong_credential_type, user_not_allowedHTTP instead of HTTPS, an IP address outside the allow-list, a management key, or a connection whose WordPress user is no longer an administrator.
429locked_out, rate_limitedToo many failed attempts, or too many requests. See Retry-After.
503mcp_disabledThe AI access switch is off.

Protocol problems use the JSON-RPC codes:

CodeMeaning
-32700The body is not valid JSON.
-32600Not a valid request, a wrong method for the endpoint, or an unsupported protocol version on older sessions.
-32601Unknown method.
-32602Invalid parameters, such as an unknown tool, prompt or cursor.
-32603Internal error.
-32001Session not found.
-32020An MCP header is missing or does not match the body.
-32022Unsupported protocol version. data.supported lists the versions.

A tool that fails returns a normal result with isError: true. The text starts with Error:, or with Invalid arguments: and a list. A missing permission answers "Permission denied", followed by {"required_scope": "files"} with the internal permission name from Permissions. On the Free plan the data also carries "license": "read_only".

If PHP stops with a fatal error during a tool call, the result is an error that names the tool, the error and the change IDs recorded before the crash.

↑↓ moveEnter open