- New komodo_server_stats: system_information, system_stats, historical_server_stats, server_state, periphery_information, containers_summary, version, core_info - New komodo_resource_stats: deployment_stats, deployment_container, build_monthly_stats, action_state (9 resource types), concurrency_limit_usage, resource_matching_container - New komodo_updates: get (full execution logs) and list (recent operations history) - Expanded komodo_logs: add build resource type (built_contents, remote_contents, remote_error, hashes) - Expanded komodo_list_detail: terminals, alerts, containers_summary - Expanded komodo_execute: refresh_server, refresh_server_containers, refresh_stack_cache, refresh_stack_content, remove_orphan_containers, check_stack_for_update, check_deployment_for_update, get_mcp_token
100 lines
3.8 KiB
TypeScript
100 lines
3.8 KiB
TypeScript
import { z } from "zod";
|
|
import { KomodoClient } from "../komodo-client.js";
|
|
import { RESOURCE_STATS_REQUEST_MAP, ACTION_STATE_REQUEST_MAP } from "../types.js";
|
|
|
|
const ResourceStatType = z.enum([
|
|
"deployment_stats",
|
|
"deployment_container",
|
|
"build_monthly_stats",
|
|
"action_state",
|
|
"concurrency_limit_usage",
|
|
"resource_matching_container",
|
|
]);
|
|
|
|
const ActionStateResourceType = z.enum([
|
|
"action", "build", "deployment", "procedure",
|
|
"repo", "server", "stack", "swarm", "sync_resource",
|
|
]);
|
|
|
|
export const resourceStatsInputSchema = {
|
|
stat_type: ResourceStatType.describe(
|
|
"Resource stat to retrieve: deployment_stats (CPU/mem/net usage), deployment_container (container details), build_monthly_stats (build frequency), action_state (is resource currently running), concurrency_limit_usage (active limits), resource_matching_container (reverse-lookup container → resource)."
|
|
),
|
|
id: z.string().optional().describe("Resource ID or name (required for deployment_stats, deployment_container, build_monthly_stats, action_state)"),
|
|
resource_type: ActionStateResourceType.optional().describe("Resource type for action_state (e.g. 'stack', 'deployment', 'build'). Required when stat_type is 'action_state'."),
|
|
server: z.string().optional().describe("Server name (required for resource_matching_container)"),
|
|
container: z.string().optional().describe("Container name (required for resource_matching_container)"),
|
|
};
|
|
|
|
export async function handleResourceStats(
|
|
args: {
|
|
stat_type: z.infer<typeof ResourceStatType>;
|
|
id?: string;
|
|
resource_type?: z.infer<typeof ActionStateResourceType>;
|
|
server?: string;
|
|
container?: string;
|
|
},
|
|
client: KomodoClient,
|
|
): Promise<{ content: { type: "text"; text: string }[] }> {
|
|
const { stat_type, id, resource_type, server, container } = args;
|
|
|
|
// Handle action_state separately — it dispatches to different endpoints per resource type
|
|
if (stat_type === "action_state") {
|
|
if (!resource_type) throw new Error(`action_state requires a resource_type (e.g. 'stack', 'deployment', 'build')`);
|
|
if (!id) throw new Error(`action_state requires an id`);
|
|
|
|
const requestName = ACTION_STATE_REQUEST_MAP[resource_type];
|
|
if (!requestName) {
|
|
throw new Error(`No action state endpoint for resource type: ${resource_type}`);
|
|
}
|
|
|
|
// The param key matches the resource type for most, but sync_resource uses "resource_sync"
|
|
const paramKey = resource_type === "sync_resource" ? "resource_sync" : resource_type;
|
|
const params: Record<string, unknown> = { [paramKey]: id };
|
|
|
|
const result = await client.rpc("read", requestName, params);
|
|
return {
|
|
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
};
|
|
}
|
|
|
|
const requestName = RESOURCE_STATS_REQUEST_MAP[stat_type];
|
|
if (!requestName) {
|
|
throw new Error(`Unknown resource stat type: ${stat_type}`);
|
|
}
|
|
|
|
const params: Record<string, unknown> = {};
|
|
|
|
switch (stat_type) {
|
|
case "deployment_stats":
|
|
case "deployment_container":
|
|
if (!id) throw new Error(`${stat_type} requires an id (deployment name or ID)`);
|
|
params.deployment = id;
|
|
break;
|
|
case "build_monthly_stats":
|
|
if (!id) throw new Error(`${stat_type} requires an id (build name or ID)`);
|
|
params.build = id;
|
|
break;
|
|
case "concurrency_limit_usage":
|
|
// No params needed
|
|
break;
|
|
case "resource_matching_container":
|
|
if (!server) throw new Error(`resource_matching_container requires a server`);
|
|
if (!container) throw new Error(`resource_matching_container requires a container name`);
|
|
params.server = server;
|
|
params.container = container;
|
|
break;
|
|
}
|
|
|
|
const result = await client.rpc("read", requestName, params);
|
|
|
|
return {
|
|
content: [
|
|
{
|
|
type: "text",
|
|
text: JSON.stringify(result, null, 2),
|
|
},
|
|
],
|
|
};
|
|
}
|