Skip to content

Commit d80da41

Browse files
committed
fix(server): include registered tool icons
1 parent 4fbcfcd commit d80da41

4 files changed

Lines changed: 74 additions & 2 deletions

File tree

.changeset/register-tool-icons.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@modelcontextprotocol/server': patch
3+
---
4+
5+
Add `icons` support to `McpServer.registerTool()` and task tool registration, and include tool icons in `tools/list` responses.

packages/server/src/experimental/tasks/mcpServer.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* @experimental
66
*/
77

8-
import type { StandardSchemaWithJSON, TaskToolExecution, ToolAnnotations, ToolExecution } from '@modelcontextprotocol/core';
8+
import type { Icon, StandardSchemaWithJSON, TaskToolExecution, ToolAnnotations, ToolExecution } from '@modelcontextprotocol/core';
99

1010
import type { AnyToolHandler, McpServer, RegisteredTool } from '../../server/mcp.js';
1111
import type { ToolTaskHandler } from './interfaces.js';
@@ -21,6 +21,7 @@ interface McpServerInternal {
2121
description: string | undefined,
2222
inputSchema: StandardSchemaWithJSON | undefined,
2323
outputSchema: StandardSchemaWithJSON | undefined,
24+
icons: Icon[] | undefined,
2425
annotations: ToolAnnotations | undefined,
2526
execution: ToolExecution | undefined,
2627
_meta: Record<string, unknown> | undefined,
@@ -82,6 +83,7 @@ export class ExperimentalMcpServerTasks {
8283
title?: string;
8384
description?: string;
8485
outputSchema?: OutputArgs;
86+
icons?: Icon[];
8587
annotations?: ToolAnnotations;
8688
execution?: TaskToolExecution;
8789
_meta?: Record<string, unknown>;
@@ -96,6 +98,7 @@ export class ExperimentalMcpServerTasks {
9698
description?: string;
9799
inputSchema: InputArgs;
98100
outputSchema?: OutputArgs;
101+
icons?: Icon[];
99102
annotations?: ToolAnnotations;
100103
execution?: TaskToolExecution;
101104
_meta?: Record<string, unknown>;
@@ -110,6 +113,7 @@ export class ExperimentalMcpServerTasks {
110113
description?: string;
111114
inputSchema?: InputArgs;
112115
outputSchema?: OutputArgs;
116+
icons?: Icon[];
113117
annotations?: ToolAnnotations;
114118
execution?: TaskToolExecution;
115119
_meta?: Record<string, unknown>;
@@ -130,6 +134,7 @@ export class ExperimentalMcpServerTasks {
130134
config.description,
131135
config.inputSchema,
132136
config.outputSchema,
137+
config.icons,
133138
config.annotations,
134139
execution,
135140
config._meta,

packages/server/src/server/mcp.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
CreateTaskResult,
99
CreateTaskServerContext,
1010
GetPromptResult,
11+
Icon,
1112
Implementation,
1213
ListPromptsResult,
1314
ListResourcesResult,
@@ -143,6 +144,7 @@ export class McpServer {
143144
name,
144145
title: tool.title,
145146
description: tool.description,
147+
icons: tool.icons,
146148
inputSchema: tool.inputSchema
147149
? (standardSchemaToJsonSchema(tool.inputSchema, 'input') as Tool['inputSchema'])
148150
: EMPTY_OBJECT_JSON_SCHEMA,
@@ -772,6 +774,7 @@ export class McpServer {
772774
description: string | undefined,
773775
inputSchema: StandardSchemaWithJSON | undefined,
774776
outputSchema: StandardSchemaWithJSON | undefined,
777+
icons: Icon[] | undefined,
775778
annotations: ToolAnnotations | undefined,
776779
execution: ToolExecution | undefined,
777780
_meta: Record<string, unknown> | undefined,
@@ -788,6 +791,7 @@ export class McpServer {
788791
description,
789792
inputSchema,
790793
outputSchema,
794+
icons,
791795
annotations,
792796
execution,
793797
_meta,
@@ -824,6 +828,7 @@ export class McpServer {
824828
}
825829

826830
if (updates.outputSchema !== undefined) registeredTool.outputSchema = updates.outputSchema;
831+
if (updates.icons !== undefined) registeredTool.icons = updates.icons;
827832
if (updates.annotations !== undefined) registeredTool.annotations = updates.annotations;
828833
if (updates._meta !== undefined) registeredTool._meta = updates._meta;
829834
if (updates.enabled !== undefined) registeredTool.enabled = updates.enabled;
@@ -871,6 +876,7 @@ export class McpServer {
871876
description?: string;
872877
inputSchema?: InputArgs;
873878
outputSchema?: OutputArgs;
879+
icons?: Icon[];
874880
annotations?: ToolAnnotations;
875881
_meta?: Record<string, unknown>;
876882
},
@@ -884,6 +890,7 @@ export class McpServer {
884890
description?: string;
885891
inputSchema?: InputArgs;
886892
outputSchema?: OutputArgs;
893+
icons?: Icon[];
887894
annotations?: ToolAnnotations;
888895
_meta?: Record<string, unknown>;
889896
},
@@ -896,6 +903,7 @@ export class McpServer {
896903
description?: string;
897904
inputSchema?: StandardSchemaWithJSON | ZodRawShape;
898905
outputSchema?: StandardSchemaWithJSON | ZodRawShape;
906+
icons?: Icon[];
899907
annotations?: ToolAnnotations;
900908
_meta?: Record<string, unknown>;
901909
},
@@ -905,14 +913,15 @@ export class McpServer {
905913
throw new Error(`Tool ${name} is already registered`);
906914
}
907915

908-
const { title, description, inputSchema, outputSchema, annotations, _meta } = config;
916+
const { title, description, inputSchema, outputSchema, icons, annotations, _meta } = config;
909917

910918
return this._createRegisteredTool(
911919
name,
912920
title,
913921
description,
914922
normalizeRawShapeSchema(inputSchema),
915923
normalizeRawShapeSchema(outputSchema),
924+
icons,
916925
annotations,
917926
{ taskSupport: 'forbidden' },
918927
_meta,
@@ -1162,6 +1171,7 @@ export type RegisteredTool = {
11621171
description?: string;
11631172
inputSchema?: StandardSchemaWithJSON;
11641173
outputSchema?: StandardSchemaWithJSON;
1174+
icons?: Icon[];
11651175
annotations?: ToolAnnotations;
11661176
execution?: ToolExecution;
11671177
_meta?: Record<string, unknown>;
@@ -1177,6 +1187,7 @@ export type RegisteredTool = {
11771187
description?: string;
11781188
paramsSchema?: StandardSchemaWithJSON;
11791189
outputSchema?: StandardSchemaWithJSON;
1190+
icons?: Icon[];
11801191
annotations?: ToolAnnotations;
11811192
_meta?: Record<string, unknown>;
11821193
callback?: ToolCallback<StandardSchemaWithJSON>;

test/integration/test/server/mcp.test.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1038,6 +1038,57 @@ describe('Zod v4', () => {
10381038
});
10391039
});
10401040

1041+
/***
1042+
* Test: Tool Registration with Icons
1043+
*/
1044+
test('should register tool with icons', async () => {
1045+
const mcpServer = new McpServer({
1046+
name: 'test server',
1047+
version: '1.0'
1048+
});
1049+
const client = new Client({
1050+
name: 'test client',
1051+
version: '1.0'
1052+
});
1053+
1054+
mcpServer.registerTool(
1055+
'test',
1056+
{
1057+
icons: [
1058+
{
1059+
src: 'https://example.com/icon.png',
1060+
mimeType: 'image/png'
1061+
}
1062+
]
1063+
},
1064+
async () => ({
1065+
content: [
1066+
{
1067+
type: 'text',
1068+
text: 'Test response'
1069+
}
1070+
]
1071+
})
1072+
);
1073+
1074+
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
1075+
1076+
await Promise.all([client.connect(clientTransport), mcpServer.server.connect(serverTransport)]);
1077+
1078+
const result = await client.request({
1079+
method: 'tools/list'
1080+
});
1081+
1082+
expect(result.tools).toHaveLength(1);
1083+
expect(result.tools[0]!.name).toBe('test');
1084+
expect(result.tools[0]!.icons).toEqual([
1085+
{
1086+
src: 'https://example.com/icon.png',
1087+
mimeType: 'image/png'
1088+
}
1089+
]);
1090+
});
1091+
10411092
/***
10421093
* Test: Tool Registration with Parameters and Annotations
10431094
*/

0 commit comments

Comments
 (0)