API reference

MCP tools

The fifteen tools the prom.codes context server exposes over stdio. Includes input schemas and example responses.

The context server registers fifteen tools. Each one is callable by any MCP-aware host (Claude Code, Cursor, VS Code, your own runtime) once the server is wired up — see Claude Code for the canonical setup.

search_code

Hybrid retrieval over the indexed workspace. Combines lexical and semantic ranking over the indexed code, then expands one hop in the symbol graph.

{
  "name": "search_code",
  "arguments": {
    "query": "validate incoming webhook signature",
    "k": 8
  }
}

k is optional (default 10, capped at 50). Returns { query, k, reranked, results: [{ score, provenance, symbol }] }, where each symbol carries { name, kind, language, container, exported, filePath, range } and provenance is the per-source score breakdown.

Graceful degradation (≥ 0.4.3). If the embedder is unavailable (missing/invalid key → 401, provider outage, rate-limit), the semantic leg is skipped and search continues on lexical + symbol-graph only. The response then also carries degraded: "lexical+graph-only", a human-readable note, and vectorError (the underlying cause), so the caller knows ranking is keyword-based until a working embedder is configured. The tool never fails outright on an embedding error.

get_symbol

Looks up symbols by exact name, returning each definition's kind, language, container, export flag, file path, and range. Optional file narrows the result to a single workspace-relative path; optional limit caps the count (default 10, max 50).

{
  "name": "get_symbol",
  "arguments": { "name": "enqueue", "file": "src/queue.ts" }
}

Returns { name, file, symbols: [symbol] }.

find_references

Lists all static references (calls / imports / member-access) whose target name matches.

{
  "name": "find_references",
  "arguments": { "name": "chargeCustomer", "limit": 20 }
}

Returns { name, references: [{ name, kind, filePath, fromContainer, moduleSpecifier, range }] }.

find_callers

Inbound call-graph edge: every symbol whose body calls the named symbol. Materialised from call / member_access references whose byte-range is enclosed by the caller symbol's range, matched case-insensitively on the seed name. Use this to answer "who calls this?" without scanning the whole tree.

{
  "name": "find_callers",
  "arguments": { "name": "chargeCustomer", "limit": 20 }
}

Returns { name, callers: [{ name, kind, language, filePath, ... }] }.

find_callees

Outbound call-graph edge: every symbol the named symbol calls. Resolves call / member_access references emitted from inside the seed symbol's body to their definitions (excluding the seed itself). Use this to answer "what does this depend on?".

{
  "name": "find_callees",
  "arguments": { "name": "checkout", "limit": 20 }
}

Returns { name, callees: [{ name, kind, language, filePath, ... }] }.

expand_context

One-hop (or two-hop) symbol-graph expansion around a single symbol name. Returns neighbours bucketed by edge type and walk depth, so an agent can grow a tight retrieval into something it can reason about. depth is 1 (direct, default) or 2; limit caps the count (default 10, max 50); edgeTypes optionally restricts the walk to a subset of defines / calls / imports / same-file.

{
  "name": "expand_context",
  "arguments": {
    "name": "RetryQueue",
    "depth": 1,
    "edgeTypes": ["calls", "imports"]
  }
}

Returns { name, depth, edgeTypes, neighbours: [{ via, depth, symbol }] }.

get_file

Verbatim UTF-8 file contents, resolved against the configured workspace root (path traversal outside the root is rejected). Optional startByte / endByte slice the file; the returned payload is capped at 256 KiB and flags truncated when the slice exceeded it.

{
  "name": "get_file",
  "arguments": { "path": "src/queue.ts", "startByte": 0, "endByte": 4096 }
}

Returns { path, startByte, endByte, truncated, content }.

list_changed_since

Returns file records with indexedAt greater than timestampMs, ordered ascending — an incremental cursor for watchers and review flows. Use the largest returned indexedAt (nextCursor) as the next cursor. limit caps the page (default 10, max 50).

{
  "name": "list_changed_since",
  "arguments": { "timestampMs": 1717000000000, "limit": 50 }
}

Returns { cursor, nextCursor, files: [{ path, language, contentHash, size, mtimeMs, indexedAt }] }.

list_workspaces

Metadata for every workspace this server indexes. The local SQLite MVP serves a single workspace; the Supabase backend is multi-tenant. Each entry carries the index roll-up (file / symbol / reference counts) and the per-language file distribution. Takes no arguments.

{
  "name": "list_workspaces",
  "arguments": {}
}

Returns { workspaces: [{ id, name, root, storageBackend, regionMode, embeddingProvider, stats, languages }] }.

framework_overview

