envpkt headers
Print the HTTP headers for one MCP server as a JSON object. Claude Code runs this as a
headersHelper and sends the result with every request
to that server.
envpkt headers [server] [options]server defaults to $CLAUDE_CODE_MCP_SERVER_NAME, which Claude Code sets to the server’s name
before it runs the helper. The command fails if neither is given.
Options
Section titled “Options”| Option | Description | Default |
| --------------------- | --------------------- | ------------- |
| -c, --config <path> | Path to envpkt.toml | Auto-detected |
| --profile <profile> | fnox profile to use | — |
Claude Code expands ${VAR} references in .mcp.json from its own environment. When Claude is
started by a launcher that strips the environment, those references expand empty and HTTP MCP
servers answer 401. A helper command does not depend on the launch environment: envpkt
decrypts the sealed value from envpkt.toml itself, using identity.key_file.
Bind a secret to a server with the mcp field:
[secret.GITHUB_MCP_API_KEY]service = "github"mcp = [{ server = "civala-github" }]encrypted_value = """..."""Point the server’s headersHelper at envpkt in .mcp.json:
{ "mcpServers": { "civala-github": { "type": "http", "url": "https://github.civala.ai/mcp", "headersHelper": "envpkt headers" } }}Claude Code then sends Authorization: Bearer <value> to civala-github.
Output
Section titled “Output”$ envpkt headers civala-github{"Authorization":"Bearer ghp_..."}- stdout holds the JSON object and nothing else. Claude parses it as-is.
- stderr holds everything else: config source, audit and fnox warnings, errors.
- Every secret that names the server is merged into one object, one header per secret.
- Aliases (
from_key) and namespaces resolve exactly as they do forenvpkt env export. Themcpbinding uses the logical TOML key, not the namespaced wire name. scopedoes not apply. Likeenvpkt exec, this is an explicit request for values.
Exit codes
Section titled “Exit codes”| Code | Meaning |
| ---- | ---------------------------------------------------------------------------------------------------------- |
| 0 | Headers printed |
| 1 | No secret names the server, a bound value is missing, empty or can’t be decrypted, or a binding is invalid |
| 2 | No server named, the config failed to load or resolve, or no age key was found at all |
A sealed value that fails to decrypt (for example, the wrong key) exits 1. The age error is printed as a
warning, then the command reports which key did not resolve. Every error names the server on stderr, so
Claude’s MCP log shows which server failed.
Checks
Section titled “Checks”- Only the requested server’s bindings are checked. A broken binding on another server never blocks this one.
- Header names must be valid HTTP header names, and a non-empty
schememust be one word. - A value containing a line break or NUL is refused rather than sent. The error names the key, never the value.
Config lookup
Section titled “Config lookup”envpkt headers finds envpkt.toml the same way every command does: -c, then ENVPKT_CONFIG, then the
working directory and its parents, then the global package (~/.envpkt/envpkt.toml and cloud-storage
copies). If the project has no envpkt.toml, the global package answers. Pass -c in .mcp.json to pin
the file: "headersHelper": "envpkt headers -c ./envpkt.toml".
How Claude Code runs it
Section titled “How Claude Code runs it”- The helper has a 10-second timeout. It runs at each connect and reconnect, and again after a
401or403. - For a project
.mcp.json, it runs with the project directory as its working directory, so envpkt finds the project’senvpkt.toml. - Claude strips variables whose names contain
TOKEN,SECRET,PASSWORD,KEYorAUTHbefore running a project helper. Sealed values withidentity.key_fileneed none of them.ENVPKT_AGE_KEYandENVPKT_AGE_KEY_FILEmatch that filter, so a key passed through either will not reach the helper.