Skip to content

Commit 5b5e192

Browse files
authored
Merge branch 'main' into main
2 parents 18d266b + f822c12 commit 5b5e192

File tree

9 files changed

+1339
-239
lines changed

9 files changed

+1339
-239
lines changed

README.md

Lines changed: 146 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,22 +54,30 @@ import { z } from "zod";
5454

5555
// Create an MCP server
5656
const server = new McpServer({
57-
name: "Demo",
57+
name: "demo-server",
5858
version: "1.0.0"
5959
});
6060

6161
// Add an addition tool
62-
server.tool("add",
63-
{ a: z.number(), b: z.number() },
62+
server.registerTool("add",
63+
{
64+
title: "Addition Tool",
65+
description: "Add two numbers",
66+
inputSchema: { a: z.number(), b: z.number() }
67+
},
6468
async ({ a, b }) => ({
6569
content: [{ type: "text", text: String(a + b) }]
6670
})
6771
);
6872

6973
// Add a dynamic greeting resource
70-
server.resource(
74+
server.registerResource(
7175
"greeting",
7276
new ResourceTemplate("greeting://{name}", { list: undefined }),
77+
{
78+
title: "Greeting Resource", // Display name for UI
79+
description: "Dynamic greeting generator"
80+
},
7381
async (uri, { name }) => ({
7482
contents: [{
7583
uri: uri.href,
@@ -100,7 +108,7 @@ The McpServer is your core interface to the MCP protocol. It handles connection
100108

101109
```typescript
102110
const server = new McpServer({
103-
name: "My App",
111+
name: "my-app",
104112
version: "1.0.0"
105113
});
106114
```
@@ -111,9 +119,14 @@ Resources are how you expose data to LLMs. They're similar to GET endpoints in a
111119

112120
```typescript
113121
// Static resource
114-
server.resource(
122+
server.registerResource(
115123
"config",
116124
"config://app",
125+
{
126+
title: "Application Config",
127+
description: "Application configuration data",
128+
mimeType: "text/plain"
129+
},
117130
async (uri) => ({
118131
contents: [{
119132
uri: uri.href,
@@ -123,9 +136,13 @@ server.resource(
123136
);
124137

125138
// Dynamic resource with parameters
126-
server.resource(
139+
server.registerResource(
127140
"user-profile",
128141
new ResourceTemplate("users://{userId}/profile", { list: undefined }),
142+
{
143+
title: "User Profile",
144+
description: "User profile information"
145+
},
129146
async (uri, { userId }) => ({
130147
contents: [{
131148
uri: uri.href,
@@ -141,11 +158,15 @@ Tools let LLMs take actions through your server. Unlike resources, tools are exp
141158

142159
```typescript
143160
// Simple tool with parameters
144-
server.tool(
161+
server.registerTool(
145162
"calculate-bmi",
146163
{
147-
weightKg: z.number(),
148-
heightM: z.number()
164+
title: "BMI Calculator",
165+
description: "Calculate Body Mass Index",
166+
inputSchema: {
167+
weightKg: z.number(),
168+
heightM: z.number()
169+
}
149170
},
150171
async ({ weightKg, heightM }) => ({
151172
content: [{
@@ -156,9 +177,13 @@ server.tool(
156177
);
157178

158179
// Async tool with external API call
159-
server.tool(
180+
server.registerTool(
160181
"fetch-weather",
161-
{ city: z.string() },
182+
{
183+
title: "Weather Fetcher",
184+
description: "Get weather data for a city",
185+
inputSchema: { city: z.string() }
186+
},
162187
async ({ city }) => {
163188
const response = await fetch(`https://api.weather.com/${city}`);
164189
const data = await response.text();
@@ -167,16 +192,54 @@ server.tool(
167192
};
168193
}
169194
);
195+
196+
// Tool that returns ResourceLinks
197+
server.registerTool(
198+
"list-files",
199+
{
200+
title: "List Files",
201+
description: "List project files",
202+
inputSchema: { pattern: z.string() }
203+
},
204+
async ({ pattern }) => ({
205+
content: [
206+
{ type: "text", text: `Found files matching "${pattern}":` },
207+
// ResourceLinks let tools return references without file content
208+
{
209+
type: "resource_link",
210+
uri: "file:///project/README.md",
211+
name: "README.md",
212+
mimeType: "text/markdown",
213+
description: 'A README file'
214+
},
215+
{
216+
type: "resource_link",
217+
uri: "file:///project/src/index.ts",
218+
name: "index.ts",
219+
mimeType: "text/typescript",
220+
description: 'An index file'
221+
}
222+
]
223+
})
224+
);
170225
```
171226

227+
#### ResourceLinks
228+
229+
Tools can return `ResourceLink` objects to reference resources without embedding their full content. This is essential for performance when dealing with large files or many resources - clients can then selectively read only the resources they need using the provided URIs.
230+
172231
### Prompts
173232

174233
Prompts are reusable templates that help LLMs interact with your server effectively:
175234

176235
```typescript
177-
server.prompt(
236+
server.registerPrompt(
178237
"review-code",
179-
{ code: z.string() },
238+
{
239+
title: "Code Review",
240+
description: "Review code for best practices and potential issues",
241+
arguments: { code: z.string() }
242+
},
180243
({ code }) => ({
181244
messages: [{
182245
role: "user",
@@ -189,6 +252,44 @@ server.prompt(
189252
);
190253
```
191254

255+
### Display Names and Metadata
256+
257+
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.
258+
259+
**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.
260+
261+
#### Title Precedence for Tools
262+
263+
For tools specifically, there are two ways to specify a title:
264+
- `title` field in the tool configuration
265+
- `annotations.title` field (when using the older `tool()` method with annotations)
266+
267+
The precedence order is: `title``annotations.title``name`
268+
269+
```typescript
270+
// Using registerTool (recommended)
271+
server.registerTool("my_tool", {
272+
title: "My Tool", // This title takes precedence
273+
annotations: {
274+
title: "Annotation Title" // This is ignored if title is set
275+
}
276+
}, handler);
277+
278+
// Using tool with annotations (older API)
279+
server.tool("my_tool", "description", {
280+
title: "Annotation Title" // This is used as title
281+
}, handler);
282+
```
283+
284+
When building clients, use the provided utility to get the appropriate display name:
285+
286+
```typescript
287+
import { getDisplayName } from "@modelcontextprotocol/sdk/shared/metadataUtils.js";
288+
289+
// Automatically handles the precedence: title → annotations.title → name
290+
const displayName = getDisplayName(tool);
291+
```
292+
192293
## Running Your Server
193294

194295
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:
@@ -416,13 +517,17 @@ import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mc
416517
import { z } from "zod";
417518

418519
const server = new McpServer({
419-
name: "Echo",
520+
name: "echo-server",
420521
version: "1.0.0"
421522
});
422523

423-
server.resource(
524+
server.registerResource(
424525
"echo",
425526
new ResourceTemplate("echo://{message}", { list: undefined }),
527+
{
528+
title: "Echo Resource",
529+
description: "Echoes back messages as resources"
530+
},
426531
async (uri, { message }) => ({
427532
contents: [{
428533
uri: uri.href,
@@ -431,17 +536,25 @@ server.resource(
431536
})
432537
);
433538

434-
server.tool(
539+
server.registerTool(
435540
"echo",
436-
{ message: z.string() },
541+
{
542+
title: "Echo Tool",
543+
description: "Echoes back the provided message",
544+
inputSchema: { message: z.string() }
545+
},
437546
async ({ message }) => ({
438547
content: [{ type: "text", text: `Tool echo: ${message}` }]
439548
})
440549
);
441550

442-
server.prompt(
551+
server.registerPrompt(
443552
"echo",
444-
{ message: z.string() },
553+
{
554+
title: "Echo Prompt",
555+
description: "Creates a prompt to process a message",
556+
argsSchema: { message: z.string() }
557+
},
445558
({ message }) => ({
446559
messages: [{
447560
role: "user",
@@ -465,7 +578,7 @@ import { promisify } from "util";
465578
import { z } from "zod";
466579

467580
const server = new McpServer({
468-
name: "SQLite Explorer",
581+
name: "sqlite-explorer",
469582
version: "1.0.0"
470583
});
471584

@@ -478,9 +591,14 @@ const getDb = () => {
478591
};
479592
};
480593

481-
server.resource(
594+
server.registerResource(
482595
"schema",
483596
"schema://main",
597+
{
598+
title: "Database Schema",
599+
description: "SQLite database schema",
600+
mimeType: "text/plain"
601+
},
484602
async (uri) => {
485603
const db = getDb();
486604
try {
@@ -499,9 +617,13 @@ server.resource(
499617
}
500618
);
501619

502-
server.tool(
620+
server.registerTool(
503621
"query",
504-
{ sql: z.string() },
622+
{
623+
title: "SQL Query",
624+
description: "Execute SQL queries on the database",
625+
inputSchema: { sql: z.string() }
626+
},
505627
async ({ sql }) => {
506628
const db = getDb();
507629
try {

0 commit comments

Comments
 (0)