Retrieval MCP server for the self-docs RAG pipeline exposing search_docs, list_doc_sources, propose_doc_source, and upload_doc_text tools over stateless HTTP
Four tools with clear verb-noun naming (search_docs, list_doc_sources, propose_doc_source, upload_doc_text). All have descriptions (194 - 350 chars, within baseline 34 - 392 range). Input schemas present with types and descriptions for all parameters. Tool descriptions explain WHAT, WHEN, and constraints clearly. Key strength: propose_doc_source and upload_doc_text include detailed safety guardrails (human approval, caps, validation rules) documented in descriptions. Weakness: no output schemas documented; no error handling guidance (e.g., what to do if a source is not found); no pagination support for search_docs despite potentially large result sets.
List indexed documentation sets with their last-sync time.
Propose a NEW documentation source for indexing. This does NOT create a live source: it queues a `status='pending'` row that a HUMAN must review and approve in the admin UI before anything is ever crawled. Do not tell the user their docs are "being indexed" — tell them the proposal is queued for human approval. `base_url` is the only REQUIRED input. Whichever of `name`, `include_prefixes`, and `max_pages` you OMIT is derived from `base_url` — independently of whether you supplied the others — so leaving any of them out never crawls an entire shared docs host uncapped, even if you do supply a `name`. `name`, if given, must match ^[a-z0-9-]+$ and be unique. `base_url`/`sitemap` must be valid http(s) URLs; `rate_limit_rps` must be positive. `max_pages`, if given, must be positive; there is no way to pass an "unlimited" `max_pages` — omitting it (or passing null, which is treated the same as omitting it) always applies the derived cap, so to crawl more pages pass an explicit, larger `max_pages`. Rejected (with a clear reason) on invalid input or a name that is already taken, pending or not.
Search locally indexed framework/library documentation (static reference knowledge: API syntax, config options, examples). Use this INSTEAD of guessing framework syntax from memory. NOT for project state or decisions — use Mem0 for those. `source` optionally filters to one doc set (see list_doc_sources).
Add a page of Markdown/plain text to an EXISTING upload-type documentation source. `source` is a NAME (not an id) of a doc source a HUMAN has already created as `source_type='upload'` via the admin UI — this tool can NEVER create a new source and can NEVER write into a crawl-type source; both are rejected. `content` is capped at 1 MB and `title` at 200 characters (either cap being exceeded rejects the whole call with no partial processing); `title` is slugified into the stored page's URL, so re-uploading under the same `title` replaces that page rather than duplicating it. Rejected (with a clear reason) if `source` does not exist, is not an upload-type source, or either cap is exceeded.
No output schemas documented for any tool. LLMs cannot plan downstream calls or extract required fields (e.g., does search_docs return source_id, page_url, relevance_score?). Breaks tool chaining.
search_docs lacks pagination (limit clamped 1 - 20 but no offset/cursor or total_count). Large result sets risk context window exhaustion; no guidance on how to iterate through results.
No error recovery guidance. Descriptions do not explain what to do if source not found, URL invalid, or name already taken. LLMs receive rejection but no actionable next step.
list_doc_sources description (70 chars) is minimal. Does not explain what 'last-sync time' means, whether sources are sorted, or what fields are returned. Insufficient for LLM planning.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 64 | 2026-07-28+ | v2 |
propose_doc_source description is verbose (350+ chars) but buries key constraints in prose. Regex pattern '^[a-z0-9-]+$' for name is stated in text, not as a JSON Schema pattern constraint. LLMs may not parse it correctly.