Skip to content

提示

创建可重用的提示模板和工作流

提示使服务器能够定义可重用的提示模板和工作流,客户端可以轻松地向用户和 LLM 显示这些模板和工作流。它们提供了一种强大的方法来标准化和共享常见的 LLM 交互。

image-20250306205357609

一、概述

MCP 中的提示是预定义的模板,可以:

  • 接受动态参数
  • 包括来自资源的上下文
  • 链接多个交互
  • 指导特定工作流程
  • Surface 作为 UI 元素(如斜杠命令)

二、提示结构

每个提示都定义如下:

typescript
{
  name: string;              // 提示(prompt)的唯一标识符
  description?: string;      // 可选,提示的人类可读描述
  arguments?: [              // 可选,参数列表
    {
      name: string;          // 参数的标识符
      description?: string;  // 可选,参数的描述信息
      required?: boolean;    // 可选,表示该参数是否必填
    }
  ]
}

三、发现提示

客户端可以通过终端节点发现可用的提示:prompts/list

typescript
// 请求
{
  method: "prompts/list"
}

//响应
{
  prompts: [
    {
      name: "analyze-code",
      description: "分析代码,找出可能的改进之处",
      arguments: [
        {
          name: "language",
          description: "编程语言",
          required: true    //该参数必传
        }
      ]
    }
  ]
}

四、使用提示

要使用提示,客户端会发出请求:prompts/get

typescript
// 请求
{
  method: "prompts/get",
  params: {
    name: "analyze-code",
    arguments: {
      language: "python"
    }
  }
}

// 响应
{
  description: "分析 Python 代码,寻找可能的改进",
  messages: [
    {
      role: "user",
      content: {
        type: "text",
        text: "请分析 Python 代码,寻找可能的改进:\n\n```python\ndef calculate_sum(numbers):\n    total = 0\n    for num in numbers:\n        total = total + num\n    return total\n\nresult = calculate_sum([1, 2, 3, 4, 5])\nprint(result)\n```"
      }
    }
  ]
}

五、动态提示

提示可以是动态的,包括:

1、嵌入式资源上下文

json
{
  "name": "analyze-project",
  "description": "分析项目日志和代码",
  "arguments": [
    {
      "name": "timeframe",
      "description": "分析日志的时间段",
      "required": true
    },
    {
      "name": "fileUri",
      "description": "要审查的代码文件的 URI",
      "required": true
    }
  ]
}

处理请求时:prompts/get

json
{
  "messages": [
    {
      "role": "user",
      "content": {
        "type": "text",
        "text": "分析这些系统日志和代码文件,查找任何问题:"
      }
    },
    {
      "role": "user",
      "content": {
        "type": "resource",
        "resource": {
          "uri": "logs://recent?timeframe=1h",
          "text": "[2024-03-14 15:32:11] ERROR: Connection timeout in network.py:127\n[2024-03-14 15:32:15] WARN: Retrying connection (attempt 2/3)\n[2024-03-14 15:32:20] ERROR: Max retries exceeded",
          "mimeType": "text/plain"
        }
      }
    },
    {
      "role": "user",
      "content": {
        "type": "resource",
        "resource": {
          "uri": "file:///path/to/code.py",
          "text": "def connect_to_service(timeout=30):\n    retries = 3\n    for attempt in range(retries):\n        try:\n            return establish_connection(timeout)\n        except TimeoutError:\n            if attempt == retries - 1:\n                raise\n            time.sleep(5)\n\ndef establish_connection(timeout):\n    # Connection implementation\n    pass",
          "mimeType": "text/x-python"
        }
      }
    }
  ]
}

2、多步骤工作流

typescript
const debugWorkflow = {
  name: "debug-error",
  async getMessages(error: string) {
    return [
      {
        role: "user",
        content: {
          type: "text",
          text: `下面是我看到的一个错误: ${error}`
        }
      },
      {
        role: "assistant",
        content: {
          type: "text",
          text: "我来帮你分析这个错误。 您目前尝试了哪些方法?"
        }
      },
      {
        role: "user",
        content: {
          type: "text",
          text: "我试过重启服务,但错误依然存在."
        }
      }
    ];
  }
};

六、示例实现

以下是在 MCP 服务器中实现提示的完整示例:

