add title
This commit is contained in:
parent
e7284d29c8
commit
4d03b243e3
1 changed files with 599 additions and 171 deletions
138
README.md
138
README.md
|
|
@ -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 {
|
||||
|
|
|
|||
Loading…
Reference in a new issue