You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Feature]: MCPPROXY_API_KEY_FILE (and ${file:} for api_key) for container and systemd secrets #1706
Spec 111 (FR-030) plans ${file:/absolute/path} references so that upstream server secrets can come from a file (Docker/Compose secrets, Kubernetes secrets, systemd LoadCredential=). The code does not have it yet (no ${file: handling in internal/secret, only ${env:} and keyring), and the spec does not cover the proxy's own credential:
api_key can come from MCPPROXY_API_KEY, but there is no file form. In a container the choices today are an environment variable (visible in docker inspect, /proc/<pid>/environ and crash dumps) or the key saved in mcp_config.json on the data volume.
Both Docker Compose secrets and Kubernetes mount a secret as a file (/run/secrets/<name>), and the convention used by most official images is a <NAME>_FILE variable that points at it.
I checked MCPPROXY_API_KEY_FILE and ${file:} in the tree and in the open and closed issues and found neither (#58 asked for credentials not to be stored in plaintext in the config, and was closed).
Proposed solution
Add MCPPROXY_API_KEY_FILE: when set, and MCPPROXY_API_KEY is not, read the key from that file (strip one trailing newline, as FR-030 does), never write it back to the config, never log it. Same rule for ${file:} if it is also accepted inside api_key. If MCPPROXY_API_KEY_FILE is the only thing that is wanted, it can ship before FR-030 does.
I can send a PR for this if it fits Spec 111's plan. I did not want to overlap with whoever implements FR-030.
Alternatives considered
Keep using MCPPROXY_API_KEY and set it from a wrapper entrypoint that reads the file. This needs a shell, which the slim image does not have.
Let the key be generated and saved to the volume (FR-014). Works for a single operator, but does not fit a secrets manager, rotation, or an agent that needs to be given the key without the config file.
Yes to both, and nobody has picked up Spec 111 FR-030 yet, so it is yours if you want it. I would do it as two small PRs: MCPPROXY_API_KEY_FILE first through one shared helper (there are six places that read the env key, including the tray, which re-injects it into the core), then the ${file:} provider with LF/CRLF, size cap and absolute-path tests. Two things to keep in mind: an unreadable file must hard-fail rather than fall back to generating and saving a new key, and ${file:} inside api_key has to resolve on a clone or as a process override so a PATCH never writes the secret back into the config file. If you amend FR-014/FR-030/US7 in the same PR so the spec covers the proxy's own key, even better.
Two PRs as suggested: #1716 adds MCPPROXY_API_KEY_FILE through one shared helper (the loader, EnsureAPIKey, the CLI client, status, the tray and the core it launches), with a hard fail on an unusable file and the Spec 111 FR-014/FR-030/US7 amendments. #1717 (draft, stacked on #1716) adds the ${file:} provider, including api_key as a process-only override so a PATCH never writes the secret back. Open questions for you are in the two PR descriptions: which of the two variables wins when both are set, and whether ${file:} should get a path allow-list.
Activity
Dumbris commentedon Oct 20, 2026
Yes to both, and nobody has picked up Spec 111 FR-030 yet, so it is yours if you want it. I would do it as two small PRs: MCPPROXY_API_KEY_FILE first through one shared helper (there are six places that read the env key, including the tray, which re-injects it into the core), then the ${file:} provider with LF/CRLF, size cap and absolute-path tests. Two things to keep in mind: an unreadable file must hard-fail rather than fall back to generating and saving a new key, and ${file:} inside api_key has to resolve on a clone or as a process override so a PATCH never writes the secret back into the config file. If you amend FR-014/FR-030/US7 in the same PR so the spec covers the proxy's own key, even better.
james-crowley commentedon Oct 20, 2026
Two PRs as suggested: #1716 adds
MCPPROXY_API_KEY_FILEthrough one shared helper (the loader,EnsureAPIKey, the CLI client,status, the tray and the core it launches), with a hard fail on an unusable file and the Spec 111 FR-014/FR-030/US7 amendments. #1717 (draft, stacked on #1716) adds the${file:}provider, includingapi_keyas a process-only override so a PATCH never writes the secret back. Open questions for you are in the two PR descriptions: which of the two variables wins when both are set, and whether${file:}should get a path allow-list.feat(secret): ${file:/absolute/path} references
feat(secret): ${file:/absolute/path} references
feat(secret): ${file:/absolute/path} references
feat(config): read the API key from MCPPROXY_API_KEY_FILE (#1716)
feat(secret): ${file:/absolute/path} references
feat(secret): ${file:/absolute/path} references (Spec 111 FR-030) (sm…