Show HN: Hubmesh – Multi-hop RAG retrieval with zero LLM calls in the query path Hubmesh, a new Python library, improves multi-hop RAG retrieval by adding a centrality-aware planner over existing vector databases, eliminating LLM calls in the query path. The library uses multi-component seed selection and budget-aware context packing to enhance retrieval quality, as demonstrated in its Show HN launch. Centrality-aware GraphRAG retrieval planner. Drop-in layer over any vector DB. hubmesh is a Python library that improves multi-hop RAG quality on top of an existing vector database. You don't replace your infrastructure — you add a smart planner between your vector DB and your LLM. Naive vector retrieval "embed query, get top-k by cosine similarity" fails on multi-hop questions like "Where was the founder of the company that acquired Slack born?" The correct answer requires retrieving entities along a reasoning path, not the single most similar item. GraphRAG and HippoRAG showed that running a small Personalized PageRank over a knowledge graph at query time can substantially improve multi-hop retrieval. hubmesh extends that line with two contributions: Multi-component seed selection. Instead of picking PPR seeds by raw query similarity which picks wrong-community seeds at high feature overlap , seeds are chosen by a multi-component score combining query relevance, structural fit, and coverage diversity. Budget-aware context packing. Once relevant entities are scored, pack them into the LLM's context window with explicit coverage and redundancy control rather than just truncating top-k. The multi-component scoring pattern is adapted from the NNSI framework Naidu Dsk, ICOMP'25 — to appear for SDN topology optimization, repurposed here for retrieval planning. python from hubmesh import Planner from hubmesh.adapters import InMemoryStore embed = ... callable: text - np.ndarray docs = ... list of Document or strings or dicts store = InMemoryStore.from documents docs, embed=embed planner = Planner store=store, embed=embed result = planner.retrieve query="...", top k=10, budget tokens=4000 python from hubmesh import Planner from hubmesh.adapters import QdrantStore store = QdrantStore.from documents docs in-memory store = QdrantStore.from documents docs, path="./qdrant data" on-disk store = QdrantStore.from documents docs, url="http://localhost:6333" remote planner = Planner store=store, embed=embed result = planner.retrieve query="...", top k=10 python from hubmesh.adapters import ChromaStore store = ChromaStore.from documents docs ephemeral store = ChromaStore.from documents docs, persist directory="./chroma data" store = ChromaStore.from documents docs, host="localhost", port=8000 python from hubmesh.kg import build entity kg import spacy nlp = spacy.load "en core web sm" kg = build entity kg docs, nlp=nlp planner = Planner store=store, kg=kg, nlp=nlp result = planner.retrieve query="Where was the founder of the company that bought Slack born?", top k=10, budget tokens=4000 RetrievalResult includes reasoning paths showing why each doc was returned for path in result.reasoning: print f" score={path.score:.3f} {' → '.join path.node ids }" python from hubmesh.kg llm import build entity kg llm from hubmesh.entity linker import EmbeddingLinker, make st embedder def llm prompt : provider-agnostic — bring your own return your llm call prompt kg = build entity kg llm docs, llm=llm, cache path="kg cache.json" optional: cross-document entity dedup — same Linker protocol as the spaCy path kg = build entity kg llm docs, llm=llm, cache path="kg cache.json", linker=EmbeddingLinker embed=make st embedder planner = Planner store=store, kg=kg python from hubmesh.kg import build entity kg from hubmesh.entity linker import EmbeddingLinker, make st embedder Cluster surface variations: "United States" / "U.S." / "USA" → one entity linker = EmbeddingLinker embed=make st embedder , threshold=0.82 kg = build entity kg docs, linker=linker r1 = planner.retrieve query=question, top k=5 your agent reads r1, spots the bridge entity, then aims hop 2 at it: r2 = planner.retrieve query=question, top k=5, seed entities= "Nimbus Analytics" , merged with the query's own seeds exclude docs= s.doc.id for s in r1.sources , don't re-retrieve consumed docs Seed mentions resolve through the alias index, so free-text entity names work. The query path stays deterministic and LLM-free — the planning intelligence lives in the caller. pip install "hubmesh mcp " python -m spacy download en core web sm {"mcpServers": {"hubmesh": {"command": "hubmesh-mcp"}}} Exposes the planner as deterministic operator tools over stdio — index corpus , retrieve seed-steerable, as above , resolve entities , entity neighbors , path between , get document , graph stats , list corpora . Your agent is the solver: it decomposes the question, reads each hop, and aims the next one; the server answers in milliseconds with zero LLM calls. Corpora persist as plain JSON/NPZ under ~/.hubmesh/corpora . The server warms up models and persisted corpora in the background at launch ~5-10s on first run , so tool calls stay fast from the start — relevant for strict-timeout connector clients Perplexity, etc. . For web-based connector clients, serve SSE natively — no gateway process needed: hubmesh-mcp --transport sse --port 8000 --allow-tunnel ngrok http 8000 paste https://