Skip to content

Commit 65ed956

Browse files
authored
mcp: formally adopt 2025-06-18 spec (microsoft#252004)
Still todo: - Support structured output - Add resource_link support to tool results Also add an event for elicitation Ref microsoft#248418
1 parent 9dc4be3 commit 65ed956

File tree

6 files changed

+200
-86
lines changed

6 files changed

+200
-86
lines changed

src/vs/workbench/contrib/mcp/browser/mcpPromptArgumentPick.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export class McpPromptArgumentPick extends Disposable {
7676
const restore = backSnapshots.at(i);
7777
quickPick.step = i + 1;
7878
quickPick.placeholder = arg.required ? arg.description : `${arg.description || ''} (${localize('optional', 'Optional')})`;
79-
quickPick.title = localize('mcp.prompt.pick.title', 'Value for: {0}', arg.name);
79+
quickPick.title = localize('mcp.prompt.pick.title', 'Value for: {0}', arg.title || arg.name);
8080
quickPick.value = restore?.value ?? ((args.hasOwnProperty(arg.name) && args[arg.name]) || '');
8181
quickPick.items = restore?.items ?? [];
8282
quickPick.activeItems = restore?.activeItems ?? [];

src/vs/workbench/contrib/mcp/browser/mcpResourceQuickAccess.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,15 @@ export class McpResourcePickHelper {
4040
if (isMcpResourceTemplate(resource)) {
4141
return {
4242
id: resource.template.template,
43-
label: resource.name,
43+
label: resource.title || resource.name,
4444
description: resource.description,
4545
detail: localize('mcp.resource.template', 'Resource template: {0}', resource.template.template),
4646
};
4747
}
4848

4949
return {
5050
id: resource.uri.toString(),
51-
label: resource.name,
51+
label: resource.title || resource.name,
5252
description: resource.description,
5353
detail: resource.mcpUri + (resource.sizeInBytes !== undefined ? ' (' + ByteSize.formatSize(resource.sizeInBytes) + ')' : ''),
5454
};

src/vs/workbench/contrib/mcp/common/mcpServer.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,18 @@ type ServerBootClassification = {
5555
serverVersion: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The version of the MCP server' };
5656
};
5757

58+
type ElicitationTelemetryData = {
59+
serverName: string;
60+
serverVersion: string;
61+
};
62+
63+
type ElicitationTelemetryClassification = {
64+
owner: 'connor4312';
65+
comment: 'Triggered when elictation is requested';
66+
serverName: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The name of the MCP server' };
67+
serverVersion: { classification: 'SystemMetaData'; purpose: 'FeatureInsight'; comment: 'The version of the MCP server' };
68+
};
69+
5870
type ServerBootState = {
5971
state: string;
6072
time: number;
@@ -477,8 +489,17 @@ export class McpServer extends Disposable implements IMcpServer {
477489
server: this,
478490
params,
479491
}).then(r => r.sample),
480-
elicitationRequestHandler: req => this._elicitationService.elicit(
481-
this, Iterable.first(this.runningToolCalls), req, CancellationToken.None),
492+
elicitationRequestHandler: req => {
493+
const serverInfo = connection.handler.get()?.serverInfo;
494+
if (serverInfo) {
495+
this._telemetryService.publicLog2<ElicitationTelemetryData, ElicitationTelemetryClassification>('mcp.elicitationRequested', {
496+
serverName: serverInfo.name,
497+
serverVersion: serverInfo.version,
498+
});
499+
}
500+
501+
return this._elicitationService.elicit(this, Iterable.first(this.runningToolCalls), req, CancellationToken.None);
502+
}
482503
});
483504

484505
this._telemetryService.publicLog2<ServerBootState, ServerBootStateClassification>('mcp/serverBootState', {
@@ -670,6 +691,7 @@ class McpPrompt implements IMcpPrompt {
670691
readonly id: string;
671692
readonly name: string;
672693
readonly description?: string;
694+
readonly title?: string;
673695
readonly arguments: readonly MCP.PromptArgument[];
674696

675697
constructor(
@@ -678,6 +700,7 @@ class McpPrompt implements IMcpPrompt {
678700
) {
679701
this.id = mcpPromptReplaceSpecialChars(this._server.definition.label + '.' + _definition.name);
680702
this.name = _definition.name;
703+
this.title = _definition.title;
681704
this.description = _definition.description;
682705
this.arguments = _definition.arguments || [];
683706
}
@@ -824,18 +847,20 @@ function warnInvalidTools(instaService: IInstantiationService, serverName: strin
824847
}
825848

826849
class McpResource implements IMcpResource {
827-
uri: URI;
828-
mcpUri: string;
829-
name: string;
830-
description: string | undefined;
831-
mimeType: string | undefined;
832-
sizeInBytes: number | undefined;
850+
readonly uri: URI;
851+
readonly mcpUri: string;
852+
readonly name: string;
853+
readonly description: string | undefined;
854+
readonly mimeType: string | undefined;
855+
readonly sizeInBytes: number | undefined;
856+
readonly title: string | undefined;
833857

834858
constructor(
835859
server: McpServer,
836860
original: MCP.Resource,
837861
) {
838862
this.mcpUri = original.uri;
863+
this.title = original.title;
839864
this.uri = McpResourceURI.fromServer(server.definition, original.uri);
840865
this.name = original.name;
841866
this.description = original.description;
@@ -846,6 +871,7 @@ class McpResource implements IMcpResource {
846871

847872
class McpResourceTemplate implements IMcpResourceTemplate {
848873
readonly name: string;
874+
readonly title?: string | undefined;
849875
readonly description?: string;
850876
readonly mimeType?: string;
851877
readonly template: UriTemplate;
@@ -857,6 +883,7 @@ class McpResourceTemplate implements IMcpResourceTemplate {
857883
this.name = _definition.name;
858884
this.description = _definition.description;
859885
this.mimeType = _definition.mimeType;
886+
this.title = _definition.title;
860887
this.template = UriTemplate.parse(_definition.uriTemplate);
861888
}
862889

src/vs/workbench/contrib/mcp/common/mcpService.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,8 @@ export class McpService extends Disposable implements IMcpService {
114114
id: tool.id,
115115
source,
116116
icon: Codicon.tools,
117-
displayName: tool.definition.annotations?.title || tool.definition.name,
117+
// duplicative: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/813
118+
displayName: tool.definition.annotations?.title || tool.definition.title || tool.definition.name,
118119
toolReferenceName: tool.referenceName,
119120
modelDescription: tool.definition.description ?? '',
120121
userDescription: tool.definition.description ?? '',
@@ -256,7 +257,8 @@ class McpToolImplementation implements IToolImpl {
256257
);
257258

258259
const needsConfirmation = !tool.definition.annotations?.readOnlyHint;
259-
const title = tool.definition.annotations?.title || ('`' + tool.definition.name + '`');
260+
// duplicative: https://github.com/modelcontextprotocol/modelcontextprotocol/pull/813
261+
const title = tool.definition.annotations?.title || tool.definition.title || ('`' + tool.definition.name + '`');
260262
const subtitle = localize('msg.subtitle', "{0} (MCP Server)", server.definition.label);
261263

262264
return {
@@ -324,6 +326,8 @@ class McpToolImplementation implements IToolImpl {
324326
} else if (item.type === 'image' || item.type === 'audio') {
325327
// default to some image type if not given to hint
326328
addAsInlineData(item.mimeType || 'image/png', item.data);
329+
} else if (item.type === 'resource_link') {
330+
// todo@connor4312 look at what we did before #250329 and use that here
327331
} else if (item.type === 'resource') {
328332
const uri = McpResourceURI.fromServer(this._server.definition, item.resource.uri);
329333
if (item.resource.mimeType && getAttachableImageExtension(item.resource.mimeType) && 'blob' in item.resource) {

src/vs/workbench/contrib/mcp/common/mcpTypes.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,13 +283,15 @@ export interface IMcpResource {
283283
/** Identifier of the file as given from the MCP server. */
284284
readonly mcpUri: string;
285285
readonly name: string;
286+
readonly title?: string;
286287
readonly description?: string;
287288
readonly mimeType?: string;
288289
readonly sizeInBytes?: number;
289290
}
290291

291292
export interface IMcpResourceTemplate {
292293
readonly name: string;
294+
readonly title?: string;
293295
readonly description?: string;
294296
readonly mimeType?: string;
295297
readonly template: UriTemplate;
@@ -326,6 +328,7 @@ export const enum McpServerCacheState {
326328
export interface IMcpPrompt {
327329
readonly id: string;
328330
readonly name: string;
331+
readonly title?: string;
329332
readonly description?: string;
330333
readonly arguments: readonly MCP.PromptArgument[];
331334

0 commit comments

Comments
 (0)