跳到主要内容

提示

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

备注

提示设计为用户控制,这意味着它们从服务器暴露给客户端,目的是让用户能够明确选择使用它们。

概述

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

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

提示结构

每个提示的定义如下:

{
  name: string;              // 提示的唯一标识符
  description?: string;      // 人类可读的描述
  arguments?: [              // 可选的参数列表
    {
      name: string;          // 参数标识符
      description?: string;  // 参数描述
      required?: boolean;    // 参数是否必需
    }
  ]
}

发现提示

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

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

// 响应
{
  prompts: [
    {
      name: "analyze-code",
      description: "分析代码以寻找潜在的改进",
      arguments: [
        {
          name: "language",
          description: "编程语言",
          required: true
        }
      ]
    }
  ]
}

使用提示

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

// 请求
{
  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```"
      }
    }
  ]
}

动态提示

提示可以是动态的,并包含:

嵌入式资源上下文

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

处理prompts/get请求时:

{
  "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"
        }
      }
    }
  ]
}

多步骤工作流

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服务器中实现提示的完整示例:

import { Server } from "@modelcontextprotocol/sdk/server";
import {
  ListPromptsRequestSchema,
  GetPromptRequestSchema
} from "@modelcontextprotocol/sdk/types";

const PROMPTS = {
  "git-commit": {
    name: "git-commit",
    description: "生成Git提交消息",
    arguments: [
      {
        name: "changes",
        description: "Git差异或更改描述",
        required: true
      }
    ]
  },
  "explain-code": {
    name: "explain-code",
    description: "解释代码如何工作",
    arguments: [
      {
        name: "code",
        description: "要解释的代码",
        required: true
      },
      {
        name: "language",
        description: "编程语言",
        required: false
      }
    ]
  }
};

const server = new Server({
  name: "example-prompts-server",
  version: "1.0.0"
}, {
  capabilities: {
    prompts: {}
  }
});

// 列出可用提示
server.setRequestHandler(ListPromptsRequestSchema, async () => {
  return {
    prompts: Object.values(PROMPTS)
  };
});

// 获取提示内容
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;
  const prompt = PROMPTS[name];

  if (!prompt) {
    throw new Error("提示未找到");
  }

  // 根据提示类型生成消息
  switch (name) {
    case "git-commit":
      return {
        description: prompt.description,
        messages: [
          {
            role: "user",
            content: {
              type: "text",
              text: `请为以下更改生成一个清晰的Git提交消息:\n\n${args.changes}`
            }
          }
        ]
      };

    case "explain-code":
      return {
        description: prompt.description,
        messages: [
          {
            role: "user",
            content: {
              type: "text",
              text: `请解释以下${args.language || ""}代码如何工作:\n\n${args.code}`
            }
          }
        ]
      };

    default:
      throw new Error("未知的提示类型");
  }
});

最佳实践

在实现提示时:

  1. 使用清晰、描述性的提示名称
  2. 提供有帮助的描述
  3. 明确定义必需的参数
  4. 验证所有参数
  5. 优雅地处理错误
  6. 考虑提示的可重用性
  7. 记录提示的使用方式
  8. 测试各种参数组合
  9. 监控提示使用情况
  10. 定期更新和维护提示

安全考虑

在实现提示时:

  • 验证所有用户输入
  • 清理敏感信息
  • 限制提示访问权限
  • 监控提示使用情况
  • 实现速率限制
  • 审计提示访问
  • 加密敏感数据
  • 验证资源访问权限