# 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

| Header | Use |
|---|---|
| `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](/docs/concepts/sign-in/).

## Protocol versions

| Version | Style |
|---|---|
| `2026-07-28` | Stateless. No `initialize` and no session. |
| `2025-11-25`, `2025-06-18`, `2025-03-26`, `2024-11-05` | Sessions, 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](/docs/reference/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](/docs/reference/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"}}}
```

| Status | `reason` | Meaning |
|---|---|---|
| 401 | `missing_credentials`, `invalid_token`, `token_revoked`, `token_expired` | No key, a wrong key, or a connection that was revoked or has expired. |
| 403 | `https_required`, `ip_not_allowed`, `wrong_credential_type`, `user_not_allowed` | HTTP instead of HTTPS, an IP address outside the allow-list, a management key, or a connection whose WordPress user is no longer an administrator. |
| 429 | `locked_out`, `rate_limited` | Too many failed attempts, or too many requests. See `Retry-After`. |
| 503 | `mcp_disabled` | The AI access switch is off. |

Protocol problems use the JSON-RPC codes:

| Code | Meaning |
|---|---|
| -32700 | The body is not valid JSON. |
| -32600 | Not a valid request, a wrong method for the endpoint, or an unsupported protocol version on older sessions. |
| -32601 | Unknown method. |
| -32602 | Invalid parameters, such as an unknown tool, prompt or cursor. |
| -32603 | Internal error. |
| -32001 | Session not found. |
| -32020 | An MCP header is missing or does not match the body. |
| -32022 | Unsupported 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](/docs/reference/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.

:::cards
- [Tools](/docs/reference/tools/) — All 85 tools.
- [Keys and access control](/docs/security/access-control/) — Expiry, IP allow-lists and lockouts.
- [Other MCP apps](/docs/connect/other-apps/) — Connect a client that is not listed.
:::

Source: https://powerwp.ai/docs/reference/mcp-endpoint/
