MCP Open Library
Un servidor del Protocolo de Contexto de Modelo (MCP) para la API de Open Library que permite a los asistentes de IA buscar información sobre libros y autores.
Documentación
MCP Open Library
Un servidor de Protocolo de Contexto de Modelo (MCP) para la API de Open Library que permite a los asistentes de IA buscar información sobre libros y autores.
Descripción general
Este proyecto implementa un servidor MCP que proporciona herramientas para que los asistentes de IA interactúen con Open Library. Permite buscar en el catálogo por título, autor, materia y otros campos, buscar autores por nombre, recuperar información detallada de autores usando su clave de Open Library y obtener URL de portadas de libros y fotos de autores. El servidor devuelve proyecciones JSON de las respuestas de Open Library en lugar de los datos brutos.
Características
- Búsqueda de libros: Busca en títulos, autores, materias, lugares, personas, editoriales e ISBN, con ordenación y paginación (
search_books). - Búsqueda de libros por título: Busca libros usando su título (
get_book_by_title). - Búsqueda de autores por nombre: Busca autores usando su nombre, con paginación (
get_authors_by_name). - Obtener detalles de autor: Recupera información detallada de un autor específico usando su clave de Open Library (
get_author_info). - Obtener foto de autor: Obtiene la URL de la foto de un autor usando su ID de Open Library (OLID) (
get_author_photo). - Obtener portada de libro: Obtiene la URL de la imagen de portada de un libro usando varios identificadores (ISBN, OCLC, LCCN, OLID, ID) (
get_book_cover). - Obtener libro por ID: Recupera información detallada del libro usando varios identificadores (ISBN, LCCN, OCLC, OLID) (
get_book_by_id).
Los resultados de búsqueda están paginados: cada herramienta de búsqueda devuelve como máximo limit resultados (10 por defecto, máximo 50) junto con num_found, el número total de coincidencias, que se recorren con offset (máximo 1000). Las dos herramientas de portadas comprueban que la imagen realmente existe y lo indican cuando no es así, en lugar de devolver una URL que resuelve a un marcador de posición en blanco.
Cada herramienta es una consulta de solo lectura y se anuncia como tal con las anotaciones readOnlyHint y openWorldHint, lo que puede permitir que un cliente omita el mensaje de confirmación que muestra para herramientas que podrían cambiar algo. Estas son sugerencias: la especificación MCP indica que los clientes tratan las anotaciones como no confiables a menos que el servidor sea confiable, por lo que la política de confirmación la decide el cliente. Los fallos (una API inalcanzable, un argumento rechazado) se devuelven como un resultado de herramienta marcado con isError, de modo que un asistente pueda leer qué salió mal y corregir su siguiente llamada en lugar de que la solicitud falle por completo.
Instalación
Inicio rápido
Nada que instalar o compilar. Apunta un cliente MCP al paquete con npx y se
obtendrá en la primera ejecución:
{
"mcpServers": {
"mcp-open-library": {
"command": "npx",
"args": ["-y", "mcp-open-library"]
}
}
}
En Claude Desktop eso va en claude_desktop_config.json; otros clientes usan la
misma estructura. Reinicia el cliente y las siete herramientas siguientes estarán disponibles.
Registro MCP
Este servidor se publica en el Registro MCP oficial como
io.github.8enSmith/mcp-open-library a partir de la v1.0.3. Los clientes que
admiten el registro pueden instalarlo con ese nombre.
Para inspeccionar la publicación:
curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.8enSmith/mcp-open-library"
Instalación manual
# Clone the repository
git clone https://github.com/8enSmith/mcp-open-library.git
cd mcp-open-library
# Install dependencies
npm install
# Build the project
npm run build
Uso
Ejecutar el servidor
- Asegúrate de estar ejecutando node v22.21.1 (probablemente funcione en una versión más reciente de node, pero es la que estoy usando para esta prueba). Si tienes
nvminstalado, ejecutanvm use. - En el directorio raíz de
mcp-open-libraryejecutanpm run build - A continuación ejecuta
npm run inspector. Una vez compilado, haz clic en la URL con el parámetro de cadena de consultaMCP_PROXY_AUTH_TOKENpara abrir el Inspector. - En el Inspector, elige el transporte 'STDIO'
- Asegúrate de que el comando esté configurado como 'build/index.js'
- Haz clic en el botón 'Connect' en el Inspector: te conectarás al servidor
- Haz clic en 'Tools' en la barra de menú superior derecha
- Intenta ejecutar una herramienta, por ejemplo, haz clic en get_book_by_title
- Busca un libro, por ejemplo, en el cuadro de título ingresa 'The Hobbit' y luego haz clic en 'Run Tool'. El servidor devolverá los detalles del libro.
Uso con un cliente MCP
Este servidor implementa el Protocolo de Contexto de Modelo, lo que significa que puede ser utilizado por cualquier asistente o cliente de IA compatible con MCP, por ejemplo, Claude Desktop. El servidor expone las siguientes herramientas:
search_books: Busca en el catálogo por cualquier combinación de consulta, título, autor, materia, lugar, persona, editorial e ISBNget_book_by_title: Busca información de libros por títuloget_authors_by_name: Busca información de autores por nombreget_author_info: Obtiene información detallada de un autor específico usando su Clave de Autor de Open Libraryget_author_photo: Obtiene la URL de la foto de un autor usando su ID de Autor de Open Library (OLID)get_book_cover: Obtiene la URL de la imagen de portada de un libro usando un identificador específico (ISBN, OCLC, LCCN, OLID o ID)get_book_by_id: Obtiene información detallada del libro usando un identificador específico (ISBN, LCCN, OCLC u OLID)
Ejemplo de entrada de search_books:
{
"author": "Ursula K. Le Guin",
"subject": "fantasy",
"sort": "old",
"limit": 2
}
Ejemplo de salida de search_books:
{
"num_found": 51,
"offset": 0,
"limit": 2,
"results": [
{
"title": "A Wizard of Earthsea",
"authors": ["Ursula K. Le Guin"],
"first_publish_year": 1968,
"open_library_work_key": "/works/OL59798W",
"edition_count": 87,
"author_keys": ["OL31353A"],
"best_edition": {
"edition_key": "OL5613890M"
},
"cover_url": "https://covers.openlibrary.org/b/id/13617691-M.jpg",
"ratings_average": 3.95,
"ebook_access": "borrowable"
}
]
}
best_edition es una edición específica de la obra: la que Open Library clasifica mejor para tu consulta, con los identificadores propios de esa edición. Los resultados de búsqueda, por lo demás, identifican una obra (open_library_work_key), que ninguna herramienta acepta, por lo que esta es la ruta desde un resultado de búsqueda hasta un libro concreto.
Su edition_key es un OLID que puedes pasar directamente a get_book_by_id para obtener el registro completo de la edición, incluidos sus arrays completos de ISBN:
{ "idType": "olid", "idValue": "OL5613890M" }
Los campos isbn_13 / isbn_10 se omiten cuando Open Library no tiene ISBN para esa edición, como en el ejemplo anterior y en aproximadamente un tercio de los resultados, mientras que edition_key está prácticamente siempre presente. Cuando una edición lista varios ISBN del mismo tipo, se informa del primero; get_book_by_id los devuelve todos.
La herramienta search_books acepta los siguientes parámetros:
- Al menos uno de
q,title,author,subject,place,person,publisheroisbn: la solicitud se rechaza sin uno, ya que una búsqueda sin filtros coincide con todo el catálogo.qacepta una consulta Solr de forma libre comosubject:cyberpunk AND first_publish_year:[1980 TO 1990] language: Código de idioma MARC opcional de 3 letras (por ejemplo,eng,fre)sort: Ordenación opcional:new,old,random,key,rating,readinglog,want_to_read,currently_reading,already_readotitle. Omítelo para relevancialimit: Opcional, 1–50, por defecto 10offset: Opcional, 0–1000, por defecto 0
Ejemplo de entrada de get_book_by_title:
{
"title": "The Hobbit",
"limit": 1
}
Ejemplo de salida de get_book_by_title:
{
"num_found": 224,
"offset": 0,
"limit": 1,
"results": [
{
"title": "The Hobbit",
"authors": ["J.R.R. Tolkien"],
"first_publish_year": 1937,
"open_library_work_key": "/works/OL27482W",
"edition_count": 481,
"author_keys": ["OL26320A"],
"best_edition": {
"edition_key": "OL51709286M",
"isbn_13": "9780395520215",
"isbn_10": "0395520215"
},
"cover_url": "https://covers.openlibrary.org/b/id/14627509-M.jpg",
"ratings_average": 4.29,
"ebook_access": "borrowable"
}
]
}
Ejemplo de entrada de get_authors_by_name:
{
"name": "J. R. R. Tolkien",
"limit": 2
}
Ejemplo de salida de get_authors_by_name:
El key de cada resultado se puede pasar a get_author_info para obtener el registro completo de ese autor. alternate_names está abreviado aquí.
{
"num_found": 2,
"offset": 0,
"limit": 2,
"results": [
{
"key": "OL26320A",
"name": "J.R.R. Tolkien",
"alternate_names": ["John Ronald Reuel Tolkien", "Tolkien"],
"birth_date": "3 January 1892",
"top_work": "The Hobbit",
"work_count": 355
},
{
"key": "OL332676A",
"name": "J. R. R. Tolkien Centenary Conference (1992 Keble College, Oxford)",
"top_work": "Proceedings of the J.R.R. Tolkien Centenary Conference, 1992",
"work_count": 2
}
]
}
Ejemplo de entrada de get_author_info:
{
"author_key": "OL26320A"
}
Ejemplo de salida de get_author_info:
{
"name": "J. R. R. Tolkien",
"personal_name": "John Ronald Reuel Tolkien",
"birth_date": "3 January 1892",
"death_date": "2 September 1973",
"bio": "John Ronald Reuel Tolkien (1892-1973) was a major scholar of the English language, specializing in Old and Middle English. He served as the Rawlinson and Bosworth Professor of Anglo-Saxon and later the Merton Professor of English Language and Literature at Oxford University.",
"alternate_names": ["John Ronald Reuel Tolkien"],
"photos": [6791763],
"key": "/authors/OL26320A",
"remote_ids": {
"viaf": "95218067",
"wikidata": "Q892"
},
"revision": 43,
"last_modified": {
"type": "/type/datetime",
"value": "2023-02-12T05:50:22.881"
}
}
Ejemplo de entrada de get_author_photo:
{
"olid": "OL26320A"
}
Ejemplo de salida de get_author_photo:
https://covers.openlibrary.org/a/olid/OL26320A-L.jpg
Cuando Open Library no tiene foto para ese autor, la herramienta lo indica en lugar de devolver una URL:
No author photo available for OLID OL99999999A.
Ejemplo de entrada de get_book_cover:
{
"key": "ISBN",
"value": "9780547928227",
"size": "L"
}
Ejemplo de salida de get_book_cover:
https://covers.openlibrary.org/b/isbn/9780547928227-L.jpg
Al igual que con las fotos de autores, un libro sin portada produce un mensaje en lugar de una URL:
No cover image available for OLID OL00000000M.
La herramienta get_book_cover acepta los siguientes parámetros:
key: El tipo de identificador (uno de:ISBN,OCLC,LCCN,OLIDoID)value: El valor del identificadorsize: Tamaño de portada opcional (Spara pequeño,Mpara mediano,Lpara grande, por defectoL)
Ejemplo de entrada de get_book_by_id:
{
"idType": "isbn",
"idValue": "9780547928227"
}
Ejemplo de salida de get_book_by_id:
{
"title": "The Hobbit",
"authors": [
"J. R. R. Tolkien"
],
"publishers": [
"Houghton Mifflin Harcourt"
],
"publish_date": "October 21, 2012",
"number_of_pages": 300,
"isbn_13": [
"9780547928227"
],
"isbn_10": [
"054792822X"
],
"oclc": [
"794607877"
],
"olid": [
"OL25380781M"
],
"open_library_edition_key": "/books/OL25380781M",
"open_library_work_key": "/works/OL45883W",
"cover_url": "https://covers.openlibrary.org/b/id/8231496-M.jpg",
"info_url": "https://openlibrary.org/books/OL25380781M/The_Hobbit",
"preview_url": "https://archive.org/details/hobbit00tolkien"
}
La herramienta get_book_by_id acepta los siguientes parámetros:
idType: El tipo de identificador (uno de:isbn,lccn,oclc,olid)idValue: El valor del identificador
Un ejemplo de esta herramienta usada en Claude Desktop se puede ver aquí:
Docker
Puedes probar este servidor MCP usando Docker. Para ello, primero ejecuta:
docker build -t mcp-open-library .
docker run -p 8080:8080 mcp-open-library
Luego puedes probar el servidor ejecutándose dentro de Docker mediante el inspector, por ejemplo:
npm run inspector http://localhost:8080
Desarrollo
Estructura del proyecto
src/index.ts- El servidor MCP: construye los clientes HTTP y maneja ambos manejadores de solicitudes desde el registro de herramientassrc/index.test.ts- Pruebas para el cableado del servidor, incluida una instantánea de los esquemas de herramientas publicadossrc/tools/<tool-name>/- Un directorio por herramienta, cada uno conindex.ts(el manejador, su esquema de argumentos Zod y suToolDefinition),index.test.tsy, para herramientas con una respuesta de API no trivial, untypes.tsque describe esa forma de respuestasrc/tools/registry.ts- El arrayTOOLS, la lista única de lo que expone el servidorsrc/tools/types.ts- Los contratosToolDefinitionyToolHandlersrc/utils/- Infraestructura compartida:http.ts(los clientes Axios de API y portadas),errors.ts(análisis de argumentos y resultados de error),results.ts,schema.ts(Zod → JSON Schema),search.ts(la proyección de búsqueda compartida y los esquemas de paginación),covers.tsscripts/- Automatización de lanzamientos (sync-server-json.mjs,promote-changelog.mjs,assert-release-consistency.mjs) y sus pruebas
El contrato de entrada de una herramienta se declara una sola vez, como un esquema Zod. El JSON Schema que ven los clientes MCP
se genera a partir de él mediante toInputSchema, por lo que no pueden divergir. Las descripciones de campos provienen
de .describe() en el esquema Zod. Ten en cuenta que las restricciones de .refine() se omiten en la
traducción: una regla entre campos debe indicarse también en el description de la herramienta, o los clientes
nunca se enterarán de ella.
Agregar una herramienta implica crear el directorio y agregar una entrada a TOOLS en
src/tools/registry.ts. src/index.test.ts deriva sus expectativas de ese array, por lo que el
único cambio de prueba es una instantánea de esquema actualizada (npx vitest run -u).
Scripts disponibles
npm run build- Compila el código TypeScriptnpm run watch- Observa cambios y recompilanpm test- Ejecuta la suite de pruebas en modo de observaciónnpm run test:precommit- Ejecuta la suite de pruebas una vez y salenpm run lint/npm run lint:fix- Lint desrcyscriptscon ESLintnpm run format- Formatea el código con Prettiernpm run inspector- Ejecuta el Inspector MCP contra el servidor
Ejecutar pruebas
npm test inicia Vitest en modo de observación:
npm test
Para una sola pasada (lo que ejecutan el hook de pre-commit y CI), usa:
npm run test:precommit
Para ejecutar un archivo o un caso de prueba:
npx vitest run src/tools/get-book-by-id/index.test.ts
npx vitest run -t "should return book details when given a valid OLID"
Lanzamientos
Los lanzamientos están automatizados. Pulsar una etiqueta v* activa
publish-mcp.yml, que ejecuta las comprobaciones, publica el paquete
en npm, registra la nueva versión en el Registro MCP y luego crea un Lanzamiento de GitHub usando
la sección CHANGELOG.md de esa versión como notas. Tanto npm como el registro se autentican mediante
GitHub OIDC, por lo que no hay secretos de publicación que gestionar.
El version de package.json es la única fuente de verdad. npm version deriva todo lo demás de
él mediante un hook de ciclo de vida version, por lo que un lanzamiento es un solo comando:
npm version patch # or minor / major
git push --follow-tags
Ese único comando incrementa package.json, reescribe server.json para que coincida, promueve el encabezado
## [Unreleased] del changelog a la nueva versión y la fecha de hoy, y confirma todo bajo una sola etiqueta.
Dos cosas que debes saber antes de ejecutarlo:
- Escribe primero tus entradas de changelog. Van bajo un encabezado
## [Unreleased]enCHANGELOG.mda medida que fusionas trabajo.npm versionfalla si falta ese encabezado, en lugar de publicar algo sin documentar. Si falla, deshaz el incremento parcial congit restore --source=HEAD --staged --worktree package.json package-lock.json server.json. - El árbol de trabajo debe estar limpio, y el hook de pre-commit (lint + suite de pruebas completa) se ejecuta dentro de
npm version.
CI vuelve a verificar que la etiqueta, package.json, server.json y CHANGELOG.md coincidan antes de
publicar cualquier cosa — consulta scripts/assert-release-consistency.mjs. La misma verificación se ejecuta en pull
requests que tocan esos archivos.
npm version no es un reintento
Una vez que imprime la nueva etiqueta, el commit y la etiqueta existen y el lanzamiento está hecho localmente — el siguiente paso es
git push --follow-tags, no ejecutar npm version de nuevo. Una segunda ejecución intenta la versión siguiente,
y fallará por el encabezado ## [Unreleased] faltante (que la primera ejecución consumió). Ese
fallo es seguro por diseño, pero deja package.json, package-lock.json y server.json
incrementados y sin commit. Deshazlo con:
git restore --source=HEAD --staged --worktree package.json package-lock.json server.json
Si el flujo de trabajo de publicación falla
Re-ejecutar el trabajo desde la pestaña de Actions solo ayuda con un fallo transitorio. GitHub ejecuta el flujo de trabajo
tal como existía en el commit etiquetado, por lo que un error en el propio flujo de trabajo o en server.json no puede
solucionarse con una re-ejecución — la corrección debe estar en el commit al que apunta la etiqueta.
Nada se publica hasta que el flujo de trabajo llega a su paso de npm, así que si falló antes de eso, la versión sigue libre y puedes mover la etiqueta:
# fix the problem on main and commit it first
VERSION="$(node -p "require('./package.json').version")"
git push origin ":v${VERSION}" # delete the remote tag e.g. git push origin :v1.0.3
git tag -d "v${VERSION}" # delete it locally
git tag -a "v${VERSION}" -m "${VERSION}" # re-tag at the fixed commit
git push origin "v${VERSION}"
El commit de corrección debe dejar package.json en esa misma versión, o la verificación de consistencia rechazará
la etiqueta. Si npm ya publicó, no reutilices la versión — ese lanzamiento es inmutable. Incrementa a
la siguiente versión de parche en su lugar; el paso de npm protegido significa que una re-ejecución omite lo que ya tuvo éxito.
Contribuciones
¡Las contribuciones son bienvenidas! No dudes en enviar un pull request.
