【翻译、转载】MCP 提示 (Prompts)

原文地址:https://modelcontextprotocol.io/docs/concepts/prompts#python

---

提示 (Prompts)

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

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

提示被设计为用户控制 (user-controlled),这意味着它们从服务器暴露给客户端,目的是让用户能够显式选择它们来使用。

在这里插入图片描述

概述

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

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

在这里插入图片描述

提示结构

每个提示都通过以下结构定义:

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

发现提示

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

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

// 响应
{
  prompts: [
    {
      name: "analyze-code",
      description: "分析代码以寻找潜在改进", // Analyze code for potential improvements
      arguments: [
        {
          name: "language",
          description: "编程语言", // Programming language
          required: true
        }
      ]
    }
    // ... 其他提示
  ]
}

使用提示

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

// 请求
{
  method: "prompts/get",
  params: {
    name: "analyze-code", // 要使用的提示名称
    arguments: {         // 提供的参数
      language: "python"
    }
  }
}

// 响应
{
  description: "分析 Python 代码以寻找潜在改进", // Analyze Python code for potential improvements
  messages: [ // 生成的、准备发送给 LLM 的消息列表
    {
      role: "user", // 角色通常是 "user" 或 "assistant"
      content: {
        type: "text", // 内容类型,可以是 "text" 或 "resource"
        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": "分析项目日志和代码", // Analyze project logs and code
  "arguments": [
    {
      "name": "timeframe",
      "description": "要分析日志的时间段", // Time period to analyze logs
      "required": true
    },
    {
      "name": "fileUri",
      "description": "要审查的代码文件的 URI", // URI of code file to review
      "required": true
    }
  ]
}

当处理 prompts/get 请求时,服务器可以动态获取资源内容并将其嵌入到消息中:

// prompts/get 的响应
{
  "messages": [
    {
      "role": "user",
      "content": {
        "type": "text",
        "text": "请分析这些系统日志和代码文件是否存在任何问题:" // Analyze these system logs and the code file for any issues:
      }
    },
    {
      "role": "user",
      "content": {
        "type": "resource", // 内容类型为资源
        "resource": {      // 包含资源详情
          "uri": "logs://recent?timeframe=1h", // 资源的 URI (可能是动态生成的)
          // 服务器动态获取的资源内容
          "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", // 另一个资源的 URI
          // 该资源的内容
          "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}` // Here's an error I'm seeing: ${error}
        }
      },
      {
        role: "assistant", // 预设的助手回应
        content: {
          type: "text",
          text: "我来帮你分析这个错误。你目前尝试了哪些方法?" // I'll help analyze this error. What have you tried so far?
        }
      },
      {
        role: "user", // 预设的用户后续输入提示
        content: {
          type: "text",
          text: "我尝试重启了服务,但错误依旧存在。" // I've tried restarting the service, but the error persists.
        }
      }
      // ... 后续可以由 LLM 或用户继续
    ];
  }
};

实现示例

这是一个在 MCP 服务器中实现提示的完整示例:

from mcp.server import Server
import mcp.types as types

# Define available prompts
PROMPTS = {
    "git-commit": types.Prompt(
        name="git-commit",
        description="Generate a Git commit message",
        arguments=[
            types.PromptArgument(
                name="changes",
                description="Git diff or description of changes",
                required=True
            )
        ],
    ),
    "explain-code": types.Prompt(
        name="explain-code",
        description="Explain how code works",
        arguments=[
            types.PromptArgument(
                name="code",
                description="Code to explain",
                required=True
            ),
            types.PromptArgument(
                name="language",
                description="Programming language",
                required=False
            )
        ],
    )
}

# Initialize server
app = Server("example-prompts-server")

@app.list_prompts()
async def list_prompts() -> list[types.Prompt]:
    return list(PROMPTS.values())

@app.get_prompt()
async def get_prompt(
    name: str, arguments: dict[str, str] | None = None
) -> types.GetPromptResult:
    if name not in PROMPTS:
        raise ValueError(f"Prompt not found: {name}")

    if name == "git-commit":
        changes = arguments.get("changes") if arguments else ""
        return types.GetPromptResult(
            messages=[
                types.PromptMessage(
                    role="user",
                    content=types.TextContent(
                        type="text",
                        text=f"Generate a concise but descriptive commit message "
                        f"for these changes:\n\n{changes}"
                    )
                )
            ]
        )

    if name == "explain-code":
        code = arguments.get("code") if arguments else ""
        language = arguments.get("language", "Unknown") if arguments else "Unknown"
        return types.GetPromptResult(
            messages=[
                types.PromptMessage(
                    role="user",
                    content=types.TextContent(
                        type="text",
                        text=f"Explain how this {language} code works:\n\n{code}"
                    )
                )
            ]
        )

    raise ValueError("Prompt implementation not found")

最佳实践

在实现提示时:

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

UI 集成

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

  • 斜杠命令 (Slash commands)
  • 快捷操作 (Quick actions)
  • 上下文菜单项 (Context menu items)
  • 命令面板条目 (Command palette entries)
  • 引导式工作流 (Guided workflows)
  • 交互式表单 (Interactive forms)

更新与变更

服务器可以通知客户端关于提示的变更:

  1. 服务器能力声明:prompts.listChanged(表明服务器支持此通知)
  2. 通知消息:notifications/prompts/list_changed
  3. 客户端收到通知后重新获取提示列表

安全注意事项

在实现提示时:

  • 验证所有参数
  • 净化用户输入
  • 考虑速率限制
  • 实施访问控制
  • 审计提示使用情况
  • 适当地处理敏感数据
  • 验证生成的内容(如果适用)
  • 实现超时机制
  • 考虑提示注入 (prompt injection) 风险
  • 记录安全要求

### 解决 `spawn npx ENOENT` 错误的方法 当遇到 `spawn npx ENOENT` 的错误时,这通常意味着 Node.js 尝试通过子进程启动 `npx` 命令失败。此问题可能由多种原因引起,包括环境变量配置不当、Node.js 版本不兼容或其他依赖项缺失。 #### 方法一:检查并修复环境变量设置 确保系统的 PATH 环境变量已正确配置,以便能够找到全局安装的 npm 和 npx 可执行文件。对于 Windows 用户来说,可以尝试重启计算机使新的环境变量生效[^1]。 #### 方法二:更新或重新安装 Node.js 和 NPM 有时旧版本可能会引发此类问题;因此建议升级到最新稳定版的 Node.js 以及配套的 NPM 客户端。如果已经是最新的,则考虑完全卸载后再重装一次[^2]。 #### 方法三:修改 `.vuerc` 配置文件中的 package manager 设置 针对特定情况下由于 Yarn 导致的问题,在 C:\Users\User\.vuerc 文件里调整 `"packageManager"` 字段值为 `"npm"` 而不是默认的 `"yarn"` ,这样可以让 Vue CLI 使用 npm 来管理包而不是 Yarn[^5]。 ```json { "useTaobaoRegistry": false, "packageManager": "npm" } ``` #### 方法四:显式指定命令路径或者使用绝对路径来调用 npx 在某些场景下直接传入完整的可执行程序路径给 spawn 函数参数也可以解决问题。另外一种方式是在构建过程中加入判断逻辑以适应不同操作系统平台的需求: ```javascript const { execFile } = require('child_process'); execFile(process.platform === 'win32' ? 'npx.cmd' : 'npx', ['--version'], (err, stdout) => { console.log(stdout); }); ``` 以上几种方法可以帮助解决 `spawn npx ENOENT` 这样的常见错误。具体采取哪种取决于实际开发环境中所面临的情况和个人偏好。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

superdont

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值