在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应用服务。