Skip to main content
Glama

catalogue-api

A read-only API over the book catalogue built by book-data-pipeline.

It serves the same data two ways — HTTP for developers, MCP for AI agents — through one repository layer, so the two cannot disagree. A test asserts exactly that.

Why an MCP server

The catalogue records where every book came from: which sources supplied it, when each was last read, and where they disagreed. That makes a question possible which a single-source book API cannot ask:

Who says this book was published in 1965, and does anything contradict it?

The MCP surface exists for that, not to restate the HTTP routes in another protocol.

mcp_servers = [{"type": "url", "name": "book-catalogue", "url": "https://<service>/mcp"}]
tools = [{"type": "mcp_toolset", "mcp_server_name": "book-catalogue"}]

No credential — attach it and ask.

Tool

Answers

search_books

"Find me books like…"

get_book

"Tell me everything about this one"

get_series

"What order do I read these in?"

get_book_provenance

"Where did this come from, and do sources agree?"

catalogue_stats

"How complete is this data?"

Three things shape the tool design:

  • Responses are sized for a context window. Null fields are dropped, subject lists truncate with a remainder count, and search returns a projection. An unnecessary field is not a few bytes once — it is a cost on every call.

  • No cursors. An agent threading an opaque token across turns loses its place. search_books reports that more matches exist and suggests narrowing, which is something a model can act on.

  • Errors are instructions. "No book with ISBN 9780000000000 — use search_books to find its identifier" continues the agent's turn; a bare 404 ends it.

Related MCP server: bookclaw-mcp

HTTP

Route

Purpose

GET /live /ready /health

Probes; liveness touches no database

GET /v1/books

Filterable, keyset-paginated collection

GET /v1/books/search

Full-text search with a fuzzy fallback

GET /v1/books/{isbn13}

One book by canonical identity

GET /v1/series/{id}

A series and its books in reading order

GET /v1/stats

Coverage and provenance statistics

Errors are RFC 9457 application/problem+json.

Pagination

Keyset on (lower(title), id), not offset. The pipeline writes while the API reads, and under OFFSET n a row inserted earlier in the sort order shifts everything after it — a client paging through sees a book twice or misses one, with no error either time.

Sorting by publication year would have been the obvious choice and is unusable: about a third of the catalogue has no year, and NULLs cannot anchor a cursor.

websearch_to_tsquery against the pipeline's generated search_vector, falling back to trigram similarity when full text finds nothing at all. Ranks are numeric, rounded before ordering, and never pass through a float — a rank that shifts in its last bits names a row that does not exist, and the page boundary then skips or repeats.

Schema ownership

This service owns no migrations. The pipeline creates the tables; this API only selects from them, and pins the columns it reads in a contract checked at startup. /ready fails with the missing column named, rather than a 500 on one endpoint in production days later.

Integration tests apply the pipeline's own migrations at a pinned tag. A schema reconstructed from the contract would have no pg_trgm — so the trigram operator the author and series filters use would not parse — and no generated search_vector. The two features most likely to break are the two a reconstruction cannot reproduce.

Running it

uv sync --all-groups
API_DATABASE_URL=postgresql://... uv run catalogue-api   # http://localhost:8000/docs
docker build -f docker/api.Dockerfile -t catalogue-api .
docker run -p 8000:8000 -e API_DATABASE_URL=postgresql://... catalogue-api

Development

uv run ruff check . && uv run mypy src/    # gates
uv run pytest tests/unit/                  # fast
uv run pytest tests/integration/           # needs Docker
./scripts/coverage.sh                      # combined gate, 98%

Integration tests clone the pipeline at PIPELINE_SCHEMA_REF and apply its migrations to a throwaway container. Point PIPELINE_LOCAL_PATH at a working copy to skip the clone.

The coverage gate is on the combined report. The repository layer is SQL, and SQL is only meaningfully covered by running it — a unit-only gate would either fail honestly or be lowered until it meant nothing.

F
license - not found
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    -
    quality
    C
    maintenance
    Read-only MCP server for accessing local Kindle library data, exposing tools to query profile, health, and book metadata.
    MIT
  • F
    license
    A
    quality
    C
    maintenance
    Read-only MCP server that provides tools to search books, get book details, list authors, and view library statistics from a PostgreSQL database.
    5
  • A
    license
    -
    quality
    C
    maintenance
    Enables search and reading of Project Gutenberg books with tools for searching by title/author/subject and fetching word-range slices of book text.
    MIT

View all related MCP servers

Related MCP Connectors

  • Search books and authors, fetch editions, browse subjects, and resolve cover images.

  • BookBrainz MCP — open book metadata (MetaBrainz / sister of MusicBrainz)

  • Search MusicBrainz artists, releases, works, labels; resolve ISRC/ISWC/barcode; fetch cover art.

View all MCP Connectors

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/ibraheemmawwal/catalogue-api'

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