Self-hosted, hybrid-search knowledge base exposed as an MCP server.
Server has 4 well-named tools with clear descriptions and documented schemas. All tools start with action verbs (search_, get_, add_). Descriptions are substantive (100-200 chars), explaining what the tool does and when to use it. Input schemas are present with type definitions and parameter descriptions. Tool annotations (readOnlyHint, idempotentHint) are correctly applied. However, output schemas are not formally documented, responses are JSON strings without declared structure. Error handling is minimal (no recovery guidance or categorization). Parameters lack some constraints (e.g., no enum for 'dimension', no min/max for 'limit'). The add_annotation tool correctly documents idempotency, but other tools lack explicit side-effect declarations.
Add an annotation (dimension-tagged note) to a document. Idempotent on content: if an annotation with the same document_id, dimension, and text already exists, this is a no-op (returns success without inserting a duplicate).
Retrieve a single document by ID with all annotations and tags.
Search annotations (dimension-tagged notes on documents). Hybrid search: FTS5 over dimension and text, plus semantic matches over embeddings.
Search the knowledge base for documents. Hybrid search: FTS5 over title, source, body, plus tag matches and annotation matches. Semantic matches (cosine similarity over embeddings) fill in once exact matches are exhausted.
Output schemas not formally documented. Tools return JSON strings but no schema is declared for the response structure (e.g., what fields are in a document object, what does search_documents return?). LLMs cannot plan downstream calls without knowing response shape.
Parameter 'dimension' in search_annotations and add_annotation lacks enum constraint. Description says 'e.g. methodology, caveats, references' but does not enforce valid values. LLMs may hallucinate invalid dimensions.
Error responses are generic JSON strings without recovery guidance. No distinction between retryable errors (e.g., timeout) and user-fixable errors (e.g., invalid dimension). LLMs cannot determine next action.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 65 | 2026-07-28+ | v2 |
No pagination parameters visible in search_documents or search_annotations. SEARCH_LIMIT is hardcoded to 20 in server.py, but tools do not expose limit or offset/cursor parameters. Agents cannot control result size or iterate through large result sets.
get_document description is minimal (18 chars). Does not explain what 'annotations and tags' means or when to call this vs search_documents. Baseline for param descriptions is 72 chars; this falls short.