Open source · MIT · v0.8.0

Make your docs answerable, by people and by agents.

One static index, built with your site, serves a cited Ask box for people, and an MCP server and llms.txt for agents. A function you deploy searches it in memory and answers with your own model key, citing the exact section. Agents bring their own model, so their traffic costs you no model tokens.

  • No vector database
  • No vendor
  • Your own function and key
  • MCP and llms.txt included
npm i ondocs

Ask these docs

Question: How do I add it to Docusaurus?

Put ondocs/docusaurus in the plugins array of docusaurus.config.ts 2:

// docusaurus.config.ts
export default {
  // …
  plugins: ['ondocs/docusaurus'],
};

Set up

One line for Docusaurus and Starlight. A script tag for everything else.

Every setup has the same two halves: an index built with your site, and one function that answers from it. The plugins do the first half for you.

A Docusaurus 3 plugin. After every build it indexes the pages your site serves into build/ask-index.json, and it adds the dialog behind a floating “Ask AI” button and ⌘I.

  1. Install

    Terminal
    npm i ondocs ai @ai-sdk/openai @radix-ui/react-dialog cmdk
  2. Add the plugin

    TypeScript
    // docusaurus.config.ts
    export default {
      plugins: [['ondocs/docusaurus', { endpoint: '/api/ask' }]],
    };
  3. Write the endpoint

    One function on your host answers from the index, with your model key, rate-limited and on a daily budget. init writes it for Vercel, Netlify, Cloudflare, or GitHub Pages with Workers AI and no API key, and deploys nothing. What it writes for each host

    Terminal
    npx ondocs init
Docusaurus guide

For agents

The same index, for the agents that read your docs.

Coding agents and AI apps search and read your docs over MCP, with their own model. Search is keyword-only by default, so it calls no model at all. These docs do it at /api/mcp:

Terminal
claude mcp add --transport http ondocs https://ondocs.vercel.app/api/mcp

search and fetch

Ranked sections with a snippet and a link to the anchor, then the page or section as Markdown: the shape ChatGPT’s connectors expect, over MCP 2026-07-28 and 2025-11-25.

llms.txt and .md pages

The plugins also write llms.txt, llms-full.txt and a Markdown copy of every page, and leave alone what another llms plugin writes.

Add to Cursor, VS Code, Claude

With the plugins’ mcp option, a docs page shows the install links and the Claude Code command for your endpoint.

The MCP server

How it works

Indexed when you deploy. Searched in memory when someone asks.

Docs change when you deploy, not between requests, so the index is a file built with the site instead of a database kept in sync with it.

Build time once per deploy

CLI or framework pluginondocs indexReads your Markdown, MDX or built HTML. Splits it at every heading, embeds each chunk and quantizes the vectors to int8.
Static fileask-index.json1.6 MB per 1,000 chunks, deployed with the site.

Rebuilt on every deploy, re-embedding only the chunks whose text changed. --check fails CI when a committed index is stale.

Request time per question

VisitorAsks a questionIn the dialog, or your own UI with useAsk.
Relevance gateAnything relevant?Cosine ≥ 0.25, or keyword coverage ≥ 0.5.
YesStreamed answer, cited 12Written by your model, from the sources only.
No“I don’t know”Streamed at once. The model is never called.

Keywords and meaning

BM25 finds exact names like createAskHandler and error codes; vectors find paraphrases. Reciprocal rank fusion merges the two rankings by rank alone.

A gate before the model

Nothing relevant means “I don’t know”, fast and free. The model only sees questions your docs can answer, and is told to answer from the sources alone.

Citations that land

Pages are split at every heading, so 1 opens the section an answer came from, at the URL your framework serves.

How retrieval works

Numbers

Measured, at the sizes a docs site has.

1.6 MBindex for 1,000 chunks
int8 vectors in base64; 0.9 MB gzipped. The same index as float JSON is 7.5 MB.
0.71 msmedian query over 1,000 chunks
BM25, cosine scan and fusion, in memory. 6.96 ms at 10,000 chunks.
22 / 22agent searches with the right page in the top three
On docusaurus.io’s own docs, keyword-only: no model call. Checked in CI.
2.7 KBscript tag on each page, gzipped
The button and shortcut. The dialog loads the first time it is wanted.
0model calls to answer what the docs don’t cover
The gate says “I don’t know” before the model is reached; a follow-up may cost a short rewrite first.
≤ 800output tokens per answer, by default
With at most 8,000 characters of sources in: one embedding call and one model call.

From pnpm bench on an Apple M1 Max with Node 24.18: synthetic, documentation-shaped corpora with 512-dimension vectors, 1,000 queries per size. Query times exclude the embedding API call. All results

Compared

A local index like Pagefind’s, plus cited answers. No cloud account.

Hosted assistants, ondocs and search-only tools compared
Hosted assistantsKapa, Inkeep, Algolia Ask AI, Biel.aiondocsA library, on your infrastructureSearch onlyPagefind, Orama’s local index
What a visitor getsWritten answers with citationsWritten answers citing the exact sectionA list of matching pages
Where your docs are indexedOn the vendor’s platformA static file in your buildStatic files in your build
What you runNothing, it is hostedOne function: Vercel, Netlify, Cloudflare or any Request → Response runtimeNothing
Model and keyThe vendor’sYours, through any AI SDK providerNone
Account and pricingA vendor account and planNone. You pay your model provider per questionNone
For agentsVaries by vendorAn MCP server and llms.txt from the same indexNo
Follow-up questions and dashboardsTypically includedFollow-ups, yes. No dashboard: log questions with onFinishNo

When it’s the wrong tool

  • Past about 50,000 chunks. Search is an exact scan; at that size an approximate index or a vector database is better.
  • Content that changes per user or per request. The index is rebuilt when you deploy.
  • Multi-turn chat with a dashboard, and nothing to run. A hosted assistant does that.
  • Search results with no server at all. Use Pagefind.
Limits and trade-offs

Add it to your docs.

Try it on your own content in two minutes, without an API key: index with the mock model and run npx ondocs dev.

npm i ondocs