Skip to main content
ClaudeWave

MCP server that searches inside several archives at once, browses their catalogues and reads records. No API key.

MCP ServersOfficial Registry0 stars0 forksTypeScriptMITUpdated today
ClaudeWave Trust Score
87/100
Trusted
Passed
  • Open-source license (MIT)
  • Actively maintained (<30d)
  • Clear description
  • Documented (README)
Last scanned: 8/27/2026
Install in Claude Code / Claude Desktop
Method: NPX · mcp-books
Claude Code CLI
claude mcp add mcp-books -- npx -y mcp-books
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "mcp-books": {
      "command": "npx",
      "args": ["-y", "mcp-books"]
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
Use cases

MCP Servers overview

# mcp-books

[![npm](https://img.shields.io/npm/v/mcp-books.svg)](https://www.npmjs.com/package/mcp-books)
[![CI](https://github.com/smeet666/mcp-books/actions/workflows/ci.yml/badge.svg)](https://github.com/smeet666/mcp-books/actions/workflows/ci.yml)
[![license](https://img.shields.io/npm/l/mcp-books.svg)](./LICENSE)
[![MCP Registry](https://img.shields.io/badge/MCP_Registry-listed-6E56CF)](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.smeet666/mcp-books)
[![Glama](https://glama.ai/mcp/servers/smeet666/mcp-books/badges/score.svg)](https://glama.ai/mcp/servers/smeet666/mcp-books)
[![M8ven](https://m8ven.ai/badge/mcp/smeet666-mcp-books-1kpajy?variant=verified)](https://m8ven.ai/mcp/smeet666-mcp-books-1kpajy)
[![Install in Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en/install-mcp?name=books&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIm1jcC1ib29rcyJdfQ%3D%3D)
[![Install in VS Code](https://img.shields.io/badge/VS_Code-Install-0098FF?style=flat&logo=visualstudiocode&logoColor=white)](https://insiders.vscode.dev/redirect/mcp/install?name=books&config=%7B%22name%22%3A%22books%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22mcp-books%22%5D%7D)
<!-- m8ven-verify: 9550b67f15a2d999bf8a5859c9368aeb -->

One question, several archives. An MCP server that asks every archive it reads
at the same time, inside the scanned text and across the catalogues, and merges
what comes back without flattening what makes the two answers different.

Today it reads three: the **Internet Archive**, holding the machine-read text of
digitised books, periodicals and documents; the **Library of Congress**, holding
the text of American newspaper pages and one catalogue per kind of material; and
**data.bnf.fr**, the open catalogue of the Bibliothèque nationale de France,
which describes works as entities and holds no text of its own.

No API key. No account. Read-only.

---

## What it does

These archives answer different questions with the same gesture. One reads the
text inside digitised books; another reads the text printed on newspaper pages;
another describes works a national library has catalogued, and carries no text
at all. Searching for a phrase asks where that phrase was ever printed, in books
and in the press at once, and the archive that holds no text is named as absent
from that question rather than quietly left out.

The merge is therefore **additive**. It is what each archive holds, put
together. Nothing is set side by side, because archives holding different things
have nothing to compare.

This server:

- **searches the machine-read text of every archive at once** and returns one
  list of matches, each naming the archive it came from;
- **searches every catalogue at once**, each in that archive's own vocabulary;
- **reads one record**, routed by the archive its identifier names.

### What makes the answers usable

Merging two archives is easy if you are willing to lose what tells them apart.
This one keeps every difference visible:

| The difference                                                                | What a flattened answer would do  | What happens here                                                                                                                               |
| ----------------------------------------------------------------------------- | --------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| One index holds a page number, the other holds none                           | Invent a page, or drop a true one | `page_number` is a real leaf on one archive and `null` on the other, and the answer says which                                                  |
| One returns the matched passage, the other the opening of the page            | Present both under one field name | `excerpt_kind` travels with every match, the note counts how many are openings, and an opening is placed after the matches that carry the words |
| The archives count different things                                           | Add the counts into a total       | Each count is reported in that archive's own terms, and none is added to another                                                                |
| A year means an edition's date in one place and a catalogue date in the other | Sort the merged list by year      | No date order spans the archives; a sort is applied inside each, and what that order can and cannot express is said                             |
| One record states terms of reuse, another states none                         | Summarise the answer as reusable  | Terms are stated per record, and a record stating none has granted nothing                                                                      |
| One archive searches a whole record, another searches titles alone            | Present one query as one question | `searches_on` says which fields each archive read, and the notes say the same words were not the same question                                  |
| One archive applies a year range and an order, another applies neither        | Report the filter as applied      | A narrowing an archive cannot apply is never sent to it, and `filters_dropped` names the archive and the reason                                 |
| One row is a copy held somewhere, another is a work as an entity              | Call them all the same thing      | `row_describes` says what a row is on each archive, and `identifier_provisional` marks an identifier its archive can still replace              |

### One query, several questions

The archives do not read the same fields. An index over a whole record answers a
person's name with the books that person wrote; an index over titles alone
answers the same name with the books written **about** them. Sending one query to
several archives therefore asks several questions, and the answer says which:
`searches_on` in `per_source` names the fields each archive matched against, and
a note says so in the block a text-only client renders.

The narrowings work the same way. `year_from`, `year_to` and `sort` are applied
by the archives whose catalogues carry them. An archive whose catalogue carries
neither is **never sent them**, and `filters_dropped` names it with the reason,
because a merged list that honoured a criterion on two of its halves and dropped
it in silence on the third would claim a filter one of its halves never received.
A row from such an archive that happens to satisfy the range does so by chance.

A row is not one kind of thing either. It is a copy an archive holds on one, a
catalogue record that may name something on a shelf on another, and a work as an
entity on a third, whose editions and whose author are records of their own.
`row_describes` says which, `media_type` carries each archive's own word for it,
and `identifier_provisional` marks a row whose identifier the archive itself
calls provisional and can replace once a cataloguer settles the record.

### Excerpts, and what they are worth

Every excerpt is what optical recognition read off a scanned page. The words can
be wrong, so they are quoted as scanned text and the page is linked.

Beyond that, an excerpt is one of two objects, and the difference is the whole
reason the field carries a kind:

- **`passage`** is the text around the words that matched.
- **`page_opening`** is the start of the page. It arrives when the machine-read
  text that came back with a row stops before the searched words appear, so it
  does not carry the match at all. Quoting one as the archive's answer puts words
  in front of a reader that the excerpt does not hold.

Every answer counts how many of its excerpts are openings.

Matches whose excerpt carries the searched words are also placed **before** the
matches whose excerpt does not. Whether an excerpt holds those words is a
property each row states about itself, so ordering on it compares no score
across archives and invents no relevance. Nothing is dropped for it: a page
opening still names a page where the words were found, and it stays in the
answer behind the matches that show them. The one-from-each-archive order holds
inside each of the two groups. An answer whose matches are all of one kind was
placed by nothing, and keeps quiet about an order it did not perform.

### One question, several wordings

The archives do not read a query the same way, and `per_source` says which each
one does. An index that answers only where every word given appears comes back
empty on a question written as a sentence, even for a work it holds several
copies of, and that emptiness reads as an archive holding nothing. An index that
scores the words instead answers the same question with whatever it ranks
highest, so a row of its can carry only some of the words given.

Both searches answer it by deriving further wordings from the query and asking
each archive for the **union** of what they return. The derivations are made
from the words themselves, with no corpus statistics and no language model, so
every wording sent is one a reader can retype:

- the words as asked, always first;
- a quoted phrase without its quotation marks, which an index requiring those
  words adjacent can then match apart;
- the words a question writes with a capital letter inside the sentence, kept in
  the order they were written and with a run of them kept whole: a capital there
  is the writing's own mark on a name, a name is what a catalogue files a record
  under, and reading the mark needs no lexicon and no list of words to ignore;
- failing any such mark, the longest words of a long question, which is all the
  letters can say once nothing in the question names anything;
- the same words with their diacritics removed, and two words run together,
  because a name is filed under more than one spelling.

Three derivations

What people ask about mcp-books

What is smeet666/mcp-books?

+

smeet666/mcp-books is mcp servers for the Claude AI ecosystem. MCP server that searches inside several archives at once, browses their catalogues and reads records. No API key. It has 0 GitHub stars and its last recorded update is dated 2026-08-27.

How do I install mcp-books?

+

You can install mcp-books by cloning the repository (https://github.com/smeet666/mcp-books) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is smeet666/mcp-books safe to use?

+

Our security agent has analyzed smeet666/mcp-books and assigned a Trust Score of 87/100 (tier: Trusted). See the full breakdown of passed checks and flags on this page.

Who maintains smeet666/mcp-books?

+

smeet666/mcp-books is maintained by smeet666. The last recorded GitHub activity is dated 2026-08-27, with 3 open issues.

Are there alternatives to mcp-books?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy mcp-books to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: smeet666/mcp-books
[![Featured on ClaudeWave](https://claudewave.com/api/badge/smeet666-mcp-books)](https://claudewave.com/repo/smeet666-mcp-books)
<a href="https://claudewave.com/repo/smeet666-mcp-books"><img src="https://claudewave.com/api/badge/smeet666-mcp-books" alt="Featured on ClaudeWave: smeet666/mcp-books" width="320" height="64" /></a>

More MCP Servers

mcp-books alternatives