Improved MCP tool call rendering for non-local agents (#289505)

* Improved MCP tool call rendering for non-local agents

* Update src/vs/workbench/api/common/extHostTypeConverters.ts

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Don Jayamanne
2026-01-22 14:01:01 +11:00
committed by GitHub
parent abf16d1726
commit 0ffdfb45f4
4 changed files with 72 additions and 2 deletions
@@ -1972,6 +1972,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
McpStdioServerDefinition: extHostTypes.McpStdioServerDefinition,
McpStdioServerDefinition2: extHostTypes.McpStdioServerDefinition,
McpToolAvailability: extHostTypes.McpToolAvailability,
McpToolInvocationContentData: extHostTypes.McpToolInvocationContentData,
SettingsSearchResultKind: extHostTypes.SettingsSearchResultKind,
};
};
@@ -2815,6 +2815,19 @@ export namespace ChatResponseMovePart {
export namespace ChatToolInvocationPart {
export function from(part: vscode.ChatToolInvocationPart): IChatToolInvocationSerialized {
// Check if toolSpecificData is ChatMcpToolInvocationData (has input and output)
// If so, convert to resultDetails for rendering via ChatInputOutputMarkdownProgressPart
let resultDetails: IToolResultInputOutputDetails | undefined;
let toolSpecificData: any;
if (part.toolSpecificData && isChatMcpToolInvocationData(part.toolSpecificData)) {
// Convert ChatMcpToolInvocationData to IToolResultInputOutputDetails
resultDetails = convertMcpToResultDetails(part.toolSpecificData, part.isError);
toolSpecificData = undefined; // MCP data goes to resultDetails, not toolSpecificData
} else {
toolSpecificData = part.toolSpecificData ? convertToolSpecificData(part.toolSpecificData) : undefined;
}
// Convert extension API ChatToolInvocationPart to internal serialized format
return {
kind: 'toolInvocationSerialized',
@@ -2827,7 +2840,8 @@ export namespace ChatToolInvocationPart {
isComplete: part.isComplete ?? true,
source: ToolDataSource.External,
// isError: part.isError ?? false,
toolSpecificData: part.toolSpecificData ? convertToolSpecificData(part.toolSpecificData) : undefined,
toolSpecificData,
resultDetails,
presentation: part.presentation === 'hidden'
? ToolInvocationPresentation.Hidden
: part.presentation === 'hiddenAfterComplete'
@@ -2837,6 +2851,28 @@ export namespace ChatToolInvocationPart {
};
}
function isChatMcpToolInvocationData(data: any): data is vscode.ChatMcpToolInvocationData {
return data !== null && typeof data === 'object' &&
'input' in data && typeof data.input === 'string' &&
'output' in data && Array.isArray(data.output);
}
function convertMcpToResultDetails(data: vscode.ChatMcpToolInvocationData, isError?: boolean): IToolResultInputOutputDetails {
return {
input: data.input,
output: data.output.map((o) => {
const isText = o.mimeType.startsWith('text/');
return {
type: 'embed' as const,
mimeType: o.mimeType,
value: isText ? VSBuffer.wrap(o.data).toString() : encodeBase64(VSBuffer.wrap(o.data)),
isText: isText,
};
}),
isError: isError ?? false,
};
}
function convertToolSpecificData(data: any): any {
// Convert extension API terminal tool data to internal format
if ('command' in data && 'language' in data) {
@@ -3166,6 +3166,15 @@ export class ChatResponseMultiDiffPart {
}
}
export class McpToolInvocationContentData {
mimeType: string;
data: Uint8Array;
constructor(data: Uint8Array, mimeType: string) {
this.data = data;
this.mimeType = mimeType;
}
}
export class ChatResponseExternalEditPart {
applied: Thenable<string>;
didGetApplied!: (value: string) => void;
@@ -120,6 +120,30 @@ declare module 'vscode' {
language: string;
}
export class McpToolInvocationContentData {
/**
* The mime type which determines how the data property is interpreted.
*/
mimeType: string;
/**
* The byte data for this part.
*/
data: Uint8Array;
/**
* Construct a generic data part with the given content.
* @param data The byte data for this part.
* @param mimeType The mime type of the data.
*/
constructor(data: Uint8Array, mimeType: string);
}
export interface ChatMcpToolInvocationData {
input: string;
output: McpToolInvocationContentData[];
}
export class ChatToolInvocationPart {
toolName: string;
toolCallId: string;
@@ -129,7 +153,7 @@ declare module 'vscode' {
pastTenseMessage?: string | MarkdownString;
isConfirmed?: boolean;
isComplete?: boolean;
toolSpecificData?: ChatTerminalToolInvocationData;
toolSpecificData?: ChatTerminalToolInvocationData | ChatMcpToolInvocationData;
subAgentInvocationId?: string;
presentation?: 'hidden' | 'hiddenAfterComplete' | undefined;