Published as @automattic/mcp-remote@0.1.50.
Changes
Fix hourly browser re-auth against rotating refresh-token servers (#6): silent token renewal always fell back to a browser re-authorization against servers that issue single-use refresh tokens, such as WordPress.com's oauth2-1. Three independent causes, each fixed here.
- OAuth errors were unparseable under a proxy. With
--socks-proxy/--enable-proxywe replacedglobal.fetchwith npm undici's fetch, but the SDK checks responses withinstanceof Responseagainst the built-in class. Every OAuth error —invalid_grantincluded — parsed as garbage and was silently swallowed before falling through to a browser flow.Headers,RequestandResponseare now aliased together withfetch. - Concurrent refreshes inside one process raced each other. The MCP SDK lets concurrent sends enter authorization independently, all sharing one provider, so two flows would read the same single-use refresh token and one would lose a race with no other process involved. The provider now supplies the
fetchthe transports use, which the SDK threads into its token request; refresh grants queue behind each other, each is retargeted at whatever token is current on disk, and the rotated pair is persisted before the queue is released. - Concurrent processes deleted each other's credentials. Where several mcp-remote processes share one
tokens.json, the first refresh wins the rotation and the rest fail withinvalid_grant; the SDK then deleted the winner's fresh tokens and opened a browser, orphaning a live grant. Those tokens are now kept when the pair on disk was rotated by another party, and the SDK's own retry picks them up.
Also in this release: config files are written atomically (temp file plus rename), since a torn read of tokens.json surfaced as "no tokens saved" and made the rotation guard delete live credentials in exactly the window it exists to protect; an invalid_grant that escapes the SDK's single auth retry reconnects once rather than failing the connection; a failed forward answers the client with a JSON-RPC error instead of leaving the request hanging until its own timeout; and debugLog resolves function-valued arguments only after checking DEBUG, so hot-path callers stop paying for stack captures and JSON.stringify that get discarded.
Known limitations
Refreshes are still not serialized across processes, and the remaining gaps follow from that: the rotation guard's read and delete are not atomic, and recovery is bounded at roughly four attempts before the connection fails rather than degrading to a re-authorization. Both are documented at invalidateTokens in src/lib/node-oauth-client-provider.ts. Closing them is a single change — a lock around read, refresh, write and conditional delete — which would retire the rotation guard, the reconnect and the duplicate-save bookkeeping together.
Install: npx @automattic/mcp-remote@0.1.50 https://remote.mcp.server/sse