Books and Archives
Busca en Internet Archive, la Biblioteca del Congreso y data.bnf.fr a la vez, en una sola respuesta.
Documentación
mcp-books
Tres grandes archivos conservan el registro escaneado de lo que se publicó, y cada uno lo describe con sus propias palabras. El Internet Archive guarda libros, películas, grabaciones y software depositados por cualquier persona, y ha sometido millones de ellos al reconocimiento óptico de caracteres. La Library of Congress publica las colecciones nacionales de los Estados Unidos, un catálogo por tipo de material. data.bnf.fr publica los registros de autoridad de la Bibliothèque nationale de France, que describen obras y a las personas que las escribieron, más que copias.
Este servidor consulta los tres con una sola pregunta. Puedes buscar las palabras dentro de los documentos escaneados, buscar en los catálogos y leer un registro con una única forma, sea cual sea el archivo que lo conserve. No requiere clave de API ni cuenta.
Instalación
Instalación en un clic
Claude Code
claude mcp add books -- npx -y mcp-books
Claude Desktop, Cursor y cualquier cliente que use el formato de configuración estándar
{
"mcpServers": {
"books": {
"command": "npx",
"args": ["-y", "mcp-books"]
}
}
}
Se requiere Node 24 o posterior, y no es necesario establecer ninguna variable de entorno.
Con Docker
{
"mcpServers": {
"books": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-books:2.0.1"]
}
}
}
-i mantiene abierta la entrada estándar, que es por donde viaja el protocolo, y -t se omite
porque una TTY reescribe el flujo. El contenedor necesita HTTPS saliente hacia
archive.org, openlibrary.org, www.loc.gov y data.bnf.fr, y nada
más: sin volumen, sin puerto, sin credencial.
Paquete, sin npm
Descarga mcp-books-2.0.1.mcpb desde
la última versión y
ábrelo. Un cliente que admita paquetes MCP lo instala por sí solo, sin npm
y sin archivo de configuración que editar. El paquete incluye sus dependencias, por lo que
no se descarga nada en el momento de la instalación.
Qué puedes preguntar
- "¿Qué libros mencionan el faro de Beaumont?"
- "Encuéntrame algo sobre el terremoto de San Francisco de 1906."
- "Léeme ese registro y dime quién conserva el original."
- "¿Qué tiene la BnF sobre ese autor?"
- "Busca en las fotografías, no en los libros."
Una respuesta tarda varios segundos: se consulta a tres archivos, cada uno a su propio ritmo.
Las tres fuentes
| Fuente | Archivo | Qué describe |
|---|---|---|
archive | el Internet Archive | copias depositadas, de todo tipo |
loc | la Library of Congress | las colecciones nacionales, un catálogo por tipo |
bnf | la Bibliothèque nationale de France | obras y las personas que las escribieron |
El id de una fila nombra su archivo, de modo que un identificador leído de una respuesta vuelve
al correcto. Los recuentos nunca se suman entre archivos, y un archivo que
falló se informa como fallido, no como si no hubiera encontrado nada.
Herramientas
| Herramienta | Qué hace |
|---|---|
search_inside | Busca las palabras dentro de los documentos escaneados. |
search_items | Busca en los catálogos por título, creador, materia o palabras simples. |
get_item | Lee un registro con una única forma, sea cual sea el archivo que lo conserve. |
search_inside
Busca el texto dentro de los documentos escaneados, que salió de la página mediante reconocimiento óptico de caracteres.
| Argumento | Tipo | Obligatorio | Qué hace |
|---|---|---|---|
query | cadena, de 2 a 300 caracteres | sí | La frase que se busca dentro de los documentos. |
limit | entero, de 1 a 25, por defecto 3 | no | Coincidencias que se conservan de cada archivo. |
page | entero, de 1 a 100, por defecto 1 | no | Qué página de coincidencias. |
max_excerpt_chars | entero, de 80 a 1200, por defecto 300 | no | Cuánto pasaje se sirve. |
max_excerpts_per_match | entero, de 1 a 10, por defecto 2 | no | Pasajes servidos por documento coincidente. |
fan_out | booleano, por defecto true | no | Preguntar a todos los archivos en lugar de detenerse en el primero que responda. |
sources | matriz de identificadores de fuente | no | Preguntar solo a estos archivos. |
A cambio: hits, cada uno con id, que get_item toma y que nombra su
archivo; source y source_name; el identifier propio del archivo sin
el prefijo; title, creator y year; page_number cuando el archivo indica
uno; excerpts; y excerpt_kind.
excerpt_kind decide cuánto vale un extracto. Un passage es el texto
alrededor de las palabras que coincidieron. Un page_opening es el inicio de la página, enviado
porque el texto leído por máquina que devolvió el archivo se detiene antes de que esas palabras
aparezcan: no contiene la coincidencia, por lo que citarlo cita otra cosa. Todos los
extractos de una coincidencia son del mismo tipo.
search_items
Busca en los catálogos.
| Argumento | Tipo | Obligatorio | Qué hace |
|---|---|---|---|
query | cadena, de 1 a 300 caracteres | sí | Un título, un creador, una materia o palabras simples. |
media_type | un tipo que uno de los archivos conserve | no | Qué tipo de material buscar. |
year_from | entero, de 1000 a 2100 | no | Año más temprano. |
year_to | entero, de 1000 a 2100 | no | Año más reciente. |
sort | relevance, newest, oldest o title, por defecto relevance | no | Cómo se ordenan las filas. |
limit | entero, de 1 a 25, por defecto 5 | no | Filas que se conservan de cada archivo. |
page | entero, de 1 a 100, por defecto 1 | no | Qué página de filas. |
fan_out | booleano, por defecto true | no | Preguntar a todos los archivos. |
sources | matriz de identificadores de fuente | no | Preguntar solo a estos archivos. |
Los tres archivos dividen su material de manera diferente. El Internet Archive
busca todos los tipos a la vez cuando no se nombra ninguno; la Library of Congress es una
ruta por tipo, por lo que una búsqueda que no nombra ninguno indica cuál se leyó; y la búsqueda
de la BnF lee obras. Un media_type que un archivo no conoce hace que ese archivo
lo omita, y la respuesta lo dice.
A cambio: filas con la forma que lleva una coincidencia, con per_source dando un
informe por archivo: su status, el count que aportó, su
reported_total y reported_total_means, que dice qué cuenta ese número
allí.
get_item
Lee un registro con una única forma, sea cual sea el archivo que lo conserve.
| Argumento | Tipo | Obligatorio | Qué hace |
|---|---|---|---|
identifier | cadena, de 1 a 500 caracteres | sí | El id que lleva una fila. |
sections | matriz de description, subjects, copies, context, por defecto ["description"] | no | Qué partes devolver. |
max_copies | entero, de 1 a 50, por defecto 10 | no | Copias que listar. |
text_offset | entero, de 0 a 1000000, por defecto 0 | no | Dónde reanudar el texto. |
max_text_chars | entero, de 200 a 8000, por defecto 1500 | no | Cuánto texto servir. |
A cambio: el registro con su id, source y source_name, el
identifier propio del archivo, title, creator, date exactamente como se publicó, y
year junto a year_means, que dice de qué año es ese año, ya que los
tres archivos fechan un registro de manera diferente. attribution es lo que ese archivo pide
que se le atribuya, y identifier_provisional dice cuándo se construyó el identificador
en lugar de leerse, para que quien lo invoque sepa que puede no resolverse.
Qué dice una respuesta sobre los archivos
Cada respuesta da cuenta de cada archivo por separado. Uno que falló, uno al que nadie preguntó y uno que respondió sin nada son tres cosas distintas, y se informan como tres. Un total permanece junto al archivo que lo publicó, con lo que ese archivo cuenta cuando lo dice: uno cuenta documentos, otro cuenta hojas de periódico.
Cuánto vale el texto escaneado
Las palabras dentro de un documento escaneado salieron de la página mediante reconocimiento óptico de caracteres. Un extracto lleva los errores de lectura de ese proceso, y se sirve tal como se leyó, sin corregir. Cítalo como texto escaneado y enlaza el registro para que quien lea pueda mirar la página.
Configuración
Toda variable es opcional. Establécelas en el bloque env de la configuración de tu cliente.
| Variable | Default | What it does |
|---|---|---|
BOOKS_USER_AGENT | the project identity | Names your application to the three archives, with an address where a person can be reached. |
BOOKS_MIN_INTERVAL_MS | each archive's own pace | Widens the gap between two requests to one archive, from 500 to 60000. Left unset, every archive keeps the pace it publishes, and a figure set here applies only where it is wider. |
BOOKS_TIMEOUT_MS | 45000 | Deadline for one request, from 1000 to 120000. |
BOOKS_MAX_RETRIES | 3 | Attempts after a transient failure, from 0 to 8. |
BOOKS_CACHE_TTL_MS | 900000 | How long an answer stays in memory, from 0 to 86400000. |
BOOKS_CACHE_MAX_ENTRIES | 200 | Answers held in memory at once, from 1 to 5000. |
BOOKS_LOG_LEVEL | error | silent, error, info or debug, written to stderr. |
A value outside its range falls back to the default, and the reason is written to stderr.
Errors
Every failure carries one of six codes, a message, and where it helps a hint naming the next move.
| Code | What happened | What to do |
|---|---|---|
not_found | An archive answered, and holds no such record. | Check the identifier with search_items. |
invalid_input | The arguments were refused before any request went out. | Read the message, which names the argument. |
rate_limited | An archive asked this client to slow down. | Wait, then call again with the same arguments. The record is still there. |
parse_failure | An answer arrived in a shape this client cannot read. | Report it at the issue tracker. |
network_error | The request did not complete. | Try again shortly. |
timeout | The request passed its deadline. | Raise BOOKS_TIMEOUT_MS, or ask for fewer rows. |
An archive that failed is reported per archive rather than failing the whole answer, so one silent archive never hides the others.
As a library
The layer reading the three archives is published on its own, with its pacing, its cache and its errors, and with no protocol attached.
import { BooksClient } from "mcp-books/client";
const client = new BooksClient();
const read = await client.searchItems({ query: "beaumont light-house", limit: 3 });
console.log(read.data.rows.length);
Each read answers { data, cached }, and throws an error carrying one of the six
codes. Each archive keeps its own pace, and its floor holds here as well.
Pacing and attribution
Each archive is paced on its own, one request at a time, and the widest of its
own floor and the configured interval governs: the Library of Congress publishes
the slowest, and asking all three at once therefore costs each of them one
request rather than three. The User-Agent always ends with the project identity
and an address where a person can be reached.
Every record carries the address of its page and the attribution its archive
asks for. The Internet Archive items belong to their depositors, the Library of
Congress records state their own rights, and the BnF asks that the source and the
date of retrieval be stated wherever its metadata are shown.
This MCP server is an unofficial project, with no affiliation to any of the archives it reads.
Privacy
This server collects nothing about you and sends nothing to its author. It runs
on your machine, contacts archive.org, openlibrary.org, www.loc.gov and
data.bnf.fr and nothing else, holds its answers in memory while it runs, and
writes nothing to disk. PRIVACY.md states what a request carries
and which settings change any of it.
Development
npm install
npm run build:fixtures
npm test
npm run check
Tests run against generated fixtures and make no network request. The live suite,
npm run test:live, makes one request per route and runs nightly against the
archives themselves.
Contributing
Bugs, questions and ideas belong in the issue tracker. Pull requests are welcome; opening an issue first helps agree on the shape of the change. See CONTRIBUTING.md.
License
MIT, see LICENSE. The records belong to the archives that published them and to their depositors.
mcp-books (français)
Trois grandes archives conservent la trace numérisée de ce qui a été publié, et chacune la décrit dans ses propres mots. L'Internet Archive garde les livres, les films, les enregistrements et les logiciels que chacun y dépose, et en a passé des millions par la reconnaissance optique de caractères. La Library of Congress publie les collections nationales des États-Unis, un catalogue par type de document. data.bnf.fr publie les notices d'autorité de la Bibliothèque nationale de France, qui décrivent des œuvres et ceux qui les ont écrites plutôt que des exemplaires.
Ce serveur lit les trois avec une seule question. On peut chercher dans les mots contenus dans les documents numérisés, chercher dans les catalogues, et lire une notice sous une forme unique quelle que soit l'archive qui la détient. Aucune clé d'API, aucun compte.
Installation
Installation en un clic
Claude Code
claude mcp add books -- npx -y mcp-books
Claude Desktop, Cursor, et tout client au format de configuration standard
{
"mcpServers": {
"books": {
"command": "npx",
"args": ["-y", "mcp-books"]
}
}
}
Node 24 ou plus récent est nécessaire, et aucune variable d'environnement n'est à renseigner.
Avec Docker
{
"mcpServers": {
"books": {
"command": "docker",
"args": ["run", "-i", "--rm", "ghcr.io/smeet666/mcp-books:2.0.1"]
}
}
}
-i garde l'entrée standard ouverte, qui est le canal du protocole, et -t est
omis parce qu'un TTY réécrit le flux. Le conteneur a besoin d'un accès HTTPS
sortant vers archive.org, openlibrary.org, www.loc.gov et data.bnf.fr, et
de rien d'autre : aucun volume, aucun port, aucun identifiant.
Bundle, sans npm
Téléchargez mcp-books-2.0.1.mcpb depuis
la dernière publication
et ouvrez-le. Un client qui gère les bundles MCP l'installe seul, sans npm et
sans fichier de configuration à modifier. Le bundle emporte ses dépendances, donc
rien n'est téléchargé à l'installation.
Ce qu'on peut demander
- « Quels livres mentionnent le phare de Beaumont ? »
- « Trouve-moi ce qu'il y a sur le tremblement de terre de San Francisco en 1906. »
- « Lis-moi cette notice et dis-moi qui conserve l'original. »
- « Qu'est-ce que la BnF a sur cet auteur ? »
- « Cherche dans les photographies plutôt que dans les livres. »
Une réponse prend plusieurs secondes : trois archives sont interrogées, chacune à son rythme.
Les trois sources
| Source | Archive | Ce qu'elle décrit |
|---|---|---|
archive | l'Internet Archive | les exemplaires déposés, de tout type |
loc | la Library of Congress | les collections nationales, un catalogue par type |
bnf | la Bibliothèque nationale de France | les œuvres et ceux qui les ont écrites |
L'id d'une ligne nomme son archive, donc un identifiant lu dans une réponse
retourne vers la bonne. Les comptes ne sont jamais additionnés entre
archives, et une archive qui a échoué est rapportée comme ayant échoué plutôt
que comme n'ayant rien trouvé.
Les outils
| Outil | Ce qu'il fait |
|---|---|
search_inside | Cherche dans les mots contenus dans les documents numérisés. |
search_items | Cherche dans les catalogues par titre, auteur, sujet ou mots simples. |
get_item | Lit une notice sous une forme unique, quelle que soit l'archive. |
search_inside
Cherche dans le texte contenu dans les documents numérisés, texte issu de la reconnaissance optique de caractères.
| Argument | Type | Requis | Ce qu'il fait |
|---|---|---|---|
query | chaîne, 2 à 300 caractères | oui | La phrase à chercher dans les documents. |
limit | entier, 1 à 25, défaut 3 | non | Correspondances à garder de chaque archive. |
page | entier, 1 à 100, défaut 1 | non | Quelle page de correspondances. |
max_excerpt_chars | entier, 80 à 1200, défaut 300 | non | La longueur de passage à servir. |
max_excerpts_per_match | entier, 1 à 10, défaut 2 | non | Passages servis par document correspondant. |
fan_out | booléen, défaut true | non | Interroger chaque archive plutôt que s'arrêter à la première qui répond. |
sources | tableau d'identifiants de source | non | N'interroger que ces archives. |
En retour : hits, chacun portant id, que get_item reprend et qui nomme
son archive ; source et source_name ; l'identifier propre à l'archive, sans
le préfixe ; title, creator et year ; page_number là où l'archive en
indique un ; excerpts ; et excerpt_kind.
excerpt_kind decide cuánto vale un extracto. Un passage es el texto
alrededor de las palabras encontradas. Un page_opening es el inicio de la página, enviado porque
el texto leído por máquina que el archivo ha devuelto se detiene antes de que esas palabras
aparezcan: no lleva la coincidencia, por lo que citarlo cita otra cosa.
Todos los extractos de una coincidencia son de un solo tipo.
search_items
Busca en los catálogos.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
query | cadena, de 1 a 300 caracteres | sí | Un título, un autor, un tema o palabras simples. |
media_type | un tipo que uno de los archivos posee | no | El tipo de documento a buscar. |
year_from | entero, de 1000 a 2100 | no | Año más antiguo. |
year_to | entero, de 1000 a 2100 | no | Año más reciente. |
sort | relevance, newest, oldest o title, por defecto relevance | no | El orden de las líneas. |
limit | entero, de 1 a 25, por defecto 5 | no | Líneas a conservar de cada archivo. |
page | entero, de 1 a 100, por defecto 1 | no | Qué página de líneas. |
fan_out | booleano, por defecto true | no | Consultar cada archivo. |
sources | matriz de identificadores de fuente | no | Consultar solo esos archivos. |
Los tres archivos dividen sus fondos de manera diferente. Internet Archive busca
en todos los tipos a la vez cuando no se nombra ninguno; la Library of Congress tiene una
ruta por tipo, por lo que una búsqueda que no nombra ninguno recibe la indicación de cuál se ha
leído; y la búsqueda de la BnF lee obras. Un media_type que un
archivo no reconoce lo excluye de la respuesta, y la respuesta lo indica.
En retorno: líneas en la forma de un hit, con per_source que ofrece
un informe por archivo: su status, el count que ha proporcionado, su
reported_total y reported_total_means, que indica qué cuenta ese número
allí.
get_item
Lee un registro en una forma única, sin importar qué archivo lo posea.
| Argumento | Tipo | Requerido | Qué hace |
|---|---|---|---|
identifier | cadena, de 1 a 500 caracteres | sí | El id que lleva una línea. |
sections | matriz de description, subjects, copies, context, por defecto ["description"] | no | Las partes a devolver. |
max_copies | entero, de 1 a 50, por defecto 10 | no | Ejemplares a listar. |
text_offset | entero, de 0 a 1000000, por defecto 0 | no | Dónde retomar el texto. |
max_text_chars | entero, de 200 a 8000, por defecto 1500 | no | La longitud de texto a servir. |
En retorno: el registro con su id, source y source_name,
el identifier propio del archivo, title, creator, date exactamente tal como
se publicó, y year acompañado de year_means, que indica de qué es año
ese año, ya que los tres archivos fechan un registro de manera diferente. attribution es
lo que ese archivo pide que se le atribuya, y identifier_provisional indica
cuándo el identificador se construyó en lugar de leerse, para que quien llama sepa
que puede no resolverse.
Lo que una respuesta dice de los archivos
Cada respuesta informa de cada archivo por separado. Uno que ha fallado, uno al que nadie ha consultado y uno que ha respondido vacío son tres cosas diferentes, y se informan como tres. Un total permanece junto al archivo que lo ha publicado, con lo que ese archivo cuenta al decirlo: uno cuenta documentos, otro hojas de periódicos.
Lo que vale un texto digitalizado
Las palabras contenidas en un documento digitalizado provienen del reconocimiento óptico de caracteres. Un extracto lleva los errores de lectura de ese proceso, y se sirve tal como se ha leído en lugar de corregido. Cítelo como un texto digitalizado y enlace el registro para que un lector pueda mirar la página.
Configuración
Cada variable es opcional. Se colocan en el bloque env de la
configuración del cliente.
| Variable | Por defecto | Qué hace |
|---|---|---|
BOOKS_USER_AGENT | la identidad del proyecto | Nombra su aplicación ante los tres archivos, con una dirección para contactar a una persona. |
BOOKS_MIN_INTERVAL_MS | el ritmo propio de cada archivo | Amplía el intervalo entre dos solicitudes hacia un mismo archivo, de 500 a 60000. Si no se establece, cada archivo mantiene el ritmo que publica, y un valor establecido aquí solo se aplica donde es más amplio. |
BOOKS_TIMEOUT_MS | 45000 | Tiempo de espera de una solicitud, de 1000 a 120000. |
BOOKS_MAX_RETRIES | 3 | Intentos después de un fallo pasajero, de 0 a 8. |
BOOKS_CACHE_TTL_MS | 900000 | Duración durante la cual una respuesta permanece en memoria, de 0 a 86400000. |
BOOKS_CACHE_MAX_ENTRIES | 200 | Respuestas guardadas en memoria a la vez, de 1 a 5000. |
BOOKS_LOG_LEVEL | error | silent, error, info o debug, escrito en la salida de error. |
Un valor fuera de su rango cae en el valor por defecto, y la razón se escribe en la salida de error.
Errores
Cada fallo lleva uno de los seis códigos, un mensaje y, cuando ayuda, una indicación del siguiente paso.
| Código | Qué ha sucedido | Qué hacer |
|---|---|---|
not_found | Un archivo ha respondido y no tiene este registro. | Verifique el identificador con search_items. |
invalid_input | Los argumentos fueron rechazados antes de cualquier solicitud. | Lea el mensaje, que nombra el argumento. |
rate_limited | Un archivo pide a este cliente que reduzca la velocidad. | Espere y vuelva a llamar con los mismos argumentos. El registro sigue allí. |
parse_failure | Una respuesta llegó en una forma ilegible aquí. | Infórmelo en el seguimiento de incidencias. |
network_error | La solicitud no se completó. | Reintente en breve. |
timeout | La solicitud superó su tiempo de espera. | Aumente BOOKS_TIMEOUT_MS, o solicite menos líneas. |
Un archivo que falla se informa archivo por archivo en lugar de hacer fallar toda la respuesta, por lo que un archivo silencioso nunca oculta a otros.
Como biblioteca
La capa que lee los tres archivos se publica sola, con su ritmo, su caché y sus errores, sin protocolo adjunto.
import { BooksClient } from "mcp-books/client";
const client = new BooksClient();
const read = await client.searchItems({ query: "beaumont light-house", limit: 3 });
console.log(read.data.rows.length);
Cada lectura responde { data, cached } y lanza un error que lleva uno de los seis
códigos. Cada archivo mantiene su propio ritmo, y su mínimo también se aplica
aquí.
Ritmo y atribución
Cada archivo está regulado por sí mismo, una solicitud a la vez, y es el
más amplio entre su propio mínimo y el intervalo configurado lo que gobierna: la
Library of Congress publica el más lento, y consultar los tres a la vez cuesta
por tanto a cada uno una solicitud en lugar de tres. El User-Agent termina siempre
con la identidad del proyecto y una dirección para contactar a una persona.
Cada registro lleva la dirección de su página y el attribution que su archivo
solicita. Los documentos de Internet Archive pertenecen a quienes los han
depositado, los registros de la Library of Congress enuncian sus propios derechos, y
la BnF solicita que la fuente y la fecha de recuperación se indiquen en todos los lugares
donde se muestran sus metadatos.
Este MCP es un proyecto no oficial, sin afiliación con ninguno de los archivos que lee.
Privacidad
Este servidor no recopila nada sobre usted y no envía nada a su autor. Se ejecuta en
su máquina, solo adjunta archive.org, openlibrary.org, www.loc.gov y
data.bnf.fr, guarda sus respuestas en memoria mientras se ejecuta y no escribe
nada en el disco. PRIVACY.md indica qué lleva una solicitud y
qué ajustes cambian eso.
Desarrollo
npm install
npm run build:fixtures
npm test
npm run check
Las pruebas se ejecutan sobre fixtures generados y no emiten ninguna solicitud.
La suite en vivo, npm run test:live, emite una solicitud por ruta y se ejecuta
cada noche contra los propios archivos.
Contribuir
Las anomalías, las preguntas y las ideas tienen su lugar en el seguimiento de incidencias. Las propuestas de modificación son bienvenidas; abrir un ticket primero ayuda a acordar la forma del cambio. Ver CONTRIBUTING.md.
Licencia
MIT, ver LICENSE. Los registros pertenecen a los archivos que los han publicado y a quienes los han depositado allí.