我發現官方網站上的範例其實有點過時, 舉註冊 tool 的方式為例, 可以看到在官方 github readme 已經說建議用 registerTool 來做:
// Using registerTool (recommended)
server.registerTool("my_tool", {
title: "My Tool", // This title takes precedence
annotations: {
title: "Annotation Title" // This is ignored if title is set
}
}, handler);
// Using tool with annotations (older API)
server.tool("my_tool", "description", {
title: "Annotation Title" // This is used as title
}, handler);
我們用註冊 create_journal
為例比較三者寫法:
server.tool(
'create_journal',
'Create a new journal',
{
content: z.string(),
date: z.string(),
},
async ({ content, date }) => {
journals.push({ content, date });
return { success: true };
},
);
ref: https://github.com/JHIH-LEI/simple-journal-mcp/blob/main/src/index.ts
server.registerTool(
'create_journal',
{
description: 'Create a new journal',
inputSchema: {
content: z.string(),
date: z.string(),
},
},
async ({ content, date }) => {
journals.push({ content, date });
return { success: true };
},
);
這裡用 server.setRequestHandler 來攔截特定 request schema(如 ListToolsRequestSchema),並回傳工具清單。
後面還需要自己定義每一個工具對應的 handler 是什麼, 會藉由攔截 CallToolRequestSchema 做。
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'create_journal',
description: 'Create a new journal entry',
inputSchema: {
type: 'object',
properties: {
content: {
type: 'string',
description: 'Content of the journal entry',
},
date: {
type: 'string',
description: 'Date in YYYY-MM-DD format',
},
},
required: ['content', 'date'],
},
},
]
}
}
後來我把 server.tool 的寫法都暫且改成跟開源專案看到的一致, 如果想看完整的原始碼可至:
https://github.com/JHIH-LEI/simple-journal-mcp/blob/main/src/index.ts