You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm using the sampling http client and server examples, but it doesn't work for me. The server receives a tool call and initiates sampling, but the the sampling request never reaches the client.
Code below:
Server:
package main import ( "context" "fmt" "log" "time" "github.com/mark3labs/mcp-go/mcp" "github.com/mark3labs/mcp-go/server" ) func main() { // Create MCP server with sampling capability mcpServer := server.NewMCPServer("sampling-http-server", "1.0.0") // Enable sampling capability mcpServer.EnableSampling() // Add a tool that uses sampling to get LLM responses mcpServer.AddTool(mcp.Tool{ Name: "ask_llm", Description: "Ask the LLM a question using sampling over HTTP", InputSchema: mcp.ToolInputSchema{ Type: "object", Properties: map[string]any{ "question": map[string]any{ "type": "string", "description": "The question to ask the LLM", }, "system_prompt": map[string]any{ "type": "string", "description": "Optional system prompt to provide context", }, }, Required: []string{"question"}, }, }, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { fmt.Println("DEBUG - Tool has been called.") // Extract parameters question, err := request.RequireString("question") if err != nil { return nil, err } fmt.Println("DEBUG - question is ", question) systemPrompt := request.GetString("system_prompt", "You are a helpful assistant.") // Create sampling request samplingRequest := mcp.CreateMessageRequest{ CreateMessageParams: mcp.CreateMessageParams{ Messages: []mcp.SamplingMessage{ { Role: mcp.RoleUser, Content: mcp.TextContent{ Type: "text", Text: question, }, }, }, SystemPrompt: systemPrompt, MaxTokens: 1000, Temperature: 0.7, }, } // Request sampling from the client with timeout samplingCtx, cancel := context.WithTimeout(ctx, 2*time.Minute) defer cancel() fmt.Println("About to request sampling from the client.") serverFromCtx := server.ServerFromContext(ctx) result, err := serverFromCtx.RequestSampling(samplingCtx, samplingRequest) if err != nil { fmt.Println("DEBUG - error requesting sampling from the client") fmt.Println("DEBUG - error is ", err) return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Error requesting sampling: %v", err), }, }, IsError: true, }, nil } // Extract response text safely var responseText string if textContent, ok := result.Content.(mcp.TextContent); ok { responseText = textContent.Text } else { responseText = fmt.Sprintf("%v", result.Content) } fmt.Println("DEBUG - response text is: ", responseText) // Return the LLM response return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("LLM Response (model: %s): %s", result.Model, responseText), }, }, }, nil }) // Add a simple echo tool for testing mcpServer.AddTool(mcp.Tool{ Name: "echo", Description: "Echo back the input message", InputSchema: mcp.ToolInputSchema{ Type: "object", Properties: map[string]any{ "message": map[string]any{ "type": "string", "description": "The message to echo back", }, }, Required: []string{"message"}, }, }, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { message := request.GetString("message", "") return &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: fmt.Sprintf("Echo: %s", message), }, }, }, nil }) // Create HTTP server httpServer := server.NewStreamableHTTPServer(mcpServer) log.Println("Starting HTTP MCP server with sampling support on :8080") log.Println("Endpoint: http://localhost:8080/mcp") log.Println("") log.Println("This server supports sampling over HTTP transport.") log.Println("Clients must:") log.Println("1. Initialize with sampling capability") log.Println("2. Establish SSE connection for bidirectional communication") log.Println("3. Handle incoming sampling requests from the server") log.Println("4. Send responses back via HTTP POST") log.Println("") log.Println("Available tools:") log.Println("- ask_llm: Ask the LLM a question (requires sampling)") log.Println("- echo: Simple echo tool (no sampling required)") // Start the server if err := httpServer.Start(":8080"); err != nil { log.Fatalf("Server failed to start: %v", err) } }
Client:
package main import ( "context" "fmt" "log" "os" "os/signal" "syscall" "github.com/mark3labs/mcp-go/client" "github.com/mark3labs/mcp-go/client/transport" "github.com/mark3labs/mcp-go/mcp" ) // MockSamplingHandler implements client.SamplingHandler for demonstration. // In a real implementation, this would integrate with an actual LLM API. type MockSamplingHandler struct{} func (h *MockSamplingHandler) CreateMessage(ctx context.Context, request mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) { fmt.Println("DEBUG - sampling handler activated") // Extract the user's message if len(request.Messages) == 0 { return nil, fmt.Errorf("no messages provided") } // Get the last user message lastMessage := request.Messages[len(request.Messages)-1] userText := "" if textContent, ok := lastMessage.Content.(mcp.TextContent); ok { userText = textContent.Text } // Generate a mock response responseText := fmt.Sprintf("Mock LLM response to: '%s'", userText) log.Printf("Mock LLM generating response: %s", responseText) result := &mcp.CreateMessageResult{ SamplingMessage: mcp.SamplingMessage{ Role: mcp.RoleAssistant, Content: mcp.TextContent{ Type: "text", Text: responseText, }, }, Model: "mock-model-v1", StopReason: "endTurn", } return result, nil } func main() { // Create sampling handler samplingHandler := &MockSamplingHandler{} // Create HTTP transport directly httpTransport, err := transport.NewStreamableHTTP( "http://localhost:8080/mcp", // Replace with your MCP server URL // You can add HTTP-specific options here like headers, OAuth, etc. ) if err != nil { log.Fatalf("Failed to create HTTP transport: %v", err) } defer httpTransport.Close() // Create client with sampling support mcpClient := client.NewClient( httpTransport, client.WithSamplingHandler(samplingHandler), ) // Start the client ctx := context.Background() err = mcpClient.Start(ctx) if err != nil { log.Fatalf("Failed to start client: %v", err) } // Initialize the MCP session initRequest := mcp.InitializeRequest{ Params: mcp.InitializeParams{ ProtocolVersion: mcp.LATEST_PROTOCOL_VERSION, Capabilities: mcp.ClientCapabilities{ // Sampling capability will be automatically added by the client }, ClientInfo: mcp.Implementation{ Name: "sampling-http-client", Version: "1.0.0", }, }, } _, err = mcpClient.Initialize(ctx, initRequest) if err != nil { log.Fatalf("Failed to initialize MCP session: %v", err) } ctx = context.Background() result, err := mcpClient.ListTools(ctx, mcp.ListToolsRequest{}) fmt.Println(result) fmt.Println("About to print the results of the request:") requestResult, err := mcpClient.CallTool(ctx, mcp.CallToolRequest{ Params: mcp.CallToolParams{ Name: "ask_llm", Arguments: map[string]interface{}{ "question": "What's the capital city of the UK?", "format": "text", }, }, }) fmt.Println(requestResult) log.Println("HTTP MCP client with sampling support started successfully!") log.Println("The client is now ready to handle sampling requests from the server.") log.Println("When the server sends a sampling request, the MockSamplingHandler will process it.") // In a real application, you would keep the client running to handle sampling requests // For this example, we'll just demonstrate that it's working // Keep the client running (in a real app, you'd have your main application logic here) sigChan := make(chan os.Signal, 1) signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM) select { case <-ctx.Done(): log.Println("Client context cancelled") case <-sigChan: log.Println("Received shutdown signal") } }
Server log:
2025/09/17 14:07:42 Starting HTTP MCP server with sampling support on :8080 2025/09/17 14:07:42 Endpoint: http://localhost:8080/mcp 2025/09/17 14:07:42 2025/09/17 14:07:42 This server supports sampling over HTTP transport. 2025/09/17 14:07:42 Clients must: 2025/09/17 14:07:42 1. Initialize with sampling capability 2025/09/17 14:07:42 2. Establish SSE connection for bidirectional communication 2025/09/17 14:07:42 3. Handle incoming sampling requests from the server 2025/09/17 14:07:42 4. Send responses back via HTTP POST 2025/09/17 14:07:42 2025/09/17 14:07:42 Available tools: 2025/09/17 14:07:42 - ask_llm: Ask the LLM a question (requires sampling) 2025/09/17 14:07:42 - echo: Simple echo tool (no sampling required)
Client log:
&{{{<nil>} } [{<nil> ask_llm Ask the LLM a question using sampling over HTTP {map[] object map[question:map[description:The question to ask the LLM type:string] system_prompt:map[description:Optional system prompt to provide context type:string]] [question]} [] {map[] map[] []} [] { <nil> <nil> <nil> <nil>}} {<nil> echo Echo back the input message {map[] object map[message:map[description:The message to echo back type:string]] [message]} [] {map[] map[] []} [] { <nil> <nil> <nil> <nil>}}]} About to print the results of the request: &{{<nil>} [{{<nil>} <nil> text Error requesting sampling: context deadline exceeded}] <nil> true} 2025/09/17 14:39:04 HTTP MCP client with sampling support started successfully! 2025/09/17 14:39:04 The client is now ready to handle sampling requests from the server. 2025/09/17 14:39:04 When the server sends a sampling request, the MockSamplingHandler will process it.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
-
Hello,
I'm using the sampling http client and server examples, but it doesn't work for me.
The server receives a tool call and initiates sampling, but the the sampling request never reaches the client.
Code below:
Server:
Client:
Server log:
Client log:
Any help would be appreciated.
Beta Was this translation helpful? Give feedback.
All reactions