microsoft / microsoft/vscode

Agent Plugins format: ${PLUGIN_ROOT} / ${PLUGIN_DATA} not expanded in plugin mcp.json and hooks.json (stdio MCP server cannot start)

Open
#336,882 0 comments 0 reactions 1 assignee View on GitHub

@sandy081 is already working on this.

Since Sep 19, 2026.

chat
Dominant language
TypeScript
Stars
193k
Forks
42.7k
PR merge metrics
PR metrics pending

Description

Summary

For plugins in the Agent Plugins 1.0.0 format (root plugin.json with "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json"), VS Code does not expand ${PLUGIN_ROOT} (nor ${PLUGIN_DATA}) in mcp.json args/env/cwd, does not set PLUGIN_ROOT/PLUGIN_DATA in the server environment, and does not use the plugin root as the default working directory. The literal string reaches the spawned process, so a stdio MCP server that references a bundled file cannot start. The same plugin works in Copilot CLI, which does expand the placeholder.

The Agent Plugins specification requires this expansion (§9.1, §9.2, §11.1 items 6–7): https://agent-plugins.org/specification#9-environment-variables-and-placeholder-expansion

Steps to reproduce
  1. Install a plugin with this mcp.json (e.g. neqsim from the marketplace https://github.com/equinor/neqsim-copilot-plugin, or any minimal Agent Plugins-format plugin):

    {
      "$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
      "mcpServers": {
        "neqsim": {
          "type": "stdio",
          "command": "java",
          "args": ["${PLUGIN_ROOT}/servers/NeqsimMcpLauncher.java"]
        }
      }
    }
    
  2. Start a chat so the server is launched.

  3. Open Output → MCP: neqsim.

Actual
Starting server from LocalProcess extension host
[server stderr] Error: Could not find or load main class ${PLUGIN_ROOT}.servers.NeqsimMcpLauncher.java
[server stderr] Caused by: java.lang.ClassNotFoundException: ${PLUGIN_ROOT}.servers.NeqsimMcpLauncher.java
Connection state: Error Process exited with code 1

The plugin's com.github.copilot/hooks/hooks.json SessionStart command containing ${PLUGIN_ROOT} fails the same way.

Expected

${PLUGIN_ROOT} replaced by the absolute plugin directory in args, env and cwd; PLUGIN_ROOT and PLUGIN_DATA present in the subprocess environment; plugin root used as the default cwd (spec §7.2.1). Same behaviour as for the Copilot / Claude / OpenPlugin formats, which already substitute the token.

Cause

src/vs/platform/agentPlugins/common/pluginParsers.tsAGENT_PLUGIN_FORMAT is declared with

pluginRootTokens: [],
pluginRootEnvVars: [],

and parseMcpServerDefinitionMap only sets defaultCwd and applies interpolateMcpPluginRoot / convertBareEnvVarsToVsCodeSyntax when formatConfig.format !== PluginFormat.AgentPlugin. COPILOT_FORMAT, CLAUDE_FORMAT and OPEN_PLUGIN_FORMAT all list ['${PLUGIN_ROOT}', '${CLAUDE_PLUGIN_ROOT}']. The exporter for this format (Lhn/s_r in the bundle) does accept ${PLUGIN_ROOT}/${PLUGIN_DATA} in cwd, so the token is recognised on the way out but never resolved on the way in.

Presumably the intent was to defer to the agent host / Copilot SDK, which knows CLAUDE_PLUGIN_ROOT / COPILOT_PLUGIN_ROOT / PLUGIN_ROOT — but plugin MCP servers are started by the LocalProcess extension host, so nothing in the chain performs the substitution.

Environment
  • VS Code 1.138.0 (stable), commit 7debcd0e2acdea1c52de81bf9ee1620444407dda, Windows 11
  • Still present in main (pluginParsers.ts as of 2026-09-19)
  • Plugin: https://github.com/equinor/neqsim-copilot-plugin (neqsim/mcp.json, neqsim/com.github.copilot/hooks/hooks.json)
Workaround

Register the server in the user mcp.json with the absolute path of the installed plugin (~/.vscode/agent-plugins/github.com/<owner>/<marketplace>/<plugin>/...). Not viable for a distributed plugin, since the install location differs per client and install method.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.