codebase_health
Check the health of Docker, Qdrant, Ollama, and embedding model infrastructure to diagnose setup issues.
Instructions
Check the health of all infrastructure: Docker, Qdrant container, Ollama, and embedding model. Use this to diagnose setup issues.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/tools/manage-tools.ts:58-246 (handler)The handleManageTool function contains the 'codebase_health' case (lines 63-129) which performs the full health check logic: checks Docker availability, Qdrant container status (managed or external mode), embedding provider health, and returns a formatted status report.
export async function handleManageTool( name: string, _args: Record<string, unknown>, ): Promise<string> { switch (name) { case "codebase_health": { const config = getEmbeddingConfig(); const status: HealthStatus = { docker: false, ollama: false, qdrant: false, ollamaModel: false, qdrantImage: false, ollamaImage: false, }; const icon = (ok: boolean) => (ok ? "[OK]" : "[MISSING]"); const lines: string[] = [ "SocratiCode — Infrastructure Health Check:", "", `Qdrant mode: ${QDRANT_MODE}`, ]; if (QDRANT_MODE === "external") { const endpoint = QDRANT_URL ?? `http://${QDRANT_HOST}:${QDRANT_PORT}`; lines.push(`Qdrant endpoint: ${endpoint}`); try { await listCodebaseCollections(); status.qdrant = true; lines.push(`${icon(true)} External Qdrant (${endpoint}): Reachable`); } catch { lines.push(`${icon(false)} External Qdrant (${endpoint}): Unreachable — check QDRANT_URL / QDRANT_HOST`); } } else { // managed mode — Docker-managed container const docker = await isDockerAvailable(); status.docker = docker; lines.push(`${icon(status.docker)} Docker: ${status.docker ? "Running" : "Not found — install from https://docker.com"}`); if (docker) { const [qdrantRunning, qdrantImage] = await Promise.all([ isQdrantRunning(), isQdrantImagePresent(), ]); status.qdrant = qdrantRunning; status.qdrantImage = qdrantImage; lines.push(`${icon(status.qdrantImage)} Qdrant image: ${status.qdrantImage ? "Pulled" : "Not pulled — will be pulled on first index"}`); lines.push(`${icon(status.qdrant)} Qdrant container: ${status.qdrant ? "Running" : "Not running — will be started on first index"}`); } } // Embedding provider health check (works for ollama, openai, google) lines.push(""); lines.push(`Embedding provider: ${config.embeddingProvider}`); const provider = await getEmbeddingProvider(); const health = await provider.healthCheck(); lines.push(...health.statusLines); lines.push(""); if (QDRANT_MODE === "external") { lines.push("External Qdrant mode — Docker is not required for the vector database."); } else { lines.push( status.docker ? "Docker is available. Qdrant container will be auto-managed." : "Docker is required for Qdrant. Install from https://docker.com", ); } return lines.join("\n"); } case "codebase_list_projects": { try { const collections = await listCodebaseCollections(); if (collections.length === 0) { return "No projects have been indexed yet. Use codebase_index to index a project."; } const codebaseCollections = collections.filter((c) => c.startsWith("codebase_")); const graphCollections = collections.filter((c) => c.startsWith("codegraph_")); const lines = ["Indexed projects:\n"]; for (const c of codebaseCollections) { const projectId = c.replace("codebase_", ""); const hasGraph = graphCollections.includes(`codegraph_${projectId}`); const metadata = await getProjectMetadata(c); const pathInfo = metadata?.projectPath || "(path unknown — indexed before path tracking)"; lines.push(` - ${pathInfo}`); lines.push(` Collection: ${c}`); if (metadata?.lastIndexedAt) { lines.push(` Last indexed: ${metadata.lastIndexedAt}`); } if (metadata?.filesIndexed !== undefined) { if (metadata.indexingStatus === "in-progress") { lines.push(` Files: ${metadata.filesIndexed}/${metadata.filesTotal} (INCOMPLETE — run codebase_index to resume)`); } else { lines.push(` Files: ${metadata.filesIndexed}`); } } if (hasGraph) { const graphMeta = await getGraphMetadata(`codegraph_${projectId}`); if (graphMeta) { lines.push(` Code graph: ${graphMeta.nodeCount} files, ${graphMeta.edgeCount} edges (built: ${graphMeta.lastBuiltAt})`); } else { lines.push(` Code graph: present`); } } else { lines.push(` Code graph: not built`); } // Context artifacts try { const pathInfo2 = metadata?.projectPath; if (pathInfo2) { const artifactSummary = await getArtifactStatusSummary(pathInfo2); if (artifactSummary) { lines.push(` ${artifactSummary.lines[0]}`); } } } catch { // non-critical } } return lines.join("\n"); } catch { return "Could not connect to Qdrant. Run codebase_health to check infrastructure status."; } } case "codebase_about": { const infraStatus = await getInfraStatusSummary(); return [ "SocratiCode — Codebase intelligence MCP server", "Hybrid semantic + keyword search, dependency graphs, context artifacts.", "", ...infraStatus, "", "━━━ Quick Reference ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", "", "Indexing:", " codebase_index — Index a project (background). Poll with codebase_status.", " codebase_update — Incremental re-index (changed files only).", " codebase_stop — Gracefully stop in-progress indexing.", " codebase_remove — Delete a project's index.", " codebase_watch — Start/stop/status of live file watcher.", "", "Search:", " codebase_search — Hybrid semantic + BM25 search. Use after indexing.", " codebase_status — Check index status, progress, watcher state.", "", "Dependency Graph:", " codebase_graph_build — Build AST-based dependency graph (background).", " codebase_graph_query — Imports & dependents for a file.", " codebase_graph_stats — Graph stats: files, edges, most connected, orphans.", " codebase_graph_circular — Find circular dependencies.", " codebase_graph_visualize — Mermaid diagram (default) or interactive HTML explorer (mode=\"interactive\"), colour-coded by language.", " codebase_graph_status — Poll graph build progress.", " codebase_graph_remove — Delete a project's graph.", "", "Context Artifacts:", " codebase_context — List artifacts (.socraticodecontextartifacts.json).", " codebase_context_search — Search schemas, API specs, configs, docs.", " codebase_context_index — Re-index artifacts (usually automatic).", " codebase_context_remove — Delete indexed artifacts.", "", "Management:", " codebase_health — Check Docker, Qdrant, embeddings status.", " codebase_list_projects — List all indexed projects.", "", "━━━ Typical Workflow ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━", "", "1. codebase_index → poll codebase_status until complete.", "2. codebase_search to find code. Search before reading files.", "3. codebase_graph_query to explore dependencies.", "4. codebase_context_search for schemas, API specs, configs.", "", `v${SOCRATICODE_VERSION} · © 2026 Giancarlo Erra — Altaire Limited · AGPL-3.0`, "https://github.com/giancarloerra/socraticode", ].join("\n"); } default: return `Unknown tool: ${name}`; } } - src/index.ts:414-421 (registration)Registration of the 'codebase_health' tool via server.tool(), with description and delegation to handleManageTool.
server.tool( "codebase_health", "Check the health of all infrastructure: Docker, Qdrant container, Ollama, and embedding model. Use this to diagnose setup issues.", {}, async (args) => ({ content: [{ type: "text", text: await handleManageTool("codebase_health", args) }], }), ); - src/types.ts:46-53 (schema)HealthStatus interface defining the boolean fields tracked during health checks (docker, ollama, qdrant, ollamaModel, qdrantImage, ollamaImage).
export interface HealthStatus { docker: boolean; ollama: boolean; qdrant: boolean; ollamaModel: boolean; qdrantImage: boolean; ollamaImage: boolean; } - EmbeddingHealthStatus interface returned by provider.healthCheck(), including available, modelReady, and statusLines used in the health tool output.
export interface EmbeddingHealthStatus { /** Provider is reachable and ready. */ available: boolean; /** The model/endpoint is accessible. */ modelReady: boolean; /** Human-readable status lines for the health tool. */ statusLines: string[]; } - src/tools/manage-tools.ts:12-56 (helper)getInfraStatusSummary helper used by codebase_about, sharing infrastructure check logic similar to codebase_health.
/** Quick infrastructure check for embedding in codebase_about */ async function getInfraStatusSummary(): Promise<string[]> { const lines: string[] = []; const config = getEmbeddingConfig(); try { if (QDRANT_MODE === "external") { const endpoint = QDRANT_URL ?? `http://${QDRANT_HOST}:${QDRANT_PORT}`; try { await listCodebaseCollections(); // throws if unreachable const provider = await getEmbeddingProvider(); const health = await provider.healthCheck(); if (health.available) { lines.push(`Infrastructure: ✅ External Qdrant reachable (${endpoint}), ${config.embeddingProvider} embeddings ready`); } else { lines.push(`Infrastructure: ⚠️ External Qdrant reachable (${endpoint}), but ${config.embeddingProvider} embeddings not ready`); } } catch { lines.push(`Infrastructure: ❌ Cannot reach external Qdrant at ${endpoint}`); lines.push(" Check QDRANT_URL / QDRANT_HOST and make sure the server is running."); } } else { const docker = await isDockerAvailable(); if (!docker) { lines.push("Infrastructure: ❌ Docker not available"); lines.push(" Install from https://docker.com and start Docker Desktop."); return lines; } const qdrant = await isQdrantRunning(); const provider = await getEmbeddingProvider(); const health = await provider.healthCheck(); if (qdrant && health.available) { lines.push(`Infrastructure: ✅ All services running (Docker, Qdrant, ${config.embeddingProvider} embeddings)`); } else { const missing: string[] = []; if (!qdrant) missing.push("Qdrant"); if (!health.available) missing.push(`${config.embeddingProvider} embeddings`); lines.push(`Infrastructure: ⚠️ Docker OK, but ${missing.join(" and ")} not running`); lines.push(" Run codebase_index or codebase_health to auto-start services."); } } } catch { lines.push("Infrastructure: ❓ Could not check status"); } return lines; }