跳转到主要内容
Prompts 是由用户控制的消息模板。与由 LLM 调用的 tools 不同,prompts 由用户选择,并被渲染为对话中的 messages。 Prompts 在模型上下文协议 (MCP) 中的处理流程如下:
  1. Client 通过 prompts/list 发现 prompts(每个 prompt 可以包含 arguments 和元数据)。
  2. Client 通过携带字符串值 argumentsprompts/get 渲染一个 prompt。
  3. 服务器执行你的 prompt 渲染器。
  4. 服务器返回一个 GetPromptResult,其中包含 messages(以及可选的 description),具体格式遵循模型上下文协议 (MCP) 规范。
使用 @prompt(...) 定义 prompts,并通过 server.collect(...)(或在 with server.binding(): ... 中)注册它们。

装饰器签名

  • prompt(...): prompt(name: str, *, description=None, title=None, arguments=None, icons=None, meta=None)
你的渲染器将以如下方式被调用:
  • fn(arguments: dict[str, str] | None) → 返回 messages / 映射 / GetPromptResult / None

基础 prompt

from dedalus_mcp import MCPServer, prompt, types

@prompt(
    "code-review",
    description="审查代码问题",
    arguments=[
        types.PromptArgument(name="language", required=False),
        types.PromptArgument(name="focus", required=False),
    ],
)
def code_review(arguments: dict[str, str] | None):
    args = arguments or {}
    language = args.get("language", "python")
    focus = args.get("focus")
    focus_text = f" Focus on: {focus}." if focus else ""

    return [
        ("assistant", "你是一位资深代码审查专家。"),
        ("user", f"请审查以下 {language} 代码。{focus_text}"),
    ]

server = MCPServer("assistant")
server.collect(code_review)
description 用于告诉 Client/LLM 这个 prompt 的用途。arguments=[...] 定义了 Client 应该向 prompts/get 传递哪些内容。

参数(必填 vs 可选)

Dedalus 模型上下文协议 (MCP) 只有在你在装饰器的 arguments=[...] 中将参数标记为 required=True 时,才会将这些参数视为必填。
from dedalus_mcp import MCPServer, prompt, types

@prompt(
    "translate",
    description="翻译文本",
    arguments=[
        types.PromptArgument(name="text", required=True),
        types.PromptArgument(name="target_lang", required=False),
    ],
)
def translate(arguments: dict[str, str] | None):
    args = arguments or {}
    text = args["text"]
    target = args.get("target_lang", "English")
    return [("user", f"Translate this to {target}: {text}")]

server = MCPServer("assistant")
server.collect(translate)
如果缺少必填参数,Dedalus 会抛出一个带有 INVALID_PARAMS 的模型上下文协议 (MCP) 错误。

复杂参数值(列表/字典)

MCP prompt 的参数是字符串。如果你需要结构化的值,请传入 JSON 字符串并自行解析:
import json
from dedalus_mcp import prompt, types

@prompt(
    "summarize",
    description="总结文档",
    arguments=[types.PromptArgument(name="focus_areas_json", required=False)],
)
def summarize(arguments: dict[str, str] | None):
    args = arguments or {}
    focus_areas = json.loads(args.get("focus_areas_json", "[]"))
    return [("user", f"Summarize this document. Focus on: {focus_areas}")]

返回格式

prompt 渲染器可以返回:
  • messages 的列表/可迭代对象,其中每一项可以是:
    • (role, content) 元组
    • 形如 {"role": "...", "content": ...} 的映射
    • PromptMessage 实例
  • 具有显式控制的 映射
    • 必需"messages"
    • 可选"description"
  • GetPromptResult
  • None(不会生成任何消息)
不支持:返回原始 str(Dedalus 会抛出 TypeError,从而确保你始终提供 role + content)。

显式控制(映射)

from dedalus_mcp import prompt

@prompt("status", description="Daily status template")
def status(arguments: dict[str, str] | None):
    return {
        "description": "Status template",
        "messages": [
            ("assistant", "You summarize daily status reports."),
            ("user", "Write yesterday/today/blockers."),
        ],
    }

消息内容

对于消息的 content,你可以使用:
  • 一个 str(会自动转换为文本内容)
  • 一个完整的内容块映射对象(例如 {"type": "text", "text": "..."}
  • 来自 dedalus_mcp.types 的内容块实例(例如 TextContentImageContent 等)

异步 prompt

from dedalus_mcp import prompt

@prompt("db-summary", description="Summarize database state")
async def db_summary(arguments: dict[str, str] | None):
    # await fetch_db_stats(...)
    return [
        ("assistant", "You analyze database metrics."),
        ("user", "Summarize current DB health and recent anomalies."),
    ]
对于 I/O,优先使用 async def

装饰器选项

from dedalus_mcp import prompt

@prompt(
    "analyze",
    description="Analyze code",
    title="Code Analysis",
    icons=[{"type": "url", "url": "https://example.com/icon.png"}],
    meta={"category": "code"},
    arguments=[{"name": "language", "required": False}],
)
def analyze(arguments: dict[str, str] | None):
    language = (arguments or {}).get("language", "python")
    return [("user", f"Analyze this {language} code for bugs, style, and security.")]

上下文访问

如果在 MCP 请求期间渲染 prompt,它可以通过 get_context() 访问上下文(用于日志记录、进度跟踪等)。 注意get_context() 只能在活动的 MCP 请求处理器内部使用;在请求之外调用会引发 LookupError 异常。
from dedalus_mcp import prompt, get_context

@prompt("generate-report", description="Generate a report request")
async def generate_report(arguments: dict[str, str] | None):
    ctx = get_context()
    await ctx.info("正在渲染 prompt", data={"args": arguments or {}})
    return [("user", "Generate a concise weekly report for this project.")]

测试

像对普通函数那样测试 prompt 渲染器:
def test_code_review_prompt():
    msgs = code_review({"language": "python", "focus": "error handling"})
    assert len(msgs) == 2
通过服务器的 应用程序编程接口 API 进行集成测试(对应于 prompts/get):
import pytest
from dedalus_mcp import MCPServer

@pytest.mark.asyncio
async def test_prompt_rendering():
    server = MCPServer("test")
    server.collect(code_review)

    result = await server.invoke_prompt("code-review", arguments={"language": "rust"})
    assert result.messages