package tools import ( "context" "github.com/mark3labs/mcp-go/mcp" "spark-mcp-go/internal/rm" ) const KillApplicationName = "kill_application" // NewKillApplicationTool returns the schema for the kill_application MCP Tool. func NewKillApplicationTool() mcp.Tool { return mcp.NewTool(KillApplicationName, mcp.WithDescription("Kill (move to KILLED state) a YARN application through the ResourceManager. Returns the RM JSON response."), mcp.WithString("cluster_id", mcp.Required(), mcp.Description("ID of the configured cluster (from list_clusters)"), ), mcp.WithString("app_id", mcp.Required(), mcp.Description("YARN application ID, e.g. application_1234567890_0001"), ), ) } // KillApplicationHandler sends a KILLED state update to the ResourceManager. func (d *Deps) KillApplicationHandler(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { clusterID, err := req.RequireString("cluster_id") if err != nil { return errResult("kill_application: " + err.Error()), nil } appID, err := req.RequireString("app_id") if err != nil { return errResult("kill_application: " + err.Error()), nil } callLog := startToolCall(ctx, d.Logger, KillApplicationName, map[string]any{ "cluster_id": clusterID, "app_id": appID, }) defer callLog.End() cl, err := d.ClusterRepo.Get(ctx, clusterID) if err != nil { callLog.WithError(err) return errResult("kill_application: cluster " + clusterID + ": " + err.Error()), nil } rmc := rm.New(d.HTTPClient, cl) raw, err := rmc.KillApp(ctx, appID) if err != nil { callLog.WithError(err) return errResult("kill_application: " + err.Error()), nil } callLog.WithResult(map[string]any{"bytes": len(raw)}) return textResult(string(raw)), nil }