Skip to content

User Config Interpolation #217

@dandelionrosegroup

Description

@dandelionrosegroup

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

  1. Create a manifest with a user_config field and reference it in mcp_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"
    }
  }
}
  1. Install the extension in Claude Desktop (macOS).
  2. Open the extension settings in Claude Desktop UI.
  3. Set data_directory to a custom path (e.g., /Users/me/my-project/data).
  4. 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"
  }
}
  1. Restart Claude Desktop.
  2. Inspect the spawned process environment:
ps -p $(pgrep -f "server.py") -wwE | tr ' ' '\n' | grep LOCKSTEP

Expected 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 .mcpb file (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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions