• OAuth authorization fails when connecting to Claude.ai. After clicking Authorize, Claude returns ‘Authorization with the MCP server failed’. The MCP endpoint responds correctly to HTTP POST requests. Site hosted on SiteGround. Error reference codes change on every attempt. We have tried: regenerating OAuth credentials, removing Cloudflare, and multiple reconnection attempts. The authorization window appears correctly but the callback always fails.

    The page I need help with: [log in to see the link]

Viewing 14 replies - 1 through 14 (of 14 total)
  • Thread Starter terraexperty

    (@terraexperty)

    Hello Royal MCP team, I hope you are doing well.
    My name is René, technical support at Terra Experty, and I am reaching out because we are experiencing issues connecting our WordPress site (terraexperty.com) with Claude.ai using the Royal MCP plugin.
    The specific problem is that the OAuth authorization fails right after clicking ‘Authorize’. The authorization window appears correctly and we can confirm that the MCP endpoint responds properly to HTTP POST requests, however Claude.ai always returns the error ‘Authorization with the MCP server failed’.
    We have tried the following without success: regenerating OAuth credentials, removing Cloudflare from the domain, reconnecting the connector multiple times, and creating a custom connector with a Bearer Token.
    Our site is hosted on SiteGround with self-hosted WordPress. Could this be a compatibility issue with SiteGround or with the OAuth callback URL?
    We truly appreciate your help and look forward to any solution you can suggest.
    Best regards,
    René
    Technical Support — Terra Experty
    terraexperty.com

    Plugin Support rpteam

    (@rpteam)

    Hi René,

    Thanks for the detailed write-up — you’ve already ruled out most of the usual suspects, which actually helps a lot. We’ve seen this exact failure mode on managed-WordPress hosts that run NGINX-level dynamic caching (SiteGround, o2switch, LiteSpeed). Even with Cloudflare removed, SiteGround’s own Speed Optimizer cache layer is still in front of WordPress, and it sometimes ignores the cache-bypass headers we send on the OAuth endpoints.

    Before we dig deeper, two quick checks will tell us exactly what’s happening:

    1. Confirm your Royal MCP version WP Admin → Plugins → Royal MCP. We need 1.4.13 or newer — earlier versions had a known cache-poisoning bug we fixed in 1.4.13. If you’re on an older build, please update first and retry the connection.
    2. Check the Activity Log WP Admin → Royal MCP → Activity Log, then attempt the Claude.ai authorization again. Look for entries timestamped at the moment you clicked “Authorize.”
    • Entries appear: OAuth is reaching WordPress — the issue is in the flow itself, and we’ll dig into the specific log lines.
    • Log stays empty: The request never reached PHP, which confirms an upstream cache or WAF is short-circuiting it. This is the more likely scenario on SiteGround.
    1. Inspect the cache headers (1 minute) Run this from any terminal — it tells us whether SiteGround is serving cached responses for our OAuth endpoints: curl -I https://terraexperty.com/wp-json/royal-mcp/v1/oauth/.well-known/oauth-authorization-server Send us the full response headers. We’re looking specifically for x-cache, x-proxy-cache, or x-sg-cache — if any of those show HIT, we’ve found the problem. If the Activity Log is empty (most likely): The fix is to exclude the OAuth and MCP endpoints from SiteGround’s Dynamic Cache. In WP Admin → SG Optimizer → Caching → Dynamic Cache → Exclude URLs, add these patterns: /wp-json/royal-mcp/*
      /wp-json/royal-mcp/v1/oauth/*
      /.well-known/oauth-authorization-server
      /.well-known/oauth-protected-resource

    Then click Purge Cache in the SG Optimizer toolbar and retry the Claude.ai connection. This has resolved the same symptom for us on other NGINX-cached hosts.

    If that doesn’t clear it, also worth checking SiteGround → Site Tools → Security → Site Scanner / Web Application Firewall — some custom WAF rules block JSON POSTs to non-standard REST namespaces, which would also produce the silent failure you’re describing.

    Reply with the Activity Log findings and curl headers and we’ll take it from there. We’ll get this connected!

    Best,
    Jameson
    Royal Plugins

    Thread Starter terraexperty

    (@terraexperty)

    Hi Jameson,
    Here are the curl headers for the OAuth endpoint:
    HTTP/2 404
    server: nginx
    x-cache-enabled: False
    x-proxy-cache-info: DT:1
    access-control-allow-methods: GET, POST, OPTIONS
    access-control-allow-origin: *
    Cache is disabled for this URL after adding the SG Optimizer exclusions. Activity Log is still empty after retrying the connection. What should we check next?
    Best regards,
    René — Technical Support, Terra Experty

    Plugin Support rpteam

    (@rpteam)

    Hi René!
    Quick follow-up, I just tested your endpoint from my end and we have a
    definitive answer.

    The good news: Royal MCP is working correctly on your site. Your MCP endpoint,
    /authorize, /register, and /token all reach WordPress and respond properly with our
    1.4.13 cache-control headers.

    The actual issue: SiteGround’s nginx is intercepting /.well-known/* requests at the
    host level and returning its own static 404 — the requests never reach WordPress.
    Here’s the proof:

    Your MCP endpoint — works fine, served by PHP/WordPress:
    $ curl -I https://terraexperty.com/wp-json/royal-mcp/v1/
    HTTP/1.1 200 OK
    X-Httpd: 1 ← PHP processed this

    OAuth discovery — nginx 404, never reached WordPress:
    $ curl -I https://terraexperty.com/.well-known/oauth-authorization-server
    HTTP/1.1 404 Not Found
    Content-Length: 93 ← tiny nginx static page, not WP
    (no X-Httpd header, no CORS headers — request died at nginx)

    Same behavior on any other .well-known path:
    $ curl -I https://terraexperty.com/.well-known/security.txt
    HTTP/1.1 404 Not Found
    Content-Length: 93 ← identical fingerprint

    Compare to a WP-handled 404:
    $ curl -s https://terraexperty.com/this-does-not-exist/
    <html lang=”es” … ← full WP page in your site’s language

    SiteGround reserves /.well-known/ for their own use (ACME SSL certificate renewals,
    security.txt). Anything else under that path returns nginx’s default 404 before
    WordPress can register a route there. This is why Claude.ai fails the connection: it
    tries to discover the OAuth metadata at /.well-known/oauth-authorization-server, gets
    a 404, and can’t continue the flow.

    What you need to do: open a support ticket with SiteGround and ask them to allow these
    two paths through to PHP/WordPress:

    /.well-known/oauth-authorization-server
    /.well-known/oauth-protected-resource

    Suggested wording for the ticket:

    “We use a WordPress plugin (Royal MCP) that needs to serve OAuth 2.0 discovery
    metadata at the standard RFC 8414 paths (/.well-known/oauth-authorization-server and
    /.well-known/oauth-protected-resource). These requests are currently returning a 404
    from your nginx layer instead of reaching WordPress. Could you please add an exception
    to allow these specific paths to pass through to PHP? They’re standard OAuth
    discovery endpoints required by client applications like Claude.ai.”

    If SiteGround declines or this is a hard blocker for you, let us know — we’re scoping
    a workaround on our end (writing the metadata as a static file in the webroot) for the
    next Royal MCP release that could route around this.

    Best,
    Jameson
    -Royal Plugins

    Thread Starter terraexperty

    (@terraexperty)

    Hi Jameson, SiteGround confirmed the /.well-known/ files don’t exist on the server. Could you provide the exact content needed for these two static files so we can create them manually in the webroot?
    – /.well-known/oauth-authorization-server
    – /.well-known/oauth-protected-resource

    Best regards, René — Terra Experty

    Plugin Support rpteam

    (@rpteam)

    Hi René,

    Perfect — that confirms exactly what we suspected. SiteGround’s nginx will serve files
    from /.well-known/ if they physically exist; it just refuses to fall through to
    WordPress when they don’t. So the workaround is to drop two static files in your
    webroot.

    File 1: /.well-known/oauth-authorization-server (no file extension)

    {
    “issuer”: “https://terraexperty.com&#8221;,
    “authorization_endpoint”: “https://terraexperty.com/authorize&#8221;,
    “token_endpoint”: “https://terraexperty.com/token&#8221;,
    “registration_endpoint”: “https://terraexperty.com/register&#8221;,
    “response_types_supported”: [“code”],
    “grant_types_supported”: [“authorization_code”, “refresh_token”],
    “token_endpoint_auth_methods_supported”: [“none”, “client_secret_post”],
    “code_challenge_methods_supported”: [“S256”],
    “scopes_supported”: [“mcp:full”],
    “service_documentation”: “https://royalplugins.com/support/royal-mcp/&#8221;
    }

    File 2: /.well-known/oauth-protected-resource (no file extension)

    {
    “resource”: “https://terraexperty.com/wp-json/royal-mcp/v1&#8221;,
    “authorization_servers”: [“https://terraexperty.com”%5D,
    “bearer_methods_supported”: [“header”],
    “scopes_supported”: [“mcp:full”]
    }

    Steps:

    1. Via SiteGround File Manager (Site Tools → Site → File Manager) or SFTP, navigate to
      your WordPress root (the folder containing wp-config.php).
    2. Create a folder named .well-known if it doesn’t exist.
    3. Inside it, create two files with no extension — name them exactly
      oauth-authorization-server and oauth-protected-resource.
    4. Paste the JSON content above into each, save. Verify with curl: curl -i https://terraexperty.com/.well-known/oauth-authorization-server
      curl -i https://terraexperty.com/.well-known/oauth-protected-resource You should see HTTP/2 200 and the JSON body. If you see a 404, the file path is off —
      double-check the folder name starts with a dot. If the Content-Type header comes back as application/octet-stream rather than
      application/json, that’s fine — Claude.ai parses these endpoints as JSON regardless.
      If for any reason Claude still rejects, drop a .htaccess next to the files with: ForceType application/json
      ForceType application/json Once the files are live, retry the Claude.ai connection. We’re scoping a 1.4.14
      release that will auto-create these for SiteGround/managed-host users so this isn’t a
      manual step going forward — thanks for the patience and for helping us pin this down.

    Best
    Jameson

    Thread Starter terraexperty

    (@terraexperty)

    Hi Jameson,
    Complete technical findings after extensive testing:
    ✅ /.well-known/oauth-authorization-server → HTTP/2 200
    ✅ /.well-known/oauth-protected-resource → HTTP/2 200
    ✅ /register → HTTP/2 201 (dynamic registration works)
    ✅ /authorize → reaches WordPress (x-httpd: 1)
    ❌ /authorize → returns ‘Unknown client_id. The application has not been registered’
    ❌ Activity Log always empty
    ❌ Claude.ai never calls /register automatically before /authorize
    ❌ Result: ‘Authorization with the MCP server failed’
    Root cause identified: Claude.ai attempts /authorize directly without first calling /register to obtain a valid client_id. Royal MCP rejects the unknown client_id.
    Question: Should /register be called manually before connecting? Or should Royal MCP accept unknown client_ids and register them on the fly during /authorize?
    Error ref: ofid_f0f889e086a13da4
    Best regards,
    René — Terra Experty

    Plugin Support rpteam

    (@rpteam)

    Hi René,

    That diagnostic is gold — those green checkmarks prove the static-file workaround unblocked the host-level OAuth handshake. The “Unknown client_id” is the next layer down, and it points at Claude.ai’s
    connector configuration on your side, not a Royal MCP bug.

    What’s happening:

    Claude.ai’s MCP connector supports two modes:

    1. Automatic OAuth (the standard flow Royal MCP expects) — you give Claude only your MCP URL. Claude auto-discovers your OAuth metadata at /.well-known/oauth-authorization-server, calls /register to
      dynamically register itself per RFC 7591, receives a fresh client_id, then sends the user to /authorize. Royal MCP recognizes the freshly-registered client_id and the handshake completes.
    2. Custom OAuth credentials / Bearer Token — you pre-register a client and paste a client_id (or token) into Claude’s connector form manually. Claude skips /register entirely and sends whatever client_id you
      entered straight to /authorize. If that ID doesn’t exist in Royal MCP’s clients table, you get exactly the error you’re seeing. Your first message mentioned “creating a custom connector with a Bearer Token” — that’s mode 2, and Claude.ai may still be using that cached configuration even if you’ve since pasted the URL alone. That
      perfectly matches your observation that /register is never called and /authorize arrives with an unknown ID. The fix:
    3. In Claude.ai → Settings → Connectors, fully remove the existing Royal MCP / Terra Experty connector. Don’t just edit it — remove it completely so Claude purges its cached config.
    4. Wait ~10 seconds.
    5. Click Add connector and select the standard “Add MCP server by URL” option (not the “Custom OAuth” / “Bearer Token” option).
    6. Paste only the MCP URL: https://terraexperty.com/wp-json/royal-mcp/v1/mcp — no client_id, no secret, nothing else.
    7. Click through the OAuth flow. Verify it’s now using DCR: While you click “Add connector”, tail your access log: tail -f /var/log/nginx/access.log | grep -E ‘(register|authorize|token)’ You should see POST /register HTTP/2 201, then GET /authorize …, then POST /token …. If /register does not appear, Claude is still running in the custom-credentials mode — back to step 1. About the empty Activity Log: Royal MCP’s Activity Log records MCP tool calls (post-auth), not the OAuth handshake itself. So an empty log during the connection attempt is expected behavior, not a separate signal of trouble — once you’re
      connected and Claude makes its first tool call, you’ll see it land in the log. Try the remove-and-re-add and send back the access-log lines. We’re one click away from a working connector.

    Best
    Jameson

    Thread Starter terraexperty

    (@terraexperty)

    Hi Jameson,
    We have identified the exact problem. When adding the connector with ONLY the MCP URL (no OAuth credentials), Claude.ai returns ‘Couldn’t reach the MCP server’ WITHOUT showing the authorization window.
    The MCP endpoint returns HTTP/2 405 on GET requests:
    curl -i https://terraexperty.com/wp-json/royal-mcp/v1/mcp → HTTP/2 405
    We believe Claude.ai first sends a GET request to verify the server is reachable. Since it gets a 405, it considers the server unreachable and never starts the OAuth flow.
    When we add OAuth Client ID and Secret manually, the authorization window DOES appear but fails with ‘Authorization with the MCP server failed’ — suggesting Claude.ai skips /register and sends an unknown client_id directly to /authorize.
    Questions:
    1. Should the MCP endpoint return 200 on GET requests?
    2. Is there a way to pre-register Claude.ai’s client_id in Royal MCP?
    Error ref: ofid_b8f0d40261cecb59
    Best regards,
    René — Terra Experty

    Plugin Support rpteam

    (@rpteam)

    Hi René,

    I see the issue now, will have update addressing this in next 24hrs V1.4.14 – be on the lookout

    Plugin Support rpteam

    (@rpteam)

    V.1.4.14 is live, test it and let me know

    Thread Starter terraexperty

    (@terraexperty)

    Hi Jameson,
    Update after extensive troubleshooting on SiteGround:
    Current status:
    ✅ Royal MCP v1.4.14 fresh install
    ✅ PHP 7.4.33
    ✅ /.well-known/oauth-authorization-server → HTTP/2 200
    ✅ /.well-known/oauth-protected-resource → HTTP/2 200
    ✅ /wp-json/royal-mcp/v1/mcp → HTTP/2 401 (correct)
    ✅ WpResidence theme updated to v5.6
    ❌ OAuth flow never completes — debug.log shows NO activity during authorization attempts
    ❌ Claude.ai returns: ‘Authorization with the MCP server failed’
    Latest error ref: ofid_234d00cf310dabfb
    The requests from Claude.ai never reach WordPress PHP during the OAuth handshake. We have been working on this for several days. Could you please provide the exact working configuration for SiteGround hosted sites?
    Best regards,
    René — Terra Experty

    Plugin Support rpteam

    (@rpteam)

    Hi René,

    I tested every endpoint on terraexperty.com from our side just now, and have a definitive picture for you. The good news: Royal MCP on your site is fully functional. Every OAuth endpoint reaches PHP correctly:

    GET /.well-known/oauth-authorization-server → 200 ✅
    GET /.well-known/oauth-protected-resource → 200 ✅
    GET /wp-json/royal-mcp/v1/mcp → 401 ✅ (with WWW-Authenticate:
    Bearer resource_metadata=”…”)
    POST /register → 201 ✅ (dynamic client registration confirmed working — I just registered a test client and it succeeded)
    GET /authorize → reaches PHP (X-Httpd: 1)

    The 1.4.14 fix is verified live. DCR works. The plugin is doing its job.

    Two important corrections on what you’re seeing:

    1. Empty debug.log is GOOD news, not bad. WordPress’s debug.log only captures PHP
      errors and notices, not request traffic. An empty debug.log during OAuth attempts
      means no PHP errors were thrown — which is exactly what you want. It does NOT mean
      Claude.ai’s requests aren’t reaching your server. Royal MCP also doesn’t write
      OAuth handshake events to its own Activity Log (that log is for post-auth MCP tool
      calls). To see actual request traffic during OAuth attempts, pull your nginx
      access log from SiteGround Site Tools → Statistics → Access Log.
    2. The most likely remaining blocker is Content-Type on your static files. Both
      .well-known/ files are returning: Content-Type: text/plain RFC 8414 §3.2 requires OAuth discovery responses to be served as application/json (“a successful response MUST use the 200 OK HTTP status code and return a JSON object using the application/json content type”). Most clients are lenient and parse JSON regardless of Content-Type. Strict clients reject the metadata even
      though the body is valid JSON. Another customer on SiteGround GrowBig hit this
      same fingerprint recently — same host configuration, same text/plain, same OAuth
      failure. That’s two production data points pointing at the same root cause. Two paths forward, depending on your use case:

    Path A — Fix the Content-Type properly (works for Claude.ai web AND Claude Desktop) Open a SiteGround support ticket with this exact wording:

    “We have two static files at /.well-known/oauth-authorization-server and /.well-known/oauth-protected-resource that are required by RFC 8414 (OAuth 2.0 Authorization Server Metadata). They are currently being served with Content-Type: text/plain because they have no file extension, but RFC 8414 §3.2 mandates Content-Type: application/json. .htaccess ForceType doesn’t apply since nginx serves these files directly without falling through to Apache. Could you please add an nginx-level MIME type override so files at these two specific paths are served as application/json? They contain valid JSON; only the Content-Type header needs correction.”

    SiteGround has granted similar exceptions for other customers’ OAuth needs.

    Path B — Skip OAuth entirely on Claude Desktop (works in 2 minutes, today)

    If your goal is to get Royal MCP working with an AI assistant and Claude Desktop
    is acceptable for your workflow, you can bypass the OAuth flow entirely. Royal MCP
    supports API-key authentication via mcp-remote’s –header flag — no
    /.well-known/, no discovery, no consent screen. Confirmed working on SiteGround
    GrowBig.

    Full walkthrough:
    https://royalplugins.com/support/royal-mcp/connect-claude-desktop-api-key.html

    Quick version — paste this into your Claude Desktop config
    (claude_desktop_config.json), substituting your API key from WP Admin → Royal MCP
    → Settings:

    {
    "mcpServers": {
    "terra-experty": {
    "command": "npx",
    "args": [
    "-y",
    "mcp-remote",
    "https://terraexperty.com/wp-json/royal-mcp/v1/mcp",
    "--header",
    "X-Royal-MCP-API-Key: YOUR_KEY_HERE"
    ]
    }
    }
    }

    Restart Claude Desktop and you’re connected.

    Path A is the proper fix and unblocks Claude.ai web. Path B works around the issue
    today if waiting on SiteGround isn’t workable.

    Best,
    Jameson

    – Royal Plugins

    Plugin Support rpteam

    (@rpteam)

    Hi René,

    Owe you an apology before anything else — I made a mistake in my very first reply that’s been quietly compounding through this entire thread. The SG Optimizer cache exclusion list I gave you was both wrong in one place and missing the most important endpoints. That alone could explain why nothing has stuck. Let me correct it and give you a definitive next step.

    The exclusion list I gave you originally:
    /wp-json/royal-mcp/*
    /wp-json/royal-mcp/v1/oauth/* ← MISTAKE: this path has never existed in
    Royal MCP
    /.well-known/oauth-authorization-server
    /.well-known/oauth-protected-resource

    The /wp-json/royal-mcp/v1/oauth/* line does nothing. There’s no such REST namespace in the plugin — Royal MCP’s OAuth endpoints are root-level rewrite rules at /authorize, /token, and /register — and those three paths were never in your exclusion list. They’re the actual OAuth handshake endpoints, and they’re the ones SG’s edge cache is most likely poisoning. Anyone who got “Authorization with the MCP server failed” on SG without those exclusions was probably hitting a cached response from a stale GET
    probe.

    Step 1 — fix the SG Optimizer exclusion list

    WP Admin → SG Optimizer → Caching → Dynamic Cache → Exclude URLs. Replace the list with:

    /wp-json/royal-mcp/*
    /.well-known/oauth-authorization-server
    /.well-known/oauth-protected-resource
    /authorize
    /token
    /register

    Save, then click Purge SG Cache in the SG Optimizer toolbar. The purge is critical — without it any cached 4xx responses from your earlier test attempts (when GET /mcp was still returning 405 pre-1.4.14) will keep getting served regardless of the new exclusions.

    Step 2 — two diagnostic curls (run AFTER the cache purge)

    These will tell us if anything else is in the way:

    (A) Content-Type on the metadata files — should be application/json
    curl -sI https://terraexperty.com/.well-known/oauth-authorization-server | grep -i content-type
    curl -sI https://terraexperty.com/.well-known/oauth-protected-resource | grep -i content-type

    (B) Force a cache-busted POST to /register — should return 201 with a client_id
    curl -v -X POST “https://terraexperty.com/register?=$(date +%s)” \ -H “Content-Type: application/json” \ -H “Cache-Control: no-cache” \ -d ‘{“client_name”:”Test”,”redirect_uris”:[“https://claude.ai/api/mcp/auth_callback&#8221; ],”grant_types”:[“authorization_code”],”response_types”:[“code”],”token_endpoint_auth
    method”:”none”}’

    Send back the output of both. If (A) shows text/plain, that’s a separate Content-Type
    blocker (covered in step 3). If (B) returns 201 Created with a client_id, the OAuth
    registration plumbing is working and you can retry the Claude.ai connection right
    then.

    Step 3 — retract my “Path A” SiteGround support ticket recommendation

    In my last reply I told you to open a SiteGround ticket asking for an nginx MIME-type override on the /.well-known/ paths. Don’t bother — that path is now closed. SiteGround confirmed to another Royal MCP customer yesterday that they no longer make per-customer nginx changes since their migration to Google Cloud infrastructure. The escalation route I pointed you at has been removed.

    If diagnostic (A) above shows text/plain, the working alternative is a free Cloudflare Transform Rule that overrides the response Content-Type at the edge — works around SG entirely:
    https://royalplugins.com/support/royal-mcp/siteground-cloudflare-content-type-fix.html

    Two-minute setup on Cloudflare’s free plan, no SG involvement needed. Walkthrough on
    that page.

    The .htaccess ForceType application/json advice I gave you earlier in the thread also doesn’t work on these paths — nginx serves /.well-known/ files directly without falling through to Apache, so .htaccess is silently ignored. Apologies for sending you down that road.

    Step 4 — fallback if you just need it working today

    If the goal is simply “get Royal MCP usable with Claude” and Claude Desktop is acceptable, you can sidestep OAuth entirely with the API-key bypass — works in two minutes, no /.well-known/, no consent screen, no Cloudflare:
    https://royalplugins.com/support/royal-mcp/connect-claude-desktop-api-key.html

    Quick version: paste this into your Claude Desktop config, substituting your API key from WP Admin → Royal MCP → Settings:

     {
    "mcpServers": {
    "terra-experty": {
    "command": "npx",
    "args": [
    "-y",
    "mcp-remote",
    "https://terraexperty.com/wp-json/royal-mcp/v1/mcp",
    "--header",
    "X-Royal-MCP-API-Key: YOUR_KEY_HERE"
    ]
    }
    }
    }

    Restart Claude Desktop. Connected.

    Send back the curl output from step 2 once you’ve done step 1 and we’ll either be done or know exactly which layer to tackle next. Sorry again for the runaround on the wrong cache list — that should have been right from the start.

    Best,
    Jameson

    -Royal Plugins

Viewing 14 replies - 1 through 14 (of 14 total)

You must be logged in to reply to this topic.