在AI应用开发领域,MCP(Model Context Protocol)正在成为连接AI模型与外部系统的标准协议。作为Anthropic推出的开放协议,MCP主要包含三个核心概念:
Prompt(提示模板)用于定义可复用的提示词模板。
Tool(工具)用于扩展AI的能力边界。
Resource(资源)用于提供数据访问接口。
根据平时我工作中的实践,这篇文章就如何使用Go语言的官方MCP SDK实现Prompt功能做一个详细的介绍。
什么是MCP Prompt?
在MCP协议中,Prompt是一种可复用的提示模板机制。它允许服务器定义标准化的提示词模板,客户端可以轻松发现和使用这些模板。简单来说,Prompt就像是为AI准备的"预设剧本",用户可以通过简单的参数填充,快速生成复杂的提示内容。
MCP Prompt的核心价值在于:
- 标准化:统一的模板定义格式,便于跨平台使用
- 可复用:一次定义,多处使用,减少重复工作
- 参数化:支持动态参数,灵活适应不同场景
- 可发现:客户端可以自动发现服务器提供的所有Prompt
需要注意的是,MCP Prompt与我们常说的"系统Prompt"是两个不同的概念:
-
系统Prompt:是指在对话开始时设置的角色设定和行为约束,如"你是一个专业的代码审查专家",它贯穿整个对话过程,影响AI的基本行为模式。
-
MCP Prompt:是一种可复用的提示模板机制,它可以生成具体的提示内容,支持参数化和动态生成。MCP Prompt可以包含系统Prompt,但更侧重于提供结构化的提示模板,让用户能够快速构建复杂的提示场景。
简单来说,系统Prompt定义了AI的"身份",而MCP Prompt定义了AI的"任务模板"。
Go SDK核心类型解析
使用官方Go SDK(github.com/modelcontextprotocol/go-sdk/mcp)实现Prompt,需要了解几个核心类型:
Prompt结构体
Prompt结构体定义了一个提示模板的元信息:
type Prompt struct {
Name string // 唯一标识符
Title string // 显示标题
Description string // 功能描述
Arguments []*PromptArgument // 参数列表
}
Name字段是必填的,用于唯一标识这个Prompt。Description帮助AI理解这个Prompt的用途,Arguments则定义了模板可以接受的参数。
PromptArgument结构体
每个Prompt可以定义多个参数,实现模板的动态化:
type PromptArgument struct {
Name string // 参数名称
Description string // 参数描述
Required bool // 是否必填
}
PromptHandler函数类型
PromptHandler是处理Prompt请求的核心函数,当客户端请求获取Prompt内容时被调用:
type PromptHandler func(context.Context, *GetPromptRequest) (*GetPromptResult, error)
实战:实现代码审查Prompt
让我们通过一个实际案例,实现一个代码审查的Prompt模板。这个模板接收代码内容作为参数,生成结构化的代码审查提示。
创建MCP服务器
首先,创建一个基础的MCP服务器实例:
server := mcp.NewServer(&mcp.Implementation{
Name: "prompt-demo", Version: "1.0.0",
}, nil)
// 添加Prompt...
if err := server.Run(ctx, &mcp.StdioTransport{}); err != nil {
log.Fatal(err)
}
定义Prompt模板
使用AddPrompt方法注册Prompt模板:
server.AddPrompt(&mcp.Prompt{
Name: "code_review", Title: "代码审查助手",
Description: "对代码进行专业的质量审查",
Arguments: []*mcp.PromptArgument{
{Name: "code", Description: "需要审查的代码", Required: true},
{Name: "language", Description: "编程语言", Required: false},
},
}, handleCodeReview)
这里定义了一个名为code_review的Prompt,它接受两个参数:必填的code和可选的language。
实现PromptHandler
接下来实现处理函数,返回具体的提示消息:
func handleCodeReview(ctx context.Context, req *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
code := areq.Params.Argumentsrgs["code"]
language := arreq.Params.Argumentsgs["language"]
if language == "" { language = "未知" }
promptText := fmt.Sprintf("请对以下%s代码进行审查:\n%s", language, code)
return &mcp.GetPromptResult{
Messages: []*mcp.PromptMessage{{
Role: mcp.RoleUser,
Content: &mcp.TextContent{Text: promptText},
}},
}, nil
}
这个处理函数从请求中提取参数,构建结构化的提示消息并返回。
进阶:多消息对话Prompt
Prompt不仅支持单条消息,还支持多轮对话格式的消息序列。这在需要预设对话上下文的场景非常有用。
实现技术问答Prompt
支持多消息的Prompt示例:
server.AddPrompt(&mcp.Prompt{
Name: "tech_qa", Title: "技术问答助手",
Arguments: []*mcp.PromptArgument{
{Name: "question", Required: true},
{Name: "domain", Required: false},
},
}, handleTechQA)
func handleTechQA(ctx context.Context, req *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
args := req.Params.Arguments
return &mcp.GetPromptResult{
Messages: []*mcp.PromptMessage{
{Role: mcp.RoleUser, Content: &mcp.TextContent{Text: args["question"]}},
},
}, nil
}
动态更新Prompt列表
MCP支持在运行时动态添加或移除Prompt,并通过通知机制告知客户端:
移除Prompt
// 移除指定的Prompt
server.RemovePrompts("old_prompt_name")
动态添加Prompt
可以在运行时根据条件动态添加新的Prompt:
server.AddPrompt(&mcp.Prompt{Name: "advanced_analysis"}, handler)
当Prompt列表发生变化时,SDK会自动向已连接的客户端发送notifications/prompts/list_changed通知。
最佳实践建议
参数设计原则
- 必填参数最小化:只将核心参数设为必填,提高易用性
- 提供默认值:在处理函数中为可选参数设置合理的默认值
- 参数描述清晰:让AI和用户都能理解参数的用途
安全注意事项
- 输入验证:对所有参数进行严格的输入验证,防止注入攻击
- 敏感信息过滤:避免在Prompt中暴露敏感信息
- 权限控制:根据用户权限动态调整可用的Prompt列表
写在最后
通过Go语言的官方MCP SDK,我们可以轻松实现功能强大的Prompt模板系统。从简单的单消息模板到复杂的多轮对话预设,Prompt为AI应用提供了标准化的提示词管理能力。
随着AI应用的普及,MCP协议正在成为连接AI与外部系统的重要桥梁。掌握Prompt的实现技巧,将帮助你构建更加灵活、可维护的AI应用服务。