TypeScript范例
typescript
// 从 MCP SDK 中导入 Server 类
import { Server } from "@modelcontextprotocol/sdk/server";

// 从 MCP SDK 中导入请求的类型定义,用于处理“获取提示列表”和“获取单个提示”请求
import {
  ListPromptsRequestSchema,
  GetPromptRequestSchema
} from "@modelcontextprotocol/sdk/types";

// 定义提示(prompts)集合,键是提示名称,值是提示的详细信息
const PROMPTS = {
  // 第一个提示:生成 Git 提交信息
  "git-commit": {
    name: "git-commit",  // 唯一标识符
    description: "生成一个 Git commit 消息", // 描述
    arguments: [  // 参数列表
      {
        name: "changes",  // 参数名
        description: "Git diff 或更改说明", // 参数说明
        required: true  // 必填
      }
    ]
  },
  // 第二个提示:解释代码含义
  "explain-code": {
    name: "explain-code",  // 唯一标识符
    description: "解释代码如何工作", // 描述
    arguments: [
      {
        name: "code",  // 代码文本
        description: "需要解释的代码",  // 参数说明
        required: true  // 必填
      },
      {
        name: "language",  
        description: "编程语言", // 参数说明
        required: false  // 非必填
      }
    ]
  }
};

// 创建 MCP 服务器实例
const server = new Server(
  {
    name: "example-prompts-server",  // 服务器名称
    version: "1.0.0"  // 版本号
  },
  {
    capabilities: {
      prompts: {}  // 声明支持 "prompts" 能力
    }
  }
);

// 注册请求处理器:列出可用的 prompts(提示模板)
server.setRequestHandler(ListPromptsRequestSchema, async () => {
  return {
    prompts: Object.values(PROMPTS)  // 返回所有提示模板的数组
  };
});

// 注册请求处理器:获取指定的 prompt,并根据参数生成消息
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
  // 根据请求参数中的 name 获取对应的提示
  const prompt = PROMPTS[request.params.name];

  // 如果没有找到提示,抛出错误
  if (!prompt) {
    throw new Error(`Prompt not found: ${request.params.name}`);
  }

  // 针对 git-commit 提示的处理
  if (request.params.name === "git-commit") {
    return {
      messages: [
        {
          role: "user",  // 消息角色
          content: {
            type: "text",  // 消息类型是文本
            text: `为这些更改生成简明扼要的提交信息:\n\n${request.params.arguments?.changes}`
            // 生成的文本,将请求参数中的 changes 插入提示中
          }
        }
      ]
    };
  }

  // 针对 explain-code 提示的处理
  if (request.params.name === "explain-code") {
    const language = request.params.arguments?.language || "Unknown";  // 获取语言参数,默认 Unknown
    return {
      messages: [
        {
          role: "user",
          content: {
            type: "text",
            text: `请解释这些 ${language} 代码如何工作:\n\n${request.params.arguments?.code}`
            // 生成的文本,将请求参数中的 code 和 language 插入提示中
          }
        }
      ]
    };
  }

  // 如果没有实现对应的提示处理逻辑,抛出错误
  throw new Error("未找到提示执行");
});

其他

《模型上下文协议中文网》附注:下面部分新手可先不关注

1、最佳实践

实施提示时:

  1. 使用清晰、描述性的提示名称
  2. 提供提示和参数的详细说明
  3. 验证所有必需的参数
  4. 优雅地处理缺失的参数
  5. 考虑对提示模板进行版本控制
  6. 在适当时缓存动态内容
  7. 实施错误处理
  8. 记录预期的参数格式
  9. 考虑提示可组合性
  10. 使用各种输入的测试提示

2、UI 集成

提示可以在客户端 UI 中显示为:

  • 斜杠命令
  • 快速作
  • 上下文菜单项
  • 命令面板条目
  • 引导式工作流
  • 交互式表单

3、更新和更改

服务器可以通知客户端提示更改:

  1. 服务器功能:prompts.listChanged
  2. 通知:notifications/prompts/list_changed
  3. 客户端重新获取提示列表

4、安全注意事项

实施提示时:

  • 验证所有参数
  • 清理用户输入
  • 考虑速率限制
  • 实施访问控制
  • 审核提示使用情况
  • 适当处理敏感数据
  • 验证生成的内容
  • 实施超时
  • 考虑及时注射风险
  • 文档安全要求