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

Code before:
				state: McpConnectionState.Kind.Error,
				message: e instanceof Error ? e.message : String(e)
			};
			this._state.set(errorState, undefined);
			return errorState;
		}
	}

	private adoptLaunch(launch: IMcpMessageTransport, methods: IMcpClientMethods): IReference<IMcpMessageTransport> {
		const store = new DisposableStore();
		const cts = new CancellationTokenSource();
		const recentLogLines: string[] = [];

		store.add(toDisposable(() => cts.dispose(true)));
		store.add(launch);
		store.add(launch.onDidLog(({ level, message }) => {
			log(this._logger, level, message);
			recentLogLines.push(message);
			if (recentLogLines.length > McpServerConnection._maxRecentLogLines) {
				recentLogLines.splice(0, recentLogLines.length - McpServerConnection._maxRecentLogLines);
			}
		}));

		let didStart = false;
		store.add(autorun(reader => {
			const state = this._withLogTailOnError(launch.state.read(reader), recentLogLines);
			this._state.set(state, undefined);
			this._logger.info(localize('mcpServer.state', 'Connection state: {0}', McpConnectionState.toString(state)));

			if (state.state === McpConnectionState.Kind.Running && !didStart) {
				didStart = true;
				McpServerRequestHandler.create(this._instantiationService, {
					...methods,
					launch,
					logger: this._logger,
					requestLogLevel: this.definition.devMode ? LogLevel.Info : LogLevel.Debug,
					taskManager: this._taskManager,
				}, cts.token).then(
					handler => {
						if (!store.isDisposed) {
							this._requestHandler.set(handler, undefined);
						} else {
							handler.dispose();
						}
					},
					err => {
						if (!store.isDisposed && McpConnectionState.isRunning(this._state.read(undefined))) {
							let message = err.message;
							if (err instanceof CancellationError) {
								message = 'Server exited before responding to `initialize` request.';
								this._logger.error(message);

Review comment (bug):
We would also want to detect 'runtime' failures, not just failures that cause the server to outright fail. E.g. perplexity MCP will start fine but fail to call tools if their domain isn't allowlisted.

I suggest not keeping a tail log like this, but instead

- Have some event `onPotentialSandboxBlock` that, servers that are sandboxed, fires when something that is certainly a failure (a domain block) or may be a failure (file access issue) is encountered
- While the connection it starting, collect any such events that get emitted. If the server fails to start, then pop a dialog. THis can be handled in `McpServer.start` so that you can respect `errorOnUserInteraction`
- We could then do a similar thing for tool calls: collect events that happen while a tool is running, and then if the tool call fails and we've found some of these events, present them to the user

Code after:
			const errorState: McpConnectionState = {
				state: McpConnectionState.Kind.Error,
				message: e instanceof Error ? e.message : String(e)
			};
			this._state.set(errorState, undefined);
			return errorState;
		}
	}

	private adoptLaunch(launch: IMcpMessageTransport, methods: IMcpClientMethods): IReference<IMcpMessageTransport> {
		const store = new DisposableStore();
		const cts = new CancellationTokenSource();

		store.add(toDisposable(() => cts.dispose(true)));
		store.add(launch);
		store.add(launch.onDidLog(({ level, message }) => {
			log(this._logger, level, message);
			const potentialBlock = this._toPotentialSandboxBlock(message);
			if (potentialBlock) {
				this._onPotentialSandboxBlock.fire(potentialBlock);
			}
		}));

		let didStart = false;
		store.add(autorun(reader => {
			const state = launch.state.read(reader);
			this._state.set(state, undefined);
			this._logger.info(localize('mcpServer.state', 'Connection state: {0}', McpConnectionState.toString(state)));

			if (state.state === McpConnectionState.Kind.Running && !didStart) {
				didStart = true;
				McpServerRequestHandler.create(this._instantiationService, {
					...methods,
					launch,
					logger: this._logger,
					requestLogLevel: this.definition.devMode ? LogLevel.Info : LogLevel.Debug,
					taskManager: this._taskManager,
				}, cts.token).then(
					handler => {
						if (!store.isDisposed) {
							this._requestHandler.set(handler, undefined);
						} else {
							handler.dispose();
						}
					},
					err => {
						if (!store.isDisposed && McpConnectionState.isRunning(this._state.read(undefined))) {
							let message = err.message;
							if (err instanceof CancellationError) {
								message = 'Server exited before responding to `initialize` request.';
								this._logger.error(message);