MCP服务器开发指南 (3)
这是我们关于构建MCP服务器的四部分教程中的第三部分。在第1部分中,我们创建了一个带有基本资源的MCP服务器,并在第2部分中添加了资源模板并改进了代码组织。现在我们将进一步重构代码并添加提示功能。
1、什么是MCP提示?
MCP中的提示是服务器提供的结构化模板,用于标准化与语言模型的交互。与提供数据的资源或执行操作的工具不同,提示定义可重用的消息序列和工作流程,以一致且可预测的方式指导LLM行为。它们可以接受参数来自定义交互,同时保持标准化结构。
如果你曾经研究过提示工程,可能对提示有一个很好的理解。在MCP服务器中创建这些提示使我们可以创建一个空间来存储我们发现最有用的提示,以便轻松重用甚至共享。想象一下去餐馆,提示就像你可以从菜单上选择并向服务员提供的项目。有时,你可以通过要求添加或删除某些项目或将结果烹饪成特定方式来定制菜单项。这样提供的提示具有类似的功能。
2、为什么使用提示?
提示有助于为LLM交互创建一致且可重用的模式。以下是一些实际示例:
代码审查提示:
"name" -> code-review
请审查以下{{language}}代码,重点关注{{focusAreas}}:
```{{language}}
{{codeBlock}}
> 用户:请审查以下Python代码,重点关注安全性和性能:
> ```Python
> … 代码
> ```
数据分析提示:
"name" -> analyze-sales-data
分析{{timeframe}}销售数据,重点关注{{metrics}}
> 用户:分析第一季度销售数据,重点关注收入和增长
内容生成提示:
"name" -> generate-email
为{{context}}生成{{tone}} {{type}}邮件
> 用户:为退款请求生成正式支持邮件给Bob’s Barbecue LLC。
3、代码组织
在第2部分中,我们将处理程序代码从index.ts抽象出来,并放入handlers.ts文件。此文件可能会变得太大。我们应该将处理程序代码组织到专注的模块中:
// src/resources.ts
export const resources = [
{
uri: "hello://world",
name: "Hello World Message",
description: "A simple greeting message",
mimeType: "text/plain",
},
];
export const resourceHandlers = {
"hello://world": () => ({
contents: [
{
uri: "hello://world",
text: "Hello, World! This is my first MCP resource.",
},
],
}),
};
// src/resource-templates.ts
export const resourceTemplates = [
{
uriTemplate: "greetings://{name}",
name: "Personal Greeting",
description: "A personalized greeting message",
mimeType: "text/plain",
},
];
const greetingExp = /^greetings:\/\/(.+)$/;
const greetingMatchHandler =
(uri: string, matchText: RegExpMatchArray) => () => {
const name = decodeURIComponent(matchText[1]);
return {
contents: [
{
uri,
text: `Hello, ${name}! Welcome to MCP.`,
},
],
};
};
export const getResourceTemplate = (uri: string) => {
const greetingMatch = uri.match(greetingExp);
if (greetingMatch) return greetingMatchHandler(uri, greetingMatch);
};
更新处理器:
// src/handlers.ts
import {
ListResourcesRequestSchema,
ListResourceTemplatesRequestSchema,
ReadResourceRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { type Server } from "@modelcontextprotocol/sdk/server/index.js";
import { resourceHandlers, resources } from "./resources.js";
import {
getResourceTemplate,
resourceTemplates,
} from "./resource-templates.js";
export const setupHandlers = (server: Server): void => {
// List available resources when clients request them
server.setRequestHandler(
ListResourcesRequestSchema,
() => ({ resources }),
);
// Resource Templates
server.setRequestHandler(ListResourceTemplatesRequestSchema, () => ({
resourceTemplates,
}));
// Return resource content when clients request it
server.setRequestHandler(ReadResourceRequestSchema, (request) => {
const { uri } = request.params ?? {};
const resourceHandler =
resourceHandlers[uri as keyof typeof resourceHandlers];
if (resourceHandler) return resourceHandler();
const resourceTemplateHandler = getResourceTemplate(uri);
if (resourceTemplateHandler) return resourceTemplateHandler();
throw new Error("Resource not found");
});
};
4、添加提示
现在添加我们的新提示功能:
// src/prompts.ts
export const prompts = {
"create-greeting": {
name: "create-greeting",
description: "Generate a customized greeting message",
arguments: [
{
name: "name",
description: "Name of the person to greet",
required: true,
},
{
name: "style",
description: "The style of greeting, such a formal, excited, or casual. If not specified casual will be used"
}
],
},
};
export const promptHandlers = {
"create-greeting": ({ name, style = "casual" }: { name: string, style?: string }) => {
return {
messages: [
{
role: "user",
content: {
type: "text",
text: `Please generate a greeting in ${style} style to ${name}.`,
},
},
],
};
},
};
将新的提示处理程序添加到处理程序文件中:
// src/handlers.ts
import {
GetPromptRequestSchema,
ListPromptsRequestSchema,
// ... other imports
} from "@modelcontextprotocol/sdk/types.js";
// ... other imports
import { promptHandlers, prompts } from "./prompts.js";
export const setupHandlers = (server: Server): void => {
// ... Other resource handlers here
// Prompts
server.setRequestHandler(ListPromptsRequestSchema, () => ({
prompts: Object.values(prompts),
}));
server.setRequestHandler(GetPromptRequestSchema, (request) => {
const { name, arguments: args } = request.params;
const promptHandler = promptHandlers[name as keyof typeof promptHandlers];
if (promptHandler) return promptHandler(args as { name: string, style?: string });
throw new Error("Prompt not found");
});
};
最后,我们需要更新服务器初始化:
// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { setupHandlers } from "./handlers.js";
const server = new Server(
{
name: "hello-mcp",
version: "1.0.0",
},
{
capabilities: {
prompts: {}, // <-- Add prompts
resources: {},
},
},
);
setupHandlers(server);
// ... remaining code
模块组织:
- 资源和模板已放在各自的模块中
- 提示被清晰地分离
- 处理程序现在充当路由层
提示结构:
- 每个提示都有名称、描述以及如果需要的话的参数
- 参数描述了提示的预期输入
- 处理程序生成用于提示目标AI的结构化消息(或多条消息)
消息序列:
- 提示返回消息数组
- 消息有角色('user' 或 'assistant')
- 内容可以包括初始请求和多步工作流中的后续响应(注意,多步工作流目前支持有限)
5、使用检查器测试
启动检查器:
npx @modelcontextprotocol/inspector node build/index.js
测试提示:
- 点击“提示”标签
- 找到“create-greeting”
- 尝试不同的参数组合:
name: "Alice", style: "excited"
{
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "Please generate a greeting in excited style to Alice."
}
}
]
}
6、使用Claude桌面测试
尝试这些示例:
基本提示:
1: 打开Claude桌面
假设条件:
- 您已经构建了您的服务器(
npx tsc
)并且设置了Claude桌面以使用它。
2: 类似于我们添加资源的方式,点击“从MCP附加”
3: 在弹出窗口中,点击“选择集成”,然后从“hello-mcp”下的列表中选择“create-greeting”提示
4: 目前,只需测试名称。在名称字段中键入类似“John”的内容,然后点击“提交”
5: 您会注意到一个“create-greeting”附件。点击它查看其中的内容。
6: 您会看到这里有一个提示给Claude,内容是“请生成一个对John的随意问候。”
7: 不需要输入其他任何提示,只需点击聊天框右上角的提交箭头
8: 您会看到类似的回复“你好,John!你今天过得怎么样?”
7、样式提示
1: 现在,尝试一种不同风格的问候。打开“从MCP附加”对话框并再次选择“create-greeting”提示。这次,我们可以添加名字“Alice”和风格“正式”,然后提交聊天,再次使用箭头或简单地按回车键应该也可以,我还没有试过。
2: 这次,您可能会看到类似这样的回复:
亲爱的Alice,
希望这封信能让你一切安好。我写信是为了表达我最热烈的问候。
最好的祝愿,Claude
9、结束语
在第4部分中,我们将学习:
- MCP工具及其与提示的区别
- 向服务器添加工具功能
- 如何通过工具提供动态功能
- 完成我们的问候服务器,具备所有主要的MCP功能
原文链接:Building MCP Servers: Part 3 — Adding Prompts
汇智网翻译整理,转载请标明出处