Skip to content

Commit 4d03b24

Browse files
committed
add title
1 parent e7284d2 commit 4d03b24

File tree

7 files changed

+599
-171
lines changed

7 files changed

+599
-171
lines changed

README.md

Lines changed: 104 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,35 @@ import { z } from "zod";
5454

5555
// Create an MCP server
5656
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
5960
});
6061

6162
// 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+
},
6469
async ({ a, b }) => ({
6570
content: [{ type: "text", text: String(a + b) }]
6671
})
6772
);
6873

6974
// Add a dynamic greeting resource
70-
server.resource(
75+
server.registerResource(
7176
"greeting",
7277
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) => ({
7483
contents: [{
7584
uri: uri.href,
76-
text: `Hello, ${name}!`
85+
text: `Hello, ${params.name}!`
7786
}]
7887
})
7988
);
@@ -100,8 +109,9 @@ The McpServer is your core interface to the MCP protocol. It handles connection
100109

101110
```typescript
102111
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
105115
});
106116
```
107117

@@ -111,9 +121,14 @@ Resources are how you expose data to LLMs. They're similar to GET endpoints in a
111121

112122
```typescript
113123
// Static resource
114-
server.resource(
124+
server.registerResource(
115125
"config",
116126
"config://app",
127+
{
128+
title: "Application Config",
129+
description: "Application configuration data",
130+
mimeType: "text/plain"
131+
},
117132
async (uri) => ({
118133
contents: [{
119134
uri: uri.href,
@@ -123,13 +138,17 @@ server.resource(
123138
);
124139

125140
// Dynamic resource with parameters
126-
server.resource(
141+
server.registerResource(
127142
"user-profile",
128143
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) => ({
130149
contents: [{
131150
uri: uri.href,
132-
text: `Profile data for user ${userId}`
151+
text: `Profile data for user ${params.userId}`
133152
}]
134153
})
135154
);
@@ -141,11 +160,15 @@ Tools let LLMs take actions through your server. Unlike resources, tools are exp
141160

142161
```typescript
143162
// Simple tool with parameters
144-
server.tool(
163+
server.registerTool(
145164
"calculate-bmi",
146165
{
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+
}
149172
},
150173
async ({ weightKg, heightM }) => ({
151174
content: [{
@@ -156,9 +179,13 @@ server.tool(
156179
);
157180

158181
// Async tool with external API call
159-
server.tool(
182+
server.registerTool(
160183
"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+
},
162189
async ({ city }) => {
163190
const response = await fetch(`https://api.weather.com/${city}`);
164191
const data = await response.text();
@@ -174,9 +201,13 @@ server.tool(
174201
Prompts are reusable templates that help LLMs interact with your server effectively:
175202

176203
```typescript
177-
server.prompt(
204+
server.registerPrompt(
178205
"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+
},
180211
({ code }) => ({
181212
messages: [{
182213
role: "user",
@@ -189,6 +220,22 @@ server.prompt(
189220
);
190221
```
191222

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+
192239
## Running Your Server
193240

194241
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
401448
import { z } from "zod";
402449

403450
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"
406454
});
407455

408-
server.resource(
456+
server.registerResource(
409457
"echo",
410458
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) => ({
412464
contents: [{
413465
uri: uri.href,
414-
text: `Resource echo: ${message}`
466+
text: `Resource echo: ${params.message}`
415467
}]
416468
})
417469
);
418470

419-
server.tool(
471+
server.registerTool(
420472
"echo",
421-
{ message: z.string() },
473+
{
474+
title: "Echo Tool",
475+
description: "Echoes back the provided message",
476+
inputSchema: { message: z.string() }
477+
},
422478
async ({ message }) => ({
423479
content: [{ type: "text", text: `Tool echo: ${message}` }]
424480
})
425481
);
426482

427-
server.prompt(
483+
server.registerPrompt(
428484
"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+
},
430490
({ message }) => ({
431491
messages: [{
432492
role: "user",
@@ -450,8 +510,9 @@ import { promisify } from "util";
450510
import { z } from "zod";
451511

452512
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"
455516
});
456517

457518
// Helper to create DB connection
@@ -463,9 +524,14 @@ const getDb = () => {
463524
};
464525
};
465526

466-
server.resource(
527+
server.registerResource(
467528
"schema",
468529
"schema://main",
530+
{
531+
title: "Database Schema",
532+
description: "SQLite database schema",
533+
mimeType: "text/plain"
534+
},
469535
async (uri) => {
470536
const db = getDb();
471537
try {
@@ -484,9 +550,13 @@ server.resource(
484550
}
485551
);
486552

487-
server.tool(
553+
server.registerTool(
488554
"query",
489-
{ sql: z.string() },
555+
{
556+
title: "SQL Query",
557+
description: "Execute SQL queries on the database",
558+
inputSchema: { sql: z.string() }
559+
},
490560
async ({ sql }) => {
491561
const db = getDb();
492562
try {

src/examples/client/simpleStreamableHttp.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
LoggingMessageNotificationSchema,
1616
ResourceListChangedNotificationSchema,
1717
} from '../../types.js';
18+
import { getDisplayName } from '../../shared/metadataUtils.js';
1819

1920
// Create readline interface for user input
2021
const readline = createInterface({
@@ -317,7 +318,7 @@ async function listTools(): Promise<void> {
317318
console.log(' No tools available');
318319
} else {
319320
for (const tool of toolsResult.tools) {
320-
console.log(` - ${tool.name}: ${tool.description}`);
321+
console.log(` - ${getDisplayName(tool)}: ${tool.description}`);
321322
}
322323
}
323324
} catch (error) {
@@ -429,7 +430,7 @@ async function listPrompts(): Promise<void> {
429430
console.log(' No prompts available');
430431
} else {
431432
for (const prompt of promptsResult.prompts) {
432-
console.log(` - ${prompt.name}: ${prompt.description}`);
433+
console.log(` - ${getDisplayName(prompt)}: ${prompt.description}`);
433434
}
434435
}
435436
} catch (error) {
@@ -480,7 +481,7 @@ async function listResources(): Promise<void> {
480481
console.log(' No resources available');
481482
} else {
482483
for (const resource of resourcesResult.resources) {
483-
console.log(` - ${resource.name}: ${resource.uri}`);
484+
console.log(` - ${getDisplayName(resource)}: ${resource.uri}`);
484485
}
485486
}
486487
} catch (error) {

src/examples/server/simpleStreamableHttp.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,18 @@ const getServer = () => {
1818
const server = new McpServer({
1919
name: 'simple-streamable-http-server',
2020
version: '1.0.0',
21+
title: 'Simple Streamable HTTP Server', // Display name for UI
2122
}, { capabilities: { logging: {} } });
2223

2324
// Register a simple tool that returns a greeting
24-
server.tool(
25+
server.registerTool(
2526
'greet',
26-
'A simple greeting tool',
2727
{
28-
name: z.string().describe('Name to greet'),
28+
title: 'Greeting Tool', // Display name for UI
29+
description: 'A simple greeting tool',
30+
inputSchema: {
31+
name: z.string().describe('Name to greet'),
32+
},
2933
},
3034
async ({ name }): Promise<CallToolResult> => {
3135
return {
@@ -84,12 +88,15 @@ const getServer = () => {
8488
}
8589
);
8690

87-
// Register a simple prompt
88-
server.prompt(
91+
// Register a simple prompt with title
92+
server.registerPrompt(
8993
'greeting-template',
90-
'A simple greeting prompt template',
9194
{
92-
name: z.string().describe('Name to include in greeting'),
95+
title: 'Greeting Template', // Display name for UI
96+
description: 'A simple greeting prompt template',
97+
arguments: {
98+
name: z.string().describe('Name to include in greeting'),
99+
},
93100
},
94101
async ({ name }): Promise<GetPromptResult> => {
95102
return {
@@ -148,10 +155,14 @@ const getServer = () => {
148155
);
149156

150157
// Create a simple resource at a fixed URI
151-
server.resource(
158+
server.registerResource(
152159
'greeting-resource',
153160
'https://example.com/greetings/default',
154-
{ mimeType: 'text/plain' },
161+
{
162+
title: 'Default Greeting', // Display name for UI
163+
description: 'A simple greeting resource',
164+
mimeType: 'text/plain'
165+
},
155166
async (): Promise<ReadResourceResult> => {
156167
return {
157168
contents: [

0 commit comments

Comments
 (0)