enquire-mcp API reference - v3.11.6-rc.2
    Preparing search index...

    Function searchHybrid

    • Parameters

      • vault: Vault
      • args: {
            embedding_model?: string;
            filter_frontmatter?: Record<string, FrontmatterFilterValue>;
            folder?: string;
            granularity?: "block" | "note";
            graph_boost?: boolean;
            limit?: number;
            min_signals?: number;
            query: string;
        }
        • Optionalembedding_model?: string
        • Optionalfilter_frontmatter?: Record<string, FrontmatterFilterValue>

          v3.10 (rc.10) — optional frontmatter filter. A { key: value } map; a hit is kept only if its note's YAML frontmatter satisfies EVERY pair (AND across keys). Per key, the value matches by scalar-equality (strings case-insensitive) or array-membership, and a filter value may itself be an array for OR — see frontmatterMatches. A note with no frontmatter, or missing a filtered key, is excluded (a filter is a positive assertion). Absent ⇒ no filtering (byte-identical to pre-3.10). Filtering happens on the fused candidate pool (already excluded-pruned), so a strict filter may return fewer than limit hits — that's correct.

          `{ status: "active", type: ["meeting", "decision"] }`
          
        • Optionalfolder?: string
        • Optionalgranularity?: "block" | "note"

          v2.2.0: "note" (default) returns 1 hit per note, picking the best chunk; "block" returns each chunk as a distinct hit so you see the multiple-paragraph case where one note covers a topic in two places.

        • Optionalgraph_boost?: boolean

          v2.3.0: post-RRF graph boost — rerank by counting how many other top-K hits link to each one. Default true; set false to disable for diagnostic comparison (e.g. measuring whether boost helped).

        • Optionallimit?: number
        • Optionalmin_signals?: number
        • query: string
      • ctx: {
            embedFile: string;
            feedback?: { scores: ReadonlyMap<string, number>; weight: number };
            ftsIndex: FtsIndex | null;
            hnsw?: HnswSearchContext | null;
            recency?: { staleDays: number; weight: number };
            reranker?: { alias?: string; topN?: number };
            rerankerOverride?: {
                score(query: string, passages: readonly string[]): Promise<number[]>;
            };
        }
        • embedFile: string

          Path to the .embed.db (file may or may not exist — checked at call time).

        • Optionalfeedback?: { scores: ReadonlyMap<string, number>; weight: number }

          v3.11.0 — optional opt-in closed-loop feedback re-ranking. When weight > 0 AND scores is non-empty, the final fused order is re-sorted by a blend of relevance rank and each note's feedback score (useful/(useful+notUseful+1), from obsidian_mark_useful via the FeedbackStore). weight = 0 / empty scores is a provable no-op. Applied AFTER recency so a "human said this helped" signal is the final tie-break. scores is keyed by relPath.

        • ftsIndex: FtsIndex | null

          FTS5 index, if --persistent-index is enabled at server start.

        • Optionalhnsw?: HnswSearchContext | null

          v2.13.0 — optional HNSW context for the embeddings-search arm. When passed, the embedding-side k-NN goes through the in-memory HNSW index (sub-10ms at any scale) instead of the O(n) brute-force cosine in EmbedDb.search(). Built on serve start; lives in ServerDeps.hnswContext. Null/undefined → brute-force fallback.

        • Optionalrecency?: { staleDays: number; weight: number }

          v3.10 (rc.5) — optional opt-in recency re-ranking. When weight > 0, the final fused order is re-sorted by a blend of relevance rank and the note's live-mtime recency (see recencyScore in staleness.ts). weight = 0 (or undefined) is a no-op — the default keeps ranking purely relevance-driven. staleDays is the recency half-life (the age at which recency = 0.5).

        • Optionalreranker?: { alias?: string; topN?: number }

          v2.9.0 — optional cross-encoder reranker config. When set, the top-N hits from RRF (default 50) are re-scored by a BGE-style cross-encoder and re-sorted before truncation. Adds ~30-50ms per query on M1 CPU for a 50-candidate set.

          alias resolves to a RERANKER_MODELS entry. topN defaults to 50. Lazy-loaded — first call downloads the model from HuggingFace (~25-110 MB depending on alias). Failures are swallowed and surface via signal_errors.reranker so the whole search doesn't break on a model load issue.

        • OptionalrerankerOverride?: { score(query: string, passages: readonly string[]): Promise<number[]> }

          v2.9.0 — test-only injection point. When set, this pre-loaded reranker is used instead of lazy-loading via loadReranker(alias). Lets unit tests validate the rerank-and-resort plumbing without pulling in the real ML model. Unused in production callers.

      Returns Promise<SearchHybridResponse>