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