Skip to content

Env placeholder syntax for --header/--env is undiscoverable from CLI or npm package; ${env:VAR} silently passes through verbatim #323

Description

@elecnix

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)

  1. 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.
  2. mcporter config --help and mcporter config get --help — parent/subcommand help for the config surface.
  3. 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.
  4. 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.
  5. 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.
  6. JSON schema property descriptions for env and headers in the config schema, so editor/IDE validation surfaces the format.
  7. 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.
  8. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:linked-pr-openClawSweeper found an open linked pull request for this issue.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.clawsweeper:source-reproClawSweeper found a high-confidence source-level issue reproduction.impact:auth-providerThis issue is about auth, provider routing, model choice, or SecretRef resolution.impact:ux-frictionUser-facing flow adds avoidable confusion or support burden without fully blocking progress.issue-rating: 🦞 diamond lobsterVery strong issue quality with high-confidence source-level or clear reproduction.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions