<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kuldip Satpute</title>
    <description>The latest articles on DEV Community by Kuldip Satpute (@kuldips).</description>
    <link>https://dev.to/kuldips</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2166572%2F28aa009a-54ca-4d07-9397-c60068006675.jpg</url>
      <title>DEV Community: Kuldip Satpute</title>
      <link>https://dev.to/kuldips</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kuldips"/>
    <language>en</language>
    <item>
      <title>I built a self-hosted AI knowledge base on top of offline Wikipedia (and it speaks MCP)</title>
      <dc:creator>Kuldip Satpute</dc:creator>
      <pubDate>Fri, 16 Oct 2026 07:09:47 +0000</pubDate>
      <link>https://dev.to/kuldips/i-built-a-self-hosted-ai-knowledge-base-on-top-of-offline-wikipedia-and-it-speaks-mcp-3fpe</link>
      <guid>https://dev.to/kuldips/i-built-a-self-hosted-ai-knowledge-base-on-top-of-offline-wikipedia-and-it-speaks-mcp-3fpe</guid>
      <description>&lt;p&gt;On my home server I have a folder containing ZIM files: these are offline versions of Wikipedia, Stack Exchange, DevDocs and iFixit, all drawn from the &lt;a href="https://kiwix.org" rel="noopener noreferrer"&gt;Kiwix&lt;/a&gt; catalog. This collection amounts to tens of gigabytes of knowledge and functions without the need for an internet connection.&lt;/p&gt;

&lt;p&gt;The problem was that &lt;code&gt;kiwix-serve&lt;/code&gt; only allows you to &lt;em&gt;read&lt;/em&gt; it. What I wanted to do was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ask it questions and get answers I could verify,&lt;/li&gt;
&lt;li&gt;keep the books updated without checking for new releases by hand,
— have my other AI tools (Claude, the local LLMs) use it as a source.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is how I created &lt;strong&gt;&lt;a href="https://github.com/magicstack-llp/zim-pro" rel="noopener noreferrer"&gt;Zim Pro&lt;/a&gt;&lt;/strong&gt;, a drop-in substitute for &lt;code&gt;kiwix-serve&lt;/code&gt; which does all three things.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Read and carry out a search: perform a full-text search either within a single book or throughout the entire library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask AI&lt;/strong&gt;: this will provide answers that are based solely on your books, including numbered citations referring back to the original articles, together with the images and videos from those pages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fully offline&lt;/strong&gt;: just point it at Ollama, LM Studio, or llama.cpp and nothing will leave your network. Any API compatible with OpenAI can be used, whether it's hosted or local.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCP server&lt;/strong&gt;: Claude together with other LLM applications is able to search and read the library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-updates&lt;/strong&gt;: for each book it is compared with the Kiwix catalog; the downloads make use of multiple connections, are checksummed in parts, and can be resumed if there is a crash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Make your own ZIMs&lt;/strong&gt;: based on websites, PDFs, EPUBs, Kindle books and RSS feeds.&lt;/li&gt;
&lt;li&gt;The article's Markdown export.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The interesting part: retrieval
&lt;/h2&gt;

&lt;p&gt;A vector search covering all of Wikipedia wasn't possible since embedding millions of articles locally is slow and uses up a lot of disk space. Instead, Zim Pro makes use of the full-text index that is already contained in each ZIM file and places the intelligence around that index:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Plan&lt;/strong&gt;: the model looks at the list of books and then forms a number of brief questions from various perspectives, includes additional keywords, and selects the books that are most likely to be of assistance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deep search&lt;/strong&gt;: when carrying out each query, the selected books together with the main encyclopedia are searched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Light search&lt;/strong&gt;: the main queries are applied to every other book, ensuring that nothing obvious is overlooked.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rank&lt;/strong&gt;: The results are combined using a method known as reciprocal rank fusion. The top 24 articles are examined and evaluated based on how well a single passage addresses the subject, and only those passages which are suitable are passed on to the model.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The model receives articles in the form of cleaned Markdown, not HTML. Any navigation links, reference lists, "See also" sections, citation markers and licence footers are removed, and each passage is then given its section heading. This arrangement means that the amount of context window used is reserved for the prose.&lt;/p&gt;

&lt;p&gt;Small local models frequently generate incorrect Markdown, for example with unclosed code blocks, malformed tables or leaked reasoning. All answers undergo a repair stage before they are displayed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using it from Claude via MCP
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http zim-pro http://localhost:8083/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The available tools are &lt;code&gt;list_books&lt;/code&gt;, &lt;code&gt;search&lt;/code&gt;, &lt;code&gt;suggest&lt;/code&gt;, &lt;code&gt;get_article&lt;/code&gt;, &lt;code&gt;get_article_outline&lt;/code&gt; and &lt;code&gt;list_updates&lt;/code&gt;. You have the option of locking the &lt;code&gt;/mcp&lt;/code&gt; interface using per-app API keys, with only the SHA-256 fingerprint of each key being stored and allowing any key to be revoked individually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; zims state
docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; zim-pro &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-p&lt;/span&gt; 8083:8080 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/zims:/data"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PWD&lt;/span&gt;&lt;span class="s2"&gt;/state:/state"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--add-host&lt;/span&gt; host.docker.internal:host-gateway &lt;span class="se"&gt;\&lt;/span&gt;
  ghcr.io/magicstack-llp/zim-pro:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just open &lt;a href="http://localhost:8083" rel="noopener noreferrer"&gt;http://localhost:8083&lt;/a&gt;, drop some .zim files into the zims/ folder (or add them using the built-in catalog), and then make your request. When you first start up, two free AI services are set up, so Ask AI will work even if you haven't configured anything.&lt;/p&gt;

&lt;p&gt;There is also a standalone Linux binary, or else you can enter the command 'pip install zim-pro'.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stack
&lt;/h2&gt;

&lt;p&gt;The backend uses Python 3.13, FastAPI, the &lt;a href="https://github.com/openzim/python-libzim" rel="noopener noreferrer"&gt;python-libzim&lt;/a&gt; library and SQLite, while the UI is built with React, Vite and Tailwind. Images are available for the amd64 and arm64 architectures.&lt;/p&gt;

&lt;h2&gt;
  
  
  Known limitations
&lt;/h2&gt;

&lt;p&gt;Since libzim does not provide relevance scores, when carrying out a cross-book search it groups the results by book rather than ranking them.&lt;br&gt;
Since libzim holds onto Python's Global Interpreter Lock, other requests are briefly delayed when a full-text search is carried out.&lt;br&gt;
The articles are served from the same source as the admin UI (just as with &lt;code&gt;kiwix-serve&lt;/code&gt;). Set the &lt;code&gt;KIWIX_ADMIN_TOKEN&lt;/code&gt; if you are loading untrusted ZIMs or if you need to expose the server beyond your local area network.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI involvement
&lt;/h2&gt;

&lt;p&gt;Developed with Claude.&lt;/p&gt;




&lt;p&gt;You can find the code on GitHub at &lt;strong&gt;&lt;a href="https://github.com/magicstack-llp/zim-pro" rel="noopener noreferrer"&gt;magicstack-llp/zim-pro&lt;/a&gt;&lt;/strong&gt;. Suggestions, reports of issues and pull requests are all welcome, in particular those from people who are using large libraries or small local models.&lt;/p&gt;

</description>
      <category>selfhosted</category>
      <category>ai</category>
      <category>python</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
