can1357/oh-my-pi · error · Error
HTTP ${response.status}: server redirected a ${init.method}
Error message
HTTP ${response.status}: server redirected a ${init.method} request; refusing to follow What it means
Thrown by mcpFetch's redirect-following loop in header-policy.ts when the server responds with a redirect status (301/302/303) to a non-GET request. Per the fetch redirect spec, such redirects may not preserve the method and body, so instead of silently converting a POST (e.g. an MCP JSON-RPC call) into a GET, the client refuses to follow and surfaces the error.
Source
Thrown at packages/coding-agent/src/mcp/transports/header-policy.ts:118
originLocked: boolean,
): Promise<Response> {
if (!originLocked) {
return fetch(url, { ...init, headers: mergeMCPHeaders(sources) });
}
const configuredOrigin = new URL(url).origin;
let currentUrl = url;
for (let hop = 0; hop <= MAX_REDIRECT_HOPS; hop++) {
const attachConfigured = new URL(currentUrl).origin === configuredOrigin;
const headers = mergeMCPHeaders(attachConfigured ? sources : { generated: sources.generated });
const response = await fetch(currentUrl, { ...init, headers, redirect: "manual" });
if (!REDIRECT_STATUSES[response.status]) return response;
const location = response.headers.get("Location");
if (!location) return response;
await response.body?.cancel();
if (init.method !== "GET" && response.status !== 307 && response.status !== 308) {
throw new Error(`HTTP ${response.status}: server redirected a ${init.method} request; refusing to follow`);
}
currentUrl = new URL(location, currentUrl).href;
}
throw new Error(`Too many redirects (> ${MAX_REDIRECT_HOPS}) fetching ${url}`);
}
View on GitHub (pinned to 9690622007)
Solutions
- Update the MCP server URL to the final post-redirect destination (follow the redirect once with curl -i to find it)
- Use 307/308 redirects server-side if you control the endpoint, since those preserve method and body
- Fix reverse-proxy/lb rules so the MCP endpoint doesn't 301/302 non-GET requests
- Ensure you're using https:// directly to avoid scheme-upgrade redirects
Example fix
// before: POST to a redirecting URL
await client.callTool("http://old.example.com/mcp", params); // 301 -> error
// after: POST directly to the final URL
await client.callTool("https://api.example.com/v2/mcp", params); Defensive patterns
Strategy: try-catch
Validate before calling
// detect redirect-prone URLs before issuing non-GET MCP requests
const probe = await fetch(url, { method: "HEAD", redirect: "follow" });
if (probe.url !== url) throw new Error(`MCP endpoint redirects; use final URL ${probe.url} instead of ${url}`); Type guard
function isRedirectRefusal(err: unknown): boolean {
return err instanceof Error && /refusing to follow/.test(err.message);
} Try / catch
try {
await mcpFetch(url, { method: "POST", body });
} catch (err) {
if (isRedirectRefusal(err)) {
const finalUrl = await resolveFinalUrl(url); // HEAD with redirect:follow
return mcpFetch(finalUrl, { method: "POST", body });
}
throw err;
} Prevention
- Configure the MCP server URL as the canonical https endpoint, not a legacy path that redirects
- Use 307/308 (method-preserving) redirects if you control the server
- Check reverse-proxy rules that issue 301 on trailing-slash or scheme upgrades
- Discover the final URL once with redirect: "follow" and cache it for subsequent calls
When it happens
Trigger: Making a POST/PUT/DELETE MCP request through mcpFetch when the server answers 301, 302, or 303 with a Location header (307/308 are followed since they preserve method).
Common situations: Server migrated its MCP endpoint to a new URL and redirects old paths; a reverse proxy rewrites POSTs to a login/redirect page; trailing-slash normalization issuing 301 on POST; HTTP-to-HTTPS redirect on a POST.
Related errors
- Too many redirects (> ${MAX_REDIRECT_HOPS}) fetching ${url}
- ENXIO
- Refusing to download onto a non-regular file: ${absolutePath
- Refusing to download onto a file with ${stat.nlink} hard lin
- Tool "write" not available: this session cannot download res
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/b6544cb5f9387363.
Report an issue: GitHub.