can1357/oh-my-pi · error · Error
this server proxies OAuth through mcp-remote, which caches t
Error message
this server proxies OAuth through mcp-remote, which caches tokens machine-wide in ~/.mcp-auth (shared across every OMP profile). Clear ~/.mcp-auth to force a fresh login, or replace the proxy with ${httpHint} so OMP manages OAuth per profile. What it means
Thrown by #resolveOAuthEndpointsFromServer when /mcp reauth is requested for a server whose transport is not http/sse (i.e. stdio). OMP's OAuth flow only works over HTTP transports; for stdio servers the child process manages its own credentials, so there is no OMP-side OAuth to refresh. When the command line contains mcp-remote, the message additionally warns that mcp-remote caches tokens machine-wide in ~/.mcp-auth, shared across all OMP profiles, and suggests switching to a direct http config.
Source
Thrown at packages/coding-agent/src/modes/controllers/mcp-command-controller.ts:1210
const next = { ...config } as MCPServerConfig & { auth?: MCPAuthConfig };
delete next.auth;
return next;
}
async #resolveOAuthEndpointsFromServer(
config: MCPServerConfig,
authChallenge?: MCPAuthChallenge,
): Promise<OAuthEndpoints> {
// Stdio servers manage credentials inside the child process; OMP's OAuth
// flow only applies to http/sse transports. Without this guard the
// unauthenticated preflight below spawns the child, which happily reuses
// its own cached tokens (e.g. mcp-remote's machine-wide ~/.mcp-auth) and
// produces the misleading "reauthorization is not required".
if (config.type !== "http" && config.type !== "sse") {
const remoteUrl = config.args?.find(arg => /^https?:\/\//.test(arg));
const httpHint = `{ "type": "http", "url": ${JSON.stringify(remoteUrl ?? "<remote url>")} }`;
const usesMcpRemote = [config.command, ...(config.args ?? [])].some(part => part?.includes("mcp-remote"));
throw new Error(
usesMcpRemote
? `this server proxies OAuth through mcp-remote, which caches tokens machine-wide in ~/.mcp-auth (shared across every OMP profile). Clear ~/.mcp-auth to force a fresh login, or replace the proxy with ${httpHint} so OMP manages OAuth per profile.`
: `stdio servers manage their own credentials, so OMP has no OAuth to reauthorize. If the service supports OAuth over HTTP, configure it as ${httpHint} instead.`,
);
}
// First test if server actually needs auth by connecting without OAuth
let connectionSucceeded = false;
let connectionError: Error | undefined;
try {
await this.#handleTestConnection(this.#stripOAuthAuth(config), { oauth: false });
connectionSucceeded = true;
} catch (error) {
connectionError = error as Error;
}
// Server connected fine without auth. A tool-level challenge overrides
// this: servers may allow the anonymous handshake yet protect individual
// tool calls with `_meta["mcp/www_authenticate"]`. Even without such aView on GitHub (pinned to 9690622007)
Solutions
- If it uses mcp-remote: delete ~/.mcp-auth to clear the shared token cache, then log in again.
- Better: replace the mcp-remote proxy with a native http config — `{ "type": "http", "url": "<the remote url>" }` — so OMP manages OAuth per profile (run /mcp reauth again afterwards).
- For plain stdio servers: re-authorize through the service's own CLI/tooling; OMP has no OAuth to manage. If the service supports OAuth over HTTP, reconfigure it as an http server.
Example fix
// before (stdio via mcp-remote, shared token cache)
{ "type": "stdio", "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.example.com/mcp"] }
// after (native http transport, OMP-managed OAuth per profile)
{ "type": "http", "url": "https://mcp.example.com/mcp" } Defensive patterns
Strategy: validation
Validate before calling
const cfg = getServerConfig(name);
if (cfg.type !== "http" && cfg.type !== "sse") {
throw new Error(`/mcp reauth only applies to http/sse servers; '${name}' is ${cfg.type}`);
} Type guard
function isRemoteMcpConfig(c: MCPServerConfig): c is MCPServerConfig & { type: "http" | "sse"; url: string } {
return (c.type === "http" || c.type === "sse") && "url" in c && typeof c.url === "string";
} Try / catch
try {
await reauthServer(name);
} catch (err) {
if (err instanceof Error && err.message.includes("mcp-remote")) {
// stdio/mcp-remote target: switch config to native http and clear ~/.mcp-auth
} else throw err;
} Prevention
- Prefer native { "type": "http", "url": ... } configs over the mcp-remote proxy whenever the service supports OAuth over HTTP.
- Remember ~/.mcp-auth is machine-global — treat 'stuck' mcp-remote logins as a stale-cache problem and delete that directory.
- Only run /mcp reauth against remote (http/sse) servers; stdio credentials belong to the child process.
When it happens
Trigger: Running /mcp reauth <name> where the server config has type stdio (or any type other than http/sse) — either a plain stdio server, or one launched via `npx mcp-remote https://...`.
Common situations: Users copy a Claude Code / Cursor config that wraps a remote MCP server in mcp-remote for OAuth support, then try to re-authorize inside OMP; tokens appear 'stuck' because ~/.mcp-auth is machine-global and profile-independent.
Related errors
- Invalid OAuth URLs. Please check: Authorization URL: ${aut
- Invalid server config: ${errors.join("; ")}
- Server "${name}" already exists in ${filePath}
- Server "${name}" not found in ${filePath}
- MCP OAuth credential is missing refresh material
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/0dc608c8cfc4f0a8.
Report an issue: GitHub.