Creating a Client
The gomcp
library provides tools for building applications that act as MCP clients, connecting to MCP servers to utilize their capabilities (tools, resources, prompts).
The primary implementation for a client is found in the client
package, which uses the SSE+HTTP hybrid transport model.
Client Role
An MCP client typically:
- Connects to a known MCP server endpoint.
- Performs the initialization handshake (
initialize
/initialized
). - Discovers available server capabilities (tools, resources, prompts) using
list
requests. - Executes server tools (
tools/call
). - Accesses server resources (
resources/get
). - Subscribes to resource updates (
resources/subscribe
). - Handles server-sent notifications (e.g.,
$/progress
,notifications/message
). - Handles server-sent requests (if the server needs to request actions from the client, though less common).
Initializing the Client (client
package)
The client
package provides a Client
struct that manages the connection and communication flow using the SSE+HTTP transport.
package main
import (
"context"
"log"
"time"
"github.com/localrivet/gomcp/client"
"github.com/localrivet/gomcp/protocol"
"github.com/localrivet/gomcp/types"
)
func main() {
// Server's base URL (adjust as needed)
serverURL := "http://localhost:8080" // Example URL
// Define client information
clientInfo := types.Implementation{
Name: "my-simple-client",
Version: "0.1.0",
}
// Define client capabilities (optional, customize as needed)
clientCapabilities := protocol.ClientCapabilities{
// Add specific capabilities your client supports
}
// Create client options
opts := client.NewClientOptions(clientInfo, clientCapabilities)
// opts.Logger = /* provide a custom logger if desired */
// Create a new client instance
c := client.NewClient(serverURL, opts)
// --- Optional: Register handlers for server-sent messages ---
// Example: Handle log messages from the server
c.RegisterNotificationHandler(protocol.MethodLogMessage, func(ctx context.Context, params []byte) error {
var logParams protocol.LoggingMessageParams
if err := json.Unmarshal(params, &logParams); err != nil {
log.Printf("Error unmarshalling log message params: %v", err)
return nil // Don't kill connection for bad log message
}
log.Printf("SERVER LOG [%s]: %s", logParams.Level, logParams.Message)
return nil
})
// Register other handlers for notifications or server requests as needed...
// --- Connect and Initialize ---
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) // Add a timeout
defer cancel()
serverInfo, err := c.Connect(ctx)
if err != nil {
log.Fatalf("Failed to connect and initialize with server: %v", err)
}
log.Printf("Connected to server: %s v%s", serverInfo.Name, serverInfo.Version)
log.Printf("Server capabilities: %+v", c.ServerCapabilities()) // Access cached capabilities
// --- Client is now ready to make requests ---
// Example: List available tools
listToolsCtx, listToolsCancel := context.WithTimeout(context.Background(), 10*time.Second)
defer listToolsCancel()
toolsResult, err := c.ListTools(listToolsCtx, protocol.ListToolsRequestParams{})
if err != nil {
log.Printf("Error listing tools: %v", err)
} else {
log.Printf("Available tools (%d):", len(toolsResult.Tools))
for _, tool := range toolsResult.Tools {
log.Printf("- %s: %s", tool.Name, tool.Description)
}
}
// Add more client logic here (CallTool, GetResource, etc.)
// Keep the client running (e.g., wait for user input or another signal)
log.Println("Client running. Press Ctrl+C to exit.")
<-ctx.Done() // Wait for context cancellation (e.g., timeout or manual cancel)
// Disconnect (optional, closes SSE connection)
c.Disconnect()
log.Println("Client disconnected.")
}
Note: This example assumes a server is running at http://localhost:8080
using the SSE+HTTP transport.
Making Requests
Once connected, you can use the methods provided by the client.Client
struct to interact with the server:
ListTools(ctx, params)
CallTool(ctx, params)
ListResources(ctx, params)
GetResource(ctx, params)
SubscribeResources(ctx, params)
UnsubscribeResources(ctx, params)
ListPrompts(ctx, params)
GetPrompt(ctx, params)
SendCancellation(ctx, id)
SendProgress(ctx, params)
// If client needs to report progress- // … and others
Each method takes a context.Context
for cancellation and deadlines, and the corresponding parameter struct defined in the protocol
package.
Handling Server Messages
Use RegisterNotificationHandler
and RegisterRequestHandler
before calling Connect
to set up functions that will be called when the server sends asynchronous notifications or requests over the SSE connection.