Skip to content

VS Code MCP Server Package Transformation Issues #282860

@anurag-tiwari-3108

Description

@anurag-tiwari-3108

Does this issue occur when all extensions are disabled?: Yes

  • VS Code Version: 1.107.0-insider
  • OS Version: Windows 11

Summary

The AbstractCommonMcpManagementService.getMcpServerConfigurationFromManifest() method in VS Code's MCP management service has hardcoded package name/version insertion behavior that:

  1. Always auto-inserts package@version when both name and version fields exist in package configuration
  2. Always adds --yes flag for NuGet packages, creating duplicates if already specified

This prevents external MCP registries (like private enterprise registries) from having full control over command-line argument construction, leading to duplicate arguments and incorrect command generation.


Issue 1: Mandatory Auto-Insert of Package Name@Version

Location

File: src/vs/platform/mcp/common/mcpManagement.ts (or similar path)
Class: AbstractCommonMcpManagementService
Method: getMcpServerConfigurationFromManifest()
Lines: 177-184 (approximate)

Current Behavior

switch (serverPackage.registryType) {
    case RegistryType.NODE:
        args.push(serverPackage.version ? `${serverPackage.identifier}@${serverPackage.version}` : serverPackage.identifier);
        break;
    case RegistryType.PYTHON:
        args.push(serverPackage.version ? `${serverPackage.identifier}==${serverPackage.version}` : serverPackage.identifier);
        break;
    case RegistryType.DOCKER:
        args.push(serverPackage.version ? `${serverPackage.identifier}:${serverPackage.version}` : serverPackage.identifier);
        break;
    case RegistryType.NUGET:
        args.push(serverPackage.version ? `${serverPackage.identifier}@${serverPackage.version}` : serverPackage.identifier);
        args.push('--yes');
        if (serverPackage.packageArguments?.length) {
            args.push('--');
        }
        break;
}

Problem: This code unconditionally inserts the package identifier between runtimeArguments and packageArguments, with no way to disable this behavior.

Reproduction Case: npm Package with Custom Registry

Gallery Package Configuration:

{
  "packages": [
    {
      "registryType": "npm",
      "identifier": "@myorg/mcp-server",
      "version": "latest",
      "runtimeArguments": [
        { "type": "positional", "value": "exec" },
        { "type": "positional", "value": "-y" }
      ],
      "packageArguments": [
        { "type": "named", "name": "--registry", "value": "https://pkgs.dev.azure.com/myorg/myproject/_packaging/my-feed/npm/registry/" },
        { "type": "named", "name": "--package", "value": "@myorg/mcp-server@latest" },
        { "type": "positional", "value": "mcp-server-memory" }
      ]
    }
  ]
}

Expected VS Code Output:

{
  "command": "npx",
  "args": [
    "exec",
    "-y",
    "--registry",
    "https://pkgs.dev.azure.com/myorg/myproject/_packaging/my-feed/npm/registry/",
    "--package",
    "@myorg/mcp-server@latest",
    "my-mcp-server"
  ]
}

Actual VS Code Output:

{
  "command": "npx",
  "args": [
    "exec",
    "-y",
    "@myorg/mcp-server@latest",  // ← AUTO-INSERTED (duplicate!)
    "--registry",
    "https://pkgs.dev.azure.com/myorg/myproject/_packaging/my-feed/npm/registry/",
    "--package",
    "@myorg/mcp-server@latest",  // ← EXPECTED (from packageArguments)
    "my-mcp-server"
  ]
}

Expected Command:

npx exec -y --registry https://... --package @myorg/mcp-server@latest my-mcp-server

Actual Command:

npx exec -y @myorg/mcp-server@latest --registry https://... --package @myorg/mcp-server@latest my-mcp-server

Why This Breaks

For custom package registries (Azure DevOps, GitHub Packages, private npm registries), the package specification must be passed with the --package flag to npm exec:

npm exec --registry <url> --package <name@version> <command>

