Support / Royal MCP / OAuth Discovery Returns HTML Instead of JSON

OAuth Discovery Returns HTML Instead of JSON

Royal MCP’s admin self-check flagged that /.well-known/oauth-authorization-server is returning an HTML document at HTTP 200 instead of the JSON metadata MCP clients expect. A membership plugin, theme template, or restricted-content rule is intercepting the request and serving its own login or access-denied page. Claude.ai and other discovery-aware MCP clients fail silently when they receive HTML on this URL. This page walks through identifying the culprit and three fixes that don’t require uninstalling anything.

Detected by Royal MCP 1.4.22

This admin notice was added in Royal MCP 1.4.22. The self-check probes your discovery URL every 12 hours and classifies the response. If you arrived here from the admin notice link, the diagnosis is already done — jump straight to the Three Fixes section.

Confirm What’s Happening

From any terminal, run:

curl -i https://YOUR-DOMAIN.com/.well-known/oauth-authorization-server

You’re hitting this issue if the response is:

The Telltale Signature

  • Status: HTTP/2 200 (not 404, not 301)
  • Body: starts with <!DOCTYPE html>, <html>, or <head> — an HTML document, not JSON
  • Body content: typically a login page, access-denied notice, password prompt, or your site’s 404 template
  • Headers: may include cookies like armember_*, mepr_*, rcp_*, wp-postpass_*, or a session cookie set by your theme

If the response is JSON starting with {, you’re looking at a different issue — this guide doesn’t apply.

Why This Happens

Royal MCP registers a top-level rewrite rule mapping /.well-known/oauth-authorization-server to its OAuth metadata handler. The rule resolves at the WordPress rewrite layer, and the handler returns JSON. That’s the working path.

But several classes of plugins and themes hook earlier than the OAuth handler and short-circuit the response before it runs:

In all cases the symptom is the same: discovery clients ask for JSON, get HTML, and fail silently without a clear error message.

Three Fixes

Try them in order. Fix #1 is the cheapest. Fix #3 narrows down the culprit if the first two don’t resolve it.

Fix #1 — Add OAuth paths to your membership plugin’s unrestricted-URL list

Almost every membership plugin has an “Excluded URLs” or “Bypass Pages” setting. The five Royal MCP paths to allow are:

/.well-known/oauth-authorization-server
/.well-known/oauth-protected-resource
/authorize
/token
/register

Add each as an exact match or a wildcard pattern depending on what the plugin supports. Save the setting and re-test with the curl command above.

Plugin-specific paths to the setting:

  • ARMember → ARMember → Plugin Configuration → Login tab → “Restrict Pages” or “Page Restriction” section
  • MemberPress → MemberPress → Settings → Pages tab → “Unauthorized Access” section
  • Restrict Content Pro → Restrict → Settings → Misc tab → “Exempted URLs” or “Excluded URIs”
  • Paid Memberships Pro → Memberships → Settings → Advanced tab
  • BuddyBoss → BuddyBoss → Settings → Pages tab → Login redirect settings

Fix #2 — Re-save Permalinks to flush rewrite rules

WordPress rewrite rules are cached, and the order they evaluate in can be reshuffled by plugin activations and deactivations. Re-saving forces a fresh build and gives Royal MCP’s rules a clean priority.

Go to WP Admin → Settings → Permalinks and click Save Changes without changing anything else. Then re-test with the curl command above.

If you’re using a custom permalink structure

Royal MCP’s rewrite rules work on every standard permalink structure (Post name, Day and name, Month and name, Numeric, Custom Structure starting with /%postname%/). The Plain permalink structure (no rewriting at all) is the only configuration where these rules can’t be registered — switch to Post name if you’re currently on Plain.

Fix #3 — Bisect the culprit by deactivating suspects

If Fixes #1 and #2 don’t resolve it, identify which plugin is intercepting by deactivating candidates one at a time and re-running the curl test after each. Start with:

  1. Membership / access-control plugins
  2. Coming-soon / maintenance-mode plugins (these are often forgotten and left active in “authenticated bypass” mode that doesn’t bypass for non-browser requests)
  3. Security plugins with custom WAF rules
  4. Any other plugin whose name contains “Restrict”, “Lock”, “Private”, “Members”, “Force Login”, etc.
  5. Your active theme — switch temporarily to Twenty Twenty-Five and re-test; if the issue disappears, your theme has a template-level page lock

Once identified, you have three options:

  • Configure the plugin/theme to allow the OAuth paths (the equivalent of Fix #1 for non-membership plugins)
  • If the plugin offers a per-URL filter hook, write a small must-use plugin that bypasses for OAuth URLs only
  • Switch to a different plugin that handles allowlists more cleanly

Verify the Fix Worked

After applying any of the three fixes:

  1. Run the curl command from the top of this page again — the response should now be JSON starting with {"issuer":"https://...`}
  2. In WordPress admin, go to WP Admin → Royal MCP → Settings and save the form (this invalidates the 12-hour self-check transient so the notice refreshes immediately)
  3. Reload any Royal MCP admin page — the “OAuth discovery is being served as HTML” notice should no longer appear
  4. Reconnect Claude.ai (or whichever MCP client was failing) — the OAuth handshake should now complete

Still Stuck?

If you’ve worked through all three fixes and the curl test still returns HTML, contact support@royalplugins.com with:

Information We’ll Need

  • The full curl -i output for /.well-known/oauth-authorization-server (headers AND body, redacted if your error page contains sensitive content)
  • Your active theme name
  • Your list of active plugins (WP Admin → Plugins → copy/paste the list)
  • Royal MCP version (must be 1.4.22 or newer for the self-check to apply)
  • Whether the issue persists after switching to Twenty Twenty-Five and disabling all non-essential plugins

We respond within one business day.