Summary
The environment placeholder format supported by mcporter for HTTP headers and stdio env values (${VAR}, ${VAR:-fallback}, and whole-value $env:VAR) is not discoverable by a user or coding agent that only has the npm package installed: it is not mentioned in any --help text, the README only says configs accept "environment placeholders" without giving the syntax, and the docs that do document it (docs/config.md) are not shipped in the published package (the tarball contains only dist/, LICENSE, README.md, and package.json). The only way to learn the format without opening the repo on GitHub is to read dist/env.js / dist/runtime/utils.js in the installed package.
Worse, the ${env:VAR} syntax that is the de-facto convention in Cursor / Claude Code / Codex / Windsurf MCP configs is silently NOT expanded: a header value like Authorization: Bearer ${env:SOME_API_KEY} is sent over the wire literally, producing a 401 that looks like a wrong API key. I hit exactly this: mcporter config add <name> <url> --header "Authorization=Bearer ${env:INNGEST_API_KEY}" wrote the config fine and connected with 401; switching the config to ${INNGEST_API_KEY} worked immediately. The placeholder regex requires an identifier followed by } or :-fallback, so ${env:VAR} fails the match and falls through untouched, and materializeHeaders sends the literal string. Because the CLI help promises nothing about interpolation, a user has no way to know this is the cause.
Places where the format could be mentioned (so a user or agent knows without reading source)
mcporter config add --help — the --header KEY=value and --env KEY=value flag descriptions should state the supported placeholders and show an example, since that is the exact moment a user is authoring header/env values.
mcporter config --help and mcporter config get --help — parent/subcommand help for the config surface.
- README.md — the sentence "Config files accept JSONC, environment placeholders, ..." should include the syntax inline (at minimum
${VAR} / ${VAR:-fallback} / $env:VAR), because docs/config.md is not available to npm installers.
- The published npm package — ship the docs directory (package.json "files" field) so the existing docs/config.md content is actually reachable from an install.
- docs/config.md — already documents the syntax well (headers/env schema rows and the placeholder section); keep it as the source of truth but make it reachable per point 4.
- JSON schema property descriptions for
env and headers in the config schema, so editor/IDE validation surfaces the format.
- Runtime error handling — when a header/env value contains the unsupported
${env:...} pattern, fail fast with a clear error naming the variable instead of silently sending the literal string (which manifests as opaque 401/403 auth failures); either translate ${env:VAR} to the mcporter syntax or reject it explicitly.
- docs/import.md — imported Cursor/Claude/Codex/OpenCode configs very commonly use
${env:VAR} in mcpServers headers, so the import reference is the most likely place a user will inherit this syntax from and should warn that mcporter does not expand it.
Environment
- mcporter 0.13.7 (latest as of filing)
- Reproduced with an HTTP (SSE) remote MCP server and a Bearer auth header
- Also verified the code path in dist/env.js resolveEnvPlaceholders and dist/runtime-header-utils.js materializeHeaders
Summary
The environment placeholder format supported by mcporter for HTTP
headersand stdioenvvalues (${VAR},${VAR:-fallback}, and whole-value$env:VAR) is not discoverable by a user or coding agent that only has the npm package installed: it is not mentioned in any--helptext, the README only says configs accept "environment placeholders" without giving the syntax, and the docs that do document it (docs/config.md) are not shipped in the published package (the tarball contains onlydist/,LICENSE,README.md, andpackage.json). The only way to learn the format without opening the repo on GitHub is to readdist/env.js/dist/runtime/utils.jsin the installed package.Worse, the
${env:VAR}syntax that is the de-facto convention in Cursor / Claude Code / Codex / Windsurf MCP configs is silently NOT expanded: a header value likeAuthorization: Bearer ${env:SOME_API_KEY}is sent over the wire literally, producing a 401 that looks like a wrong API key. I hit exactly this:mcporter config add <name> <url> --header "Authorization=Bearer ${env:INNGEST_API_KEY}"wrote the config fine and connected with 401; switching the config to${INNGEST_API_KEY}worked immediately. The placeholder regex requires an identifier followed by}or:-fallback, so${env:VAR}fails the match and falls through untouched, and materializeHeaders sends the literal string. Because the CLI help promises nothing about interpolation, a user has no way to know this is the cause.Places where the format could be mentioned (so a user or agent knows without reading source)
mcporter config add --help— the--header KEY=valueand--env KEY=valueflag descriptions should state the supported placeholders and show an example, since that is the exact moment a user is authoring header/env values.mcporter config --helpandmcporter config get --help— parent/subcommand help for the config surface.${VAR}/${VAR:-fallback}/$env:VAR), because docs/config.md is not available to npm installers.envandheadersin the config schema, so editor/IDE validation surfaces the format.${env:...}pattern, fail fast with a clear error naming the variable instead of silently sending the literal string (which manifests as opaque 401/403 auth failures); either translate${env:VAR}to the mcporter syntax or reject it explicitly.${env:VAR}in mcpServers headers, so the import reference is the most likely place a user will inherit this syntax from and should warn that mcporter does not expand it.Environment