Repository navigation
docs(client): fix examples for current constructors #1196
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8663a49
5e116c3
169db91
029e101
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,17 +9,29 @@ MCP-Go provides client constructors for each supported transport. The choice of | |
| ### Client Constructor Patterns | ||
|
|
||
| ```go | ||
| // STDIO client - for command-line tools | ||
| client, err := client.NewStdioMCPClient("command", "arg1", "arg2") | ||
| // Each constructor returns a client and an error. | ||
| stdioClient, err := client.NewStdioMCPClient("command", []string{}, "arg1", "arg2") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| // StreamableHTTP client - for web services | ||
| client := client.NewStreamableHttpClient("http://localhost:8080/mcp") | ||
| httpClient, err := client.NewStreamableHttpClient("http://localhost:8080/mcp") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| // SSE client - for real-time web applications | ||
| client := client.NewSSEMCPClient("http://localhost:8080/mcp/sse") | ||
| sseClient, err := client.NewSSEMCPClient("http://localhost:8080/mcp/sse") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
|
|
||
| // In-process client - for testing and embedded scenarios | ||
| client := client.NewInProcessClient(server) | ||
| inProcessClient, err := client.NewInProcessClient(server) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| ``` | ||
|
|
||
| ### STDIO Client Creation | ||
|
|
@@ -41,7 +53,20 @@ import ( | |
| "github.com/mark3labs/mcp-go/mcp" | ||
| ) | ||
|
|
||
| func createStdioClient() (client.Client, error) { | ||
| func startAndInitializeExampleClient(ctx context.Context, c *client.Client) error { | ||
| if err := c.Start(ctx); err != nil { | ||
| return err | ||
| } | ||
| _, err := c.Initialize(ctx, mcp.InitializeRequest{ | ||
| Params: mcp.InitializeParams{ | ||
| ProtocolVersion: mcp.LATEST_PROTOCOL_VERSION, | ||
| ClientInfo: mcp.Implementation{Name: "example-client", Version: "1.0.0"}, | ||
| }, | ||
| }) | ||
| return err | ||
| } | ||
|
|
||
| func createStdioClient() (*client.Client, error) { | ||
| // Create client that spawns a subprocess | ||
| c, err := client.NewStdioMCPClient( | ||
| "go", []string{}, "run", "/path/to/server/main.go", | ||
|
|
@@ -54,7 +79,7 @@ func createStdioClient() (client.Client, error) { | |
| } | ||
|
|
||
| // With custom environment variables | ||
| func createStdioClientWithEnv() (client.Client, error) { | ||
| func createStdioClientWithEnv() (*client.Client, error) { | ||
| env := []string{ | ||
| "LOG_LEVEL=debug", | ||
| "DATABASE_URL=sqlite://test.db", | ||
|
|
@@ -73,7 +98,7 @@ func createStdioClientWithEnv() (client.Client, error) { | |
| ### StreamableHTTP Client Creation | ||
|
|
||
| ```go | ||
| func createStreamableHTTPClient() client.Client { | ||
| func createStreamableHTTPClient() *client.Client { | ||
| // Basic StreamableHTTP client | ||
| httpTransport, err := transport.NewStreamableHTTP(server.URL, | ||
| // Set timeout | ||
|
|
@@ -97,15 +122,18 @@ func createStreamableHTTPClient() client.Client { | |
| ### SSE Client Creation | ||
|
|
||
| ```go | ||
| func createSSEClient() client.Client { | ||
| func createSSEClient() *client.Client { | ||
| // Basic SSE client | ||
| c, err := NewSSEMCPClient(testServer.URL+"/sse", | ||
| c, err := client.NewSSEMCPClient("http://localhost:8080/sse", | ||
| // Set custom headers | ||
| WithHeaders(map[string]string{ | ||
| client.WithHeaders(map[string]string{ | ||
| "X-Custom-Header": "custom-value", | ||
| "Y-Another-Header": "another-value", | ||
| }), | ||
| ) | ||
| if err != nil { | ||
| log.Fatalf("Failed to create SSE client: %v", err) | ||
| } | ||
| return c | ||
| } | ||
| ``` | ||
|
|
@@ -126,7 +154,7 @@ Understanding the client lifecycle is crucial for proper resource management and | |
| ```go | ||
| func demonstrateClientLifecycle() error { | ||
| // 1. Creation | ||
| c, err := client.NewSSEMCPClient("server-command") | ||
| c, err := client.NewStdioMCPClient("server-command", []string{}) | ||
| if err != nil { | ||
| return fmt.Errorf("client creation failed: %w", err) | ||
| } | ||
|
|
@@ -141,7 +169,7 @@ func demonstrateClientLifecycle() error { | |
| ctx := context.Background() | ||
|
|
||
| // 2. Initialization | ||
| if err := c.Initialize(ctx); err != nil { | ||
| if err := startAndInitializeExampleClient(ctx, c); err != nil { | ||
| return fmt.Errorf("client initialization failed: %w", err) | ||
| } | ||
|
|
||
|
|
@@ -154,7 +182,7 @@ func demonstrateClientLifecycle() error { | |
| return nil | ||
| } | ||
|
|
||
| func performClientOperations(ctx context.Context, c client.Client) error { | ||
| func performClientOperations(ctx context.Context, c *client.Client) error { | ||
| // List available tools | ||
| tools, err := c.ListTools(ctx, mcp.ListToolsRequest{}) | ||
| if err != nil { | ||
|
|
@@ -191,24 +219,23 @@ func performClientOperations(ctx context.Context, c client.Client) error { | |
| The initialization process establishes the MCP connection and exchanges capabilities: | ||
|
|
||
| ```go | ||
| func initializeClientWithDetails(ctx context.Context, c client.Client) error { | ||
| func initializeClientWithDetails(ctx context.Context, c *client.Client) error { | ||
| // Initialize with custom client info | ||
| initReq := mcp.InitializeRequest{ | ||
| Params: mcp.InitializeRequestParams{ | ||
| Params: mcp.InitializeParams{ | ||
| ProtocolVersion: "2024-11-05", | ||
| Capabilities: mcp.ClientCapabilities{ | ||
| Tools: &mcp.ToolsCapability{}, | ||
| Resources: &mcp.ResourcesCapability{}, | ||
| Prompts: &mcp.PromptsCapability{}, | ||
| }, | ||
| ClientInfo: mcp.ClientInfo{ | ||
| Capabilities: mcp.ClientCapabilities{}, | ||
| ClientInfo: mcp.Implementation{ | ||
| Name: "My Application", | ||
| Version: "1.0.0", | ||
| }, | ||
| }, | ||
| } | ||
|
|
||
| result, err := c.InitializeWithRequest(ctx, initReq) | ||
| if err := c.Start(ctx); err != nil { | ||
| return fmt.Errorf("failed to start client: %w", err) | ||
| } | ||
| result, err := c.Initialize(ctx, initReq) | ||
| if err != nil { | ||
| return fmt.Errorf("initialization failed: %w", err) | ||
| } | ||
|
|
@@ -227,23 +254,23 @@ func initializeClientWithDetails(ctx context.Context, c client.Client) error { | |
|
|
||
| ```go | ||
| type ManagedClient struct { | ||
| client client.Client | ||
| client *client.Client | ||
| ctx context.Context | ||
| cancel context.CancelFunc | ||
| done chan struct{} | ||
| } | ||
|
|
||
| func NewManagedClient(clientType, address string) (*ManagedClient, error) { | ||
| var c client.Client | ||
| var c *client.Client | ||
| var err error | ||
|
|
||
| switch clientType { | ||
| case "stdio": | ||
| c, err = client.NewSSEMCPClient("server-command") | ||
| c, err = client.NewStdioMCPClient(address, []string{}) | ||
| case "streamablehttp": | ||
| c = client.NewStreamableHttpClient(address) | ||
| c, err = client.NewStreamableHttpClient(address) | ||
| case "sse": | ||
| c = client.NewSSEMCPClient(address) | ||
| c, err = client.NewSSEMCPClient(address) | ||
| default: | ||
| return nil, fmt.Errorf("unknown client type: %s", clientType) | ||
| } | ||
|
|
@@ -264,7 +291,7 @@ func NewManagedClient(clientType, address string) (*ManagedClient, error) { | |
| // Initialize in background | ||
| go func() { | ||
| defer close(mc.done) | ||
| if err := c.Initialize(ctx); err != nil { | ||
| if err := startAndInitializeExampleClient(ctx, c); err != nil { | ||
| log.Printf("Client initialization failed: %v", err) | ||
| } | ||
| }() | ||
|
|
@@ -330,7 +357,7 @@ var ( | |
| ### Comprehensive Error Handling | ||
|
|
||
| ```go | ||
| func handleClientErrors(ctx context.Context, c client.Client) { | ||
| func handleClientErrors(ctx context.Context, c *client.Client) { | ||
| result, err := c.CallTool(ctx, mcp.CallToolRequest{ | ||
| Params: mcp.CallToolRequestParams{ | ||
| Name: "example_tool", | ||
|
|
@@ -396,7 +423,7 @@ func handleClientErrors(ctx context.Context, c client.Client) { | |
| log.Printf("Tool result: %+v", result) | ||
| } | ||
|
|
||
| func reconnectClient(c client.Client) error { | ||
| func reconnectClient(c *client.Client) error { | ||
| // Close existing connection | ||
| if err := c.Close(); err != nil { | ||
| log.Printf("Error closing client: %v", err) | ||
|
|
@@ -409,10 +436,10 @@ func reconnectClient(c client.Client) error { | |
| ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
| defer cancel() | ||
|
|
||
| return c.Initialize(ctx) | ||
| return startAndInitializeExampleClient(ctx, c) | ||
|
Comment on lines
436
to
+439
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| func suggestAlternativeTools(ctx context.Context, c client.Client) { | ||
| func suggestAlternativeTools(ctx context.Context, c *client.Client) { | ||
| tools, err := c.ListTools(ctx, mcp.ListToolsRequest{}) | ||
| if err != nil { | ||
| log.Printf("Failed to list tools: %v", err) | ||
|
|
@@ -425,7 +452,7 @@ func suggestAlternativeTools(ctx context.Context, c client.Client) { | |
| } | ||
| } | ||
|
|
||
| func showToolSchema(ctx context.Context, c client.Client, toolName string) { | ||
| func showToolSchema(ctx context.Context, c *client.Client, toolName string) { | ||
| tools, err := c.ListTools(ctx, mcp.ListToolsRequest{}) | ||
| if err != nil { | ||
| log.Printf("Failed to list tools: %v", err) | ||
|
|
@@ -521,7 +548,7 @@ func WithRetry[T any](ctx context.Context, config RetryConfig, operation func() | |
| } | ||
|
|
||
| // Usage example | ||
| func callToolWithRetry(ctx context.Context, c client.Client, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { | ||
| func callToolWithRetry(ctx context.Context, c *client.Client, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { | ||
| config := DefaultRetryConfig() | ||
|
|
||
| return WithRetry(ctx, config, func() (*mcp.CallToolResult, error) { | ||
|
|
@@ -533,7 +560,7 @@ func callToolWithRetry(ctx context.Context, c client.Client, req mcp.CallToolReq | |
| ### Context and Timeout Management | ||
|
|
||
| ```go | ||
| func demonstrateContextUsage(c client.Client) { | ||
| func demonstrateContextUsage(c *client.Client) { | ||
| // Operation with timeout | ||
| ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) | ||
| defer cancel() | ||
|
|
@@ -559,7 +586,7 @@ func demonstrateContextUsage(c client.Client) { | |
| log.Printf("Tool completed: %+v", result) | ||
| } | ||
|
|
||
| func demonstrateCancellation(c client.Client) { | ||
| func demonstrateCancellation(c *client.Client) { | ||
| ctx, cancel := context.WithCancel(context.Background()) | ||
|
|
||
| // Start operation in goroutine | ||
|
|
@@ -597,14 +624,14 @@ func demonstrateCancellation(c client.Client) { | |
|
|
||
| ```go | ||
| type ClientHealthMonitor struct { | ||
| client client.Client | ||
| client *client.Client | ||
| interval time.Duration | ||
| timeout time.Duration | ||
| healthy bool | ||
| mutex sync.RWMutex | ||
| } | ||
|
|
||
| func NewClientHealthMonitor(c client.Client, interval, timeout time.Duration) *ClientHealthMonitor { | ||
| func NewClientHealthMonitor(c *client.Client, interval, timeout time.Duration) *ClientHealthMonitor { | ||
| return &ClientHealthMonitor{ | ||
| client: c, | ||
| interval: interval, | ||
|
|
@@ -654,13 +681,13 @@ func (chm *ClientHealthMonitor) IsHealthy() bool { | |
|
|
||
| ```go | ||
| type ResilientClient struct { | ||
| factory func() (client.Client, error) | ||
| client client.Client | ||
| factory func() (*client.Client, error) | ||
| client *client.Client | ||
| mutex sync.RWMutex | ||
| recovering bool | ||
| } | ||
|
|
||
| func NewResilientClient(factory func() (client.Client, error)) *ResilientClient { | ||
| func NewResilientClient(factory func() (*client.Client, error)) *ResilientClient { | ||
| return &ResilientClient{ | ||
| factory: factory, | ||
| } | ||
|
|
@@ -697,7 +724,7 @@ func (rc *ResilientClient) ensureConnected(ctx context.Context) error { | |
| } | ||
|
|
||
| // Initialize new client | ||
| if err := newClient.Initialize(ctx); err != nil { | ||
| if err := startAndInitializeExampleClient(ctx, newClient); err != nil { | ||
| newClient.Close() | ||
| return fmt.Errorf("failed to initialize client: %w", err) | ||
| } | ||
|
|
@@ -745,4 +772,4 @@ func isConnectionError(err error) bool { | |
| ## Next Steps | ||
|
|
||
| - **[Client Operations](/clients/operations)** - Learn to use tools, resources, and prompts | ||
| - **[Client Transports](/clients/transports)** - Explore transport-specific features | ||
| - **[Client Transports](/clients/transports)** - Explore transport-specific features | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Script executed:
Repository: mark3labs/mcp-go
Length of output: 46705
Script executed:
Repository: mark3labs/mcp-go
Length of output: 6454
Define the Streamable HTTP example’s dependencies.
The combined example does not compile:
transportis not imported, andserveris undefined. Importgithub.com/mark3labs/mcp-go/client/transportand provide a Streamable HTTP endpoint in place ofserver.URL.