package tools import ( "context" "github.com/mark3labs/mcp-go/mcp" "spark-mcp-go/internal/rm" ) const ListApplicationsName = "list_applications" // NewListApplicationsTool returns the schema for the list_applications MCP Tool. func NewListApplicationsTool() mcp.Tool { return mcp.NewTool(ListApplicationsName, mcp.WithDescription("List YARN applications from a cluster's ResourceManager. Returns the raw RM JSON response so the agent can inspect app IDs, states, and owners."), mcp.WithString("cluster_id", mcp.Required(), mcp.Description("ID of the configured cluster (from list_clusters)"), ), mcp.WithString("state", mcp.Description("Filter by application state. YARN accepts comma-separated states; common values: NEW, NEW_SAVING, SUBMITTED, ACCEPTED, RUNNING, FINISHED, FAILED, KILLED."), ), mcp.WithString("user", mcp.Description("Filter by submitting user."), ), mcp.WithString("queue", mcp.Description("Filter by YARN queue name. Matches the YARN RM ?queue= parameter."), ), mcp.WithNumber("limit", mcp.Description("Maximum number of applications to return. Defaults to 100 if not provided; set to 0 to request the RM default (no limit)."), mcp.DefaultNumber(100), ), ) } // ListApplicationsHandler queries the ResourceManager for applications. func (d *Deps) ListApplicationsHandler(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { clusterID, err := req.RequireString("cluster_id") if err != nil { return errResult("list_applications: " + err.Error()), nil } args := req.GetArguments() state := "" if v, ok := args["state"].(string); ok { state = v } user := "" if v, ok := args["user"].(string); ok { user = v } queue := "" if v, ok := args["queue"].(string); ok { queue = v } limit := 0 if v, ok := args["limit"].(float64); ok { limit = int(v) } if limit < 0 { limit = 0 } callLog := startToolCall(ctx, d.Logger, ListApplicationsName, map[string]any{ "cluster_id": clusterID, "state": state, "user": user, "queue": queue, "limit": limit, }) defer callLog.End() cl, err := d.ClusterRepo.Get(ctx, clusterID) if err != nil { callLog.WithError(err) return errResult("list_applications: cluster " + clusterID + ": " + err.Error()), nil } rmc := rm.New(d.HTTPClient, cl) raw, err := rmc.ListApps(ctx, state, user, queue, limit) if err != nil { callLog.WithError(err) return errResult("list_applications: " + err.Error()), nil } callLog.WithResult(map[string]any{"bytes": len(raw)}) return textResult(string(raw)), nil }