tessl install tessl/golang-mcp-golang@0.16.1An unofficial implementation of the Model Context Protocol in Go
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.
import mcp "github.com/metoro-io/mcp-golang"The Client type represents an MCP client that manages communication with an MCP server.
type Client struct {
// Contains unexported fields
}func NewClient(transport transport.Transport) *ClientCreates a new MCP client with the specified transport.
Parameters:
transport: A transport implementation (stdio, HTTP, etc.) for communicationReturns: 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) *ClientCreates 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 communicationinfo: Client identification informationReturns: 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)type ClientInfo struct {
Name string `json:"name"`
Version string `json:"version"`
}Information identifying the MCP client.
Fields:
Name: The name of the client applicationVersion: The version of the client applicationfunc (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 capabilitieserror: Error if initialization failsExample:
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)func (c *Client) GetCapabilities() *ServerCapabilitiesReturns 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")
}func (c *Client) Ping(ctx context.Context) errorSends a ping request to the server to check connectivity.
Parameters:
ctx: Context for the operationReturns: Error if ping fails
Example:
err := client.Ping(context.Background())
if err != nil {
log.Printf("Server is not responding: %v", err)
}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 operationcursor: Pagination cursor (nil for first page, or value from previous response's NextCursor)Returns:
*ToolsResponse: List of tools and optional pagination cursorerror: Error if the request failsExample:
// 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...
}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 operationname: The name of the tool to callarguments: Tool arguments (typically a struct that matches the tool's input schema)Returns:
*ToolResponse: The tool's outputerror: Error if the tool call failsExample:
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)
}
}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 operationcursor: Pagination cursor (nil for first page)Returns:
*ListPromptsResponse: List of prompts and optional pagination cursorerror: Error if the request failsExample:
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)
}
}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 operationname: The name of the prompt to retrievearguments: Prompt arguments for template rendering (can be nil if prompt has no arguments)Returns:
*PromptResponse: The rendered prompt messageserror: Error if the request failsExample:
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)
}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 operationcursor: Pagination cursor (nil for first page)Returns:
*ListResourcesResponse: List of resources and optional pagination cursorerror: Error if the request failsExample:
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)
}
}func (c *Client) ReadResource(ctx context.Context, uri string) (*ResourceResponse, error)Reads a specific resource from the server.
Parameters:
ctx: Context for the operationuri: The URI of the resource to readReturns:
*ResourceResponse: The resource contentserror: Error if the request failsExample:
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)
}
}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 usesServerInfo: Server name and version informationInstructions: Optional usage instructions from the serverMeta: Additional metadataMethods:
func (j *InitializeResponse) UnmarshalJSON(b []byte) errorCustom JSON unmarshaling for InitializeResponse. This method is typically called automatically by Go's encoding/json package.
Parameters:
b: JSON-encoded dataReturns: Error if unmarshaling fails
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 capabilitiesExperimental: Experimental/non-standard capabilitiestype ServerCapabilitiesTools struct {
ListChanged *bool `json:"listChanged,omitempty"`
}Tool-specific capabilities.
Fields:
ListChanged: Whether server supports notifications for changes to the tool listtype ServerCapabilitiesPrompts struct {
ListChanged *bool `json:"listChanged,omitempty"`
}Prompt-specific capabilities.
Fields:
ListChanged: Whether server supports notifications for changes to the prompt listtype 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 listSubscribe: Whether server supports subscribing to resource updatestype ServerCapabilitiesLogging map[string]interface{}Logging capabilities map.
type ServerCapabilitiesExperimental map[string]map[string]interface{}Experimental/non-standard capabilities map.
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)
}
}
}// 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)
}