Skip to content
WP EngineDocumentation

Troubleshooting

This page lists fixes for common Model Context Protocol (MCP) server failures, organized by symptom. You can also search for a specific error code: each code appears in the section that resolves it.

Before you work through this page, read the help and next_steps on the error itself. The server generates them from live state. They name your actual site and the actual missing argument, so they’re more specific than anything on this page. This page covers the failures where that isn’t enough, or where the fix isn’t where you’d expect.

The server returns a tool failure as a normal response that carries an error.code, not as an HTTP error. At the transport layer, a failing call still looks like a success. Your client should show you the code.

If your client shows no tools at all, the connection is failing before tool discovery.

  1. Confirm the endpoint is exactly https://api.ai.wpengine.com/v1/mcp. The transport is Streamable HTTP, and the client sends requests as POST.
  2. Confirm the client authenticated with OAuth. In Claude Code, run /mcp, select the server, and select Authenticate. In Claude Desktop, select Connect on the connector. See Authentication.
  3. In Claude Code, run claude mcp list to confirm the server is registered. A server added without --scope user appears only in the directory you added it from.
  4. Reproduce the problem outside your client with MCP Inspector. If MCP Inspector lists tools and your client doesn’t, the problem is client configuration, not the server.

Unlike a tool error, an authentication failure at this stage is a real HTTP 401. If sign-in succeeds and every request then fails with HTTP 403 entitlement_required, see Fix entitlement_required by turning on AI.

Every tool call fails with forbidden, and the message says the credential is not accepted for the tool.

This happens when you configure the client with an API key. The MCP server no longer accepts API keys. A key still connects, but every tool call fails. A tool call must come from a user authenticated with OAuth.

Fix:

  1. Remove the key or token and the Authorization header from the client configuration.
  2. Authenticate with OAuth. See Connect Claude Code or Connect Claude Desktop.
  3. Retry the request.

The request fails before any tool runs. This is an HTTP error, not the tool error forbidden.

If you signed in with OAuth but didn’t grant a permission that a tool needs, the server returns HTTP 403 with WWW-Authenticate: Bearer error="insufficient_scope". The header names the scopes to request. A client that supports step-up authorization asks you to sign in again. Otherwise, sign in again and grant the permissions the tool needs.

The server returns HTTP 401 for a site service token that doesn’t verify. It returns HTTP 403 with insufficient scope for one that verifies without the accounts scope. Don’t use a site service token in an MCP client. Authenticate with OAuth instead. See Connect Claude Code or Connect Claude Desktop.

The server returns entitlement_required when AI isn’t turned on for your account. The error arrives in one of two ways:

  • Every request fails with HTTP 403 before any tool runs. The message is This account is not entitled to use WP Engine AI APIs. None of the WP Engine accounts you belong to has AI turned on. Your client might show this as a server that fails to connect.
  • One tool call fails with the same message, or with AI is not turned on for the WP Engine account this call acts on. The call names an account that has AI turned off. list_accounts leaves those accounts out, so pass an account_id that it returns.

Fix: An account owner accepts the WP Engine AI terms and turns on AI for the account in the WP Engine User Portal. Then retry the request.

Fix not_personally_connected by connecting your WordPress user

Section titled “Fix not_personally_connected by connecting your WordPress user”

A tool returns not_personally_connected when your WordPress user isn’t connected to the site.

Registering a site to your account isn’t the same as connecting yourself to it. The second connection is per person and requires explicit consent in WordPress admin. See The two connections.

If the error names one site, it includes connect_url for that site:

  1. Log in to that site’s WordPress admin first, then open connect_url. If you open it while logged out, you land on a login screen and lose the flow.
  2. On the consent screen, confirm with Connect WordPress user.
  3. Retry the original request.

If the request didn’t name a site, the error has no connect_url. Choose the site to connect yourself. Your client shouldn’t choose one for you.

  1. Call list_account_sites with limit and offset, starting at offset 0. Increase offset by limit until you have covered pagination.total from the first page. A page past the end reports total 0, so keep the first page’s total.
  2. Each site includes requires_https, taken from its site_url on that same response. Use each site’s display_name and site_url to choose a site where requires_https is false. If every site is true, enable Secure Sockets Layer (SSL) on a site first. Don’t open a connect link for a site where requires_https is true.
  3. Call list_site_abilities with the chosen site_id. That response carries the Connect link when the site can be connected.
  4. Log in to that site’s WordPress admin, open the link, and confirm with Connect WordPress user.
  5. Retry the original request.

The link is the only entry point to this flow. WordPress has no button to start it manually.

A search_abilities call from a signed-in user with no connected sites doesn’t return this error. Instead, it returns found: false, reason: no_connected_sites, and the same help and next_steps.

If a connection that worked before now reports that it’s stale, the error is needs_reconnect. The connection existed and has lapsed.

Follow the three steps for an error that names one site, in Fix not_personally_connected by connecting your WordPress user. The error carries the link. Nothing is wrong with the site registration or your sign-in.

