package tools import ( "context" "encoding/json" "strings" "time" "github.com/mark3labs/mcp-go/mcp" ) const FetchClusterEnvName = "fetch_cluster_env" // NewFetchClusterEnvTool returns the schema for the fetch_cluster_env MCP Tool. func NewFetchClusterEnvTool() mcp.Tool { return mcp.NewTool(FetchClusterEnvName, mcp.WithDescription("Fetch YARN cluster environment information and metrics from the ResourceManager."), mcp.WithString("cluster_id", mcp.Required(), mcp.Description("ID of the configured cluster (from list_clusters)"), ), ) } // FetchClusterEnvHandler fetches RM cluster info and metrics. func (d *Deps) FetchClusterEnvHandler(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { clusterID, err := req.RequireString("cluster_id") if err != nil { return errResult("fetch_cluster_env: " + err.Error()), nil } callLog := startToolCall(ctx, d.Logger, FetchClusterEnvName, map[string]any{ "cluster_id": clusterID, }) defer callLog.End() cl, err := d.ClusterRepo.Get(ctx, clusterID) if err != nil { callLog.WithError(err) return errResult("fetch_cluster_env: cluster " + clusterID + ": " + err.Error()), nil } base := strings.TrimRight(cl.RMURL, "/") infoBody, err := d.fetchInternal(ctx, cl, base+"/ws/v1/cluster/info") if err != nil { callLog.WithError(err) return errResult("fetch_cluster_env: info: " + err.Error()), nil } metricsBody, err := d.fetchInternal(ctx, cl, base+"/ws/v1/cluster/metrics") if err != nil { callLog.WithError(err) return errResult("fetch_cluster_env: metrics: " + err.Error()), nil } var info, metrics any _ = json.Unmarshal(infoBody, &info) _ = json.Unmarshal(metricsBody, &metrics) result := map[string]any{ "cluster_info": info, "metrics": metrics, "fetched_at": time.Now().UTC().Format(time.RFC3339), } callLog.WithResult(map[string]any{"info_bytes": len(infoBody), "metrics_bytes": len(metricsBody)}) return textResult(encodeJSON(result)), nil }