实现提示词
提示词是帮助构建用户与 LLM 之间对话的可重用交互模板。它们提供上下文、指令,并可以包含来自资源的动态内容。
提示词基础
MCP 中的提示词作为模板,可供 LLM 调用以生成结构化的交互。它们对于复杂的工作流程、分析任务或任何需要提供一致上下文和指令的场景特别有用。
基本提示词结构
go
// 创建一个简单的提示词
prompt := mcp.NewPrompt("code_review",
mcp.WithPromptDescription("审查代码是否符合最佳实践和问题"),
mcp.WithPromptArgument("code",
mcp.Required(),
mcp.Description("要审查的代码"),
),
mcp.WithPromptArgument("language",
mcp.Description("编程语言"),
mcp.Default("auto-detect"),
),
)提示词图标
提示词可以包含视觉标识符:
go
prompt := mcp.NewPrompt("code_review",
mcp.WithPromptDescription("审查代码是否符合最佳实践"),
mcp.WithPromptIcons(
mcp.Icon{
Src: "https://example.com/icons/review.png",
MIMEType: "image/png",
},
),
// ... 参数
)显示标题
提示词及其参数可以携带人类可读的显示标题。客户端在选择器和 UI 界面中呈现标题;name 保持为稳定的程序化标识符。
go
prompt := mcp.NewPrompt("code_review",
mcp.WithPromptTitle("代码审查"), // 在 UI 中显示
mcp.WithPromptDescription("审查代码是否符合最佳实践"),
mcp.WithArgument("code",
mcp.ArgumentTitle("源代码"), // 参数显示名称
mcp.ArgumentDescription("要审查的代码"),
mcp.RequiredArgument(),
),
)当 Title 为空时,客户端会回退到 Name。两个字段都使用 omitempty 序列化,因此未设置标题的现有提示词在传输时不会改变。
提示词模板
基本代码审查提示词
go
import (
"context"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
s := server.NewMCPServer("Code Assistant", "1.0.0",
server.WithPromptCapabilities(true),
)
// 代码审查提示词
codeReviewPrompt := mcp.NewPrompt("code_review",
mcp.WithPromptDescription("审查代码的最佳实践、错误和改进"),
mcp.WithPromptArgument("code",
mcp.Required(),
mcp.Description("要审查的代码"),
),
mcp.WithPromptArgument("language",
mcp.Description("编程语言(如果未指定则自动检测)"),
),
mcp.WithPromptArgument("focus",
mcp.Description("要关注的特定领域"),
mcp.Enum("security", "performance", "readability", "best-practices", "all"),
mcp.Default("all"),
),
)
s.AddPrompt(codeReviewPrompt, handleCodeReview)
server.ServeStdio(s)
}
func handleCodeReview(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
// 安全地提取参数
args := req.Params.Arguments
if args == nil {
return nil, fmt.Errorf("missing required arguments")
}
code, ok := args["code"].(string)
if !ok {
return nil, fmt.Errorf("code argument is required and must be a string")
}
language := getStringArg(args, "language", "auto-detect")
focus := getStringArg(args, "focus", "all")
// 根据关注领域构建提示词
var instructions string
switch focus {
case "security":
instructions = "特别关注安全漏洞、输入验证和潜在攻击向量。"
case "performance":
instructions = "关注性能优化、算法效率和资源使用。"
case "readability":
instructions = "关注代码清晰度、命名约定和可维护性。"
case "best-practices":
instructions = "关注特定语言的最佳实践和设计模式。"
default:
instructions = "提供涵盖安全性、性能、可读性和最佳实践的综合审查。"
}
return &mcp.GetPromptResult{
Description: fmt.Sprintf("%s 代码审查", language),
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: mcp.NewTextContent(fmt.Sprintf(
"请审查以下 %s 代码:\n\n%s\n\n说明:%s\n\n请提供:\n1. 总体评估\n2. 发现的具体问题\n3. 建议的改进\n4. 最佳实践建议\n\n代码:\n\n```\n%s\n```",
language, code, instructions, code,
)),
},
},
}, nil
}
func getStringArg(args map[string]interface{}, key, defaultValue string) string {
if val, exists := args[key]; exists {
if str, ok := val.(string); ok {
return str
}
}
return defaultValue
}数据分析提示词
go
func handleDataAnalysis(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
datasetURI := req.Params.Arguments["dataset_uri"].(string)
analysisType := getStringArg(req.Params.Arguments, "analysis_type", "exploratory")
focusAreas := getStringSliceArg(req.Params.Arguments, "focus_areas", []string{})
// 获取数据集(这通常会从资源读取)
dataset, err := fetchDataset(ctx, datasetURI)
if err != nil {
return nil, fmt.Errorf("failed to fetch dataset: %w", err)
}
// 构建分析说明
var instructions strings.Builder
instructions.WriteString("请分析提供的数据集。")
switch analysisType {
case "exploratory":
instructions.WriteString("执行探索性数据分析,包括摘要统计、分布和模式。")
case "predictive":
instructions.WriteString("关注预测建模机会和特征关系。")
case "diagnostic":
instructions.WriteString("识别数据质量问题、异常值和潜在问题。")
}
if len(focusAreas) > 0 {
instructions.WriteString(fmt.Sprintf(" 请特别关注:%s。", strings.Join(focusAreas, ", ")))
}
return &mcp.GetPromptResult{
Description: fmt.Sprintf("%s 数据集分析", strings.Title(analysisType)),
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: mcp.NewTextContent(fmt.Sprintf(`%s
数据集信息:
- 来源:%s
- 记录数:%d
- 列:%s
数据集预览:
%s
请提供综合分析,包括:
1. 数据概览和质量评估
2. 关键洞察和模式
3. 进一步分析的建议
4. 潜在问题或关注点`,
instructions.String(),
datasetURI,
dataset.RecordCount,
strings.Join(dataset.Columns, ", "),
dataset.Preview,
)),
},
},
}, nil
}
func getStringSliceArg(args map[string]interface{}, key string, defaultValue []string) []string {
if val, exists := args[key]; exists {
if slice, ok := val.([]interface{}); ok {
result := make([]string, len(slice))
for i, v := range slice {
if str, ok := v.(string); ok {
result[i] = str
}
}
return result
}
}
return defaultValue
}提示词参数
灵活参数处理
go
func handleFlexiblePrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
// 必需参数
task := req.Params.Arguments["task"].(string)
// 带默认值的可选参数
tone := getStringArg(req.Params.Arguments, "tone", "professional")
length := getStringArg(req.Params.Arguments, "length", "medium")
audience := getStringArg(req.Params.Arguments, "audience", "general")
// 数组参数
keywords := getStringSliceArg(req.Params.Arguments, "keywords", []string{})
// 对象参数
var constraints map[string]interface{}
if c, exists := req.Params.Arguments["constraints"]; exists {
constraints = c.(map[string]interface{})
}
// 根据参数构建提示词
prompt := buildDynamicPrompt(task, tone, length, audience, keywords, constraints)
return &mcp.GetPromptResult{
Description: fmt.Sprintf("生成 %s 内容", task),
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: mcp.NewTextContent(prompt),
},
},
}, nil
}消息类型
多消息对话
go
func handleConversationPrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
scenario := req.Params.Arguments["scenario"].(string)
userRole := getStringArg(req.Params.Arguments, "user_role", "customer")
var messages []mcp.PromptMessage
switch scenario {
case "customer_support":
messages = []mcp.PromptMessage{
{
Role: "system",
Content: mcp.NewTextContent("你是一位乐于助人的客户支持代表。请保持礼貌、专业,并以解决问题为导向。"),
},
{
Role: "user",
Content: mcp.NewTextContent(fmt.Sprintf("我是一位%s,关于您的服务有问题想问。", userRole)),
},
{
Role: "assistant",
Content: mcp.NewTextContent("您好!我在这里提供帮助。您今天需要什么帮助?"),
},
{
Role: "user",
Content: mcp.NewTextContent("请根据客户的需求继续对话。"),
},
}
case "technical_interview":
messages = []mcp.PromptMessage{
{
Role: "system",
Content: mcp.NewTextContent("你正在进行技术面试。提出有思考的问题并提供建设性的反馈。"),
},
{
Role: "user",
Content: mcp.NewTextContent("让我们开始技术面试。请从一个合适的问题开始。"),
},
}
}
return &mcp.GetPromptResult{
Description: fmt.Sprintf("%s 对话场景", strings.Title(scenario)),
Messages: messages,
}, nil
}系统和用户角色
go
func handleRoleBasedPrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
expertise := req.Params.Arguments["expertise"].(string)
task := req.Params.Arguments["task"].(string)
context := getStringArg(req.Params.Arguments, "context", "")
// 根据专业知识定义系统消息
var systemMessage string
switch expertise {
case "software_engineer":
systemMessage = "你是一位经验丰富的软件工程师,在系统设计、代码质量和最佳实践方面有专业知识。"
case "data_scientist":
systemMessage = "你是一位数据科学家,在统计分析、机器学习和数据可视化方面有专业知识。"
case "product_manager":
systemMessage = "你是一位产品经理,在用户体验、市场分析和功能优先级方面有专业知识。"
default:
systemMessage = fmt.Sprintf("你是 %s 方面的专家。", expertise)
}
messages := []mcp.PromptMessage{
{
Role: "system",
Content: mcp.NewTextContent(systemMessage),
},
}
// 如果提供了上下文则添加
if context != "" {
messages = append(messages, mcp.PromptMessage{
Role: "user",
Content: mcp.NewTextContent(fmt.Sprintf("上下文:%s", context)),
})
}
// 添加主要任务
messages = append(messages, mcp.PromptMessage{
Role: "user",
Content: mcp.NewTextContent(task),
})
return &mcp.GetPromptResult{
Description: fmt.Sprintf("%s 任务", strings.Title(expertise)),
Messages: messages,
}, nil
}嵌入资源
包含资源数据
go
func handleResourceEmbeddedPrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
documentURI := req.Params.Arguments["document_uri"].(string)
analysisType := getStringArg(req.Params.Arguments, "analysis_type", "summary")
// 获取文档内容
document, err := fetchResource(ctx, documentURI)
if err != nil {
return nil, fmt.Errorf("failed to fetch document: %w", err)
}
// 构建带有嵌入内容的分析提示词
var instructions string
switch analysisType {
case "summary":
instructions = "请提供该文档要点的简明摘要。"
case "critique":
instructions = "请对提出的论点和证据进行批判性分析。"
case "questions":
instructions = "请提出该文档引发或可用于探索的有思考的问题。"
case "action_items":
instructions = "请从该文档中提取可操作的项目和建议。"
}
return &mcp.GetPromptResult{
Description: fmt.Sprintf("文档 %s", analysisType),
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: mcp.NewTextContent(fmt.Sprintf(`%s
文档:%s
内容:
---
%s
---
请按照上述说明提供您的分析。`,
instructions,
documentURI,
document.Content,
)),
},
},
}, nil
}动态资源集成
go
func handleDynamicResourcePrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
resourceURIs := req.Params.Arguments["resource_uris"].([]interface{})
promptType := getStringArg(req.Params.Arguments, "prompt_type", "compare")
// 获取所有资源
var resources []ResourceData
for _, uri := range resourceURIs {
if uriStr, ok := uri.(string); ok {
resource, err := fetchResource(ctx, uriStr)
if err != nil {
return nil, fmt.Errorf("failed to fetch resource %s: %w", uriStr, err)
}
resources = append(resources, resource)
}
}
// 根据类型和资源构建提示词
var content strings.Builder
switch promptType {
case "compare":
content.WriteString("请比较和对比以下文档:\n\n")
for i, resource := range resources {
content.WriteString(fmt.Sprintf("文档 %d (%s):\n%s\n\n", i+1, resource.URI, resource.Content))
}
content.WriteString("请提供:\n1. 主要相似之处\n2. 重要差异\n3. 总体评估")
case "synthesize":
content.WriteString("请综合以下来源的信息:\n\n")
for i, resource := range resources {
content.WriteString(fmt.Sprintf("来源 %d (%s):\n%s\n\n", i+1, resource.URI, resource.Content))
}
content.WriteString("请创建融合所有来源洞察的统一分析。")
}
return &mcp.GetPromptResult{
Description: fmt.Sprintf("%s 多个资源", strings.Title(promptType)),
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: mcp.NewTextContent(content.String()),
},
},
}, nil
}高级提示词模式
条件提示词
go
func handleConditionalPrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
userLevel := getStringArg(req.Params.Arguments, "user_level", "beginner")
topic := req.Params.Arguments["topic"].(string)
includeExamples := getBoolArg(req.Params.Arguments, "include_examples", true)
var prompt strings.Builder
// 根据用户级别调整复杂度
switch userLevel {
case "beginner":
prompt.WriteString(fmt.Sprintf("请用适合新手理解的方式解释 %s。", topic))
prompt.WriteString("使用清晰的语言,避免术语。")
case "intermediate":
prompt.WriteString(fmt.Sprintf("请详细解释 %s。", topic))
prompt.WriteString("包括技术细节但确保清晰。")
case "advanced":
prompt.WriteString(fmt.Sprintf("请对 %s 进行深入分析。", topic))
prompt.WriteString("包括高级概念、边缘案例和技术细节。")
}
if includeExamples {
prompt.WriteString("请包含相关示例和实际应用。")
}
return &mcp.GetPromptResult{
Description: fmt.Sprintf("%s 面向 %s 级别的解释", topic, userLevel),
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: mcp.NewTextContent(prompt.String()),
},
},
}, nil
}
func getBoolArg(args map[string]interface{}, key string, defaultValue bool) bool {
if val, exists := args[key]; exists {
if b, ok := val.(bool); ok {
return b
}
}
return defaultValue
}基于模板的提示词
go
type PromptTemplate struct {
Name string
Description string
Template string
Variables []string
}
var promptTemplates = map[string]PromptTemplate{
"bug_report": {
Name: "Bug Report Analysis",
Description: "分析错误报告并建议解决方案",
Template: `请分析此错误报告:
**错误描述:** {{.description}}
**复现步骤:** {{.steps}}
**预期行为:** {{.expected}}
**实际行为:** {{.actual}}
**环境:** {{.environment}}
请提供:
1. 根本原因分析
2. 可能的解决方案
3. 预防策略
4. 优先级评估`,
Variables: []string{"description", "steps", "expected", "actual", "environment"},
},
"feature_request": {
Name: "Feature Request Evaluation",
Description: "评估功能请求",
Template: `请评估此功能请求:
**功能:** {{.feature}}
**用例:** {{.use_case}}
**用户故事:** {{.user_story}}
**验收标准:** {{.criteria}}
请评估:
1. 商业价值和影响
2. 技术可行性
3. 实现复杂度
4. 潜在风险和考虑因素`,
Variables: []string{"feature", "use_case", "user_story", "criteria"},
},
}
func handleTemplatePrompt(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
templateName := req.Params.Arguments["template"].(string)
variables := req.Params.Arguments["variables"].(map[string]interface{})
template, exists := promptTemplates[templateName]
if !exists {
return nil, fmt.Errorf("unknown template: %s", templateName)
}
// 替换模板变量
content := template.Template
for _, variable := range template.Variables {
if value, exists := variables[variable]; exists {
placeholder := fmt.Sprintf("{{.%s}}", variable)
content = strings.ReplaceAll(content, placeholder, fmt.Sprintf("%v", value))
}
}
return &mcp.GetPromptResult{
Description: template.Description,
Messages: []mcp.PromptMessage{
{
Role: "user",
Content: mcp.NewTextContent(content),
},
},
}, nil
}提示词过滤
根据上下文、会话或权限过滤哪些提示词对每个客户端可见——类似于通过 WithToolFilter 进行工具过滤。
基于权限的提示词过滤
go
s := server.NewMCPServer("Prompt Server", "1.0.0",
server.WithPromptCapabilities(true),
server.WithPromptFilter(func(ctx context.Context, prompts []mcp.Prompt) []mcp.Prompt {
session := server.ClientSessionFromContext(ctx)
if session == nil {
return nil
}
// 根据会话或上下文过滤提示词
var filtered []mcp.Prompt
for _, p := range prompts {
if shouldExposePrompt(ctx, p) {
filtered = append(filtered, p)
}
}
return filtered
}),
)可以添加多个过滤器并按顺序应用:
go
s := server.NewMCPServer("Server", "1.0.0",
server.WithPromptCapabilities(true),
server.WithPromptFilter(roleFilter),
server.WithPromptFilter(environmentFilter),
)提示词处理程序中间件
用横切关注点(如日志记录、缓存或身份验证)包装提示词处理程序——类似于 WithToolHandlerMiddleware。
go
s := server.NewMCPServer("Server", "1.0.0",
server.WithPromptCapabilities(true),
server.WithPromptHandlerMiddleware(func(next server.PromptHandlerFunc) server.PromptHandlerFunc {
return func(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
start := time.Now()
log.Printf("Prompt requested: %s", req.Params.Name)
result, err := next(ctx, req)
log.Printf("Prompt %s served in %v", req.Params.Name, time.Since(start))
return result, err
}
}),
)中间件按顺序组合——第一个注册的包装最外层:
go
s := server.NewMCPServer("Server", "1.0.0",
server.WithPromptCapabilities(true),
server.WithPromptHandlerMiddleware(loggingMiddleware),
server.WithPromptHandlerMiddleware(authMiddleware),
)
