or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

client.mdcontent-types.mdindex.mdserver.mdtransport-http.mdtransport-stdio.mdtransport.md
tile.json

client.mddocs/

MCP Client API

The Client API provides functionality for connecting to and interacting with MCP servers. Clients can discover and invoke tools, retrieve prompts, and read resources from servers.

Package

import mcp "github.com/metoro-io/mcp-golang"

Client

The Client type represents an MCP client that manages communication with an MCP server.

type Client struct {
    // Contains unexported fields
}

Creating a Client

func NewClient(transport transport.Transport) *Client

Creates a new MCP client with the specified transport.

Parameters:

  • transport: A transport implementation (stdio, HTTP, etc.) for communication

Returns: A new Client instance

Example:

import (
    mcp "github.com/metoro-io/mcp-golang"
    "github.com/metoro-io/mcp-golang/transport/stdio"
)

transport := stdio.NewStdioServerTransport()
client := mcp.NewClient(transport)
func NewClientWithInfo(transport transport.Transport, info ClientInfo) *Client

Creates a new MCP client with custom client information. This is required by Anthropic MCP tools to identify the client.

Parameters:

  • transport: A transport implementation for communication
  • info: Client identification information

Returns: A new Client instance with the specified info

Example:

transport := stdio.NewStdioServerTransport()
info := mcp.ClientInfo{
    Name:    "my-mcp-client",
    Version: "1.0.0",
}
client := mcp.NewClientWithInfo(transport, info)

ClientInfo

type ClientInfo struct {
    Name    string `json:"name"`
    Version string `json:"version"`
}

Information identifying the MCP client.

Fields:

  • Name: The name of the client application
  • Version: The version of the client application

Connection and Initialization

Initialize

func (c *Client) Initialize(ctx context.Context) (*InitializeResponse, error)

Connects to the MCP server and retrieves its capabilities. This must be called before any other client operations.

Parameters:

  • ctx: Context for the operation (for cancellation and timeouts)

Returns:

  • *InitializeResponse: Server information and capabilities
  • error: Error if initialization fails

Example:

ctx := context.Background()
initResp, err := client.Initialize(ctx)
if err != nil {
    log.Fatalf("Failed to initialize: %v", err)
}

log.Printf("Connected to server: %s %s",
    initResp.ServerInfo.Name,
    initResp.ServerInfo.Version)
log.Printf("Protocol version: %s", initResp.ProtocolVersion)

GetCapabilities

func (c *Client) GetCapabilities() *ServerCapabilities

Returns the server capabilities obtained during initialization.

Returns: Server capabilities describing what features the server supports

Example:

caps := client.GetCapabilities()
if caps.Tools != nil && caps.Tools.ListChanged != nil && *caps.Tools.ListChanged {
    log.Println("Server supports tool list change notifications")
}

Ping

func (c *Client) Ping(ctx context.Context) error

Sends a ping request to the server to check connectivity.

Parameters:

  • ctx: Context for the operation

Returns: Error if ping fails

Example:

err := client.Ping(context.Background())
if err != nil {
    log.Printf("Server is not responding: %v", err)
}

Tools

ListTools

func (c *Client) ListTools(ctx context.Context, cursor *string) (*ToolsResponse, error)

Retrieves the list of available tools from the server. Supports pagination for large tool lists.

