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.
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:
- Membership plugins (ARMember, MemberPress, Restrict Content Pro, Paid Memberships Pro, MemberMouse, Ultimate Member, Restrict User Access, BuddyBoss) hook
template_redirectorparse_requestwith an “is this user allowed to see this URL?” check. If the default policy is “deny everything except an allowlist”, OAuth discovery URLs get caught. - Restricted-content themes with global page-locks (often configured in the Customizer or a theme options panel) do the same check via a theme template.
- Coming-soon and maintenance-mode plugins (SeedProd, WP Maintenance Mode, Underconstruction Page) replace the entire frontend response with their own page regardless of URL.
- Custom rewrite rules added by another plugin or by your theme’s
functions.phpcan take priority over Royal MCP’s rules. Re-saving Permalinks reshuffles priorities.
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.
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:
- Membership / access-control plugins
- Coming-soon / maintenance-mode plugins (these are often forgotten and left active in “authenticated bypass” mode that doesn’t bypass for non-browser requests)
- Security plugins with custom WAF rules
- Any other plugin whose name contains “Restrict”, “Lock”, “Private”, “Members”, “Force Login”, etc.
- 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:
- Run the
curlcommand from the top of this page again — the response should now be JSON starting with{"issuer":"https://...`} - 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)
- Reload any Royal MCP admin page — the “OAuth discovery is being served as HTML” notice should no longer appear
- 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 -ioutput 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.