Problem
Embedded hosts may keep MCP credentials in a keyring or another host-owned secret store. Supplying those values by mutating the process environment at runtime is not sound once other threads can read the environment, and it also makes secret lifetime process-global.
A process-wide callback is a useful compatibility bridge, but it still couples every engine in the process to the first installer and makes multi-runtime, multi-tenant, and isolated tests awkward.
Suggested direction
Consider an optional host-provided MCP secret provider scoped to a runtime or McpPool:
- Inject an
Arc<dyn McpSecretProvider> (exact type intentionally open) when constructing the owning runtime/MCP context.
- Use one resolution seam for stdio
${...} expansion, request env_headers, bearer_token_env_var, and OAuth discovery/login/refresh headers.
- Keep process-environment fallback as an explicit compatibility policy rather than an implicit second implementation.
- Preserve the reviewed-plugin trust boundary: plugin-contributed MCPs should continue to use their captured, reviewed
HostEnvironment, not an ambient host secret store.
- Keep errors and diagnostics privacy-bounded: variable names and typed outcomes may be useful; secret values must never enter logs or user-facing errors.
The provider can remain a synchronous in-memory lookup if hosts hydrate it from their keyring ahead of time. Whether an async provider, cache invalidation, zeroizing value wrapper, or per-server authorization belongs in the public contract is left open for maintainer input.
Current downstream bridge
Pinvou/CodeWhale PR #25 uses a process-wide first-install-wins resolver to remove runtime environment writes from an embedded desktop host. It is deliberately narrow and should not grow into the general lifecycle design in the downstream fork.
Non-goal
This issue is a design direction, not a complete implementation proposal or an implementation commitment from the downstream fork.
Problem
Embedded hosts may keep MCP credentials in a keyring or another host-owned secret store. Supplying those values by mutating the process environment at runtime is not sound once other threads can read the environment, and it also makes secret lifetime process-global.
A process-wide callback is a useful compatibility bridge, but it still couples every engine in the process to the first installer and makes multi-runtime, multi-tenant, and isolated tests awkward.
Suggested direction
Consider an optional host-provided MCP secret provider scoped to a runtime or
McpPool:Arc<dyn McpSecretProvider>(exact type intentionally open) when constructing the owning runtime/MCP context.${...}expansion, requestenv_headers,bearer_token_env_var, and OAuth discovery/login/refresh headers.HostEnvironment, not an ambient host secret store.The provider can remain a synchronous in-memory lookup if hosts hydrate it from their keyring ahead of time. Whether an async provider, cache invalidation, zeroizing value wrapper, or per-server authorization belongs in the public contract is left open for maintainer input.
Current downstream bridge
Pinvou/CodeWhale PR #25 uses a process-wide first-install-wins resolver to remove runtime environment writes from an embedded desktop host. It is deliberately narrow and should not grow into the general lifecycle design in the downstream fork.
Non-goal
This issue is a design direction, not a complete implementation proposal or an implementation commitment from the downstream fork.