Skip to main content
MCP SERVER · v1.2.0

# Knowledge that works offline.

OpenZIM MCP gives any AI model structured, secure access to ZIM archives — Wikipedia, MedlinePlus, the Stack Exchange dumps — without an internet connection.

Get started → View on GitHub ↗
`uv tool install openzim-mcp`

- v1.2.0 Latest release
- 1 + 21 Simple / advanced tools
- 80%+Test coverage
- MIT License

What is this

## An MCP server for offline knowledge.

ZIM archives package Wikipedia, Project Gutenberg, MedlinePlus, the Stack Exchange network, and more into self-contained files you can carry on a USB stick. OpenZIM MCP is the Model Context Protocol server that turns those static files into intelligent, structured access for any LLM client — Claude Desktop, Cursor, Cline, or your own.

- ### Offline

  No network round-trips. The whole archive — every article, every link — sits on disk and stays accessible whether the network is up or down.

- ### Secure

  Path-traversal protection, sanitized error messages, bearer-token auth on HTTP, multi-arch container running as non-root.

- ### Structured

  Search, browse, summarize, traverse — one intelligent NL tool by default, or 21 specialized tools in advanced mode, designed for how LLMs actually consume knowledge.

- 0 Known CVEs
- 80%+Test coverage
- 100%Type-annotated

1.0
The 1.0 release

## Four headlines, dozens of fixes.

v1.0.0 ships streamable HTTP, batch retrieval, per-entry resources, and resource subscriptions — plus an end-to-end review pass before tagging.

- ### Streamable HTTP & SSE transports

  Run as a long-running service. Bearer-token auth, CORS allow-list, `/healthz` & `/readyz`, multi-arch Docker.

      docker run -p 8000:8000 \
        -e OPENZIM_MCP_AUTH_TOKEN="$TOKEN" \
        -v /path/to/zim:/data:ro \
        ghcr.io/cameronrye/openzim-mcp:1.2.0 \
        --transport http --host 0.0.0.0 /data

- ### Batch entry retrieval

  `get_zim_entries` fetches up to 50 entries per call. Multi-archive batches, partial-success reporting, rate-limit-aware.

      {
        "name": "get_zim_entries",
        "arguments": {
          "zim_file_path": "wiki.zim",
          "entries": ["C/Evolution",
                      "C/Genetics",
                      "C/Mendel"]
        }
      }

- ### Per-entry MCP resources

  Each entry exposed as `zim://{name}/entry/{path}` with libzim's native MIME type — HTML, PDFs, images render in MCP-aware clients.

      zim://wikipedia_en/entry/C%2FEvolution
      # returns text/html

      zim://gutenberg/entry/I%2Fbook_cover.jpg
      # returns image/jpeg

- ### Resource subscriptions

  Subscribe to `zim://files` or `zim://{name}`. mtime-polling watcher emits `notifications/resources/updated` when archives change.

      // client subscribes
      { "method": "resources/subscribe",
        "params": { "uri": "zim://files" } }

      // server notifies on change
      { "method": "notifications/resources/updated",
        "params": { "uri": "zim://files" } }

Also in 1.0 — polish, fixes, and scope cuts

#### Smarter archive handling

- `get_related_articles` resolves relative hrefs against the source entry's directory and detects the content namespace correctly on domain-scheme archives.
- Suggestion fallback uses `SuggestionSearcher(archive).suggest(text)` (the prior `archive.suggest()` call didn't exist).
- `list_zim_files` gains a case-insensitive `name_filter` substring argument.
- `search_zim_file` accepts an opaque `cursor` parameter; passing the cursor alone resumes pagination.

#### Cleaner content extraction

- Heading-id resolution falls through `id` → mw-headline anchor → `<a name="">` → slug.
- Summary extraction skips USWDS banners and skip-nav blocks above the first `<h1>`.
- Link extraction drops non-navigable schemes (`javascript:`, `mailto:`, `tel:`, `data:`, `blob:`, `vbscript:`).
- Per-entry paths sanitized in `get_zim_entries`.

#### Server hygiene

- `__version__` reads from `importlib.metadata`; `serverInfo.version` reports openzim-mcp's actual version.
- HTTP transport's subscription watcher starts via wrapped lifespan.
- Per-entry `zim://` returns libzim's native MIME type.

#### Streamlined scope

Advanced-mode tool surface drops 27 → 21. Removed: `warm_cache`, `cache_stats`, `cache_clear`, `get_random_entry`, `diagnose_server_state`, `resolve_server_conflicts`. The cache itself remains. Multi-instance conflict tracking removed entirely.

### v0.9.0 — previously

- Multi-archive search — `search_all` queries every ZIM file in your allowed directories at once.
- MCP Prompts — `/research`, `/summarize`, `/explore` as ready-made workflows.
- Find entries by title — `find_entry_by_title` resolves a title to entry paths, optionally cross-file.
- MCP Resources — `zim://files` and `zim://{name}` show up in your client's resource browser.
- Power-user tools — `walk_namespace` for cursor-paginated iteration; `get_related_articles` for outbound link-graph neighbours.

Try it

## Three steps to a knowledge engine.

1. 1

   ### Install

       uv tool install openzim-mcp

       docker pull ghcr.io/cameronrye/openzim-mcp:1.2.0

       git clone https://github.com/cameronrye/openzim-mcp.git
       cd openzim-mcp
       uv sync

2. 2

   ### Get a ZIM

   Download an archive from the Kiwix library ↗.

       mkdir ~/zim-files && cd ~/zim-files
       # place .zim files here

3. 3

   ### Run it

       uv run openzim-mcp ~/zim-files

   Or as an HTTP service: `OPENZIM_MCP_AUTH_TOKEN=$TOKEN openzim-mcp --transport http --host 0.0.0.0 ~/zim-files`

### See it in action

#### Request

    {
      "name": "search_zim_file",
      "arguments": {
        "zim_file_path": "wikipedia_en.zim",
        "query": "artificial intelligence",
        "limit": 5
      }
    }

#### Response

    Found 42 matches, showing 1-5:

    ## 1. Artificial Intelligence
    Path: C/Artificial_intelligence
    Snippet: Artificial intelligence (AI) is
    intelligence demonstrated by machines...

    ## 2. Machine Learning
    Path: C/Machine_learning
    Snippet: Machine learning is a subset of
    artificial intelligence...

#### Request

    {
      "name": "browse_namespace",
      "arguments": {
        "zim_file_path": "wikipedia_en.zim",
        "namespace": "C",
        "limit": 10
      }
    }

#### Response

    {
      "namespace": "C",
      "total_in_namespace": 80000,
      "returned_count": 10,
      "has_more": true,
      "entries": [
        { "path": "C/Biology",
          "title": "Biology",
          "preview": "Biology is the scientific
                      study of life..." }
      ]
    }

#### Subscribe

    {
      "method": "resources/subscribe",
      "params": { "uri": "zim://files" }
    }

#### Notification (when archive changes)

    {
      "method": "notifications/resources/updated",
      "params": { "uri": "zim://files" }
    }

Deeper

## Documentation & resources.

- ### API Reference ↗

  Every MCP tool with parameters, response schema, and intent examples.

- ### Deployment Guide ↗

  Streamable HTTP, Docker, reverse proxies, auth tokens, multi-arch images.

- ### Architecture ↗

  Modules, mixins, the `zim/` package split, dependency injection.

- ### Configuration ↗

  Environment variables, cache tuning, content limits, logging levels.

- ### Troubleshooting ↗

  Common failures, error-message decoder, performance hints.

- ### Contributing ↗

  Local setup, Makefile workflow, test structure, PR conventions.