The auto-inserted @myorg/mcp-server@latest (without --package flag) is interpreted as:

  1. A command to execute (npm tries to find and run this as a binary)
  2. Creates incorrect argument order that fails validation

Issue 2: Hardcoded --yes Flag for NuGet Packages

Location

File: src/vs/platform/mcp/common/mcpManagement.ts
Class: AbstractCommonMcpManagementService
Method: getMcpServerConfigurationFromManifest()
Line: 184 (approximate)

Current Behavior

case RegistryType.NUGET:
    args.push(serverPackage.version ? `${serverPackage.identifier}@${serverPackage.version}` : serverPackage.identifier);
    args.push('--yes'); // ← ALWAYS ADDED
    if (serverPackage.packageArguments?.length) {
        args.push('--');
    }
    break;

Problem: The --yes flag is unconditionally added even if already present in runtimeArguments, creating duplicates.

Reproduction Case: NuGet Package with --yes in Arguments

Gallery Package Configuration:

{
  "packages": [
    {
      "registryType": "nuget",
      "identifier": "MyOrg.McpServer",
      "version": "latest",
      "runtimeArguments": [
        { "type": "positional", "value": "MyOrg.McpServer" },
        { "type": "named", "name": "--source", "value": "https://pkgs.dev.azure.com/myorg/myproject/_packaging/my-feed/nuget/v3/index.json" },
        { "type": "positional", "value": "--yes" }
      ],
      "packageArguments": []
    }
  ]
}

Expected VS Code Output:

{
  "command": "dnx",
  "args": [
    "MyOrg.McpServer",
    "--source",
    "https://pkgs.dev.azure.com/myorg/myproject/_packaging/my-feed/nuget/v3/index.json",
    "--yes"
  ]
}

Actual VS Code Output:

{
  "command": "dnx",
  "args": [
    "MyOrg.McpServer",
    "--source",
    "https://pkgs.dev.azure.com/myorg/myproject/_packaging/my-feed/nuget/v3/index.json",
    "--yes",                      // ← From runtimeArguments
    "MyOrg.McpServer@latest",  // ← Auto-inserted
    "--yes"                       // ← Auto-inserted (duplicate!)
  ]
}

Impact

Affected Use Cases

  1. Private Package Registries - Azure DevOps Artifacts, GitHub Packages, JFrog Artifactory
  2. Custom npm/NuGet Configurations - Organizations with internal package feeds
  3. Non-Standard Package Managers - Custom tooling that wraps standard package managers
  4. External MCP Registry Providers - Third-party services hosting MCP server catalogs

Environment

  • VS Code Version: 1.107.0-insider
  • OS: Windows 11
  • MCP Registry: Private Enterprise MCP Registry (third-party external registry)
  • Package Managers Affected: npm, NuGet

Additional Context

Code References

Main transformation method:

export abstract class AbstractCommonMcpManagementService extends Disposable implements IMcpManagementService {
    getMcpServerConfigurationFromManifest(manifest: IGalleryMcpServerConfiguration, packageType: RegistryType): McpServerConfigurationParseResult {
        // Lines 157-166: Process runtimeArguments
        if (serverPackage.runtimeArguments?.length) {
            const result = this.processArguments(serverPackage.runtimeArguments ?? []);
            args.push(...result.args);
        }
        
        // Lines 177-184: AUTO-INSERT (Issue 1)
        switch (serverPackage.registryType) {
            case RegistryType.NODE:
                args.push(serverPackage.version ? `${serverPackage.identifier}@${serverPackage.version}` : serverPackage.identifier);
                break;
            case RegistryType.NUGET:
                args.push(serverPackage.version ? `${serverPackage.identifier}@${serverPackage.version}` : serverPackage.identifier);
                args.push('--yes'); // Issue 2: Hardcoded --yes
                break;
        }
        
        // Lines 186-191: Process packageArguments (too late, duplicate already exists)
        if (serverPackage.packageArguments?.length) {
            const result = this.processArguments(serverPackage.packageArguments);
            args.push(...result.args);
        }
    }
}

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions