构建 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.pswp.cn/diannao/86256.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL 索引优化(Explain执行计划) 详细讲解

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 MySQL 索引优化&#xff08;Explain执行计划…

使用 IntelliJ IDEA 安装通义灵码(TONGYI Lingma)插件,进行后端 Java Spring Boot 项目的用户用例生成及常见问题处理

一、什么是通义灵码&#xff08;TONGYI Lingma&#xff09;&#xff1f; 通义灵码是阿里巴巴推出的智能代码辅助工具&#xff0c;结合大模型技术&#xff0c;支持代码生成、用例生成、代码补全等功能&#xff0c;能极大提升开发效率。 二、在 IDEA 中安装通义灵码插件 打开 In…

AI编程在BOSS项目的实践经验分享

前言 在人工智能技术革新浪潮的推动下&#xff0c;智能编程助手正以前所未有的速度重塑开发领域。这些基于AI的代码辅助工具通过智能提示生成、实时错误检测和自动化重构等功能&#xff0c;显著提升了软件工程的全流程效率。无论是初入行业的开发者还是资深程序员&#xff0c;…

JVM 类加载器 详解

类加载器 两个类来源于同一个 Class文件&#xff0c;被同一个Java虚拟机加载&#xff0c;只要加载它们的类加载器不同&#xff0c;那这两个类就必定不相等 这里所指的“相等”&#xff0c;包括代表类的Class对象的equals()方法、isAssignableFrom()方法、isInstance()方法的返…

Javascript 编程基础(5)面向对象 | 5.1、构造函数实例化对象

文章目录 一、构造函数实例化对象1、基本语法2、构造函数与原型的关系3、完整的原型链4、构造函数的特点5、prototype与__proto__属性5.1、对象实例的__proto__属性5.2、prototype属性仅存在于函数对象5.3、实例与原型的关系5.4、获取对象原型 6、注意事项 前言&#xff1a; 在…

自动驾驶科普(百度Apollo)学习笔记

1. 写在前面 在过去的几年里&#xff0c;自动驾驶技术取得飞速发展&#xff0c;人类社会正逐渐走向一个新时代&#xff0c;这个时代中&#xff0c;汽车不仅仅是一个交通工具&#xff0c;更是一个智能的、能够感知环境、做出决策并自主导航的机器伙伴。现在正好也从事这块的工作…

Windows应用-音视频捕获

下载“Windows应用-音视频捕获”项目 本应用可以同时捕获4个视频源和4个音频源&#xff0c;可以监视视频源图像&#xff0c;监听音频源&#xff1b;可以将视频源图像写入MP4文件&#xff0c;将音频源写入MP3或WAV文件&#xff1b;还可以录制系统播放的声音。本应用使用MFC对话框…

MATLAB生成大规模无线通信网络拓扑(任意节点数量)

功能&#xff1a; 生成任意节点数量的网络拓扑&#xff0c;符合现实世界节点空间分布和连接规律 效果&#xff1a; 30节点&#xff1a; 100节点&#xff1a; 500节点&#xff1a; 程序&#xff1a; %创建时间&#xff1a;2025年6月8日 %zhouzhichao %自然生长出n节点的网络% …

TDengine 开发指南—— UDF函数

UDF 简介 在某些应用场景中&#xff0c;应用逻辑需要的查询功能无法直接使用内置函数来实现&#xff0c;TDengine 允许编写用户自定义函数&#xff08;UDF&#xff09;&#xff0c;以便解决特殊应用场景中的使用需求。UDF 在集群中注册成功后&#xff0c;可以像系统内置函数一…

C#提取CAN ASC文件时间戳:实现与性能优化

C#提取CAN ASC文件时间戳&#xff1a;实现与性能优化 在汽车电子和工业控制领域&#xff0c;CAN总线是最常用的通信协议之一。而ASC&#xff08;ASCII&#xff09;文件作为CAN总线数据的标准日志格式&#xff0c;广泛应用于数据记录和分析场景。本文将深入探讨如何高效地从CAN…

计算机网络基础总结:TCP/IP 模型、TCP vs UDP、DNS 查询过程

在学习计算机网络的过程中&#xff0c;理解 TCP/IP 模型与 OSI 模型的对应关系、掌握 TCP 与 UDP 的区别&#xff0c;以及熟悉 DNS 的查询过程&#xff0c;是打好网络基础的关键。本文将围绕这三部分进行简明扼要的讲解。 一、TCP/IP 模型与 OSI 七层模型的对应关系 1. OSI 七…

基于PHP的扎染文创产品商城

有需要请加文章底部Q哦 可远程调试 基于PHP的扎染文创产品商城 一 介绍 扎染文创产品商城系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap&#xff0c;jquery.js等。系统角色分为用户和管理员。 技术栈&#xff1a;phpmysqlbootstrapphpstudyvscode 二…

数据库学习(三)——MySQL锁

一、MySQL锁 当多个用户或进程并发操作数据库时&#xff0c;为了避免数据冲突、脏读、不可重复读、幻读等问题&#xff0c;数据库通过锁机制来保证数据的一致性和完整性。 MySQL 锁的总体分类&#xff1a; 分类维度类型说明按作用对象表级锁&#xff08;Table Lock&#xff…

<3>-MySQL表的操作

目录 一&#xff0c;创建表 二&#xff0c;查看表结构 三&#xff0c;修改表 四&#xff0c;删除表 一&#xff0c;创建表 语法&#xff1a; CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collate 校验规则 eng…

【OSG学习笔记】Day 15: 路径动画与相机漫游

本章来学习下漫游相机。 路径动画与相机漫游 本届内容比较简单&#xff0c;其实就是实现物体的运动和相机的运动 当然这两个要一起执行。 贝塞尔曲线 贝塞尔曲线&#xff08;Bzier curve&#xff09;是一种在计算机图形学、动画制作、工业设计等领域广泛应用的参数曲线&am…

LabVIEW自感现象远程实验平台

LabVIEW开发自感现象远程实验平台&#xff0c;通过整合 NI数据采集设备、菲尼克斯&#xff08;Phoenix Contact&#xff09;继电器模块及罗技&#xff08;Logitech&#xff09;高清摄像头&#xff0c;实现远程数据采集、仪器控制与实时监控三大核心功能。平台突破传统实验装置局…

数据结构——F/图

一、图的基本概念 图是由顶点集合及顶点间的关系组成的一种数据结构&#xff1a;G (V&#xff0c; E)&#xff0c;其中&#xff1a; 顶点集合V {x|x属于某个数据对象集}是有穷非空集合&#xff1b; E {(x,y)|x,y属于V}或者E {<x, y>|x,y属于V && Path(x, y)…

springcloud openfeign 偶现 Caused by: java.net.UnknownHostException

背景 最近查看日志发现某服务偶现Caused by: java.net.UnknownHostException 同时查看eureka的access.log 出现如下异常 10.xxx.xxx.xxx - - [27/May/2025:23:57:29 0800] “PUT /eureka/apps/{appName}/{host}:xxx-job:8082?statusUP&lastDirtyTimestamp1748351637173 H…

第12篇:数据库中间件日志设计与追踪系统落地实践

12.1 引言&#xff1a;中间件日志系统为何如此关键&#xff1f; 数据库中间件作为连接前端应用与后端数据库的“网关”&#xff0c;承载着路由、负载均衡、SQL 改写、权限控制等复杂逻辑。 在出现 性能问题、故障排查、安全审计 等场景中&#xff0c;若没有完善的日志体系&am…

OpenAI对抗法庭命令:捍卫ChatGPT用户隐私之战

人工智能公司OpenAI近期正积极对抗一项涉及隐私问题的法庭命令。该命令要求OpenAI保留所有ChatGPT用户日志&#xff0c;包括已删除的对话记录以及通过API调用生成的聊天内容。 命令背后的真实动机 值得注意的是&#xff0c;法院发布这一指令并非出于对用户隐私或内容安全的考…