Repository: microsoft/vscode
File: src/vs/workbench/contrib/mcp/common/mcpServer.ts (TypeScript)

Code before:
				});
		}));

		// 2. Populate this.tools when we connect to a server.
		this._register(autorun(reader => {
			const cnx = this._connection.read(reader);
			const handler = cnx?.handler.read(reader);
			if (handler) {
				this._populateLiveData(handler, cnx?.definition.cacheNonce, reader.store);
			} else if (this._tools) {
				this.resetLiveData();
			}
		}));

		this._register(autorun(reader => {
			const cnx = this._connection.read(reader);
			const state = cnx?.state.read(reader);

			if (cnx && state?.state === McpConnectionState.Kind.Error) {
				const transitionedToError = this._lastErrorNotificationConnection !== cnx
					|| this._lastErrorNotificationState !== McpConnectionState.Kind.Error;
				if (transitionedToError) {
					if (!this._isQuietStart) {
						this.showInteractiveError(cnx, state, this._lastModeDebugged);
					} else {
						throw new UserInteractionRequiredError('start');
					}
				}
			}

			this._lastErrorNotificationConnection = cnx;
			this._lastErrorNotificationState = state?.state;
		}));

		this._register(autorun(reader => {
			const cnx = this._connection.read(reader);
			this._potentialSandboxBlockListener.value = cnx?.onPotentialSandboxBlock(block => this.recordPotentialSandboxBlock(block));
		}));

		const staticMetadata = derived(reader => {
			const def = this._fullDefinitions.read(reader).server;
			return def && def.cacheNonce !== this._tools.fromCache?.nonce ? def.staticMetadata : undefined;
		});

		// 3. Publish tools
		this._tools = new CachedPrimitive<readonly IMcpTool[], readonly ValidatedMcpTool[]>(
			this.definition.id,
			this._primitiveCache,
			staticMetadata
				.map(m => {
					const tools = m?.tools?.filter(t => t.availability === McpServerStaticToolAvailability.Initial).map(t => t.definition);

Review comment (suggestion):
This is an unhandled execption. The interaction required error should result in the promise returned from `start()` rejecting

I would handle this entirely within the start() method, start capturing events around [here](https://github.com/microsoft/vscode/blob/5496be1da981edd8d49e78f1eec416c56ed8ddb5/src/vs/workbench/contrib/mcp/common/mcpServer.ts#L632)

and then if the connection ended up in an error state, check before `return state;` to see if you captured any events that should result in a sandbox error being thrown instead

Code after:

		// 2. Populate this.tools when we connect to a server.
		this._register(autorun(reader => {
			const cnx = this._connection.read(reader);
			const handler = cnx?.handler.read(reader);
			if (handler) {
				this._populateLiveData(handler, cnx?.definition.cacheNonce, reader.store);
			} else if (this._tools) {
				this.resetLiveData();
			}
		}));

		this._register(autorun(reader => {
			const cnx = this._connection.read(reader);
			this._potentialSandboxBlockListener.value = cnx?.onPotentialSandboxBlock(block => this.recordPotentialSandboxBlock(block));
		}));

		const staticMetadata = derived(reader => {
			const def = this._fullDefinitions.read(reader).server;
			return def && def.cacheNonce !== this._tools.fromCache?.nonce ? def.staticMetadata : undefined;
		});

		// 3. Publish tools
		this._tools = new CachedPrimitive<readonly IMcpTool[], readonly ValidatedMcpTool[]>(
			this.definition.id,
			this._primitiveCache,
			staticMetadata
				.map(m => {
					const tools = m?.tools?.filter(t => t.availability === McpServerStaticToolAvailability.Initial).map(t => t.definition);
					return tools?.length ? new ObservablePromise(this._getValidatedTools(tools)) : undefined;
				})
				.map((o, reader) => o?.promiseResult.read(reader)?.data),
			(entry) => entry.tools,
			(entry) => entry.map(def => this._instantiationService.createInstance(McpTool, this, toolPrefix, def)).sort((a, b) => a.compare(b)),
			[],
		);

		// 4. Publish prompts
		this._prompts = new CachedPrimitive<readonly IMcpPrompt[], readonly StoredMcpPrompt[]>(
			this.definition.id,
			this._primitiveCache,
			undefined,
			(entry) => entry.prompts || [],
			(entry) => entry.map(e => new McpPrompt(this, e)),
			[],
		);

		this._serverMetadata = new CachedPrimitive<ServerMetadata, StoredServerMetadata | undefined>(
			this.definition.id,
			this._primitiveCache,
			staticMetadata.map(m => m ? this._toStoredMetadata(m?.serverInfo, m?.instructions) : undefined),