import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js'; import { type RagContentBlock, type RagTextContentBlock } from './error-utils.js'; import type { IngestDataInput, ListFilesInput, QueryDocumentsInput, RAGServerConfig, SyncStartInput, SyncStatusInput } from './types.js'; type QueryContent = [RagTextContentBlock, ...RagContentBlock[]]; /** RAG server compliant with MCP Protocol */ export declare class RAGServer { private readonly server; private readonly vectorStore; private readonly embedder; private readonly chunker; private readonly parser; private readonly dbPath; /** * One or more allowed document base directories — REALPATH-normalized * (the validation/security domain). Passed to `DocumentParser` as the * security boundary. NOT used for `list_files` scanning/display; that uses * the NORMAL-path `rawBaseDirs` below. Normalized from either the legacy * `{ baseDir }` config shape or the new `{ baseDirs }` shape so downstream * readers do not need to branch on shape. */ private readonly baseDirs; /** * Normal-path (resolve()) roots, index-aligned with `baseDirs`, for * user-facing `list_files` scan/display. Falls back to `baseDirs` for legacy * `{ baseDir }` callers. See {@link BaseDirsConfig} for the path policy. */ private readonly rawBaseDirs; /** Legacy single-root accessor for `rawBaseDirs`. Derived from `rawBaseDirs[0]`. */ private readonly rawBaseDir; private readonly cacheDir; private readonly excludePaths; private readonly configWarnings; /** * Structured base-dirs resolution error. When non-null, the server is in * degraded mode: `status` remains callable so the user can diagnose the * problem via MCP, while root-dependent tools should surface this error * before doing DB or filesystem work. See `resolveBaseDirs` for the error * semantics. */ private readonly configError; private readonly minChunkLength; /** * Configured byte ceiling for one ingested file. The parser enforces it for * parsing; sync also needs it before hashing, where nothing else bounds the * read. */ private readonly maxFileSize; private readonly device; private readonly storeImages; /** * The one current-or-latest sync job this process retains (SYNC-006). A new * `sync_start` replaces a terminal record, so the older id becomes unknown, * and process exit simply discards it: there is no history, persistence, * eviction policy, or recovery. */ private syncJob; /** * True while one external mutation is in flight (SYNC-007). A request-scoped * mutation clears it when the request completes; a sync keeps it until its * job reaches a terminal state. */ private mutationInFlight; constructor(config: RAGServerConfig); /** * Fail-fast guard for root-dependent tools. When a {@link BaseDirsConfigError} * is stored on the instance the server is in degraded mode (invalid * `BASE_DIRS` — see `resolveBaseDirs`) and every root-dependent tool MUST * reject BEFORE any DB / embedder / parser access so the user sees the * configuration problem unambiguously. Throws the stored * {@link BaseDirsConfigError} (kind `config`) so the central dispatcher * mapper renders it as `McpError(InvalidParams)` — error→code ownership * stays in exactly one place instead of being hand-built here. * * `status` deliberately does NOT call this helper; it remains callable in * degraded mode and exposes the error via a diagnostic content block so * the user can recover via MCP without inspecting stderr. */ private assertConfigOk; /** * Append the centralized config-warning blocks to a handler response. * Every tool handler funnels through this method so the warning shape * stays in exactly one place (design-doc-mandated countermeasure for the * "warning shape changes touch many handlers" risk). */ private withWarnings; /** * Take the single external-mutation slot, or describe the overlap. * * Returns `null` when the slot was free (the caller now holds it), otherwise * the responsive overlap result: an ordinary tool result with `isError: true` * rather than a thrown error, so it never passes through `toMcpError`. When a * sync holds the guard the message names its job id and points at * `sync_status`, which is the only way for the caller to learn when to retry. */ private acquireMutation; private releaseMutation; /** * Set up MCP handlers */ private setupHandlers; /** * Initialization */ initialize(): Promise; /** * query_documents tool handler */ handleQueryDocuments(args: QueryDocumentsInput): Promise<{ content: QueryContent; }>; /** * ingest_file tool handler (re-ingestion support, transaction processing, rollback capability) * * `options.skipOptimize` is internal: sync compacts once per run, so its reuse * of this handler must not compact once per file (a 100-file sync would * otherwise perform 101 compactions). The `ingest_file` and `ingest_data` tools * omit it and keep compacting per call, which is the behavior they always had. */ handleIngestFile(raw: unknown, options?: { skipOptimize?: boolean; images?: boolean; }): Promise<{ content: RagTextContentBlock[]; }>; private ingestFile; /** * ingest_data tool handler * Saves raw content to raw-data directory and calls handleIngestFile internally * * For HTML content: * - Parses HTML and extracts main content using Readability * - Converts to Markdown for better chunking * - Saves as .md file */ handleIngestData(args: IngestDataInput): Promise<{ content: RagTextContentBlock[]; }>; /** * list_files tool handler * * Scans the normal-path roots (`this.rawBaseDirs`) so scanned paths match the * resolve()-stored DB keys (see {@link BaseDirsConfig} for the path policy). * * Scans every effective base directory (`this.rawBaseDirs`) for supported * files and cross-references with ingested documents. Multi-root contract: * - Returns top-level `baseDirs` (all effective roots in normal-path space, * nested-root-pruned by `resolveBaseDirs`). * - Preserves legacy top-level `baseDir = rawBaseDirs[0]` for clients written * against the single-root shape. * - Annotates each file entry with the producing `baseDir`. * - De-duplicates exact duplicate file paths across roots (first occurrence * wins, preserving root iteration order). * - Preserves raw-data / orphaned DB entries under `sources` with no * producing-root annotation. * - Excludes `dbPath` and `cacheDir` uniformly across every root. */ handleListFiles(input?: ListFilesInput): Promise<{ content: RagTextContentBlock[]; }>; /** * status tool handler */ handleStatus(): Promise<{ content: RagTextContentBlock[]; }>; /** * delete_file tool handler * Deletes chunks from VectorDB and physical raw-data files * Supports both filePath (for ingest_file) and source (for ingest_data) */ handleDeleteFile(raw: unknown): Promise<{ content: RagTextContentBlock[]; }>; /** * read_chunk_neighbors tool handler * Returns chunks around a target chunkIndex within a single ingested document. * Context-expansion utility — not a search tool. Mirrors handleDeleteFile's * dual-input (filePath XOR source) resolution pattern. */ handleReadChunkNeighbors(raw: unknown): Promise<{ content: RagTextContentBlock[]; }>; /** Resolve the shared filePath/source reference without changing its DB-key spelling. */ private resolveDocumentTarget; /** * sync_start tool handler * * Registers the one current job, schedules the run, and answers with its id * without waiting for any of it: the caller polls `sync_status` (SYNC-006). * The scheduled promise is deliberately floating — an unexpected rejection is * captured into the job record instead of escaping, and the run holds the * external-mutation guard until it is terminal. */ handleSyncStart(input: SyncStartInput): Promise<{ content: RagTextContentBlock[]; }>; /** * sync_status tool handler * * Read-only, so it stays callable while a sync holds the mutation guard. Any * id other than the current one is unknown: the record was replaced by a newer * `sync_start` or lost with a previous server process. */ handleSyncStatus(input: SyncStatusInput): Promise<{ content: RagTextContentBlock[]; }>; /** Patch the current job, ignoring a write aimed at a record already replaced. */ private updateSyncJob; /** * The scheduled body of one sync job: supply the real collaborators to the * shared core (`src/features/sync.ts`) and fold its result into the pollable * record. Planning, prune eligibility, and the stop-on-first-error policy stay * in the core; path classification and depth therefore match the CLI exactly. */ private runSyncJob; /** * Sync's `ingestFile` collaborator uses the same typed ingestion operation as * `ingest_file`, preserving its backup and rollback semantics while returning * only the chunk count the sync core needs. A zero-chunk file is reported as * `empty`; the typed operation rejects it before delete, leaving prior rows * unchanged. * * Compaction is the second difference: the sync core runs one `optimize()` for * the whole run, so the per-file one is skipped here. A rollback still compacts * — that path restores rows and then aborts the run, so no later `optimize()` * follows it. */ private ingestFileForSync; /** * Serve this instance's tool registration over `transport`. * * Exposed because the registration itself — not a re-registered copy of it — * is what an MCP client talks to, and `this.server` is private. `run()` passes * the stdio transport; a test passes an in-memory pair. * * One instance serves at most one client: the sync job record and the mutation * slot are per-process, so a transport that multiplexed clients would share one * caller's job state and one caller's write lock with every other caller. */ connect(transport: Transport): Promise; /** * Start the server */ run(): Promise; /** * Stop the server and release resources */ close(): Promise; } export {}; //# sourceMappingURL=index.d.ts.map