microsoft / microsoft/vscode

agent host: derive MCP customization id from ownership instead of publication position

Open
#330,915 0 comments 0 reactions 1 assignee Claimed by @connor4312 View on GitHub
agent-host debt
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

Follow-up cleanup from the scoped-enablement work (#330566, #330715).

## Problem

An MCP server currently carries three identifiers, and most of the hard bugs in this area were *mapping errors between them*:

| Identifier | Value | Depends on |
| --- | --- | --- |
| `id` | `mcp-top-level:::` **or** the plugin child id | publication position |
| `name` | server name | SDK operations |
| durable enablement key | `#mcp=` or `mcpServers#` | ownership |

Publication position is decided by a startup race in `McpCustomizationController._applyOne`: if a plugin's children are already published the server is nested, otherwise it is **promoted** to a bare top-level customization, and promotion is deliberately sticky because re-parenting mid-session would orphan an id the client has already rendered.

Because position leaked into identity, the same server keyed differently depending on whether it happened to be promoted that session — so "disable azure globally" written in one session was invisible in the next. That was the original reported bug.

It is currently fixed by threading an ownership map (`mcpServerOwners` / `pluginMcpServerSources`) so the durable key is position-independent. That works, but it means correctness now *depends on every provider remembering to supply the map* — and Codex did not, which is #330715.

## Suggestion

Mint the top-level customization id **from the durable key** rather than from provider/session/name. Then:

- nested and promoted publications are the same identity **by construction**;
- the ownership map stops being load-bearing for correctness and is only needed for display grouping;
- sticky promotion stops being an invariant contributors must preserve;
- the whole "should we gate publication on plugin parsing?" question becomes a pure UX decision rather than a correctness one.

Higher risk than the other follow-ups because it touches id minting, which clients render — worth checking whether any client persists these ids. But it deletes the bug class rather than guarding it.

## Constraint

`getCustomizationEnablementKey` output must not change for existing keys, or users' stored decisions silently orphan and disabled servers come back enabled.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.