If the error is site_requires_https instead, the site isn’t served over HTTPS, and you can’t establish a WordPress user connection at all. Enable SSL first. The server also returns this code on the first attempt to connect an HTTP site, before any connection exists. list_account_sites sets requires_https: true on those sites.

Find a site missing from list_account_sites

Section titled “Find a site missing from list_account_sites”

Check these causes in order:

  1. Check the status filter. Unless you pass status, the tool returns only active registrations. To see the rest, ask for revoked or suspended.
  2. Check the account. site_not_found deliberately doesn’t distinguish “no such site” from “belongs to someone else.”

If you name the site directly, the two codes tell you different things:

  • site_not_found means nothing matched the identifier you gave, or the site belongs to another account. The server intentionally doesn’t distinguish the two.
  • site_not_active means the server found the site, but its registration is revoked or suspended. The identifier was right, and the site was withdrawn.

Find an ability missing from search results

Section titled “Find an ability missing from search results”

If search doesn’t return an ability that the site has, work through these checks:

  1. Check that you’re connected to the site. Ability listing and search cover only sites where your WordPress account connection is active.
  2. Check whether the catalog is out of date. Search reads a cached catalog and never syncs it. Under degraded_sites, search_abilities lists every site whose catalog might lag the site. That includes a site that hasn’t synced recently, has never synced, or failed its last sync (abilities_sync_status of error). Call list_site_abilities for that site, which refreshes an out-of-date catalog, and then search again.
  3. Check whether the ability is withheld. Some abilities are blocked from remote execution and return ability_unavailable. Retrying doesn’t help; the change has to happen in WordPress admin.

A search with no matches isn’t an error. It returns found: false with a reason:

  • no_semantic_match is the only reason that improves on a rephrase.
  • no_connected_sites means a missing WordPress account connection. Retrying returns the same answer.
  • empty_catalogs means nothing has synced yet. Retrying returns the same answer.

Search also drops weak matches instead of padding the result, so a plausible query can return nothing. Search finds abilities; it doesn’t browse them. To see everything a site can do, use list_site_abilities.

The two “not found” codes mean different things:

  • knowledge_base_not_found from get_site_knowledge_base — the site has no usable knowledge base. The error carries a setup_url and a three-step repair walkthrough. Follow the walkthrough, then call get_site_knowledge_base again to read the new collection_id.
  • collection_not_found from search or fetch — the collection_id you passed is wrong or stale. Read it again from get_site_knowledge_base; don’t reuse a cached one.

If search_knowledge_base reports that collection_id is required, call get_site_knowledge_base first. You can’t construct the collection ID from the site ID.

Fetching a document by an unknown ID isn’t an error. The call succeeds and returns not_found: true.

The server returns rate_limited when your client makes too many calls in a short window. The server applies two separate budgets, and the message says which one you hit:

  • read tool rate limit exceeded — 120 calls per minute across list_accounts, list_account_sites, search_abilities, list_site_abilities, the knowledge base tools, and the wpe_* hosting tools. A hosting tool reports it as too many hosting tool calls; retry after a short delay.
  • ability execution rate limit exceeded — run_site_ability only: 30 calls per minute on one site, or 60 across all your sites.

These limits are provisional, and WP Engine may change them.

Wait a minute, then ask again. Hitting one budget doesn’t affect the other, so a blocked search doesn’t stop you from running an ability.

If you reach the read limit repeatedly, your client is usually repeating calls, such as searching every site or reading a knowledge base again. Narrow the request to a single site or a more specific question.

service_unavailable isn’t a rate limit. It indicates a temporary server-side issue. Retry the request shortly.

ambiguous_outcome means a mutating ability failed in a way that leaves it unknown whether your site applied the change. The write might or might not have happened.

ambiguous_outcome is the only error code with that property. The server raises timeout and unavailable only for reads. They’re explicitly safe to retry, which is why their help text says so.

The message that comes with each of these codes usually explains it:

Code What it means
account_not_found The account_id isn’t one you belong to, or doesn’t exist. Call list_accounts and pass one of its values.
insufficient_scope Your sign-in didn’t grant the permission this tool needs. The message names it. Sign in again and grant it.
insufficient_credits The account’s credit balance is exhausted. Add credits in the User Portal; portal_url links there when set.
billing_account_pending AI billing isn’t set up for the account yet. The account owner sets it up in the User Portal. If they set it up recently, try again shortly.
credits_unavailable The credit balance check is temporarily unavailable. Try again shortly.
invalid_request An argument failed validation, and the message names the problem. The server rejects unknown fields instead of ignoring them. If an ability needs one of several argument sets, help lists them.
ability_not_found The name isn’t in that site’s catalog, or isn’t runnable. Check the spelling, or search again.
run_failed Your site rejected the call. The server appends the WordPress error to the message. Fix that error, then retry.
knowledge_base_unavailable Search is temporarily unavailable. Try again shortly.
request_too_large The input exceeds the size cap. Send less.
run_url_untrusted The site advertises a location that’s inconsistent with its registration. Contact support.
internal_error An unexpected server error. Retry once, then contact support.

Collect the request_id from the error and include it in your support request. WP Engine support uses it to locate the call. internal_error always includes a request_id and never includes a suggested fix.


Last updated: