Skip to main content
Glama

Search every catalogue at once

search_items
Read-onlyIdempotent

Search multiple library archives at once by title, creator, or subject and get one merged list of catalogue records, with each result showing its source archive.

Instructions

Search the catalogue of every archive this server reads, at the same time, for a title, a creator or a subject, and get one merged list. Each row carries the id get_item takes, and that id names the archive it came from, so nothing has to be guessed afterwards. 'media_type' keeps one name across the archives and a vocabulary per archive, because the same word does not name the same set of things twice. An archive that files nothing under the name you give is not asked and is named as absent, with its own names listed, rather than asked under a translation. An archive that keeps one catalogue per kind of material is asked for its default when you name none, and the answer says which catalogue that was. Rows are interleaved one archive at a time. No score orders them against each other, and 'sort' is applied inside each archive rather than across them: a year is the date of an edition in one place and the date on a catalogue record in another, so there is no date order that spans the answer. 'oldest' and 'newest' order on a date field carrying a year and no era, so a date before the common era is filed there as a year of this one, and a record stating no date is placed by a stand-in rather than by its age. The first row of a date order is therefore not established as the oldest or newest thing an archive holds, the notes count the rows carrying no year, and this server orders nothing itself. Every count in 'per_source' is that archive's own and counts something of its own. They are never added together, and there is no total across archives. The catalogues read the words given in different ways, and 'per_source' says which each one does. One answers only where every word appears, so a question written as a sentence comes back empty; another scores the words and answers with the records it ranks highest, so a row of its can carry only some of them. Either way it is the words: a character that is neither a letter nor a digit is no word to an index, and 'non_word_characters' lists any the query carried. A name is also filed under more than one spelling, so further wordings are derived from the query and asked for their union. It costs nothing extra when the words as asked already answer. Every wording sent is named in 'per_source' with what it returned, every row carries the wording that returned it in 'found_by_query', and 'fan_out' turns the derivation off. A row's 'media_type' is the word that record carries for the kind of thing, which is often none of the names this argument takes: those are the divisions of a catalogue, and 'media_types' publishes them per archive. A row states no terms of reuse. Read the record with get_item for what that record itself says, and read silence as silence. Use search_inside for a phrase printed on a page: this tool reads catalogue records and knows nothing of what a book says, so a sentence given here matches only where a catalogue happens to carry it. Answers take several seconds, because one of the archives publishes a request ceiling this server keeps to.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageNoWhich page of rows, from 1. Each archive is paged separately.
sortNoApplied inside each archive. The merged list stays interleaved, because no order runs across archives. 'oldest' and 'newest' run on a date field carrying a year and no era, and a record stating no date is placed by a stand-in, so neither end of such an order is a claim about age.relevance
limitNoRows to take from each archive, so one archive cannot fill the whole list.
queryYesA title, a creator, a subject, or plain words.
fan_outNoWhether to derive further wordings from the query and ask each archive for the union of what they return. A question written as a sentence returns nothing where every word given has to appear, and the records an index scores highest where it does not, and a spelling of a name is not the only one a catalogue files it under. An archive is asked a derived wording only when the words as asked did not return as many rows as 'limit', so a query that works costs one request. Set false to send exactly the words given. 'per_source' names every wording, sent or not, and each row names the one that returned it.
sourcesNoArchives to ask, by id. Left out, they are all asked, which is the point of this tool.
year_toNoLatest year, in each archive's own reading of what a year is. It cannot be earlier than 'year_from'.
year_fromNoEarliest year, in each archive's own reading of what a year is. Given with 'year_to', it must not be the later of the two: a range running backwards names no year and is refused rather than read differently by each archive.
media_typeNoThe kind of material, in the vocabulary of whichever archive uses that name. the Internet Archive files texts, movies, audio, image, software, data, web; the Library of Congress files books, photos, maps, audio, film-and-videos, manuscripts, notated-music, newspapers; the Bibliothèque nationale de France files work. The names are the union of those vocabularies rather than a shared one, so an archive that does not use the name you give is named as absent rather than asked under another. Naming none leaves an archive that searches every kind unnarrowed and asks an archive that keeps one catalogue per kind for its own default.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
pageYes
itemsYes
notesYes
orderYesHow the list was built, in words.
queryYes
item_countYesRows in this answer, across every archive. Never a total of what exists.
per_sourceYes
media_typesYesWhich name each archive was asked under, published rather than reconciled, so a caller can map the vocabularies once and read what was actually searched.
queries_runYesRequests this server sent for this answer, counting every wording on every archive. Each archive's own wordings are in 'per_source'.
non_word_charactersYesCharacters in the query that are neither letters nor digits. These catalogues answer on words, so a row here can carry none of them, and 'requires_every_word' covers the words that were given rather than these.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, open-world, idempotent, non-destructive. The description adds extensive behavioral context: interleaving, per-archive sorting, date semantics, fan-out derivation, media_type vocabulary differences, per_source counts, and non-word handling. There is no contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Although long, every sentence adds distinct value and no redundancy is apparent. The purpose is front-loaded in the first sentence, and subsequent paragraphs are organized by topic (sorting, counts, media_type, fan-out, alternatives). It is appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is exceptionally complete for a tool with 9 parameters, an output schema, and complex cross-archive semantics. It covers edge cases, per-archive behaviors, counting rules, and even latency. It fully compensates for any structured-field gaps and leaves no major operational ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant meaning beyond the schema: it explains sort is applied per archive rather than across, media_type vocabularies are per-archive with absence behavior, fan_out triggers only when results are sparse, and year ranges are interpreted per archive. This goes far beyond the schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource ('Search the catalogue of every archive this server reads, at the same time') and clearly distinguishes this tool from siblings by referencing get_item for reading records and search_inside for page-level phrases. It is unambiguous about the merged-list output and cross-archive scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly names alternatives: 'Use search_inside for a phrase printed on a page' and 'Read the record with get_item for what that record itself says.' It also provides usage context, such as latency, per-archive counts, and when the tool is or isn't appropriate for sentence-level queries.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/smeet666/mcp-books'

If you have feedback or need assistance with the MCP directory API, please join our Discord server