headersHelper for HTTP MCP servers is silently ignored — script never executed
Description
headersHelper in MCP server config is accepted at plugin install time but the specified command is never executed at runtime. This affects HTTP-type MCP servers in plugins. The feature is documented at code.claude.com/docs/en/mcp under "Use dynamic headers for custom authentication."
Reproduction
Minimal test plugin:
.claude-plugin/plugin.json
{
"name": "headershelper-test",
"version": "1.0.0",
"description": "Test plugin to verify headersHelper execution",
"mcpServers": {
"headershelper-test": {
"type": "http",
"url": "https://httpbin.org/get",
"headersHelper": "node \"${CLAUDE_PLUGIN_ROOT}/mcp_servers/test-headers.mjs\""
}
}
}
mcp_servers/test-headers.mjs
import { writeFileSync } from "fs";
import { join } from "path";
import { homedir } from "os";
const marker = join(homedir(), ".claude", "headershelper-test-marker.txt");
writeFileSync(marker, `headersHelper executed at ${new Date().toISOString()}\n`);
process.stdout.write(JSON.stringify({ "x-test": "headersHelper-works" }));
Steps:
- Install the plugin via a marketplace or
--path - Restart Claude Code / run
/mcp - Check for marker file:
cat ~/.claude/headershelper-test-marker.txt
Expected: Marker file exists, proving the script was called.
Actual: File does not exist. The script is never executed.
Additional observations
- Array format rejected at install: Using
"headersHelper": ["node", "..."]fails plugin validation withmcpServers: Invalid input. Only the string format is accepted. - No error output: There is no error, warning, or log indicating that headersHelper was skipped or failed. The MCP server simply connects without the dynamic headers, leading to auth failures that are hard to diagnose.
- Static
headersfield works fine as a workaround.
Platforms tested
| Platform | Claude Code version | Plugin installs? | headersHelper executed? |
|----------|-------------------|------------------|------------------------|
| macOS (Apple Silicon) | 2.1.87 | Yes | No |
| WSL (Ubuntu) | 2.1.87 | Yes | No |
| Windows (PowerShell) | 2.1.87 | Yes | No |
Workaround
Use static headers in plugin.json with a placeholder value, then have a login command inject the real token into the cached plugin.json at ~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/.claude-plugin/plugin.json.
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