@@ -54,26 +54,35 @@ import { z } from "zod";
54
54
55
55
// Create an MCP server
56
56
const server = new McpServer ({
57
- name: " Demo" ,
58
- version: " 1.0.0"
57
+ name: " demo-server" ,
58
+ version: " 1.0.0" ,
59
+ title: " Demo Server" // Optional display name
59
60
});
60
61
61
62
// Add an addition tool
62
- server .tool (" add" ,
63
- { a: z .number (), b: z .number () },
63
+ server .registerTool (" add" ,
64
+ {
65
+ title: " Addition Tool" ,
66
+ description: " Add two numbers" ,
67
+ inputSchema: { a: z .number (), b: z .number () }
68
+ },
64
69
async ({ a , b }) => ({
65
70
content: [{ type: " text" , text: String (a + b ) }]
66
71
})
67
72
);
68
73
69
74
// Add a dynamic greeting resource
70
- server .resource (
75
+ server .registerResource (
71
76
" greeting" ,
72
77
new ResourceTemplate (" greeting://{name}" , { list: undefined }),
73
- async (uri , { name }) => ({
78
+ {
79
+ title: " Greeting Resource" , // Display name for UI
80
+ description: " Dynamic greeting generator"
81
+ },
82
+ async (uri , params ) => ({
74
83
contents: [{
75
84
uri: uri .href ,
76
- text: ` Hello, ${name }! `
85
+ text: ` Hello, ${params . name }! `
77
86
}]
78
87
})
79
88
);
@@ -100,8 +109,9 @@ The McpServer is your core interface to the MCP protocol. It handles connection
100
109
101
110
``` typescript
102
111
const server = new McpServer ({
103
- name: " My App" ,
104
- version: " 1.0.0"
112
+ name: " my-app" , // Unique identifier for your server
113
+ version: " 1.0.0" , // Server version
114
+ title: " My Application" // Optional display name for UI
105
115
});
106
116
```
107
117
@@ -111,9 +121,14 @@ Resources are how you expose data to LLMs. They're similar to GET endpoints in a
111
121
112
122
``` typescript
113
123
// Static resource
114
- server .resource (
124
+ server .registerResource (
115
125
" config" ,
116
126
" config://app" ,
127
+ {
128
+ title: " Application Config" ,
129
+ description: " Application configuration data" ,
130
+ mimeType: " text/plain"
131
+ },
117
132
async (uri ) => ({
118
133
contents: [{
119
134
uri: uri .href ,
@@ -123,13 +138,17 @@ server.resource(
123
138
);
124
139
125
140
// Dynamic resource with parameters
126
- server .resource (
141
+ server .registerResource (
127
142
" user-profile" ,
128
143
new ResourceTemplate (" users://{userId}/profile" , { list: undefined }),
129
- async (uri , { userId }) => ({
144
+ {
145
+ title: " User Profile" ,
146
+ description: " User profile information"
147
+ },
148
+ async (uri , params ) => ({
130
149
contents: [{
131
150
uri: uri .href ,
132
- text: ` Profile data for user ${userId } `
151
+ text: ` Profile data for user ${params . userId } `
133
152
}]
134
153
})
135
154
);
@@ -141,11 +160,15 @@ Tools let LLMs take actions through your server. Unlike resources, tools are exp
141
160
142
161
``` typescript
143
162
// Simple tool with parameters
144
- server .tool (
163
+ server .registerTool (
145
164
" calculate-bmi" ,
146
165
{
147
- weightKg: z .number (),
148
- heightM: z .number ()
166
+ title: " BMI Calculator" ,
167
+ description: " Calculate Body Mass Index" ,
168
+ inputSchema: {
169
+ weightKg: z .number (),
170
+ heightM: z .number ()
171
+ }
149
172
},
150
173
async ({ weightKg , heightM }) => ({
151
174
content: [{
@@ -156,9 +179,13 @@ server.tool(
156
179
);
157
180
158
181
// Async tool with external API call
159
- server .tool (
182
+ server .registerTool (
160
183
" fetch-weather" ,
161
- { city: z .string () },
184
+ {
185
+ title: " Weather Fetcher" ,
186
+ description: " Get weather data for a city" ,
187
+ inputSchema: { city: z .string () }
188
+ },
162
189
async ({ city }) => {
163
190
const response = await fetch (` https://api.weather.com/${city } ` );
164
191
const data = await response .text ();
@@ -174,9 +201,13 @@ server.tool(
174
201
Prompts are reusable templates that help LLMs interact with your server effectively:
175
202
176
203
``` typescript
177
- server .prompt (
204
+ server .registerPrompt (
178
205
" review-code" ,
179
- { code: z .string () },
206
+ {
207
+ title: " Code Review" ,
208
+ description: " Review code for best practices and potential issues" ,
209
+ arguments: { code: z .string () }
210
+ },
180
211
({ code }) => ({
181
212
messages: [{
182
213
role: " user" ,
@@ -189,6 +220,22 @@ server.prompt(
189
220
);
190
221
```
191
222
223
+ ### Display Names and Metadata
224
+
225
+ All resources, tools, and prompts support an optional ` title ` field for better UI presentation. The ` title ` is used as a display name, while ` name ` remains the unique identifier.
226
+
227
+ ** Note:** The ` register* ` methods (` registerTool ` , ` registerPrompt ` , ` registerResource ` ) are the recommended approach for new code. The older methods (` tool ` , ` prompt ` , ` resource ` ) remain available for backwards compatibility.
228
+
229
+
230
+ When building clients, use the provided utility to get the appropriate display name:
231
+
232
+ ``` typescript
233
+ import { getDisplayName } from " @modelcontextprotocol/sdk/shared/metadataUtils.js" ;
234
+
235
+ // Falls back to 'name' if 'title' is not provided
236
+ const displayName = getDisplayName (tool ); // Returns title if available, otherwise name
237
+ ```
238
+
192
239
## Running Your Server
193
240
194
241
MCP servers in TypeScript need to be connected to a transport to communicate with clients. How you start the server depends on the choice of transport:
@@ -401,32 +448,45 @@ import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mc
401
448
import { z } from " zod" ;
402
449
403
450
const server = new McpServer ({
404
- name: " Echo" ,
405
- version: " 1.0.0"
451
+ name: " echo-server" ,
452
+ version: " 1.0.0" ,
453
+ title: " Echo Server"
406
454
});
407
455
408
- server .resource (
456
+ server .registerResource (
409
457
" echo" ,
410
458
new ResourceTemplate (" echo://{message}" , { list: undefined }),
411
- async (uri , { message }) => ({
459
+ {
460
+ title: " Echo Resource" ,
461
+ description: " Echoes back messages as resources"
462
+ },
463
+ async (uri , params ) => ({
412
464
contents: [{
413
465
uri: uri .href ,
414
- text: ` Resource echo: ${message } `
466
+ text: ` Resource echo: ${params . message } `
415
467
}]
416
468
})
417
469
);
418
470
419
- server .tool (
471
+ server .registerTool (
420
472
" echo" ,
421
- { message: z .string () },
473
+ {
474
+ title: " Echo Tool" ,
475
+ description: " Echoes back the provided message" ,
476
+ inputSchema: { message: z .string () }
477
+ },
422
478
async ({ message }) => ({
423
479
content: [{ type: " text" , text: ` Tool echo: ${message } ` }]
424
480
})
425
481
);
426
482
427
- server .prompt (
483
+ server .registerPrompt (
428
484
" echo" ,
429
- { message: z .string () },
485
+ {
486
+ title: " Echo Prompt" ,
487
+ description: " Creates a prompt to process a message" ,
488
+ arguments: { message: z .string () }
489
+ },
430
490
({ message }) => ({
431
491
messages: [{
432
492
role: " user" ,
@@ -450,8 +510,9 @@ import { promisify } from "util";
450
510
import { z } from " zod" ;
451
511
452
512
const server = new McpServer ({
453
- name: " SQLite Explorer" ,
454
- version: " 1.0.0"
513
+ name: " sqlite-explorer" ,
514
+ version: " 1.0.0" ,
515
+ title: " SQLite Explorer"
455
516
});
456
517
457
518
// Helper to create DB connection
@@ -463,9 +524,14 @@ const getDb = () => {
463
524
};
464
525
};
465
526
466
- server .resource (
527
+ server .registerResource (
467
528
" schema" ,
468
529
" schema://main" ,
530
+ {
531
+ title: " Database Schema" ,
532
+ description: " SQLite database schema" ,
533
+ mimeType: " text/plain"
534
+ },
469
535
async (uri ) => {
470
536
const db = getDb ();
471
537
try {
@@ -484,9 +550,13 @@ server.resource(
484
550
}
485
551
);
486
552
487
- server .tool (
553
+ server .registerTool (
488
554
" query" ,
489
- { sql: z .string () },
555
+ {
556
+ title: " SQL Query" ,
557
+ description: " Execute SQL queries on the database" ,
558
+ inputSchema: { sql: z .string () }
559
+ },
490
560
async ({ sql }) => {
491
561
const db = getDb ();
492
562
try {
0 commit comments