openclaw - ✅(Solved) Fix MCP HTTP server headers don't expand ${ENV_VAR} syntax, forcing tokens inline in config [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#70901Fetched 2026-04-24 10:38:06
View on GitHub
Comments
1
Participants
2
Timeline
2
Reactions
0
Timeline (top)
commented ×1cross-referenced ×1

When configuring an HTTP MCP server (e.g., Supabase MCP), ${ENV_VAR} substitution in the headers block is not expanded, forcing users to put tokens inline in openclaw.json.

Error Message

[bundle-mcp] failed to start server "supabase": Error: SSE error: Non-200 status code (401)

Root Cause

When configuring an HTTP MCP server (e.g., Supabase MCP), ${ENV_VAR} substitution in the headers block is not expanded, forcing users to put tokens inline in openclaw.json.

Fix Action

Fix / Workaround

Current Workaround

PR fix notes

PR #71035: fix(mcp): expand ${ENV_VAR} in HTTP MCP server headers and url

Description (problem / solution / changelog)

Summary

Fixes #70901

HTTP MCP server config headers did not expand ${ENV_VAR} syntax, forcing users to inline tokens directly in openclaw.json.

Root Cause

resolveHttpMcpServerLaunchConfig() in mcp-http.ts passed header values through toMcpStringRecord() which only coerces types to strings — it does not perform environment variable substitution.

Fix

Add expandEnvVars() that resolves ${VAR_NAME} references from process.env. Applied to both:

  • url field
  • All headers values

Unresolved references are left as-is (not silently emptied), making misconfiguration visible.

Example

{
  "mcp": {
    "servers": {
      "supabase": {
        "type": "http",
        "url": "https://mcp.supabase.com/mcp",
        "headers": {
          "Authorization": "Bearer ${SUPABASE_TOKEN}"
        }
      }
    }
  }
}

Now resolves SUPABASE_TOKEN from environment at runtime.

Changed files

  • src/agents/mcp-http.ts (modified, +28/-4)

Code Example

{
  "mcp": {
    "servers": {
      "supabase": {
        "type": "http",
        "url": "https://mcp.supabase.com/mcp?project_ref=xxx&read_only=true",
        "headers": {
          "Authorization": "Bearer ${SUPABASE_PAT}"
        }
      }
    }
  }
}

---

[bundle-mcp] failed to start server "supabase": Error: SSE error: Non-200 status code (401)

---

"headers": {
  "Authorization": "Bearer sbp_xxxxx..."
}
RAW_BUFFERClick to expand / collapse

Summary

When configuring an HTTP MCP server (e.g., Supabase MCP), ${ENV_VAR} substitution in the headers block is not expanded, forcing users to put tokens inline in openclaw.json.

Environment

  • OpenClaw: 2026.4.22
  • OS: Windows 11
  • Use case: Supabase MCP (https://mcp.supabase.com/mcp)

Current Behavior

Config:

{
  "mcp": {
    "servers": {
      "supabase": {
        "type": "http",
        "url": "https://mcp.supabase.com/mcp?project_ref=xxx&read_only=true",
        "headers": {
          "Authorization": "Bearer ${SUPABASE_PAT}"
        }
      }
    }
  }
}

Result:

[bundle-mcp] failed to start server "supabase": Error: SSE error: Non-200 status code (401)

The literal string Bearer ${SUPABASE_PAT} is sent as the Authorization header instead of the expanded token.

Expected Behavior

Either:

  1. Expand ${ENV_VAR} syntax in MCP header values (consistent with other OpenClaw config)
  2. Support SecretRef objects: {"source": "env", "id": "SUPABASE_PAT"}
  3. Document the supported syntax clearly

Supabase's own MCP docs use ${SUPABASE_ACCESS_TOKEN} syntax, suggesting this is expected to work.

Current Workaround

Inline the token directly in openclaw.json:

"headers": {
  "Authorization": "Bearer sbp_xxxxx..."
}

This degrades security:

  • Token visible in config file
  • Config backups include sensitive data
  • Can't rotate via env var refresh
  • Violates least-access patterns that env vars enable

Related

Stdio MCP servers support env block where ${VAR} does work. HTTP servers should have equivalent capability in headers.

Reference


Happy to test any fix.

extent analysis

TL;DR

The most likely fix is to modify the resolveHttpTransportConfig() function to expand environment variables in the headers block.

Guidance

  • Verify that the SUPABASE_PAT environment variable is set and accessible in the runtime environment.
  • Consider adding a feature to support SecretRef objects, such as {"source": "env", "id": "SUPABASE_PAT"}, as an alternative to expanding environment variables.
  • Review the dist/pi-bundle-mcp-runtime-CuLwVkrV.js code to understand how the resolveHttpTransportConfig() function handles headers and environment variables.
  • Test the fix by setting the SUPABASE_PAT environment variable and verifying that the expanded token is sent in the Authorization header.

Example

No code snippet is provided as the issue does not contain sufficient information to create a specific example.

Notes

The fix may require modifying the resolveHttpTransportConfig() function to expand environment variables in the headers block, which could have implications for other parts of the codebase.

Recommendation

Apply a workaround by modifying the resolveHttpTransportConfig() function to expand environment variables in the headers block, as this is the most direct way to address the issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix MCP HTTP server headers don't expand ${ENV_VAR} syntax, forcing tokens inline in config [1 pull requests, 1 comments, 2 participants]