Area
CLI
Problem or motivation
opfor setup's interactive wizard has no prompt for custom HTTP headers (auth tokens, device IDs, etc.) when configuring a url-transport MCP target — even though the underlying config schema already supports this via target.urlHeaders (documented in docs/cli.md).
Looking at collectMcpTarget() in runners/cli/src/commands/setup.ts, the url transport branch only asks for the server URL:
if (transport === "url") {
const url = await input({ message: "Server URL", ... });
return { kind: "mcp", name: name.trim(), transport, url: url.trim() };
}
There's no equivalent to the hasEnv/env prompt that the stdio branch gets a few lines later — url targets have no way to collect headers through the wizard at all.
In practice, this means anyone running opfor setup --mcp against a remote MCP server that requires bearer-token or custom-header auth (which is common — many hosted MCP servers gate access this way) gets a config with no urlHeaders field. The first opfor run then fails with an opaque transport-level error (in my case, SSE error: Non-200 status code (401) — the MCP SDK's EventSource client swallows the server's actual JSON error body, so there's no hint in the CLI output that the fix is "add an Authorization header").
The user has no way to know this without already knowing to open docs/cli.md, manually edit the generated JSON, and add urlHeaders by hand — which defeats the point of using the wizard.
Proposed solution
Add a header-collection step to collectMcpTarget()'s url branch, mirroring the existing stdio branch's env-var prompt:
if (transport === "url") {
const url = await input({ message: "Server URL", ... });
const hasHeaders = await confirm({
message: "Set custom HTTP headers (auth tokens, API keys, etc.)?",
default: false,
});
let urlHeaders: Record<string, string> | undefined;
if (hasHeaders) {
const headersRaw = await input({
message: "KEY=VALUE pairs, comma-separated (e.g. Authorization=Bearer ${TOKEN},x-device-id=${DEVICE_ID})",
});
urlHeaders = /* same parsing as the existing env-var block */;
}
return { kind: "mcp", name: name.trim(), transport, url: url.trim(), urlHeaders };
}
Since ${VAR} expansion is already supported for urlHeaders at run time, the prompt should nudge users toward env-var placeholders rather than raw secrets, the same way the existing docs do.
Separately (smaller, optional): the underlying 401 transport error could be more actionable if the CLI surfaced the server's actual JSON error body instead of just "Non-200 status code (401)" from the MCP SDK's EventSource wrapper — right now there's no signal at all pointing the user toward "add an auth header." Happy to split this into its own issue if preferred; flagging here since it compounds the same discoverability problem.
Alternatives considered
- Leaving it as documentation-only (already the case in
docs/cli.md) — insufficient, since the wizard is the primary onboarding path and most users won't cross-reference the CLI reference doc before their first run.
- Requiring users to hand-edit the generated config — works, but silently produces a broken config with no indication anything is missing, which is the actual problem being reported.
Would you like to contribute this?
Yes — but I'd need guidance
Area
CLI
Problem or motivation
opfor setup's interactive wizard has no prompt for custom HTTP headers (auth tokens, device IDs, etc.) when configuring aurl-transport MCP target — even though the underlying config schema already supports this viatarget.urlHeaders(documented indocs/cli.md).Looking at
collectMcpTarget()inrunners/cli/src/commands/setup.ts, theurltransport branch only asks for the server URL:There's no equivalent to the
hasEnv/envprompt that thestdiobranch gets a few lines later —urltargets have no way to collect headers through the wizard at all.In practice, this means anyone running
opfor setup --mcpagainst a remote MCP server that requires bearer-token or custom-header auth (which is common — many hosted MCP servers gate access this way) gets a config with nourlHeadersfield. The firstopfor runthen fails with an opaque transport-level error (in my case,SSE error: Non-200 status code (401)— the MCP SDK's EventSource client swallows the server's actual JSON error body, so there's no hint in the CLI output that the fix is "add an Authorization header").The user has no way to know this without already knowing to open
docs/cli.md, manually edit the generated JSON, and addurlHeadersby hand — which defeats the point of using the wizard.Proposed solution
Add a header-collection step to
collectMcpTarget()'surlbranch, mirroring the existingstdiobranch's env-var prompt:Since
${VAR}expansion is already supported forurlHeadersat run time, the prompt should nudge users toward env-var placeholders rather than raw secrets, the same way the existing docs do.Separately (smaller, optional): the underlying 401 transport error could be more actionable if the CLI surfaced the server's actual JSON error body instead of just "Non-200 status code (401)" from the MCP SDK's EventSource wrapper — right now there's no signal at all pointing the user toward "add an auth header." Happy to split this into its own issue if preferred; flagging here since it compounds the same discoverability problem.
Alternatives considered
docs/cli.md) — insufficient, since the wizard is the primary onboarding path and most users won't cross-reference the CLI reference doc before their first run.Would you like to contribute this?
Yes — but I'd need guidance