/** * MCP gno_status tool - Index status and health. * * @module src/mcp/tools/status */ import type { IndexStatus } from "../../store/types"; import type { ToolContext } from "../server"; import { buildContentTypeBoostStatus } from "../../config/content-types"; import { formatChunkingStatus } from "../../core/chunking-status"; import { resolveModelUri } from "../../llm/registry"; import { createStandaloneResidentStatus } from "../../serve/resident-status"; import { runTool, type ToolResult } from "./index"; type StatusInput = Record; /** * Format status as text for MCP content. */ function formatStatus(status: IndexStatus): string { const lines: string[] = []; lines.push(`Index: ${status.indexName}`); lines.push(`Config: ${status.configPath}`); lines.push(`Database: ${status.dbPath}`); lines.push(`Health: ${status.healthy ? "OK" : "DEGRADED"}`); if ("resident" in status) { const resident = status.resident as NonNullable< ReturnType> >; lines.push( `Runtime: ${resident.mode}${resident.resident ? ` (${resident.transport.activeSessions} sessions)` : " (standalone)"}` ); } lines.push(""); if (status.collections.length === 0) { lines.push("No collections configured."); } else { lines.push("Collections:"); for (const c of status.collections) { lines.push( ` ${c.name}: ${c.activeDocuments} docs, ${c.totalChunks} chunks` + (c.embeddedChunks > 0 ? `, ${c.embeddedChunks} embedded` : "") ); } } lines.push(""); lines.push( `Total: ${status.activeDocuments} documents, ${status.totalChunks} chunks` ); if (status.typedMetadata) lines.push( `Typed metadata: ${status.typedMetadata.pending} pending sync, ${status.typedMetadata.invalid} invalid` ); if (status.embeddingBacklog > 0) { lines.push(`Embedding backlog: ${status.embeddingBacklog} chunks`); } const chunking = formatChunkingStatus(status.chunking); if (chunking) lines.push(chunking); if (status.recentErrors > 0) { lines.push(`Recent errors: ${status.recentErrors} (last 24h)`); } if (status.lastUpdatedAt) { lines.push(`Last updated: ${status.lastUpdatedAt}`); } return lines.join("\n"); } /** * Handle gno_status tool call. */ export function handleStatus( _args: StatusInput, ctx: ToolContext ): Promise { return runTool( ctx, "gno_status", async () => { const result = await ctx.store.getStatus({ embedModel: resolveModelUri(ctx.config, "embed"), chunking: ctx.config.chunking ?? {}, }); if (!result.ok) { throw new Error(result.error.message); } // Override configPath with actual path from context return { ...result.value, configPath: ctx.actualConfigPath, contentTypeBoost: buildContentTypeBoostStatus( ctx.config.contentTypes ?? [] ), resident: ctx.getResidentStatus?.() ?? createStandaloneResidentStatus("stdio"), }; }, formatStatus ); }