Repository navigation
[FEATURE]: MCP config - prompt for unresolved placeholder values and store the secrets outside the config #58653
Description
- I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Config values can only interpolate {env:VAR} from the process environment, and the official
config reference states the sharp edge plainly: when the variable is not set, the reference
"will be replaced with an empty string". A keyed remote server then fails upstream with a
confusing 401 that reads like a bad token while the value never existed at all.
Request: at config parse/adopt time, scan mcp entries for placeholder-style variables; when
one is unresolved, prompt the user ONCE per variable (e.g. "PENPOT_TOKEN - personal access
token for penpot") and store the answers OUTSIDE the plaintext config - the OS keyring, or at
minimum the same protected credential store the OAuth flow already uses.
This is distinct from the MCP input requests (elicitation) shipped in v2.1.4: that covers a
server asking during a call; this is the config asking once, before any server starts.
Two open secret-hygiene reports should close in the same direction:
- mcp: server error text can write config secrets into the local engine log #53051 - server error text can write config secrets into the local engine log
- api: /api/model, /api/config and /api/provider/{id} return resolved provider credentials #53465 -
/api/configreturns resolved credentials
Why is this needed?
From one week of real use on this machine:
- a placeholder silently resolved to an empty string and produced a 401 that looked like a bad token;
- a hand-edited Authorization header cost a debugging round (
HTTP 400 Authorization header is badly formatted, visible only at connect time); - a keyed vendor's token currently sits in plaintext JSON because there is nowhere else to put it;
- the same placeholder concept is spelled three different ways across the config formats we now maintain (
{env:VAR}for OpenCode,${env:VAR}in.vscode/mcp.json,${VAR}in the portable.mcp.json), with no surface anywhere that validates any of them.
Related issues
- [FEATURE]: MCP manager UX - per-server output links (web panel URLs), placeholder prompts with secure secret storage, a full config editor, and richer ask/mention inputs #58243 (parent feature request)
- mcp: server error text can write config secrets into the local engine log #53051 / api: /api/model, /api/config and /api/provider/{id} return resolved provider credentials #53465 (secret hygiene)
- mcp: invalid server entries are silently dropped from config #55419 (invalid MCP entries silently dropped - the same silent-failure family)
- mcp: {env:...} in remote server headers not expanded (401 unauthorized) #56125 / config: unresolved {env:VAR} silently becomes an empty string (remote MCP fails with an opaque 401) #53784 (the
{env:}expansion reports that motivated this)
Additional context
- opencode v2.1.4, Windows 11, PowerShell; config reference read 2026-10-24.
- Split out of [FEATURE]: MCP manager UX - per-server output links (web panel URLs), placeholder prompts with secure secret storage, a full config editor, and richer ask/mention inputs #58243 (item 2) following the triage bot's mapping.
Activity
opencode-agent commentedon Oct 24, 2026
Thanks for splitting this out of #58243 and for the clear write-up!
To restate: when an
mcpentry in the config has a placeholder that can't be resolved, you'd like OpenCode to ask you for the value once per variable, before any server starts. The answer would be stored outside the plaintext config (the OS keyring, or the credential store the OAuth flow already uses) instead of silently becoming an empty string. Today{env:VAR}is only filled from the process environment, and a missing variable becomes an empty string, as the docs say. So this is a feature request rather than a bug. Maintainers will consider it.Related issues you may want to follow:
{env:}variable silently becoming an empty string (the opaque 401 you hit){env:}expansion in remote serverheaders/api/configThis can't be done as a plugin today: plugins have no way to ask the user for input before the config is loaded and servers start, and no access to a protected secret store.
Dante-dan commentedon Oct 24, 2026
I'd propose a bounded first version for unresolved MCP
{env:VAR}references:The current variable resolver substitutes missing environment values with an empty string. The existing Credential.Service is keyed by integration ID and stores integration credentials in the database; it is not an existing arbitrary MCP-placeholder keyring flow. This proposal therefore needs an explicit MCP credential namespace/reference mapping and a decision on protection/backend guarantees. #44803 is historical reference for keychain work, but it was closed without merging; I would not assume that backend exists in dev.
Planned acceptance checks: environment-over-store precedence; one prompt for repeated references; no prompt or network attempt on a headless missing secret; cancellation/reload/restart; credential replacement and shared-reference deletion; unavailable-store failure; no literal secret in saved config, API responses or error/log output. Other tools'
${env:VAR}/${VAR}syntax would require an explicit import conversion rather than guessing during normal OpenCode parsing.Would you approve this first-phase design, including the credential backend and reference scope? This is a design proposal based on source inspection; these changes and checks are planned, not implemented or run.