MCP 提示模板
提示(Prompts)是 MCP 提供的一种服务器端模板机制,允许服务器定义可重用的提示模板,帮助用户快速启动特定的工作流程。提示模板可以包含参数,使其能够适应不同的使用场景。
什么是提示模板?
提示模板是服务器预定义的提示内容,可以:
- 标准化常见工作流程
- 提供结构化的任务模板
- 引导 LLM 按照特定方式处理问题
- 减少用户重复输入相似内容
与普通提示的区别
| 特性 | 普通提示 | 提示模板 |
|---|---|---|
| 来源 | 用户输入 | 服务器定义 |
| 可复用性 | 低 | 高 |
| 参数化 | 无 | 支持 |
| 一致性 | 依赖用户 | 标准化 |
提示结构
每个提示模板包含以下字段:
from mcp.types import Prompt, PromptArgument
Prompt(
name="code_review", # 唯一标识符(必需)
description="代码审查助手", # 功能描述(必需)
arguments=[ # 参数列表(可选)
PromptArgument(
name="language",
description="编程语言",
required=False,
default="python"
)
]
)
字段说明
| 字段 | 类型 | 必需 | 说明 |
|---|---|---|---|
name | string | 是 | 提示模板的唯一标识符 |
description | string | 是 | 功能描述,帮助用户理解用途 |
arguments | array | 否 | 参数定义列表 |
参数定义
PromptArgument(
name="file_path", # 参数名称
description="要审查的文件路径", # 参数描述
required=True, # 是否必需
default=None # 默认值(仅对非必需参数)
)
协议消息
列出提示模板
客户端通过 prompts/list 获取可用的提示模板:
{
"jsonrpc": "2.0",
"id": "prompts-1",
"method": "prompts/list"
}
服务器响应:
{
"jsonrpc": "2.0",
"id": "prompts-1",
"result": {
"prompts": [
{
"name": "code_review",
"description": "代码审查助手",
"arguments": [
{
"name": "language",
"description": "编程语言",
"required": false
}
]
}
]
}
}
获取提示内容
客户端通过 prompts/get 获取具体的提示内容:
{
"jsonrpc": "2.0",
"id": "get-1",
"method": "prompts/get",
"params": {
"name": "code_review",
"arguments": {
"language": "python"
}
}
}
服务器响应:
{
"jsonrpc": "2.0",
"id": "get-1",
"result": {
"description": "代码审查助手",
"messages": [
{
"role": "user",
"content": {
"type": "text",
"text": "请对以下代码进行全面审查..."
}
}
]
}
}
提示列表变更通知
当提示模板列表发生变化时,服务器发送通知:
{
"jsonrpc": "2.0",
"method": "notifications/prompts/list_changed"
}
Python 实现
使用底层 Server 类
from mcp.server import Server
from mcp.types import Prompt, PromptArgument, TextContent
app = Server("prompt-server")
@app.list_prompts()
async def list_prompts() -> list[Prompt]:
"""返回可用的提示模板列表"""
return [
Prompt(
name="code_review",
description="对代码进行全面的安全、性能和风格审查",
arguments=[
PromptArgument(
name="language",
description="编程语言,如 python、javascript、java",
required=False,
default="python"
),
PromptArgument(
name="focus",
description="审查重点:security、performance、readability、bugs",
required=False,
default="all"
),
PromptArgument(
name="file_path",
description="要审查的文件路径",
required=True
)
]
),
Prompt(
name="write_tests",
description="为代码生成单元测试",
arguments=[
PromptArgument(
name="framework",
description="测试框架,如 pytest、jest、junit",
required=True
),
PromptArgument(
name="coverage_target",
description="目标覆盖率百分比",
required=False,
default="80"
)
]
),
Prompt(
name="explain_error",
description="解释错误信息并提供修复建议",
arguments=[
PromptArgument(
name="error_message",
description="完整的错误信息",
required=True
)
]
)
]
@app.get_prompt()
async def get_prompt(
name: str,
arguments: dict | None
) -> list[TextContent]:
"""返回提示模板的具体内容"""
if arguments is None:
arguments = {}
if name == "code_review":
lang = arguments.get("language", "python")
focus = arguments.get("focus", "all")
file_path = arguments.get("file_path", "")
prompt_text = f"""请对以下 {lang} 代码进行全面审查。
审查文件:{file_path}
重点关注:{focus}
请按以下结构提供审查报告:
## 1. 总体评估
- 代码质量总体评分(1-10)
- 主要优点
- 主要问题
## 2. 详细分析
### 安全性
- 潜在安全风险
- 敏感数据处理
- 输入验证
### 性能
- 性能瓶颈
- 优化建议
- 资源使用
### 可读性
- 代码结构
- 命名规范
- 注释质量
### 潜在缺陷
- 边界条件
- 异常处理
- 并发问题
## 3. 修复建议
请提供具体的代码修改建议,包括修改前后的对比。
"""
return [TextContent(type="text", text=prompt_text)]
elif name == "write_tests":
framework = arguments.get("framework", "pytest")
coverage = arguments.get("coverage_target", "80")
prompt_text = f"""请为以下代码编写 {framework} 单元测试。
目标测试覆盖率:{coverage}%
测试编写要求:
1. **测试结构**
- 每个测试函数专注单一功能
- 使用清晰的测试命名
- 遵循 AAA 模式(Arrange-Act-Assert)
2. **测试覆盖**
- 正常情况测试
- 边界条件测试
- 异常情况测试
- 输入验证测试
3. **最佳实践**
- 使用 fixture 复用测试数据
- 使用 mock 隔离外部依赖
- 参数化测试覆盖多组数据
请提供完整的测试代码,包括必要的导入和 fixture 定义。
"""
return [TextContent(type="text", text=prompt_text)]
elif name == "explain_error":
error_msg = arguments.get("error_message", "")
prompt_text = f"""请分析以下错误信息,提供详细的解释和修复建议。
错误信息:
请提供:
1. **错误类型识别**
- 这是什么类型的错误?
- 错误发生在哪个层级(编译/运行时/逻辑)?
2. **根本原因分析**
- 错误的根本原因是什么?
- 可能的触发条件有哪些?
3. **修复方案**
- 提供具体的修复代码
- 解释修复的原理
- 是否有其他替代方案?
4. **预防措施**
- 如何避免类似错误?
- 有哪些最佳实践可以遵循?
"""
return [TextContent(type="text", text=prompt_text)]
raise ValueError(f"Unknown prompt: {name}")
使用 FastMCP
FastMCP 提供了更简洁的提示定义方式:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("prompt-server")
@mcp.prompt()
def code_review(
language: str = "python",
focus: str = "all",
file_path: str = ""
) -> str:
"""代码审查助手
对代码进行全面的安全、性能和风格审查。
Args:
language: 编程语言,如 python、javascript、java
focus: 审查重点:security、performance、readability、bugs
file_path: 要审查的文件路径
"""
return f"""请对 {file_path} 中的 {language} 代码进行审查。
重点关注:{focus}
请提供:
1. 安全性分析
2. 性能评估
3. 代码质量评分
4. 具体改进建议
"""
@mcp.prompt()
def write_tests(framework: str, coverage_target: int = 80) -> str:
"""生成单元测试
为代码生成完整的单元测试套件。
Args:
framework: 测试框架(pytest、jest、junit)
coverage_target: 目标覆盖率百分比
"""
return f"""请使用 {framework} 编写单元测试,目标覆盖率 {coverage_target}%。"""
@mcp.prompt()
def explain_error(error_message: str) -> str:
"""解释错误信息
分析错误并提供修复建议。
Args:
error_message: 完整的错误信息
"""
return f"""请分析以下错误并提供修复方案:\n{error_message}"""
多消息提示
提示可以返回多条消息,构建完整的对话上下文:
from mcp.types import TextContent, ImageContent
@app.get_prompt()
async def get_prompt(name: str, arguments: dict | None):
if name == "analyze_screenshot":
screenshot_path = arguments.get("screenshot_path")
# 读取图像并编码
image_data = read_and_encode_image(screenshot_path)
# 返回多条消息
return [
TextContent(
type="text",
text="请分析以下截图,识别 UI 元素并提供改进建议。"
),
ImageContent(
type="image",
data=image_data,
mimeType="image/png"
),
TextContent(
type="text",
text="""
请提供以下分析:
1. **UI 元素识别**
- 列出所有可见的 UI 组件
- 标注组件类型和位置
2. **设计评估**
- 布局合理性
- 颜色搭配
- 字体可读性
3. **可访问性检查**
- 对比度是否足够
- 是否支持屏幕阅读器
4. **改进建议**
- 具体的优化方案
"""
)
]
动态提示生成
提示内容可以根据运行时状态动态生成:
# 存储项目状态
project_state = {
"language": None,
"framework": None,
"test_coverage": None
}
@app.get_prompt()
async def get_prompt(name: str, arguments: dict | None):
if name == "project_summary":
# 根据项目状态生成提示
lang = project_state.get("language", "未知")
framework = project_state.get("framework", "未知")
coverage = project_state.get("test_coverage", "未知")
prompt = f"""请为当前项目生成一份总结报告。
项目信息:
- 编程语言:{lang}
- 框架:{framework}
- 当前测试覆盖率:{coverage}
请包含:
1. 项目结构概述
2. 主要功能模块
3. 技术债务清单
4. 改进优先级建议
"""
return [TextContent(type="text", text=prompt)]
条件提示
根据条件返回不同的提示内容:
@app.get_prompt()
async def get_prompt(name: str, arguments: dict | None):
if name == "debug":
error_type = arguments.get("error_type", "general")
# 根据错误类型选择不同的提示模板
templates = {
"memory": """内存问题调试指南:
1. 检查内存泄漏
- 使用 memory_profiler 分析
- 查找未关闭的资源
2. 优化内存使用
- 减少大对象创建
- 使用生成器替代列表
3. 监控建议
- 设置内存限制
- 添加内存使用日志
""",
"performance": """性能问题调试指南:
1. 性能分析
- 使用 cProfile 定位瓶颈
- 分析函数调用频率
2. 优化策略
- 缓存计算结果
- 使用更高效的数据结构
3. 监控建议
- 添加性能指标
- 设置性能告警
""",
"general": """通用调试指南:
1. 问题复现
- 记录复现步骤
- 收集相关日志
2. 问题定位
- 二分法排查
- 添加调试日志
3. 解决验证
- 验证修复效果
- 添加回归测试
"""
}
prompt = templates.get(error_type, templates["general"])
return [TextContent(type="text", text=prompt)]
提示使用流程
提示与工具的区别
理解提示和工具的区别对于正确设计 MCP 服务器至关重要:
| 特性 | 提示 (Prompts) | 工具 (Tools) |
|---|---|---|
| 方向 | 服务器 → 客户端 → LLM | LLM → 客户端 → 服务器 |
| 用途 | 提供模板,引导思考 | 执行具体操作 |
| 主动性 | 被动(用户选择) | 主动(LLM 决定) |
| 返回内容 | 文本模板 | 执行结果 |
| 副作用 | 无 | 可能有 |
选择指南:
- 如果要引导 LLM 按特定方式思考 → 使用提示
- 如果要执行实际操作或获取数据 → 使用工具
- 如果要提供可选的工作流程模板 → 使用提示
最佳实践
1. 清晰的描述
每个提示都要有清晰的描述,帮助用户理解其用途:
# ❌ 差:描述不清
Prompt(name="review", description="审查代码")
# ✅ 好:描述详细
Prompt(
name="code_review",
description="""
对代码进行全面的审查,包括:
- 安全漏洞检测
- 性能瓶颈分析
- 代码风格检查
- 最佳实践建议
"""
)
2. 合理的参数设计
只暴露必要的参数,避免过度复杂:
# ❌ 差:参数过多
Prompt(
name="review",
arguments=[
PromptArgument(name="lang"),
PromptArgument(name="style"),
PromptArgument(name="max_lines"),
PromptArgument(name="output_format"),
PromptArgument(name="severity_threshold"),
# ... 太多参数
]
)
# ✅ 好:参数精简
Prompt(
name="review",
arguments=[
PromptArgument(name="language", required=False, default="auto"),
PromptArgument(name="focus", required=False, default="all")
]
)
3. 提供默认值
为可选参数设置合理的默认值:
PromptArgument(
name="coverage_target",
description="目标覆盖率",
required=False,
default="80" # 行业标准默认值
)
4. 结构化输出指导
在提示中引导 LLM 生成结构化的输出:
prompt = """请分析代码并提供报告,使用以下结构:
## 总体评估
[评分和概述]
## 发现的问题
| 问题类型 | 严重程度 | 位置 | 描述 |
|---------|---------|------|------|
| 安全 | 高 | L15 | ... |
## 修复建议
```python
# 修复代码
"""
### 5. 模板保持简洁
提示模板不应过长,保持聚焦:
```python
# ✅ 好:简洁聚焦
prompt = """请审查以下代码的安全性:
{code}
请列出发现的安全问题及其修复建议。
"""
# ❌ 差:过于冗长
prompt = """请审查以下代码,首先检查安全性,然后检查性能,
然后检查可读性,然后检查...(继续冗长内容)
"""
典型应用场景
1. 代码审查工作流
@mcp.prompt()
def review_pr(pr_number: int, focus: str = "all") -> str:
"""审查 Pull Request
Args:
pr_number: PR 编号
focus: 审查重点
"""
return f"""请审查 PR #{pr_number},重点关注 {focus}。
审查清单:
- [ ] 代码逻辑正确性
- [ ] 测试覆盖率
- [ ] 文档完整性
- [ ] 向后兼容性
"""
2. 问题诊断模板
@mcp.prompt()
def diagnose_issue(
symptoms: str,
environment: str = "production"
) -> str:
"""诊断问题
Args:
symptoms: 问题症状描述
environment: 环境类型
"""
return f"""问题诊断报告
环境:{environment}
症状:{symptoms}
请按以下步骤诊断:
1. 可能原因分析(按可能性排序)
2. 验证步骤
3. 解决方案
"""
3. 文档生成模板
@mcp.prompt()
def generate_docs(
module_name: str,
doc_style: str = "google"
) -> str:
"""生成模块文档
Args:
module_name: 模块名称
doc_style: 文档风格(google、numpy、sphinx)
"""
return f"""请为 {module_name} 生成 {doc_style} 风格的文档。
包含:
- 模块概述
- 类和函数说明
- 使用示例
- 注意事项
"""