Parameters:

  • ctx: Context for the operation
  • cursor: Pagination cursor (nil for first page, or value from previous response's NextCursor)

Returns:

  • *ToolsResponse: List of tools and optional pagination cursor
  • error: Error if the request fails

Example:

// Get first page of tools
toolsResp, err := client.ListTools(context.Background(), nil)
if err != nil {
    log.Fatalf("Failed to list tools: %v", err)
}

for _, tool := range toolsResp.Tools {
    log.Printf("Tool: %s - %s", tool.Name, *tool.Description)
}

// Get next page if available
if toolsResp.NextCursor != nil {
    nextResp, err := client.ListTools(context.Background(), toolsResp.NextCursor)
    // Process next page...
}

CallTool

func (c *Client) CallTool(ctx context.Context, name string, arguments any) (*ToolResponse, error)

Calls a specific tool on the server with the provided arguments.

Parameters:

  • ctx: Context for the operation
  • name: The name of the tool to call
  • arguments: Tool arguments (typically a struct that matches the tool's input schema)

Returns:

  • *ToolResponse: The tool's output
  • error: Error if the tool call fails

Example:

type CalculateArgs struct {
    Operation string `json:"operation"`
    A         int    `json:"a"`
    B         int    `json:"b"`
}

args := CalculateArgs{
    Operation: "add",
    A:         10,
    B:         5,
}

response, err := client.CallTool(context.Background(), "calculate", args)
if err != nil {
    log.Fatalf("Tool call failed: %v", err)
}

// Process tool response
for _, content := range response.Content {
    if content.Type == mcp.ContentTypeText {
        log.Printf("Result: %s", content.TextContent.Text)
    }
}

Prompts

ListPrompts

func (c *Client) ListPrompts(ctx context.Context, cursor *string) (*ListPromptsResponse, error)

Retrieves the list of available prompts from the server. Supports pagination.

Parameters:

  • ctx: Context for the operation
  • cursor: Pagination cursor (nil for first page)

Returns:

  • *ListPromptsResponse: List of prompts and optional pagination cursor
  • error: Error if the request fails

Example:

promptsResp, err := client.ListPrompts(context.Background(), nil)
if err != nil {
    log.Fatalf("Failed to list prompts: %v", err)
}

for _, prompt := range promptsResp.Prompts {
    log.Printf("Prompt: %s", prompt.Name)
    if prompt.Description != nil {
        log.Printf("  Description: %s", *prompt.Description)
    }
    for _, arg := range prompt.Arguments {
        log.Printf("  Argument: %s", arg.Name)
    }
}

GetPrompt

func (c *Client) GetPrompt(ctx context.Context, name string, arguments any) (*PromptResponse, error)

Retrieves a specific prompt from the server, optionally with arguments for template rendering.

Parameters:

  • ctx: Context for the operation
  • name: The name of the prompt to retrieve
  • arguments: Prompt arguments for template rendering (can be nil if prompt has no arguments)

Returns:

  • *PromptResponse: The rendered prompt messages
  • error: Error if the request fails

Example:

type PromptArgs struct {
    Topic string `json:"topic"`
    Style string `json:"style"`
}

args := PromptArgs{
    Topic: "quantum computing",
    Style: "educational",
}

response, err := client.GetPrompt(context.Background(), "explain-topic", args)
if err != nil {
    log.Fatalf("Failed to get prompt: %v", err)
}

for _, msg := range response.Messages {
    log.Printf("[%s]: %s", msg.Role, msg.Content.TextContent.Text)
}

Resources

ListResources

func (c *Client) ListResources(ctx context.Context, cursor *string) (*ListResourcesResponse, error)

Retrieves the list of available resources from the server. Supports pagination.

Parameters:

  • ctx: Context for the operation
  • cursor: Pagination cursor (nil for first page)

Returns:

  • *ListResourcesResponse: List of resources and optional pagination cursor
  • error: Error if the request fails

Example:

resourcesResp, err := client.ListResources(context.Background(), nil)
if err != nil {
    log.Fatalf("Failed to list resources: %v", err)
}

for _, resource := range resourcesResp.Resources {
    log.Printf("Resource: %s", resource.Name)
    log.Printf("  URI: %s", resource.Uri)
    if resource.MimeType != nil {
        log.Printf("  MIME Type: %s", *resource.MimeType)
    }
}

ReadResource

func (c *Client) ReadResource(ctx context.Context, uri string) (*ResourceResponse, error)

Reads a specific resource from the server.

Parameters:

  • ctx: Context for the operation
  • uri: The URI of the resource to read

Returns:

  • *ResourceResponse: The resource contents
  • error: Error if the request fails

Example:

response, err := client.ReadResource(context.Background(), "file://config.json")
if err != nil {
    log.Fatalf("Failed to read resource: %v", err)
}

for _, content := range response.Contents {
    if content.EmbeddedResourceType == /* text */ {
        log.Printf("Resource content: %s", content.TextResourceContents.Text)
    }
}

Response Types

InitializeResponse

type InitializeResponse struct {
    Capabilities    ServerCapabilities `json:"capabilities"`
    ProtocolVersion string             `json:"protocolVersion"`
    ServerInfo      implementation     `json:"serverInfo"`
    Instructions    *string            `json:"instructions,omitempty"`
    Meta            initializeResultMeta `json:"_meta,omitempty"`
}

Server's response to initialization request.

Fields:

  • Capabilities: Server capabilities (tools, prompts, resources, etc.)
  • ProtocolVersion: MCP protocol version the server uses
  • ServerInfo: Server name and version information
  • Instructions: Optional usage instructions from the server
  • Meta: Additional metadata

Methods:

func (j *InitializeResponse) UnmarshalJSON(b []byte) error

Custom JSON unmarshaling for InitializeResponse. This method is typically called automatically by Go's encoding/json package.

Parameters:

  • b: JSON-encoded data

Returns: Error if unmarshaling fails

ServerCapabilities

type ServerCapabilities struct {
    Tools        *ServerCapabilitiesTools     `json:"tools,omitempty"`
    Prompts      *ServerCapabilitiesPrompts   `json:"prompts,omitempty"`
    Resources    *ServerCapabilitiesResources `json:"resources,omitempty"`
    Logging      ServerCapabilitiesLogging    `json:"logging,omitempty"`
    Experimental ServerCapabilitiesExperimental `json:"experimental,omitempty"`
}

Capabilities that the server supports.

Fields:

  • Tools: Tool capabilities (present if server offers tools)
  • Prompts: Prompt capabilities (present if server offers prompts)
  • Resources: Resource capabilities (present if server offers resources)
  • Logging: Logging capabilities
  • Experimental: Experimental/non-standard capabilities

ServerCapabilitiesTools

type ServerCapabilitiesTools struct {
    ListChanged *bool `json:"listChanged,omitempty"`
}

Tool-specific capabilities.

Fields:

  • ListChanged: Whether server supports notifications for changes to the tool list

ServerCapabilitiesPrompts

type ServerCapabilitiesPrompts struct {
    ListChanged *bool `json:"listChanged,omitempty"`
}

Prompt-specific capabilities.

Fields:

  • ListChanged: Whether server supports notifications for changes to the prompt list

ServerCapabilitiesResources

type ServerCapabilitiesResources struct {
    ListChanged *bool `json:"listChanged,omitempty"`
    Subscribe   *bool `json:"subscribe,omitempty"`
}

Resource-specific capabilities.

Fields:

  • ListChanged: Whether server supports notifications for changes to the resource list
  • Subscribe: Whether server supports subscribing to resource updates

ServerCapabilitiesLogging

type ServerCapabilitiesLogging map[string]interface{}

Logging capabilities map.

ServerCapabilitiesExperimental

type ServerCapabilitiesExperimental map[string]map[string]interface{}

Experimental/non-standard capabilities map.

Usage Patterns

Complete Client Example

package main

import (
    "context"
    "log"
    "os/exec"

    mcp "github.com/metoro-io/mcp-golang"
    "github.com/metoro-io/mcp-golang/transport/stdio"
)

func main() {
    // Start server subprocess
    cmd := exec.Command("./mcp-server")
    stdin, err := cmd.StdinPipe()
    if err != nil {
        log.Fatal(err)
    }
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }

    if err := cmd.Start(); err != nil {
        log.Fatal(err)
    }
    defer cmd.Process.Kill()

    // Create client
    transport := stdio.NewStdioServerTransportWithIO(stdout, stdin)
    client := mcp.NewClientWithInfo(transport, mcp.ClientInfo{
        Name:    "my-client",
        Version: "1.0.0",
    })

    // Initialize
    ctx := context.Background()
    initResp, err := client.Initialize(ctx)
    if err != nil {
        log.Fatalf("Initialize failed: %v", err)
    }
    log.Printf("Connected to %s", initResp.ServerInfo)

    // List and call tools
    toolsResp, err := client.ListTools(ctx, nil)
    if err != nil {
        log.Fatalf("ListTools failed: %v", err)
    }

    for _, tool := range toolsResp.Tools {
        log.Printf("Available tool: %s", tool.Name)
    }

    // Call a tool
    type Args struct {
        Input string `json:"input"`
    }
    result, err := client.CallTool(ctx, "process", Args{Input: "test"})
    if err != nil {
        log.Fatalf("CallTool failed: %v", err)
    }

    for _, content := range result.Content {
        if content.Type == mcp.ContentTypeText {
            log.Printf("Tool result: %s", content.TextContent.Text)
        }
    }
}

Error Handling

// Always check initialization
initResp, err := client.Initialize(ctx)
if err != nil {
    // Handle connection failure
    log.Fatalf("Failed to connect to server: %v", err)
}

// Check for tool existence before calling
toolsResp, err := client.ListTools(ctx, nil)
if err != nil {
    log.Fatalf("Failed to list tools: %v", err)
}

toolExists := false
for _, tool := range toolsResp.Tools {
    if tool.Name == "my-tool" {
        toolExists = true
        break
    }
}

if !toolExists {
    log.Fatal("Required tool 'my-tool' not available")
}

// Call tool with timeout
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

result, err := client.CallTool(ctx, "my-tool", args)
if err != nil {
    // Handle tool call failure
    log.Printf("Tool call failed: %v", err)
}