Skip to content

MCP remote OAuth: two bugs block streamable-http servers (regex \: under /u; OAuth errors surfaced as [object Response]) #91433

@marcusbsorensen

Description

@marcusbsorensen

Summary

Remote MCP servers that use OAuth fail to connect. I hit two distinct bugs in the MCP OAuth client, both reproducible against public servers (PayPal and Calendly). Reproduced on 2026.6.1 (2e08f0f) and 2026.6.5-beta.2 (131c9bf).

Environment

  • OpenClaw 2026.6.1 / 2026.6.5-beta.2
  • macOS, Node v24
  • Servers added with openclaw mcp add <name> --url <url> --transport streamable-http --auth oauth

Bug 1 — Invalid regular expression: /^https\:\/\//u: Invalid escape (post-auth crash)

Server: https://mcp.paypal.com/mcp (streamable-http, OAuth).

Repro

  1. openclaw mcp add paypal --url https://mcp.paypal.com/mcp --transport streamable-http --auth oauth
  2. openclaw mcp login paypal → authorize in browser → openclaw mcp login paypal --code <code>MCP OAuth credentials saved for "paypal" (OAuth succeeds).
  3. openclaw mcp probe paypal

Result

[bundle-mcp] failed to start server "paypal" (https://mcp.paypal.com/mcp): SyntaxError: Invalid regular expression: /^https\:\/\//u: Invalid escape

The token is saved; the crash is downstream, while building a regex that matches ^https://. The pattern is written as /^https\:\/\// and compiled with the unicode (u) flag. In unicode mode, an identity escape of a non-syntax character (\:) is an Invalid escape.

Fix: drop the unnecessary backslash before : (and / need not be escaped): use /^https:\/\// rather than /^https\:\/\//u, or remove the u flag from that pattern.


Bug 2 — OAuth error responses surfaced as "[object Response]" (masks the real error)

Server: https://mcp.calendly.com/ (streamable-http, OAuth).

Repro

  1. openclaw mcp add calendly --url https://mcp.calendly.com --transport streamable-http --auth oauth
  2. openclaw mcp login calendly

Result (immediately, before any authorize URL is printed)

Invalid OAuth error response: SyntaxError: Unexpected token 'o', "[object Response]" is not valid JSON. Raw body: [object Response]

This masks the real failure, which is at the RFC 7591 dynamic client registration step. Calendly's discovery is well-formed:

  • GET https://mcp.calendly.com/.well-known/oauth-protected-resource → 200, authorization_servers: ["https://calendly.com/"]
  • GET https://calendly.com/.well-known/oauth-authorization-server → 200, valid JSON, advertises registration_endpoint: https://calendly.com/oauth/register

Reproducing the registration POST that OpenClaw makes (redirect_uri http://127.0.0.1:<port>/oauth/callback) returns HTTP 400 with a perfectly readable JSON body:

{"error":"invalid_client_metadata","errors":{"redirect_uri":["must be an HTTPS/SSL URI or redirect to localhost."]}}

There are two issues here:

2a) The error body is not read. OpenClaw appears to pass the fetch Response object to JSON.parse (hence the literal string "[object Response]") instead of await response.text() / .json(). This swallows every OAuth error and makes failures undiagnosable. Reading and surfacing the body would have shown the cause immediately.

2b) Loopback redirect uses 127.0.0.1 where the AS requires localhost. OpenClaw registers http://127.0.0.1:<port>/oauth/callback. Calendly's /oauth/register rejects the IP literal but accepts http://localhost:<port>/oauth/callback:

# 127.0.0.1  -> 400 invalid_client_metadata (as above)
# localhost  -> 201 Created, client registered successfully

RFC 8252 §7.3 permits both the loopback IP and localhost, but some authorization servers (Calendly) only accept localhost. Consider using localhost for the loopback redirect, or making the loopback host configurable / falling back from 127.0.0.1 to localhost on registration failure.


Impact

Remote OAuth MCP servers are currently unusable: PayPal crashes after a successful auth (Bug 1), and Calendly cannot register, with the real cause hidden (Bug 2). Fixing 2a alone would at least make these failures diagnosable; 1 and 2b are the concrete connectivity fixes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions