-
Notifications
You must be signed in to change notification settings - Fork 174
Description
Title
${user_config.*} values in manifest env block are not interpolated into spawned process environment
Description
MCPB-Bug-Report-user_config-interpolation.md
When a manifest defines an environment variable using ${user_config.*} interpolation in the mcp_config.env block, the variable is absent from the spawned server process's environment — even though the user has configured the value correctly in Claude Desktop's settings UI and the settings JSON file contains the expected value.
Built-in interpolation tokens like ${HOME} in the same env block resolve correctly, confirming that environment variable passing itself works. Only the ${user_config.*} resolver appears broken.
Reproduction Steps
- Create a manifest with a
user_configfield and reference it inmcp_config.env:
{
"manifest_version": "0.4",
"server": {
"type": "uv",
"mcp_config": {
"env": {
"LOCKSTEP_DATA_DIR": "${user_config.data_directory}"
},
"platform_overrides": {
"darwin": {
"env": {
"PATH": "/usr/local/bin:/usr/bin:/bin:/opt/homebrew/bin:${HOME}/.local/bin"
}
}
}
}
},
"user_config": {
"data_directory": {
"type": "directory",
"title": "Data Directory",
"description": "Where Lockstep stores chains, tickets, and capacity data",
"required": true,
"default": "${HOME}/.lockstep/data"
}
}
}- Install the extension in Claude Desktop (macOS).
- Open the extension settings in Claude Desktop UI.
- Set
data_directoryto a custom path (e.g.,/Users/me/my-project/data). - Confirm the settings JSON is correct:
~/Library/Application Support/Claude/Claude Extensions Settings/local.mcpb.<extension-id>.json
Contents:
{
"isEnabled": true,
"userConfig": {
"data_directory": "/Users/me/my-project/data"
}
}- Restart Claude Desktop.
- Inspect the spawned process environment:
ps -p $(pgrep -f "server.py") -wwE | tr ' ' '\n' | grep LOCKSTEPExpected Behavior
LOCKSTEP_DATA_DIR=/Users/me/my-project/data should appear in the process environment.
Actual Behavior
LOCKSTEP_DATA_DIR is completely absent from the process environment. It is not set to empty string — it simply doesn't exist.
Meanwhile, ${HOME} in the same platform_overrides.darwin.env.PATH resolves correctly to the user's home directory.
Impact
This is a data-loss-adjacent bug for any extension that uses user_config to configure file paths. When ${user_config.*} silently fails:
- The server starts without the expected env var
- Server-side fallback logic kicks in (if any), typically defaulting to
~/.extension-name/data - The user sees an empty/default state instead of their actual data
- No error is raised anywhere — the failure is completely silent
- Users believe their data is lost (it's not — it's just in the original location, unreachable by the server)
This was discovered during a v0.1.0 → v0.2.0 upgrade of a sideloaded MCPB extension. The user had configured a custom data directory through the UI. After reinstalling the updated bundle, the server started with no data visible despite the settings JSON containing the correct path.
Environment
- Claude Desktop: macOS (latest as of 2026-03-21)
- manifest_version:
"0.4" - server.type:
"uv" - Extension source: Sideloaded
.mcpbfile (not from directory) - macOS version: Sequoia (Apple Silicon, M4 Max)
Workaround
Users can bypass the broken interpolation by creating a config.json in the extension's data directory that the server reads directly, or by using a startup script that sets the env var before launching the server. Neither of these should be necessary — the manifest spec documents ${user_config.*} as a supported interpolation pattern.
Additional Context
The MANIFEST.md spec explicitly shows ${user_config.allowed_directories} as an interpolation example in the env block, confirming this is intended functionality. The bug is in the resolver implementation within Claude Desktop's extension loader, not in the spec.