当前位置: 首页 > news >正文

构建 MCP 服务器:第 3 部分 — 添加提示

这是我们构建 MCP 服务器的四部分教程的第三部分。在第一部分中,我们使用基本资源创建了第一个MCP 服务器;在第二部分中,我们添加了资源模板并改进了代码组织。现在,我们将进一步重构代码并添加提示功能。

什么是 MCP 提示?

MCP 中的提示符是服务器提供的结构化模板,用于标准化与语言模型的交互。与提供数据的资源或执行操作的工具不同,提示符定义了可重用的消息序列和工作流,有助于以一致、可预测的方式指导 LLM 行为。它们可以接受参数来自定义交互,同时保持标准化的结构。如果您曾经研究过提示符工程,那么您可能对提示符的概念已经有了相当的了解。在 MCP 服务器中创建这些提示符,使我们能够为我们认为最有用的提示符创建一个空间,使其易于重用甚至共享。想象一下去餐厅,提示符就像一个菜单项,您可以从中挑选并提供给服务员。有时,您可以通过要求添加或删除某些菜品或以特定方式烹饪来自定义菜单项。以这种方式提供的提示符具有类似的功能。

为什么要使用提示?

提示有助于为 LLM 交互创建一致、可重复使用的模式。以下是一些实际示例:

代码审查提示

"name" -> code-review
Please review the following {{language}} code focusing on {{focusAreas}} for the following block of code:
```{{language}}
{{codeBlock}}
```

用户:请检查以下关注安全性和性能的 Python 代码:
“Python
...代码

数据分析提示

"name" -> analyze-sales-data
Analyze {{timeframe}} sales data focusing on {{metrics}}User: Analyze Q1 sales data focusing on revenue and growth

内容生成提示

"name" -> generate-email
Generate a {{tone}} {{type}} email for {{context}}

用户:生成一封正式的支持电子邮件,以向 Bob's Barbecue LLC 提出退款请求。

代码组织

在第二部分中,我们从 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 themserver.setRequestHandler(ListResourcesRequestSchema,() => ({ resources }),);// Resource Templatesserver.setRequestHandler(ListResourceTemplatesRequestSchema, () => ({resourceTemplates,}));// Return resource content when clients request itserver.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");});
};

添加提示

现在添加我们的新提示功能:

// 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// Promptsserver.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 promptsresources: {},},},
);setupHandlers(server);// ... remaining code

理解代码

模块组织

  • 资源和模板已放置在各自的模块中
  • 提示清晰地分开
  • 处理程序现在充当路由层

提示结构

  • 每个提示都有名称、描述和参数(如果需要)
  • 参数描述提示的预期输入
  • 处理程序生成结构化消息以提示目标 AI

消息序列

  • 提示返回消息数组
  • 消息具有角色(“用户”或“助手”)
  • 内容可以包括多步骤工作流的初始请求和后续响应(请注意,目前多步骤工作流的支持有限)

使用检查器进行测试

启动检查器:

npx @modelcontextprotocol/inspector node build/index.js

测试提示:

  • 点击“提示”选项卡
  • 找到“create-greeting”
  • 尝试不同的参数组合:
名字:“爱丽丝”,风格:“兴奋”
{"messages": [{"role": "user","content": {"type": "text","text": "Please generate a greeting in excited style to Alice."}}]
}

使用 Claude Desktop 进行测试

尝试以下示例:

基本提示:

1:打开Claude桌面
假设:

  • 您已经构建了服务器(npx tsc)并设置了 Claude Desktop来使用它。

2:与我们添加资源的方式类似,点击“从 MCP 附加”

3:在模态弹出窗口中,点击“选择并集成”,然后从“hello-mcp”下的列表中选择“create-greeting”提示

4:现在,只需输入姓名即可进行测试。在姓名字段中输入类似“John”的内容,然后点击“提交”。

5:您将看到一个“create-greeting”附件。点击它查看其中的内容。

6:您将看到这里有一个给克劳德的提示,上面写着“请向约翰致以随意的问候”。

7:无需输入任何其他提示,只需单击聊天框右上角的提交箭头即可

8:您将看到类似“嗨,约翰!你今天过得怎么样?”的回复。

样式提示:

1:现在,尝试使用不同的特定样式创建问候语。打开“从 MCP 附加”对话框,然后再次选择“创建问候语”提示。这次,我们可以添加名称“Alice”和样式“正式”,然后提交聊天。再次使用箭头键,或者直接按 Enter 键也可以,我还没试过。

2:这一次,您可能会看到返回如下消息:

亲爱的爱丽丝,

祝您一切安好。谨致以最诚挚的问候。

谨致问候,
克劳德

下一步是什么?

在第 4 部分中,我们将:

  • 了解MCP 工具及其与提示的区别
  • 为我们的服务器添加工具功能
  • 了解工具如何提供动态功能
  • 使用所有主要的 MCP 功能完成我们的问候服务器

资料来源及其他阅读材料:

  • Prompts - Model Context Protocol
  • GitHub - amidabuddha/unichat-mcp-server
  • Prompt engineering overview - Anthropic
  • 10 Prompt Engineering Best Practices - DEV Community
  • https://promptingguide.ai
http://www.lqws.cn/news/176923.html

相关文章:

  • 智能心理医疗助手开发实践:从技术架构到人文关怀——CangjieMagic情感医疗应用技术实践
  • 【Maven打包错误】 Fatal error compiling: 错误: 不支持发行版本 21
  • MongoDB检查慢查询db.system.profile.find 分析各参数的作用
  • MongoDB学习和应用(高效的非关系型数据库)
  • Cursor 1.0正式推出:全面解析你的AI 编程助手
  • for AC500 PLCs 3ADR025003M9903的安全说明
  • uni-app 项目支持 vue 3.0 详解及版本升级方案?
  • coze平台创建智能体,关于智能体后端接入的问题
  • 文件上传漏洞深度解析:检测与绕过技术矩阵
  • 鸿蒙图片缓存(一)
  • Python读取PDF:文本、图片与文档属性
  • 《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
  • Tika Server:企业级文档内容解析的轻量级服务化方案
  • CppCon 2015 学习:How to Make Your Data Structures Wait-Free for Reads
  • 【iOS安全】iPhone X iOS 16.7.11 (20H360) WinRa1n 越狱教程
  • 主流 AI IDE 之一的 Cursor 介绍
  • 2506,字节对齐
  • 【配置 YOLOX 用于按目录分类的图片数据集】
  • 96. 2017年蓝桥杯省赛 - Excel地址(困难)- 进制转换
  • transformer和 RNN以及他的几个变体区别 改进
  • cnn卷积神经变体
  • 豆包和deepseek 元宝 百度ai区别是什么
  • 大语言模型提示词(LLM Prompt)工程系统性学习指南:从理论基础到实战应用的完整体系
  • 大数据学习(132)-HIve数据分析
  • 【LLMs篇】14:扩散语言模型的理论优势与局限性
  • 海康工业相机文档大小写错误
  • vite配置@别名,以及如何让IDE智能提示路经
  • 亚矩阵云手机实测体验:稳定流畅背后的技术逻辑​
  • RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
  • Visual Studio 中的 MD、MTD、MDD、MT 选项详解