提示词是可复用的消息模板,能帮助大语言模型生成结构化、有目的性的响应。FastMCP通过@mcp.prompt装饰器简化了这些模板的定义流程。

什么是提示词?

提示词为大型语言模型提供参数化的消息模板。当客户端请求一个提示时:

  1. FastMCP 查找对应的提示定义。
  2. 如果函数包含参数,系统会依据您的函数签名对这些参数进行验证。
  3. 您的函数将使用经过验证的输入执行。
  4. 生成的提示信息会被返回给LLM,用于指导其生成响应。

这允许您定义一致且可复用的模板,LLM可以在不同客户端和上下文中使用这些模板。

提示词

@prompt 装饰器

定义提示词最常见的方式是通过装饰一个Python函数。该装饰器使用函数名作为提示词的标识符。

from fastmcp import FastMCP
from fastmcp.prompts.prompt import Message, PromptMessage, TextContent

mcp = FastMCP(name="PromptServer")

# Basic prompt returning a string (converted to user message automatically)
@mcp.prompt()
def ask_about_topic(topic: str) -> str:
    """Generates a user message asking for an explanation of a topic."""
    return f"Can you please explain the concept of '{topic}'?"

# Prompt returning a specific message type
@mcp.prompt()
def generate_code_request(language: str, task_description: str) -> PromptMessage:
    """Generates a user message requesting code generation."""
    content = f"Write a {language} function that performs the following task: {task_description}"
    return PromptMessage(role="user", content=TextContent(type="text", text=content))

关键概念:

  • 名称: 默认情况下,提示名称取自函数名称。
  • 参数: 函数参数定义了生成提示所需的输入。
  • Inferred Metadata: By default:
    • 提示名称:取自函数名称(ask_about_topic)。
    • 提示描述:取自该函数的文档字符串(docstring)。

不支持将带有*args**kwargs的函数作为提示词。该限制存在是因为FastMCP需要为MCP协议生成完整的参数模式,而可变参数列表无法实现这一点。

返回值

FastMCP智能处理来自您提示函数的不同返回类型:

  • str: 自动转换为单个PromptMessage
  • PromptMessage: 直接按原样使用。(注意:提供了一个更用户友好的Message构造函数,可以接受原始字符串而非TextContent对象。)
  • list[PromptMessage | str]: 用作消息序列(对话)。
  • Any: 如果返回类型不是上述类型之一,系统会尝试将返回值转换为字符串并作为PromptMessage使用。
from fastmcp.prompts.prompt import Message

@mcp.prompt()
def roleplay_scenario(character: str, situation: str) -> list[Message]:
    """Sets up a roleplaying scenario with initial messages."""
    return [
        Message(f"Let's roleplay. You are {character}. The situation is: {situation}"),
        Message("Okay, I understand. I am ready. What happens next?", role="assistant")
    ]

类型注解

类型注解对提示词非常重要。它们:

  1. 告知FastMCP每个参数的预期类型。
  2. 允许验证从客户端接收的参数。
  3. 用于为MCP协议生成提示的schema。
from pydantic import Field
from typing import Literal, Optional

@mcp.prompt()
def generate_content_request(
    topic: str = Field(description="The main subject to cover"),
    format: Literal["blog", "email", "social"] = "blog",
    tone: str = "professional",
    word_count: Optional[int] = None
) -> str:
    """Create a request for generating content in a specific format."""
    prompt = f"Please write a {format} post about {topic} in a {tone} tone."
    
    if word_count:
        prompt += f" It should be approximately {word_count} words long."
        
    return prompt

必选参数与可选参数

函数签名中的参数如果没有默认值,则被视为必填参数。

@mcp.prompt()
def data_analysis_prompt(
    data_uri: str,                        # Required - no default value
    analysis_type: str = "summary",       # Optional - has default value
    include_charts: bool = False          # Optional - has default value
) -> str:
    """Creates a request to analyze data with specific parameters."""
    prompt = f"Please perform a '{analysis_type}' analysis on the data found at {data_uri}."
    if include_charts:
        prompt += " Include relevant charts and visualizations."
    return prompt

在本示例中,客户端必须提供data_uri。如果省略analysis_typeinclude_charts,将使用它们的默认值。

提示元数据

虽然FastMCP会从您的函数中推断名称和描述,但您可以通过@mcp.prompt装饰器的参数来覆盖这些内容并添加标签:

@mcp.prompt(
    name="analyze_data_request",          # Custom prompt name
    description="Creates a request to analyze data with specific parameters",  # Custom description
    tags={"analysis", "data"}             # Optional categorization tags
)
def data_analysis_prompt(
    data_uri: str = Field(description="The URI of the resource containing the data."),
    analysis_type: str = Field(default="summary", description="Type of analysis.")
) -> str:
    """This docstring is ignored when description is provided."""
    return f"Please perform a '{analysis_type}' analysis on the data found at {data_uri}."
  • name: 设置通过MCP公开的显式提示名称。
  • description: 提供通过MCP暴露的描述信息。如果设置此项,将忽略函数的文档字符串用于此目的。
  • tags: 一组用于对提示进行分类的字符串。客户端可能会使用标签来筛选或分组可用的提示。

异步提示

FastMCP无缝支持标准函数(def)和异步函数(async def)作为提示词。

# Synchronous prompt
@mcp.prompt()
def simple_question(question: str) -> str:
    """Generates a simple question to ask the LLM."""
    return f"Question: {question}"

# Asynchronous prompt
@mcp.prompt()
async def data_based_prompt(data_id: str) -> str:
    """Generates a prompt based on data that needs to be fetched."""
    # In a real scenario, you might fetch data from a database or API
    async with aiohttp.ClientSession() as session:
        async with session.get(f"https://api.example.com/data/{data_id}") as response:
            data = await response.json()
            return f"Analyze this data: {data['content']}"

当您的提示函数执行I/O操作(如网络请求、数据库查询、文件I/O或外部服务调用)时,请使用async def

访问MCP上下文

New in version: 2.2.5

提示词可以通过Context对象访问额外的MCP信息和功能。要访问它,请在提示函数中添加一个类型标注为Context的参数:

from fastmcp import FastMCP, Context

mcp = FastMCP(name="PromptServer")

@mcp.prompt()
async def generate_report_request(report_type: str, ctx: Context) -> str:
    """Generates a request for a report."""
    return f"Please create a {report_type} report. Request ID: {ctx.request_id}"

有关Context对象及其所有功能的完整文档,请参阅Context文档

服务器行为

重复提示

New in version: 2.1.0

你可以配置FastMCP服务器如何处理尝试注册多个同名提示词的情况。在FastMCP初始化时使用on_duplicate_prompts设置。

from fastmcp import FastMCP

mcp = FastMCP(
    name="PromptServer",
    on_duplicate_prompts="error"  # Raise an error if a prompt name is duplicated
)

@mcp.prompt()
def greeting(): return "Hello, how can I help you today?"

# This registration attempt will raise a ValueError because
# "greeting" is already registered and the behavior is "error".
# @mcp.prompt()
# def greeting(): return "Hi there! What can I do for you?"

重复行为选项包括:

  • "warn" (默认值): 记录警告日志,并用新提示替换旧提示。
  • "error": 抛出ValueError错误,阻止重复注册。
  • "replace": 静默地用新提示替换现有提示。
  • "ignore": 保留原始提示并忽略新的注册尝试。