High-level shape of the workspace: frameworks detected from manifest files (package.json, composer.json, requirements.txt, pyproject.toml) plus the per-language file distribution from the index. Heuristic and dependency-driven — absence of a hit means "not declared in a manifest", not "not used". Takes no arguments.

{
  "name": "framework_overview",
  "arguments": {}
}

Returns { workspaceRoot, manifestsInspected, frameworks: [{ name, version, source }], languages }.

index_status

Health check for the workspace's code index. Call it first when search_code returns nothing, when you're unsure whether the right folder is indexed, or to confirm the API key works. Takes no arguments.

{
  "name": "index_status",
  "arguments": {}
}

Returns { installed, workspace: { id, name, root }, storage: { backend, dbPath, regionMode }, autoIndex: { managed, allowedForThisRoot, reason }, index: { indexed, files, symbols, references, languages, lastIndexedAt }, embeddings: { provider, reachable, coverage, error? }, hooks, update, summary }. autoIndex.allowedForThisRoot is false when the workspace resolved to your home directory or a filesystem root — the server refuses to crawl those (open a project folder or set PROMETHEUS_WORKSPACE_ROOT, then restart). embeddings.reachable is a zero-cost probe of the configured key (false with an error when the key is missing/invalid; null when the provider can't be cheaply probed).

Two fields deserve special attention (both since 0.10.0): embeddings.coverage is { embeddedChunks, totalChunks, percent } — the share of code chunks that have a semantic vector. Below ~80 % the summary suggests running reindex, which embeds only what is missing. update is { current, latest, updateAvailable, command, lastResult? } — the cache-first version check (see update_servers; lastResult reports what the last detached update run did).

reindex

Rebuilds this workspace's index on demand: re-scans every file (parse + hash-diff; entries for files deleted on disk are removed), then runs the embedding pass. The embed pass is incremental by default — it embeds only the new/changed symbols that are missing a vector, so this is the fast way to populate embeddings after fixing an API key or to pick up changes without restarting the host. Pass force: true to clear the snapshot and re-embed every symbol from scratch (use after switching embedding providers, or to repair a partial index). Requires a PROMETHEUS_API_KEY and a real project folder (refused for the home directory / filesystem root).

{
  "name": "reindex",
  "arguments": { "force": false }
}

Returns { ok, force, index: { scanned, indexed, skippedUnchanged, removed, errors }, embeddings: { embedded, provider, model, dimension, driftRecovered, embedMs }, summary }. When indexing is disabled (no key) or the workspace is the home/root, returns { ok: false, reason } instead.

install_hooks

Installs (or removes) the Claude Code awareness hooks — the active layer that makes agents actually use these tools instead of falling back to grep out of habit. A SessionStart hook injects a binding directive at turn 0 (and after every compaction), a UserPromptSubmit hook re-asserts it per prompt, and the SessionStart hook also surfaces pending server updates.

{
  "name": "install_hooks",
  "arguments": { "scope": "user", "strict": false, "uninstall": false }
}

scope: user (default — every project), project (committed .claude/settings.json) or project-local (gitignored; the auto-bootstrap target). strict: true additionally denies Grep/Glob and redirects to search_code (opt-in). Idempotent, reversible, backs up settings.json, preserves foreign hooks. Claude-Code-specific.

dashboard

Renders the local status dashboard as one self-contained HTML page and returns its file path — running servers (via heartbeats), per-workspace index health incl. embedding coverage %, memory roll-up, hooks/key health and the current month's cloud usage. Read-only and local-first: only the cloud tile queries the metered proxy. See the Local dashboard guide for the full tour and the CLI variant (… dashboard --out … --no-open --json).

{
  "name": "dashboard",
  "arguments": { "open": true }
}

open: true also launches the default browser. Returns { ok, htmlPath, servers, currentWorkspace, workspacesIndexed, memoryRecords, hooksInstalled, keyValid, cloud, summary }.

update_servers

Safe, guided self-update for all three prom.codes servers. It never runs npm install while servers are running (a running server locks its native modules — the classic Windows EBUSY half-install trap). Instead it reports the plan and launches a detached updater that waits until every prom server has exited (you reload/close the editor windows), then runs the one documented upgrade command. The outcome lands in index_status.update.lastResult after the restart.

{
  "name": "update_servers",
  "arguments": { "dryRun": false, "force": false }
}

dryRun: true only reports the plan (installed vs latest versions, install kind, npm config get ignore-scripts, running servers). force: true — always explicit, never assumed — lets the updater terminate the remaining servers instead of waiting for their windows to close. Running via npx …@latest? Then there is nothing to install — the response says to simply restart the session. See the Local dashboard & updates guide for the full flow.