fix(providers): MCP env var expansion supports ${VAR} brace syntax#1650
fix(providers): MCP env var expansion supports ${VAR} brace syntax#1650kombiz wants to merge 2 commits into
Conversation
The expandEnvVarsInRecord function only matched the bare $VAR form, so
${VAR} references in MCP env/headers were silently passed through to
servers verbatim. ${VAR} is the dominant form in shell, Docker Compose,
and most MCP server docs, so copied examples were broken with no error.
Changes:
- Extend regex in expandEnvVarsInRecord to match both $VAR and ${VAR}
via a non-capturing alternation with separate capture groups
- Update JSDoc to document both forms
- Add 4 tests covering ${VAR} in env, mixed $VAR/${VAR} in same string,
missingVars reporting for braced form, and ${VAR} in headers
- Document the ${VAR} form in guides/mcp-servers.md
Fixes coleam00#1612
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
🔍 Comprehensive PR ReviewPR: #1650 — fix(providers): MCP env var expansion supports `${VAR}` brace syntax SummaryThis XS PR extends Verdict: ✅
🟡 Medium Issue (Optional — Recommended Fix)Boundary test missing for
|
| Issue | Location | Agent | Suggestion |
|---|---|---|---|
varName === undefined guard is unreachable dead code (TypeScript narrowing workaround) |
provider.ts:226 |
code-review, test-coverage | Add a comment: // varName is always string — regex alternation guarantees one group matches, or replace with (braced ?? bare) as string |
New tests use inline delete without try/finally |
dag-executor.test.ts:2317, 2335–2336, 2367 |
code-review | Consistent with pre-existing pattern in same describe block; leave as-is or refactor whole block to afterEach |
No code example in mcp-servers.md shows ${VAR} in practice |
mcp-servers.md |
docs-impact | Add one mixed-syntax example to the "Environment Variable Expansion" section (e.g., "DATABASE_URL": "${DATABASE_URL}") |
| Duplicate of first finding (reported by 2 agents) | provider.ts:226 |
test-coverage | See above |
✅ What's Good
- Regex correctness:
/\$(?:\{([A-Z_][A-Z0-9_]*)\}|([A-Z_][A-Z0-9_]*))/gcorrectly alternates between brace and bare forms. Non-capturing outer group is the right choice. - Minimal scope: Only
expandEnvVarsInRecordis touched. The security boundary (command,args,urlnot expanded) is preserved. - Symmetric test coverage: 4 new tests mirror the 4 pre-existing bare-syntax tests — including a mixed-syntax test that validates the alternation doesn't cause offset corruption.
- Env var naming:
_1612suffixes prevent cross-test pollution with pre-existing_445variables. - Doc included in PR:
mcp-servers.mdupdate is accurate with both forms documented and the security boundary noted. - No new abstractions: Pure extension of an existing function. No new interfaces, modules, or config keys.
- CLAUDE.md compliance: No
anytypes, noconsole.log, immutable result construction, zero ESLint disable comments.
📋 Suggested Follow-up Issues
| Issue Title | Priority |
|---|---|
Harden loadMcpConfig tests: use afterEach for env var cleanup in loadMcpConfig describe block |
P3 |
Add ${VAR} mixed-syntax example to mcp-servers.md Environment Variable Expansion section |
P3 |
Reviewed by Archon comprehensive-pr-review workflow — 3 agents (code-review, test-coverage, docs-impact)
Full artifacts: /home/laddy/.archon/workspaces/coleam00/Archon/artifacts/runs/542c3767a32d7c79a3beae7acf273715/review/
Fixed:
- Add clarifying comment to varName === undefined guard (unreachable
TypeScript narrowing workaround for regex alternation invariant)
- Extend boundary test to cover ${VAR} brace syntax in command/args fields
- Update mcp-servers.md example to show ${VAR} form alongside $VAR
Skipped:
- try/finally env var cleanup in tests (consistent with pre-existing pattern
in same describe block; full refactor is a separate follow-up)
⚡ Self-Fix Report (Aggressive)Status: COMPLETE Fixes Applied (3 total)
View all fixes
Tests Added(none — existing boundary test extended, not a new file) Docs Updated
Skipped (1)
Suggested Follow-up Issues
Validation✅ Type check | ✅ Lint | ✅ Tests (210 passed) Self-fix by Archon · aggressive mode · fixes pushed to |
Summary
expandEnvVarsInRecordinpackages/providers/src/claude/provider.tsonly matched the bare$VAR_NAMEform. The${VAR_NAME}brace syntax — standard in shell, Docker Compose, and MCP server documentation — was silently passed through unexpanded, causing MCP servers to receive literal${...}strings instead of resolved secrets.${VAR}form. The silent failure (no error, garbage value) makes this particularly hard to debug.expandEnvVarsInRecordto a two-branch alternation that handles both$VARand${VAR}in a single pass; added 4 new test cases; updated the MCP servers guide to document both forms.command,args, andurlfields are intentionally not expanded (security boundary). Lowercase variable names remain unsupported. No other env expansion systems (workflow variable substitution) were touched.UX Journey
Before
After
Architecture Diagram
Before
After
Connection inventory:
dag-executor.tsloadMcpConfigloadMcpConfigexpandEnvVarsexpandEnvVarsexpandEnvVarsInRecordexpandEnvVarsInRecordLabel Snapshot
risk: lowsize: XSprovidersproviders:claudeChange Metadata
bugprovidersLinked Issue
Validation Evidence (required)
${VAR}brace syntax are inpackages/workflows/src/dag-executor.test.tsand pass. The targeted runbun test packages/workflows/src/dag-executor.test.ts --test-name-pattern "loadMcpConfig"shows 15/15 pass (11 existing + 4 new).Security Impact (required)
${VAR}syntax will now receive the actual secret value instead of the unexpanded string. This is the intended behavior; the prior behavior was a bug.The expansion is scoped to
envandheadersfields only — same as before.command,args, andurlare intentionally excluded (security boundary, unchanged).Compatibility / Migration
$VARexpansion is unchanged;${VAR}previously passed through as-is (broken), now resolves correctly.Human Verification (required)
${VAR}in env values expands to the env value$VARand${VAR}mixed in the same string both expand correctly in one pass${MISSING_VAR}is reported inmissingVarsand replaced with''${VAR}inheadersvalues expands correctly$VARtests continue to pass (no regression)Side Effects / Blast Radius (required)
expandEnvVarsInRecordin@archon/providers. Called only fromexpandEnvVars→loadMcpConfig→dag-executor.ts. No other call sites.$VARbranch behavior is preserved exactly.missingVarsreporting is unchanged for both forms.Rollback Plan (required)
git revert c9c8c88f— single commit, no migrations, no config changes.${VAR_NAME}literal strings instead of resolved values; auth failures in MCP-dependent workflow nodes.Risks and Mitigations
\{([A-Z_][A-Z0-9_]*)\}— it requires a closing}, so${VAR(unclosed) won't match either branch and passes through unchanged (same behavior as before). Test coverage includes both forms.