The client API enables connecting to MCP servers and invoking their capabilities including tools, prompts, resources, and sampling.
func NewClient(impl *Implementation, opts *ClientOptions) *ClientCreates a new MCP client instance.
type Client struct {
// Has unexported fields
}type ClientOptions struct {
CreateMessageHandler func(context.Context, *CreateMessageRequest) (*CreateMessageResult, error)
ElicitationHandler func(context.Context, *ElicitRequest) (*ElicitResult, error)
ToolListChangedHandler func(context.Context, *ToolListChangedRequest)
PromptListChangedHandler func(context.Context, *PromptListChangedRequest)
ResourceListChangedHandler func(context.Context, *ResourceListChangedRequest)
ResourceUpdatedHandler func(context.Context, *ResourceUpdatedNotificationRequest)
LoggingMessageHandler func(context.Context, *LoggingMessageRequest)
ProgressNotificationHandler func(context.Context, *ProgressNotificationClientRequest)
KeepAlive time.Duration
}Fields:
CreateMessageHandler: Handler for server sampling requests (LLM generation)ElicitationHandler: Handler for server elicitation requests (user input)ToolListChangedHandler: Notified when server's tool list changesPromptListChangedHandler: Notified when server's prompt list changesResourceListChangedHandler: Notified when server's resource list changesResourceUpdatedHandler: Notified when a specific resource is updatedLoggingMessageHandler: Handler for server log messagesProgressNotificationHandler: Handler for server progress notificationsKeepAlive: Duration for connection keep-alive (0 to disable)func (c *Client) Connect(ctx context.Context, t Transport, _ *ClientSessionOptions) (*ClientSession, error)Connects to a server over the given transport and performs initialization handshake.
func (c *Client) AddRoots(roots ...*Root)Adds roots to the client and notifies all connected servers.
func (c *Client) RemoveRoots(uris ...string)Removes roots by URI and notifies all connected servers.
func (c *Client) AddReceivingMiddleware(middleware ...Middleware)Adds middleware for processing incoming requests from servers.
func (c *Client) AddSendingMiddleware(middleware ...Middleware)Adds middleware for processing outgoing requests to servers.
type ClientSession struct {
// Has unexported fields
}A logical connection with an MCP server.
type ClientSessionOptions struct{}Reserved for future use.
func (s *ClientSession) ID() stringReturns the unique session identifier.
func (s *ClientSession) InitializeResult() *InitializeResultReturns the initialization result from the server containing capabilities and server info.
func (s *ClientSession) Close() errorGracefully closes the connection to the server.
func (s *ClientSession) Wait() errorWaits for the server to close the connection.
func (s *ClientSession) Ping(ctx context.Context, params *PingParams) errorPings the server to check connectivity.
func (s *ClientSession) ListTools(ctx context.Context, params *ListToolsParams) (*ListToolsResult, error)Lists available tools from the server.
func (s *ClientSession) Tools(ctx context.Context, params *ListToolsParams) iter.Seq2[*Tool, error]Returns an iterator over all tools, automatically handling pagination.
func (s *ClientSession) CallTool(ctx context.Context, params *CallToolParams) (*CallToolResult, error)Calls a tool on the server.
func (s *ClientSession) ListPrompts(ctx context.Context, params *ListPromptsParams) (*ListPromptsResult, error)Lists available prompts from the server.
func (s *ClientSession) Prompts(ctx context.Context, params *ListPromptsParams) iter.Seq2[*Prompt, error]Returns an iterator over all prompts, automatically handling pagination.
func (s *ClientSession) GetPrompt(ctx context.Context, params *GetPromptParams) (*GetPromptResult, error)Gets a specific prompt with arguments.
func (s *ClientSession) ListResources(ctx context.Context, params *ListResourcesParams) (*ListResourcesResult, error)Lists available resources from the server.
func (s *ClientSession) Resources(ctx context.Context, params *ListResourcesParams) iter.Seq2[*Resource, error]Returns an iterator over all resources, automatically handling pagination.
func (s *ClientSession) ListResourceTemplates(ctx context.Context, params *ListResourceTemplatesParams) (*ListResourceTemplatesResult, error)Lists available resource templates from the server.
func (s *ClientSession) ResourceTemplates(ctx context.Context, params *ListResourceTemplatesParams) iter.Seq2[*ResourceTemplate, error]Returns an iterator over all resource templates, automatically handling pagination.
func (s *ClientSession) ReadResource(ctx context.Context, params *ReadResourceParams) (*ReadResourceResult, error)Reads a resource from the server.
func (s *ClientSession) Subscribe(ctx context.Context, params *SubscribeParams) errorSubscribes to updates for a resource.
func (s *ClientSession) Unsubscribe(ctx context.Context, params *UnsubscribeParams) errorUnsubscribes from updates for a resource.
func (s *ClientSession) Complete(ctx context.Context, params *CompleteParams) (*CompleteResult, error)Requests argument completion suggestions from the server.
func (s *ClientSession) SetLoggingLevel(ctx context.Context, params *SetLoggingLevelParams) errorSets the logging level for the server.
func (s *ClientSession) NotifyProgress(ctx context.Context, params *ProgressNotificationParams) errorSends a progress notification to the server.
These types represent requests received by the client from servers.
type ClientRequest[P Params] struct {
Session *ClientSession
Params P
}Generic client request with session and parameters.
Methods:
func (r *ClientRequest[P]) GetExtra() *RequestExtra
func (r *ClientRequest[P]) GetParams() Params
func (r *ClientRequest[P]) GetSession() Sessiontype InitializeRequest = ClientRequest[*InitializeParams]
type CreateMessageRequest = ClientRequest[*CreateMessageParams]
type ElicitRequest = ClientRequest[*ElicitParams]
type ListRootsRequest = ClientRequest[*ListRootsParams]
type ToolListChangedRequest = ClientRequest[*ToolListChangedParams]
type PromptListChangedRequest = ClientRequest[*PromptListChangedParams]
type ResourceListChangedRequest = ClientRequest[*ResourceListChangedParams]
type ResourceUpdatedNotificationRequest = ClientRequest[*ResourceUpdatedNotificationParams]
type LoggingMessageRequest = ClientRequest[*LoggingMessageParams]
type ProgressNotificationClientRequest = ClientRequest[*ProgressNotificationParams]type Root struct {
Meta `json:"_meta,omitempty"`
Name string `json:"name,omitempty"`
URI string `json:"uri"`
}Represents a root directory or file that the server can operate on.
Fields:
Meta: Additional metadataName: Human-readable nameURI: Root URI (typically a file:// URL)package main
import (
"context"
"fmt"
"log"
"os/exec"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
func main() {
ctx := context.Background()
// Create client with handlers
client := mcp.NewClient(
&mcp.Implementation{Name: "example-client", Version: "1.0.0"},
&mcp.ClientOptions{
// Handle server sampling requests
CreateMessageHandler: func(ctx context.Context, req *mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) {
return &mcp.CreateMessageResult{
Role: "assistant",
Model: "gpt-4",
Content: &mcp.TextContent{
Text: "This is a generated response",
},
}, nil
},
// Handle server log messages
LoggingMessageHandler: func(ctx context.Context, req *mcp.LoggingMessageRequest) {
log.Printf("[%s] %v", req.Params.Level, req.Params.Data)
},
// Handle resource list changes
ResourceListChangedHandler: func(ctx context.Context, req *mcp.ResourceListChangedRequest) {
log.Println("Server's resource list changed")
},
},
)
// Add roots
client.AddRoots(&mcp.Root{
URI: "file:///home/user/projects",
Name: "Projects Directory",
})
// Connect to server
transport := &mcp.CommandTransport{
Command: exec.Command("my-mcp-server"),
}
session, err := client.Connect(ctx, transport, nil)
if err != nil {
log.Fatal(err)
}
defer session.Close()
// Check server capabilities
initResult := session.InitializeResult()
fmt.Printf("Connected to: %s v%s\n",
initResult.ServerInfo.Name,
initResult.ServerInfo.Version)
// List and call tools
toolsResult, err := session.ListTools(ctx, &mcp.ListToolsParams{})
if err != nil {
log.Fatal(err)
}
for _, tool := range toolsResult.Tools {
fmt.Printf("Tool: %s - %s\n", tool.Name, tool.Description)
}
if len(toolsResult.Tools) > 0 {
result, err := session.CallTool(ctx, &mcp.CallToolParams{
Name: toolsResult.Tools[0].Name,
Arguments: map[string]any{"input": "test"},
})
if err != nil {
log.Fatal(err)
}
if result.IsError {
log.Println("Tool call failed")
} else {
for _, content := range result.Content {
if text, ok := content.(*mcp.TextContent); ok {
fmt.Println(text.Text)
}
}
}
}
// Use iterator for all resources
for resource, err := range session.Resources(ctx, &mcp.ListResourcesParams{}) {
if err != nil {
log.Printf("Error iterating resources: %v", err)
break
}
fmt.Printf("Resource: %s (%s)\n", resource.Name, resource.URI)
// Read the resource
readResult, err := session.ReadResource(ctx, &mcp.ReadResourceParams{
URI: resource.URI,
})
if err != nil {
log.Printf("Error reading resource: %v", err)
continue
}
for _, content := range readResult.Contents {
if content.Text != "" {
fmt.Printf(" Content: %s\n", content.Text[:min(50, len(content.Text))])
}
}
}
// Get a prompt
promptResult, err := session.GetPrompt(ctx, &mcp.GetPromptParams{
Name: "greeting",
Arguments: map[string]string{"name": "Alice"},
})
if err == nil {
for _, msg := range promptResult.Messages {
if text, ok := msg.Content.(*mcp.TextContent); ok {
fmt.Printf("Prompt: %s\n", text.Text)
}
}
}
// Wait for server to disconnect
if err := session.Wait(); err != nil {
log.Printf("Session ended: %v", err)
}
}
func min(a, b int) int {
if a < b {
return a
}
return b
}// Iterate over all tools automatically handling pagination
for tool, err := range session.Tools(ctx, &mcp.ListToolsParams{}) {
if err != nil {
log.Printf("Error: %v", err)
break
}
fmt.Printf("Tool: %s\n", tool.Name)
}
// Iterate over all prompts
for prompt, err := range session.Prompts(ctx, &mcp.ListPromptsParams{}) {
if err != nil {
log.Printf("Error: %v", err)
break
}
fmt.Printf("Prompt: %s\n", prompt.Name)
}
// Iterate over all resources
for resource, err := range session.Resources(ctx, &mcp.ListResourcesParams{}) {
if err != nil {
log.Printf("Error: %v", err)
break
}
fmt.Printf("Resource: %s\n", resource.URI)
}
// Iterate over all resource templates
for template, err := range session.ResourceTemplates(ctx, &mcp.ListResourceTemplatesParams{}) {
if err != nil {
log.Printf("Error: %v", err)
break
}
fmt.Printf("Template: %s\n", template.URITemplate)
}client := mcp.NewClient(
&mcp.Implementation{Name: "reactive-client", Version: "1.0.0"},
&mcp.ClientOptions{
// Automatically refetch when lists change
ToolListChangedHandler: func(ctx context.Context, req *mcp.ToolListChangedRequest) {
tools, err := req.Session.ListTools(ctx, &mcp.ListToolsParams{})
if err != nil {
log.Printf("Error refreshing tools: %v", err)
return
}
log.Printf("Tools updated: %d available", len(tools.Tools))
},
// Subscribe to resource updates
ResourceUpdatedHandler: func(ctx context.Context, req *mcp.ResourceUpdatedNotificationRequest) {
log.Printf("Resource updated: %s", req.Params.URI)
// Re-read the resource
content, err := req.Session.ReadResource(ctx, &mcp.ReadResourceParams{
URI: req.Params.URI,
})
if err != nil {
log.Printf("Error reading updated resource: %v", err)
return
}
log.Printf("New content received: %d items", len(content.Contents))
},
// Handle progress from long-running operations
ProgressNotificationHandler: func(ctx context.Context, req *mcp.ProgressNotificationClientRequest) {
progress := (req.Params.Progress / req.Params.Total) * 100
log.Printf("Progress: %.1f%% - %s", progress, req.Params.Message)
},
},
)