add title

This commit is contained in:
ihrpr 2025-06-15 20:42:25 +01:00
commit 4d03b243e3
No known key found for this signature in database

138
README.md
View file

@ -54,26 +54,35 @@ import { z } from "zod";
// Create an MCP server
const server = new McpServer({
name: "Demo",
version: "1.0.0"
name: "demo-server",
version: "1.0.0",
title: "Demo Server" // Optional display name
});
// Add an addition tool
server.tool("add",
{ a: z.number(), b: z.number() },
server.registerTool("add",
{
title: "Addition Tool",
description: "Add two numbers",
inputSchema: { a: z.number(), b: z.number() }
},
async ({ a, b }) => ({
content: [{ type: "text", text: String(a + b) }]
})
);
// Add a dynamic greeting resource
server.resource(
server.registerResource(
"greeting",
new ResourceTemplate("greeting://{name}", { list: undefined }),
async (uri, { name }) => ({
{
title: "Greeting Resource", // Display name for UI
description: "Dynamic greeting generator"
},
async (uri, params) => ({
contents: [{
uri: uri.href,
text: `Hello, ${name}!`
text: `Hello, ${params.name}!`
}]
})
);
@ -100,8 +109,9 @@ The McpServer is your core interface to the MCP protocol. It handles connection
```typescript
const server = new McpServer({
name: "My App",
version: "1.0.0"
name: "my-app", // Unique identifier for your server
version: "1.0.0", // Server version
title: "My Application" // Optional display name for UI
});
```
@ -111,9 +121,14 @@ Resources are how you expose data to LLMs. They're similar to GET endpoints in a
```typescript
// Static resource
server.resource(
server.registerResource(
"config",
"config://app",
{
title: "Application Config",
description: "Application configuration data",
mimeType: "text/plain"
},
async (uri) => ({
contents: [{
uri: uri.href,
@ -123,13 +138,17 @@ server.resource(
);
// Dynamic resource with parameters
server.resource(
server.registerResource(
"user-profile",
new ResourceTemplate("users://{userId}/profile", { list: undefined }),
async (uri, { userId }) => ({
{
title: "User Profile",
description: "User profile information"
},
async (uri, params) => ({
contents: [{
uri: uri.href,
text: `Profile data for user ${userId}`
text: `Profile data for user ${params.userId}`
}]
})
);
@ -141,11 +160,15 @@ Tools let LLMs take actions through your server. Unlike resources, tools are exp
```typescript
// Simple tool with parameters
server.tool(
server.registerTool(
"calculate-bmi",
{
weightKg: z.number(),
heightM: z.number()
title: "BMI Calculator",
description: "Calculate Body Mass Index",
inputSchema: {
weightKg: z.number(),
heightM: z.number()
}
},
async ({ weightKg, heightM }) => ({
content: [{
@ -156,9 +179,13 @@ server.tool(
);
// Async tool with external API call
server.tool(
server.registerTool(
"fetch-weather",
{ city: z.string() },
{
title: "Weather Fetcher",
description: "Get weather data for a city",
inputSchema: { city: z.string() }
},
async ({ city }) => {
const response = await fetch(`https://api.weather.com/${city}`);
const data = await response.text();
@ -174,9 +201,13 @@ server.tool(
Prompts are reusable templates that help LLMs interact with your server effectively:
```typescript
server.prompt(
server.registerPrompt(
"review-code",
{ code: z.string() },
{
title: "Code Review",
description: "Review code for best practices and potential issues",
arguments: { code: z.string() }
},
({ code }) => ({
messages: [{
role: "user",
@ -189,6 +220,22 @@ server.prompt(
);
```
### Display Names and Metadata
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.
**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.
When building clients, use the provided utility to get the appropriate display name:
```typescript
import { getDisplayName } from "@modelcontextprotocol/sdk/shared/metadataUtils.js";
// Falls back to 'name' if 'title' is not provided
const displayName = getDisplayName(tool); // Returns title if available, otherwise name
```
## Running Your Server
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
import { z } from "zod";
const server = new McpServer({
name: "Echo",
version: "1.0.0"
name: "echo-server",
version: "1.0.0",
title: "Echo Server"
});
server.resource(
server.registerResource(
"echo",
new ResourceTemplate("echo://{message}", { list: undefined }),
async (uri, { message }) => ({
{
title: "Echo Resource",
description: "Echoes back messages as resources"
},
async (uri, params) => ({
contents: [{
uri: uri.href,
text: `Resource echo: ${message}`
text: `Resource echo: ${params.message}`
}]
})
);
server.tool(
server.registerTool(
"echo",
{ message: z.string() },
{
title: "Echo Tool",
description: "Echoes back the provided message",
inputSchema: { message: z.string() }
},
async ({ message }) => ({
content: [{ type: "text", text: `Tool echo: ${message}` }]
})
);
server.prompt(
server.registerPrompt(
"echo",
{ message: z.string() },
{
title: "Echo Prompt",
description: "Creates a prompt to process a message",
arguments: { message: z.string() }
},
({ message }) => ({
messages: [{
role: "user",
@ -450,8 +510,9 @@ import { promisify } from "util";
import { z } from "zod";
const server = new McpServer({
name: "SQLite Explorer",
version: "1.0.0"
name: "sqlite-explorer",
version: "1.0.0",
title: "SQLite Explorer"
});
// Helper to create DB connection
@ -463,9 +524,14 @@ const getDb = () => {
};
};
server.resource(
server.registerResource(
"schema",
"schema://main",
{
title: "Database Schema",
description: "SQLite database schema",
mimeType: "text/plain"
},
async (uri) => {
const db = getDb();
try {
@ -484,9 +550,13 @@ server.resource(
}
);
server.tool(
server.registerTool(
"query",
{ sql: z.string() },
{
title: "SQL Query",
description: "Execute SQL queries on the database",
inputSchema: { sql: z.string() }
},
async ({ sql }) => {
const db = getDb();
try {