提示詞

提示詞使服務器能夠定義可重用的提示詞模板和工作流,客戶端可以輕鬆地將其呈現給用戶和 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] 錯誤: network.py:127 中的連接超時\n[2024-03-14 15:32:15] 警告: 重試連接(嘗試 2/3)\n[2024-03-14 15:32:20] 錯誤: 超過最大重試次數",
          "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    # 連接實現\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: "Generate a Git commit message",
        arguments: [
          {
            name: "changes",
            description: "Git diff or description of changes",
            required: true
          }
        ]
      },
      "explain-code": {
        name: "explain-code",
        description: "Explain how code works",
        arguments: [
          {
            name: "code",
            description: "Code to explain",
            required: true
          },
          {
            name: "language",
            description: "Programming language",
            required: false
          }
        ]
      }
    };

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

    // List available prompts
    server.setRequestHandler(ListPromptsRequestSchema, async () => {
      return {
        prompts: Object.values(PROMPTS)
      };
    });

    // Get specific prompt
    server.setRequestHandler(GetPromptRequestSchema, async (request) => {
      const prompt = PROMPTS[request.params.name];
      if (!prompt) {
        throw new Error(`Prompt not found: ${request.params.name}`);
      }

      if (request.params.name === "git-commit") {
        return {
          messages: [
            {
              role: "user",
              content: {
                type: "text",
                text: `Generate a concise but descriptive commit message for these changes:\n\n${request.params.arguments?.changes}`
              }
            }
          ]
        };
      }

      if (request.params.name === "explain-code") {
        const language = request.params.arguments?.language || "Unknown";
        return {
          messages: [
            {
              role: "user",
              content: {
                type: "text",
                text: `Explain how this ${language} code works:\n\n${request.params.arguments?.code}`
              }
            }
          ]
        };
      }

      throw new Error("Prompt implementation not found");
    });
    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 中呈現為:

  • 斜槓命令
  • 快速操作
  • 上下文菜單項
  • 命令面板條目
  • 引導式工作流
  • 交互式表單

更新和變更

服務器可以通知客戶端提示詞的變更:

  1. 服務器功能: prompts.listChanged
  2. 通知: notifications/prompts/list_changed
  3. 客戶端重新獲取提示詞列表

安全考慮

在實現提示詞時:

  • 驗證所有參數
  • 淨化用戶輸入
  • 考慮速率限制
  • 實現訪問控制
  • 審計提示詞使用情況
  • 適當處理敏感數據
  • 驗證生成的內容
  • 實現超時
  • 考慮提示詞注入風險
  • 記錄安全要求 </rewritten_file>