高级Server功能
图标
图标为服务器、工具、资源和提示词提供视觉标识符。所有图标 URI 必须使用 HTTPS 或数据 URI 方案以确保安全。
安全注意事项
- 始终验证图标来源来自可信域
- 强制大小限制以防止内存问题
- 至少支持 PNG 和 JPEG 格式
- 考虑支持 SVG 和 WebP 以获得更好的质量/大小
使用数据 URI 的示例
mcp.Icon{
Src: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz4=",
MIMEType: "image/svg+xml",
}主题特定图标
图标可以选择性地声明它们设计用于哪个背景主题。客户端在浅色或深色 UI 上渲染时使用该提示来选择正确的资源:
icons := []mcp.Icon{
{
Src: "https://example.com/icons/tool-light.svg",
MIMEType: "image/svg+xml",
Theme: mcp.IconThemeLight, // 为浅色背景设计
},
{
Src: "https://example.com/icons/tool-dark.svg",
MIMEType: "image/svg+xml",
Theme: mcp.IconThemeDark, // 为深色背景设计
},
}Theme 字段是可选的——没有主题的图标被视为主题无关的。支持 mcp.IconThemeLight 和 mcp.IconThemeDark 常量;未知值会原样传递以实现向前兼容。
探索使 MCP-Go 服务器可用于生产的功能:类型工具、会话管理、中间件、钩子等。
类型工具
类型工具提供编译时类型安全和自动参数验证,减少样板代码并防止运行时错误。
基本类型工具
package main
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
// 定义输入和输出类型
type CalculateInput struct {
Operation string `json:"operation" validate:"required,oneof=add subtract multiply divide"`
X float64 `json:"x" validate:"required"`
Y float64 `json:"y" validate:"required"`
}
type CalculateOutput struct {
Result float64 `json:"result"`
Operation string `json:"operation"`
}
func main() {
s := server.NewMCPServer("Typed Server", "1.0.0",
server.WithToolCapabilities(true),
)
// 创建类型工具
tool := mcp.NewTool("calculate",
mcp.WithDescription("执行算术运算"),
mcp.WithString("operation", mcp.Required()),
mcp.WithNumber("x", mcp.Required()),
mcp.WithNumber("y", mcp.Required()),
)
// 使用类型处理程序添加工具
s.AddTool(tool, mcp.NewTypedToolHandler(handleCalculateTyped))
server.ServeStdio(s)
}
func handleCalculateTyped(ctx context.Context, req mcp.CallToolRequest, input CalculateInput) (*mcp.CallToolResult, error) {
var result float64
switch input.Operation {
case "add":
result = input.X + input.Y
case "subtract":
result = input.X - input.Y
case "multiply":
result = input.X * input.Y
case "divide":
if input.Y == 0 {
return mcp.NewToolResultError("division by zero"), nil
}
result = input.X / input.Y
}
output := CalculateOutput{
Result: result,
Operation: input.Operation,
}
jsonData, err := json.Marshal(output)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to marshal result: %v", err)), nil
}
return mcp.NewToolResultText(string(jsonData)), nil
}复杂类型工具
type UserCreateInput struct {
Name string `json:"name" validate:"required,min=1,max=100"`
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"min=0,max=150"`
Tags []string `json:"tags" validate:"dive,min=1"`
Metadata map[string]string `json:"metadata"`
Active bool `json:"active"`
}
type UserCreateOutput struct {
ID string `json:"id"`
Name string `json:"name"`
Email string `json:"email"`
CreatedAt time.Time `json:"created_at"`
Status string `json:"status"`
}
func handleCreateUser(ctx context.Context, req mcp.CallToolRequest, input UserCreateInput) (*mcp.CallToolResult, error) {
// 验证基于结构标签是自动的
// 在数据库中创建用户
user := &User{
ID: generateID(),
Name: input.Name,
Email: input.Email,
Age: input.Age,
Tags: input.Tags,
Metadata: input.Metadata,
Active: input.Active,
CreatedAt: time.Now(),
}
if err := db.Create(user); err != nil {
return nil, fmt.Errorf("failed to create user: %w", err)
}
output := &UserCreateOutput{
ID: user.ID,
Name: user.Name,
Email: user.Email,
CreatedAt: user.CreatedAt,
Status: "created",
}
return mcp.NewToolResultJSON(output)
}自定义验证
import (
"path/filepath"
"strings"
"github.com/go-playground/validator/v10"
)
type FileOperationInput struct {
Path string `json:"path" validate:"required,filepath"`
Operation string `json:"operation" validate:"required,oneof=read write delete"`
Content string `json:"content" validate:"required_if=Operation write"`
}
// 自定义验证器
func init() {
validate := validator.New()
validate.RegisterValidation("filepath", validateFilePath)
}
func validateFilePath(fl validator.FieldLevel) bool {
path := fl.Field().String()
// 防止目录遍历
if strings.Contains(path, "..") {
return false
}
// 确保路径在允许的目录内
allowedDir := "/app/data"
absPath, err := filepath.Abs(path)
if err != nil {
return false
}
return strings.HasPrefix(absPath, allowedDir)
}会话管理
使用每个会话状态和工具处理多个客户端。
每个会话状态
type SessionState struct {
UserID string
Permissions []string
Settings map[string]interface{}
StartTime time.Time
}
type SessionManager struct {
sessions map[string]*SessionState
mutex sync.RWMutex
}
func NewSessionManager() *SessionManager {
return &SessionManager{
sessions: make(map[string]*SessionState),
}
}
func (sm *SessionManager) CreateSession(sessionID, userID string, permissions []string) {
sm.mutex.Lock()
defer sm.mutex.Unlock()
sm.sessions[sessionID] = &SessionState{
UserID: userID,
Permissions: permissions,
Settings: make(map[string]interface{}),
StartTime: time.Now(),
}
}
func (sm *SessionManager) GetSession(sessionID string) (*SessionState, bool) {
sm.mutex.RLock()
defer sm.mutex.RUnlock()
session, exists := sm.sessions[sessionID]
return session, exists
}
func (sm *SessionManager) RemoveSession(sessionID string) {
sm.mutex.Lock()
defer sm.mutex.Unlock()
delete(sm.sessions, sessionID)
}会话感知工具
func main() {
sessionManager := NewSessionManager()
hooks := &server.Hooks{}
hooks.AddOnRegisterSession(func(ctx context.Context, session server.ClientSession) {
// 使用默认权限初始化会话
sessionManager.CreateSession(session.ID(), "anonymous", []string{"read"})
log.Printf("Session %s started", session.ID())
})
hooks.AddOnUnregisterSession(func(ctx context.Context, session server.ClientSession) {
sessionManager.RemoveSession(session.ID())
log.Printf("Session %s ended", session.ID())
})
s := server.NewMCPServer("Session Server", "1.0.0",
server.WithToolCapabilities(true),
server.WithHooks(hooks),
)
// 添加会话感知工具
s.AddTool(
mcp.NewTool("get_user_data",
mcp.WithDescription("获取用户特定数据"),
mcp.WithString("data_type", mcp.Required()),
),
createSessionAwareTool(sessionManager),
)
server.ServeStdio(s)
}
func createSessionAwareTool(sm *SessionManager) server.ToolHandler {
return func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
sessionID := server.GetSessionID(ctx)
session, exists := sm.GetSession(sessionID)
if !exists {
return nil, fmt.Errorf("invalid session")
}
dataType := req.Params.Arguments["data_type"].(string)
// 检查权限
if !hasPermission(session.Permissions, "read") {
return nil, fmt.Errorf("insufficient permissions")
}
// 获取用户特定数据
data, err := getUserData(session.UserID, dataType)
if err != nil {
return nil, err
}
jsonData, err := json.Marshal(data)
if err != nil {
return mcp.NewToolResultError(fmt.Sprintf("failed to marshal result: %v", err)), nil
}
return mcp.NewToolResultText(string(jsonData)), nil
}
}中间件
添加日志记录、身份验证和速率限制等横切关注点。
日志中间件
type LoggingMiddleware struct {
logger *log.Logger
}
func NewLoggingMiddleware(logger *log.Logger) *LoggingMiddleware {
return &LoggingMiddleware{logger: logger}
}
func (m *LoggingMiddleware) ToolMiddleware(next server.ToolHandlerFunc) server.ToolHandlerFunc {
return func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
start := time.Now()
sessionID := server.GetSessionID(ctx)
m.logger.Printf("Tool call started: tool=%s", req.Params.Name)
result, err := next(ctx, req)
duration := time.Since(start)
if err != nil {
m.logger.Printf("Tool call failed: session=%s tool=%s duration=%v error=%v",
sessionID, req.Params.Name, duration, err)
} else {
m.logger.Printf("Tool call completed: session=%s tool=%s duration=%v",
sessionID, req.Params.Name, duration)
}
return result, err
}
}
func (m *LoggingMiddleware) ResourceMiddleware(next server.ResourceHandler) server.ResourceHandler {
return func(ctx context.Context, req mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) {
start := time.Now()
sessionID := server.GetSessionID(ctx)
m.logger.Printf("Resource read started: session=%s uri=%s", sessionID, req.Params.URI)
result, err := next(ctx, req)
duration := time.Since(start)
if err != nil {
m.logger.Printf("Resource read failed: session=%s uri=%s duration=%v error=%v",
sessionID, req.Params.URI, duration, err)
} else {
m.logger.Printf("Resource read completed: session=%s uri=%s duration=%v",
sessionID, req.Params.URI, duration)
}
return result, err
}
}速率限制中间件
type RateLimitMiddleware struct {
limiters map[string]*rate.Limiter
mutex sync.RWMutex
rate rate.Limit
burst int
}
func NewRateLimitMiddleware(requestsPerSecond float64, burst int) *RateLimitMiddleware {
return &RateLimitMiddleware{
limiters: make(map[string]*rate.Limiter),
rate: rate.Limit(requestsPerSecond),
burst: burst,
}
}
func (m *RateLimitMiddleware) getLimiter(sessionID string) *rate.Limiter {
m.mutex.RLock()
limiter, exists := m.limiters[sessionID]
m.mutex.RUnlock()
if !exists {
m.mutex.Lock()
limiter = rate.NewLimiter(m.rate, m.burst)
m.limiters[sessionID] = limiter
m.mutex.Unlock()
}
return limiter
}
func (m *RateLimitMiddleware) ToolMiddleware(next server.ToolHandler) server.ToolHandler {
return func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
sessionID := server.GetSessionID(ctx)
limiter := m.getLimiter(sessionID)
if !limiter.Allow() {
return nil, fmt.Errorf("rate limit exceeded for session %s", sessionID)
}
return next(ctx, req)
}
}身份验证中间件
type AuthMiddleware struct {
tokenValidator TokenValidator
}
func NewAuthMiddleware(validator TokenValidator) *AuthMiddleware {
return &AuthMiddleware{tokenValidator: validator}
}
func (m *AuthMiddleware) ToolMiddleware(next server.ToolHandler) server.ToolHandler {
return func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// 从上下文或请求中提取令牌
token := extractToken(ctx, req)
if token == "" {
return nil, fmt.Errorf("authentication required")
}
// 验证令牌
user, err := m.tokenValidator.Validate(token)
if err != nil {
return nil, fmt.Errorf("invalid token: %w", err)
}
// 将用户添加到上下文
ctx = context.WithValue(ctx, "user", user)
return next(ctx, req)
}
}钩子
实现用于遥测、日志记录和自定义行为的生命周期回调。
使用 GetHooks() 的钩子可组合性
使用 GetHooks() 向现有服务器追加钩子,而不替换整个钩子配置。这对于需要在构建后添加钩子的库或插件很有用:
s := server.NewMCPServer("My Server", "1.0.0",
server.WithHooks(initialHooks),
)
// 之后,在不替换现有钩子的情况下添加更多钩子
hooks := s.GetHooks()
if hooks == nil {
hooks = &server.Hooks{}
}
hooks.AddBeforeAny(func(ctx context.Context, id any, method mcp.MCPMethod, message any) {
log.Printf("Request: %s", method)
})综合钩子
type TelemetryHooks struct {
metrics MetricsCollector
logger *log.Logger
}
func NewTelemetryHooks(metrics MetricsCollector, logger *log.Logger) *TelemetryHooks {
return &TelemetryHooks{
metrics: metrics,
logger: logger,
}
}
func (h *TelemetryHooks) OnServerStart() {
h.logger.Println("MCP Server starting")
h.metrics.Increment("server.starts")
}
func (h *TelemetryHooks) OnServerStop() {
h.logger.Println("MCP Server stopping")
h.metrics.Increment("server.stops")
}
func (h *TelemetryHooks) OnSessionStart(sessionID string) {
h.logger.Printf("Session started: %s", sessionID)
h.metrics.Increment("sessions.started")
h.metrics.Gauge("sessions.active", h.getActiveSessionCount())
}
func (h *TelemetryHooks) OnSessionEnd(sessionID string) {
h.logger.Printf("Session ended: %s", sessionID)
h.metrics.Increment("sessions.ended")
h.metrics.Gauge("sessions.active", h.getActiveSessionCount())
}
func (h *TelemetryHooks) OnToolCall(sessionID, toolName string, duration time.Duration, err error) {
h.metrics.Increment("tools.calls", map[string]string{
"tool": toolName,
"session": sessionID,
})
h.metrics.Histogram("tools.duration", duration.Seconds(), map[string]string{
"tool": toolName,
})
if err != nil {
h.metrics.Increment("tools.errors", map[string]string{
"tool": toolName,
})
}
}
func (h *TelemetryHooks) OnResourceRead(sessionID, uri string, duration time.Duration, err error) {
h.metrics.Increment("resources.reads", map[string]string{
"session": sessionID,
})
h.metrics.Histogram("resources.duration", duration.Seconds())
if err != nil {
h.metrics.Increment("resources.errors")
}
}自定义业务逻辑钩子
type BusinessHooks struct {
auditLogger AuditLogger
notifier Notifier
}
func (h *BusinessHooks) OnToolCall(sessionID, toolName string, duration time.Duration, err error) {
// 审计敏感操作
if isSensitiveTool(toolName) {
h.auditLogger.LogToolCall(sessionID, toolName, err)
}
// 警报错误
if err != nil {
h.notifier.SendAlert(fmt.Sprintf("Tool %s failed for session %s: %v",
toolName, sessionID, err))
}
// 监控性能
if duration > 30*time.Second {
h.notifier.SendAlert(fmt.Sprintf("Slow tool execution: %s took %v",
toolName, duration))
}
}
func (h *BusinessHooks) OnSessionStart(sessionID string) {
// 初始化用户特定资源
h.initializeUserResources(sessionID)
// 发送欢迎通知
h.notifier.SendWelcome(sessionID)
}
func (h *BusinessHooks) OnSessionEnd(sessionID string) {
// 清理用户资源
h.cleanupUserResources(sessionID)
// 记录会话摘要
h.auditLogger.LogSessionEnd(sessionID)
}工具过滤
根据上下文、权限或其他条件有条件地公开工具。
基于权限的过滤
type PermissionFilter struct {
sessionManager *SessionManager
}
func NewPermissionFilter(sm *SessionManager) *PermissionFilter {
return &PermissionFilter{sessionManager: sm}
}
func (f *PermissionFilter) FilterTools(ctx context.Context, tools []mcp.Tool) []mcp.Tool {
sessionID := server.GetSessionID(ctx)
session, exists := f.sessionManager.GetSession(sessionID)
if !exists {
return []mcp.Tool{} // 无效会话没有工具
}
var filtered []mcp.Tool
for _, tool := range tools {
if f.hasPermissionForTool(session, tool.Name) {
filtered = append(filtered, tool)
}
}
return filtered
}
func (f *PermissionFilter) hasPermissionForTool(session *SessionState, toolName string) bool {
requiredPermissions := map[string][]string{
"delete_user": {"admin"},
"modify_system": {"admin", "operator"},
"read_data": {"admin", "operator", "user"},
"create_report": {"admin", "operator", "user"},
}
required, exists := requiredPermissions[toolName]
if !exists {
return true // 允许没有特定要求的工具
}
for _, permission := range session.Permissions {
for _, req := range required {
if permission == req {
return true
}
}
}
return false
}基于上下文的过滤
type ContextFilter struct{}
func (f *ContextFilter) FilterTools(ctx context.Context, tools []mcp.Tool) []mcp.Tool {
timeOfDay := time.Now().Hour()
environment := os.Getenv("ENVIRONMENT")
var filtered []mcp.Tool
for _, tool := range tools {
if f.shouldIncludeTool(tool, timeOfDay, environment) {
filtered = append(filtered, tool)
}
}
return filtered
}
func (f *ContextFilter) shouldIncludeTool(tool mcp.Tool, hour int, env string) bool {
// 维护工具仅在非工作时间
maintenanceTools := map[string]bool{
"backup_database": true,
"cleanup_logs": true,
"restart_service": true,
}
if maintenanceTools[tool.Name] {
return hour < 6 || hour > 22 // 仅在晚上10点到早上6点之间
}
// 调试工具仅在开发中
debugTools := map[string]bool{
"debug_session": true,
"dump_state": true,
}
if debugTools[tool.Name] {
return env == "development"
}
return true
}通知
发送服务器到客户端的消息以获取实时更新。
自定义通知
func handleLongRunningTool(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
srv := server.ServerFromContext(ctx)
// 模拟长时间运行的工作
for i := 0; i < 100; i++ {
time.Sleep(100 * time.Millisecond)
// 向所有客户端发送自定义通知
notification := map[string]interface{}{
"type": "progress",
"progress": i + 1,
"total": 100,
"message": fmt.Sprintf("Processing step %d/100", i+1),
}
srv.SendNotificationToAllClients("progress", notification)
}
return mcp.NewToolResultText("Long operation completed successfully"), nil
}自定义通知器
type CustomNotifier struct {
sessions map[string]chan mcp.Notification
mutex sync.RWMutex
}
func NewCustomNotifier() *CustomNotifier {
return &CustomNotifier{
sessions: make(map[string]chan mcp.Notification),
}
}
func (n *CustomNotifier) RegisterSession(sessionID string) {
n.mutex.Lock()
defer n.mutex.Unlock()
n.sessions[sessionID] = make(chan mcp.Notification, 100)
}
func (n *CustomNotifier) UnregisterSession(sessionID string) {
n.mutex.Lock()
defer n.mutex.Unlock()
if ch, exists := n.sessions[sessionID]; exists {
close(ch)
delete(n.sessions, sessionID)
}
}
func (n *CustomNotifier) SendAlert(sessionID, message string, severity string) {
n.mutex.RLock()
defer n.mutex.RUnlock()
if ch, exists := n.sessions[sessionID]; exists {
select {
case ch <- mcp.Notification{
Type: "alert",
Data: map[string]interface{}{
"message": message,
"severity": severity,
"timestamp": time.Now().Unix(),
},
}:
default:
// 通道已满,丢弃通知
}
}
}
func (n *CustomNotifier) BroadcastSystemMessage(message string) {
n.mutex.RLock()
defer n.mutex.RUnlock()
notification := mcp.Notification{
Type: "system_message",
Data: map[string]interface{}{
"message": message,
"timestamp": time.Now().Unix(),
},
}
for _, ch := range n.sessions {
select {
case ch <- notification:
default:
// 通道已满,跳过此会话
}
}
}生产配置
完整生产服务器
func main() {
// 初始化组件
logger := log.New(os.Stdout, "[MCP] ", log.LstdFlags)
metrics := NewPrometheusMetrics()
sessionManager := NewSessionManager()
notifier := NewCustomNotifier()
// 创建中间件
loggingMW := NewLoggingMiddleware(logger)
rateLimitMW := NewRateLimitMiddleware(10.0, 20) // 10 req/sec, burst 20
authMW := NewAuthMiddleware(NewJWTValidator())
// 创建钩子
telemetryHooks := NewTelemetryHooks(metrics, logger)
businessHooks := NewBusinessHooks(NewAuditLogger(), NewSlackNotifier())
// 使用所有功能创建服务器
s := server.NewMCPServer("Production Server", "1.0.0",
server.WithToolCapabilities(true),
server.WithResourceCapabilities(false, true),
server.WithPromptCapabilities(true),
server.WithRecovery(),
server.WithHooks(telemetryHooks),
server.WithToolHandlerMiddleware(loggingMW.ToolMiddleware),
server.WithToolFilter(NewPermissionFilter(sessionManager)),
)
// 添加工具和资源
addProductionTools(s)
addProductionResources(s)
addProductionPrompts(s)
// 使用优雅关闭启动服务器
startWithGracefulShutdown(s)
}
func startWithGracefulShutdown(s *server.MCPServer) {
// 设置信号处理
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.Sigterm)
// 在 goroutine 中启动服务器
go func() {
if err := server.ServeStdio(s); err != nil {
log.Printf("Server error: %v", err)
}
}()
// 等待关闭信号
<-sigChan
log.Println("Shutting down server...")
// 带超时的优雅关闭
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := s.Shutdown(ctx); err != nil {
log.Printf("Shutdown error: %v", err)
}
log.Println("Server stopped")
}基于客户端能力的过滤
package main
import (
"context"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
s := server.NewMCPServer("Typed Server", "1.0.0",
server.WithToolCapabilities(true),
)
s.AddTool(
mcp.NewTool("calculate",
mcp.WithDescription("执行基本数学计算"),
mcp.WithString("operation",
mcp.Required(),
mcp.Enum("add", "subtract", "multiply", "divide"),
mcp.Description("要执行的运算"),
),
mcp.WithNumber("x", mcp.Required(), mcp.Description("第一个数字")),
mcp.WithNumber("y", mcp.Required(), mcp.Description("第二个数字")),
),
handleCalculate,
)
server.ServeStdio(s)
}
func handleCalculate(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
session := server.ClientSessionFromContext(ctx)
if session == nil {
return nil, fmt.Errorf("no active session")
}
if clientSession, ok := session.(server.SessionWithClientInfo); ok {
clientCapabilities := clientSession.GetClientCapabilities()
if clientCapabilities.Sampling == nil {
fmt.Println("sampling is not enabled in client")
}
}
// TODO: implement calculation logic
return mcp.NewToolResultError("not implemented"), nil
}采样(高级)
采样是一种高级功能,允许服务器从客户端请求 LLM 完成。这实现了双向通信,服务器可以利用客户端的 LLM 功能进行内容生成、推理和问答。
注意:采样是一种高级功能,大多数服务器不需要。仅当您的服务器明确需要使用客户端的 LLM 生成内容时才实现采样。
何时使用采样
当您的服务器需要以下功能时考虑采样:
- 基于用户输入生成内容
- 使用 LLM 推理回答问题
- 执行文本分析或摘要
- 创建需要 LLM 功能的动态响应
基本实现
// 启用采样能力
mcpServer.EnableSampling()
// 添加使用采样的工具
mcpServer.AddTool(mcp.Tool{
Name: "ask_llm",
Description: "使用采样向 LLM 提问",
InputSchema: mcp.ToolInputSchema{
Type: "object",
Properties: map[string]any{
"question": map[string]any{
"type": "string",
"description": "要问 LLM 的问题",
},
},
Required: []string{"question"},
},
}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
question, err := request.RequireString("question")
if err != nil {
return nil, err
}
// 创建采样请求
samplingRequest := mcp.CreateMessageRequest{
CreateMessageParams: mcp.CreateMessageParams{
Messages: []mcp.SamplingMessage{
{
Role: mcp.RoleUser,
Content: mcp.TextContent{
Type: "text",
Text: question,
},
},
},
SystemPrompt: "You are a helpful assistant.",
MaxTokens: 1000,
Temperature: 0.7,
},
}
// 从客户端请求采样
result, err := mcpServer.RequestSampling(ctx, samplingRequest)
if err != nil {
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("Error: %v", err),
},
},
IsError: true,
}, nil
}
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: fmt.Sprintf("LLM Response: %s", result.Content),
},
},
}, nil
})其他内容类型
AudioContent
音频数据可以嵌入在提示词消息或工具结果中:
audioResult := &mcp.CallToolResult{
Content: []mcp.Content{
mcp.AudioContent{
Type: "audio",
Data: base64EncodedAudioData,
MIMEType: "audio/wav",
},
},
}AudioContent 字段:
Type— 必须为"audio"Data— base64 编码的音频数据MIMEType— 音频的 MIME 类型(例如"audio/wav"、"audio/mp3")
ResourceLink
工具结果可以包含指向服务器资源的链接,而不是内联内容:
result := &mcp.CallToolResult{
Content: []mcp.Content{
mcp.ResourceLink{
Type: "resource_link",
URI: "files://reports/q4-summary.pdf",
Name: "Q4 Summary Report",
Description: "季度财务摘要",
MIMEType: "application/pdf",
},
},
}Roots 能力
启用 roots 能力以从连接的客户端请求根目录信息:
s := server.NewMCPServer("Server", "1.0.0",
server.WithRoots(),
)启用后,服务器在其能力中公布 roots 支持。支持 SessionWithRoots 接口的客户端可以提供服务器可用于文件操作、项目范围界定和类似用例的根目录信息。
有关完整的采样文档,请参阅**服务器采样指南**。

