Royal MCP Troubleshooting — Start Here
Connector won’t connect, OAuth failing, tools missing, or Claude returning “Couldn’t reach the MCP server”? Work through the steps below in order. Step 0 is a 30-second curl probe that tells you whether the problem is at your edge (Cloudflare, ModSecurity, host firewall) or inside WordPress — the answer determines which steps to follow next. Most connection failures resolve in under 15 minutes once you know which side of the line you’re on.
Before You Start
Have these on hand:
- WordPress admin access to the site Royal MCP is installed on
- Database access via phpMyAdmin, your host’s database manager, or SSH + WP-CLI (only needed for Step 3 if you’re on Royal MCP 1.4.16 or earlier)
- About 10 minutes of focused time. Don’t skip steps — the diagnostic data each step produces is what lets us help you if you still need support afterward
This is the basic checklist. It assumes Royal MCP is already installed and you’ve tried at least once to connect Claude (or any other MCP client) and it failed. If you’re looking for first-time setup, see the Royal MCP Support hub. If you’re looking for a host-specific advanced fix (SiteGround static files, Cloudflare Transform Rules, cache exclusions), the links at the bottom of this page route you there — but only after the steps below.
Using Claude Code in VS Code or Terminal? Start Here.
If you’re connecting through the Claude Code CLI (the claude command, or the VS Code Claude Code extension — not claude.ai web and not Claude Desktop), the fastest fix for most connection problems takes about 30 seconds and bypasses the 4-step checklist below entirely. The 4 steps are scoped for the OAuth-from-a-browser flow that claude.ai web and Claude Desktop use; Claude Code CLI manages its own MCP server connections with different lifecycle behavior.
In your VS Code terminal (or wherever you launched claude), type /mcp and press Enter. You’ll see a list of every configured MCP server. Look at the royal-mcp row:
- Green check — connection is alive. Your tools should work. If they don’t, jump to the 4-step checklist below.
- Red X — arrow down to the row, hit Enter, choose Reconnect. About 80% of "reads worked yesterday, writes are 403 today" reports are stale OAuth tokens. A reconnect grabs a fresh token and the problem disappears.
- Still red after reconnect — close the terminal completely (not just the Claude Code panel — the whole terminal), reopen it, run
/mcpagain. Stale process-side state is more common than you’d think. - Still red after a full terminal restart — re-run the OAuth flow from scratch: remove the
royal-mcpserver from your Claude Code config (claude mcp remove royal-mcp), then re-add it (claude mcp add...) so the client re-does Dynamic Client Registration against your site fresh. This is the equivalent of the “Reset OAuth State” step that claude.ai web users do server-side — for the CLI, the equivalent action is client-side.
The model selector in Royal MCP → Settings is used only by the “Test Connection” button on that admin page — it pokes Anthropic’s API with the model you picked to verify your API key. Claude Code in VS Code uses its own configured model, independently of whatever Royal MCP has selected. A 404 from the Test Connection button doesn’t mean Claude Code is broken — it usually means the model in the dropdown was retired by Anthropic. Switch to “Claude Sonnet 4.6 (Latest, Recommended)” and re-test.
That error string comes from Claude Code, not from Royal MCP. It can fire for any non-success response — expired token (401), capability check failure (403), or host-edge block. The diagnostic order is:
- Reconnect via
/mcpfirst (above) — rules out stale token, which is the common case. - If that doesn’t fix it, check Royal MCP → Activity Log in wp-admin — if recent attempts show up with errors, the request reached PHP and we can read the failure reason. If the log is empty after you reproduce the failure, the request died at the host edge (WAF, security plugin, or hosting firewall) — jump to the stack-specific section below.
- Confirm the WordPress user attached to your API key has the right capability. Post/page write tools (
wp_create_post,wp_update_page, etc.) requireedit_posts/edit_pages. Media writes requireupload_files. If your OAuth flow registered a low-privilege user, writes will fail with 403 even though reads succeed. Confirm in Users → All Users that the connected account has Editor or Administrator role.
If those three checks don’t resolve it — meaning /mcp shows green, Activity Log shows attempts reaching PHP, and the user has the right capability — continue to Step 0 below. The diagnostic path applies to your situation too.
Step 0 — The 30-Second Edge Probe
Before doing anything inside WordPress, run this one curl command from your local machine to find out whether your edge (Cloudflare, ModSecurity, host firewall, etc.) is blocking the request before it reaches WordPress. Your response pattern tells you exactly where the problem lives and which fix to apply.
The probe
Open a terminal on your own computer (not on your WordPress server) and run the command below. Two variants — use the one matching your shell:
Mac Terminal, Linux, Windows Command Prompt (cmd.exe), Git Bash:
curl -sS https://example.com/.well-known/oauth-authorization-server -H "Accept: application/json"
Windows PowerShell: PowerShell aliases curl to Invoke-WebRequest, which uses different flag syntax and will error on the command above. Use curl.exe instead — that bypasses the alias and runs Windows’ built-in real curl with the same syntax as everywhere else:
curl.exe -sS https://example.com/.well-known/oauth-authorization-server -H "Accept: application/json"
Replace example.com with your actual domain. Match the result against one of the patterns below.
Both are free GUI HTTP clients that let you GET a URL, set a User-Agent header (important for the 403 / 406 / 429 patterns below where the UA changes the result), and see the response with headers visible. Avoid plain browser tabs for this probe — browsers send a browser User-Agent, which often passes through edge filters that block Anthropic’s OAuth backend, giving you a false “healthy” result. For the deeper diagnostic walkthrough including dual-UA comparison, see the full curl diagnostic guide.
What did you see?
✅ JSON response with "issuer": "https://example.com"
JSON starting with {"issuer":"https://your-site.com","authorization_endpoint":"https://your-site.com/authorize",...} and the URLs match your actual domain. scopes_supported includes "mcp:full".
What this means
Your edge layer is fine and Royal MCP’s discovery is healthy from outside. If you’re still hitting a connection error, the problem is plugin-side — continue to Steps 1–4 below.
🛑 JSON, but "issuer" points to auth.example.com or another domain
JSON, but the issuer field references a subdomain like auth.your-site.com, OR scopes_supported includes openid / profile / email instead of mcp:full, OR endpoint paths have /oauth/ prefix (/oauth/authorize instead of /authorize).
What this means
Cloudflare Zero Trust Access is hijacking your OAuth discovery endpoint. Common when someone on your team set up a Cloudflare MCP Portal or Access app during MCP debugging — CF intercepts /.well-known/ and returns its own OIDC metadata, breaking Royal MCP’s OAuth flow. The fix is removal, not configuration.
🛑 HTML response instead of JSON
You see <!DOCTYPE html> or <html> tags. Often a login page, paywall, access-denied page, or theme-styled error page.
What this means
A membership plugin (MemberPress, Restrict Content Pro, Paid Memberships Pro), security plugin, or theme template is intercepting /.well-known/oauth-authorization-server and returning a page instead of letting Royal MCP respond with JSON. Royal MCP 1.4.22+ auto-detects this and surfaces an admin notice.
🛑 403 Forbidden + Cloudflare branding (cf-ray header)
A 403 error page that mentions Cloudflare, shows a cf-ray reference ID, or says “Sorry, you have been blocked.” The 403 reproduces with curl -A "python-httpx/0.27.0" ... even if a browser UA gets through.
What this means
Cloudflare’s Bot Fight Mode, “Block AI Bots” toggle, AI Crawl Control, or a managed WAF rule is treating Anthropic’s OAuth backend as a bot and blocking it. Check all three CF panels (Security → Bots, Bot Fight Mode, and AI Crawl Control) — the first two being off does NOT mean CF isn’t blocking.
🛑 406 Not Acceptable + “Mod Security” in the response body
A 406 error where the response body literally contains the phrase “Generally a 406 error is caused because a request has been blocked by Mod Security.” Reproduces with default curl headers.
What this means
cPanel ModSecurity is fingerprinting non-browser HTTP clients (Anthropic’s OAuth backend, scrapers, anything without the right header mix) and blocking them at the edge before WordPress sees the request. Common on InMotion, A2 Hosting, Bluehost, HostGator, GreenGeeks, Namecheap shared hosting.
🛑 429 Too Many Requests — persistent, not rate-related
A 429 error with a plain “Too Many Requests” body. Reproduces consistently with curl -A "python-httpx/0.27.0" ..., but returns 200 with curl -A "Mozilla/5.0" .... The 429 persists across multiple requests minutes apart (not a burst rate limit).
What this means
Your Apache shared host (managed-WordPress providers running Imunify360, mod_security with UA-fingerprint rules, or similar bot-defense layers) is returning 429 specifically for non-browser User-Agents — including Anthropic’s OAuth backend. The fix is host-side: you can’t configure your way out of this from inside WordPress.
🛑 404 Not Found
A 404 error. The URL appears to not exist at all.
What this means
Three possibilities, in order of likelihood:
- SiteGround (and some Hostinger, o2switch) nginx is blocking the
.well-known/path prefix. Most likely if you’re on SiteGround. SiteGround/.well-known/404 fix → - Royal MCP is not active on this site. Check WP Admin → Plugins to confirm Royal MCP is installed and activated.
- WordPress rewrite rules need flushing. Go to WP Admin → Settings → Permalinks and click Save Changes (no actual changes needed; the save action regenerates rewrite rules).
🛑 301 Moved Permanently or 302 Found redirect
The response is a redirect (usually to a URL with a trailing slash, like /.well-known/oauth-authorization-server/).
What this means
Your web server is adding a trailing slash via canonicalization. OAuth clients don’t follow redirects on POST requests, so registration and token exchange break silently even though the discovery path is technically reachable. Royal MCP 1.4.22+ auto-detects this and surfaces an admin notice.
🤷 Something else — timeout, empty response, or unclear status
The curl command times out, returns nothing, returns a status code not listed above, or shows a response you can’t match to any of the patterns.
What this means
Could be a basic connectivity issue (DNS, expired SSL certificate, hosting outage), an unusual edge configuration, or a transient hiccup. Continue to Steps 1–4 below to narrow it down. If you’re still stuck after the plugin-layer pass, the diagnostic output from Steps 1–4 is what our support process needs to triage further.
For a more thorough probe sequence (testing /register, /wp-json/royal-mcp/v1/mcp, dual-UA comparison, response header inspection), see the full curl-based MCP diagnostic guide. Useful if you’re a developer or want to understand exactly what each OAuth step is doing.
Steps 1–4 — Plugin-Layer Diagnostic Checklist
Run these steps only after Step 0 above returns the healthy “JSON with matching issuer” response — or if Step 0 gave you a result that didn’t match any of the patterns. If Step 0 surfaced a specific edge-layer issue, click through to that fix instead; the plugin-layer steps below won’t help with edge-blocking.
Update Royal MCP to the latest version
In wp-admin go to Plugins → Installed Plugins, locate “Royal MCP”, and click Update if a newer version is available. Why first: every recent release has shipped meaningful OAuth diagnostics and edge-case fixes that change what you’ll see in later steps.
- 1.4.13+ — OAuth endpoints send no-cache headers so edge caches stop poisoning them with stale responses
- 1.4.14+ — OAuth discovery (claude.ai web / ChatGPT) probes get the correct 401 +
WWW-Authenticateresponse instead of a 405 - 1.4.15+ — API key Regenerate button actually works; MCP sessions use a 24-hour sliding TTL instead of expiring at exactly 1 hour
- 1.4.16+ — every OAuth failure writes a structured row to the Activity Log, which is what Step 4 below relies on
Most pre-1.4.16 issues that look like host problems are actually fixed by the update alone.
Run a conflict test (plugin / theme / cache)
This single step resolves the majority of remaining tickets. Don’t skip it — even if you’re certain it isn’t a conflict. We see “I already tried that” very often, and “tried similar” isn’t the same as “ran these exact steps in order.”
(a) Deactivate ALL other plugins except Royal MCP. WordPress → Plugins → check the box at the top of the list, choose Deactivate from the bulk action menu, but uncheck Royal MCP first.
(b) Switch to a default theme. Appearance → Themes → activate Twenty Twenty-Five (or any unmodified default theme). Custom themes sometimes register their own URL rewrites or rewrite filters that interfere with our OAuth endpoints.
(c) Purge every cache. Three layers, all of them:
- WordPress-side — if you use a cache plugin (LiteSpeed Cache, WP Rocket, W3 Total Cache, SpeedyCache, Hummingbird, etc.), purge it. If LiteSpeed is active, also flush the object cache.
- Server-level — SiteGround Optimizer, Kinsta cache, WP Engine cache, Liquid Web cache, Cloudways Varnish — purge in your hosting control panel. Many managed hosts have their own cache layer separate from any plugin.
- Cloudflare / CDN — if you use Cloudflare, purge everything. While you’re there, check whether “Block AI Bots” is enabled in Security → Settings — if it is, turn it off (this single setting breaks MCP for many users; see Step 5 below if disabling it isn’t enough). Also check “Bot Fight Mode” — same issue.
- Browser cache — Cmd/Ctrl+Shift+R to hard-reload the relevant Claude page.
(d) Retry the connection. If it now works, the conflict was one of the deactivated plugins or the theme. Reactivate plugins one at a time, retrying after each, until it breaks — that’s your culprit. The most common offenders we see, in rough order:
- Security plugins — Wordfence, Defender Pro, Solid Security (formerly iThemes Security), All In One WP Security & Firewall, NinjaFirewall. These intercept and sometimes block POST requests to the MCP endpoint and OAuth paths. Allowlist
/wp-json/royal-mcp/*,/register,/token, and/authorizein the plugin’s firewall rules to unblock. - Caching plugins — LiteSpeed Cache and SpeedyCache running together is a confirmed reproducer of OAuth auth-code eviction. Add cache exclusions for the same paths.
- Login/registration plugins — MemberPress, Paid Memberships Pro, Restrict Content Pro, Ultimate Member, Profile Builder. These can register a page with slug
registerthat wins URL routing over our OAuth endpoint. - Custom theme functions — rare, but custom themes that filter
rewrite_rules_arraycan deregister our endpoints.
Wipe stale OAuth state
Prior connection attempts leave behind client registrations, tokens, and authorization codes that can interfere with a fresh test. Wipe them.
On Royal MCP 1.4.17 or newer (one click):
Go to Royal MCP → Settings and click the Reset OAuth State button near the bottom of the page. Confirm in the modal. Done.
On Royal MCP 1.4.16 or older (database queries):
The Reset OAuth State button doesn’t exist yet. Run these queries via phpMyAdmin, your host’s database manager, or SSH (wp db query if you have WP-CLI):
DELETE FROM wp_royal_mcp_oauth_clients; DELETE FROM wp_royal_mcp_oauth_tokens; DELETE FROM wp_options WHERE option_name LIKE '_transient_royal_mcp_authcode_%'; DELETE FROM wp_options WHERE option_name LIKE '_transient_timeout_royal_mcp_authcode_%';
Some hosts (managed-WordPress, hardened installs) randomize the wp_ prefix. Open wp-config.php and check the $table_prefix line — if it’s anything other than wp_, substitute it in all four queries above before running them.
Then on the Claude side:
- In Claude (web or Desktop), delete the existing Royal MCP connector.
- Wait 30 seconds. Claude.ai caches its own discovery state for a short window.
- Re-add the connector from scratch. This forces a full OAuth flow rather than reusing the cached (and now invalid) client credentials Claude was holding.
If the connection works after this step, the issue was stale OAuth state. You’re done.
Check the Activity Log
If steps 1–3 didn’t resolve it, this step tells us (and you) exactly which validation rule is firing — or whether the request is reaching your WordPress install at all.
In wp-admin go to Royal MCP → Activity Logs. Reproduce the failed connection attempt — click Connect in Claude, watch it fail, then come back to the Activity Log page and refresh.
If there’s a recent row whose action starts with oauth:
Click View Details. The panel shows the OAuth error code and error_description — for example:
invalid_grant: Authorization code is invalid, expired, or already used.— usually means object cache (LiteSpeed + SpeedyCache) is evicting the auth code between/authorizeand/token. Fix in Royal MCP 1.4.17.invalid_grant: PKCE verification failed.— usually means a security plugin is URL-decoding the POST body. Disable security plugins per Step 2.invalid_grant: redirect_uri mismatch.— Claude’s stored redirect URI doesn’t match what was registered. Wipe OAuth state per Step 3 and try again.invalid_client— client_id Claude is sending isn’t in our database. Wipe OAuth state per Step 3.invalid_request: Missing required parameters— something is stripping POST fields between Claude and your WordPress. Almost always a security plugin or WAF.
If the Activity Log is empty after a reproduced failure
That’s diagnostic on its own. It means the request never reached your WordPress PHP code — the failure is happening at the host edge, in a cache layer, or inside a security plugin’s firewall (before our code runs). Step 5 below lists the most common stack-specific culprits.
Additional Stack-Specific Articles
The full library of Royal MCP fix articles — including the ones Step 0 above routes to plus several others for specific situations Step 0 doesn’t cover (managed-host cache poisoning, SiteGround Content-Type issues, the static OAuth client setup trap, and the Claude Desktop API-key bypass).
If you arrived here from Step 0 above, the relevant article is already linked there — this section just lists everything in one place. If you completed Steps 1–4 and the connection still fails, browse below for your specific stack or symptom.
Still Stuck? Two Support Paths
If you’ve worked through Step 0, the relevant stack-specific article it pointed you to, and Steps 1–4 above, and the connector still fails, you have two options for further help:
Community Support (free) — wp.org Plugin Forum
Post a new thread at wordpress.org/support/plugin/royal-mcp/. The Royal Plugins team checks the forum regularly and other community members — including hosting providers and developers who’ve hit the same issues — often answer faster than email could. This is the right path if you’re not on a deadline.
Premium Support (paid) — direct one-on-one help
For priority response (24-hour SLA), direct email access, and hands-on diagnostic help, our Premium Support tier is $149/year. Useful if you’d rather have us walk you through the fix, you’re on a deadline, or your stack is genuinely complicated (Cloudflare + custom WAF + edge cache combinations). Includes a 30-day “if it breaks again” follow-up window on every resolved ticket.
What to include in your post or ticket (either path)
- Your hosting provider (SiteGround, Cloudways, Hostinger, Kinsta, WP Engine, Liquid Web, self-hosted VPS, etc.)
- Royal MCP version from WP Admin → Plugins (please be on 1.4.16 or newer — older versions don’t produce the Activity Log entries we need)
- Active caching plugins (LiteSpeed Cache, WP Rocket, W3 Total Cache, SpeedyCache, Hummingbird, none)
- Active security plugins (Wordfence, Defender Pro, Solid Security, NinjaFirewall, none)
- Cloudflare or CDN in front of the site? If yes, is “Manage AI Bots” or “Bot Fight Mode” on?
- Which Claude client — claude.ai web custom connector, Claude Desktop with
mcp-remote, ChatGPT MCP, or another MCP-compatible client - The exact error message you see, plus any
ofid_xxxxxreference code if claude.ai shows one - Screenshot of the most recent
oauth:row in your Activity Log with View Details expanded (or confirmation that the log is empty after a reproduced failure) - Your Step 0 curl output (the response pattern from the edge probe above) plus which steps you ran from the 4-step checklist and what changed at each