goodreads-mcp
Provides tools for controlling a Goodreads account, including searching books, adding books to shelves (want to read, currently reading, read), listing shelf contents, and queueing actions to be applied after authentication.
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
goodreads-mcp
Voice control for a Goodreads shelf from a Pebble Index ring.
Say "put Project Hail Mary on want to read" or "what am I reading" and it happens.
Pebble ring ──MCP/HTTPS──▶ this server ──Chromium──▶ goodreads.com
(voice) (Pi, :8005) (headless) (signed in as you)Runs on the same Raspberry Pi as the rest of my home services — see pi-home-services for the Docker Compose orchestration and Cloudflare Tunnel setup.
Why a browser and not an API
Because there is no API. Goodreads retired its public API in December 2020 and has not issued keys since. There is no sanctioned programmatic way to shelve a book, so the only route left is to be a signed-in browser.
That's a real trade-off and worth stating plainly:
It breaks when Goodreads changes their markup. The selectors in
_shelve()are the fragile part; everything else is stable.It's slower than an API — several seconds per action, since a real page has to load.
It needs a human occasionally, for a captcha or a two-factor prompt.
Alternatives with real APIs exist (Hardcover has a proper GraphQL one). This is Goodreads on purpose — that's where the books already are.
Related MCP server: hardcover-mcp
How the session works
Two entry points, one Chromium profile:
Mode | Where | |
Normal operation |
| invisible, never touches the screen |
Authentication | headed | the Pi's touchscreen, on request |
They share one profile directory, so cookies earned by the headed login
are exactly what the headless runs use afterwards. --headless=new is not
optional: the legacy headless mode doesn't share a profile with a headed run
reliably, which would mean re-authenticating constantly.
The profile lives in a volume. Losing it means signing in again — nothing worse.
When the session dies
Actions are queued, not failed. Say "add X to want to read" while signed out and it's recorded; the next authentication applies it.
The tools say "queued", never "added". A queued book isn't shelved yet, and reporting otherwise would mean the ring tells you something is done when it isn't.
add_to_shelf → "Goodreads is signed out, so I've queued 'Piranesi' for
want to read. It'll go up next time you authenticate."
pending_books → what's waiting
sync_books → apply the queue (also runs automatically after signing in)Tools
Tool | What it does |
| Signed in? Anything queued? |
| Find a book, to confirm which one is meant |
| Shelve it — want to read / currently reading / read |
| Read a shelf back |
| What's queued while signed out |
| Apply the queue |
Only the three built-in shelves are supported. Spoken variants map onto them —
"finished" and "done" both mean read, "wishlist" means to-read.
Signing in
docker compose exec goodreads-mcp python authenticate.pyA Chromium window opens on the touchscreen over the kiosk. Sign in, clear any captcha or two-factor prompt, and it closes once it sees a valid session, then applies anything queued. The kiosk keeps running underneath.
This runs inside the container, not against the host's Chromium, because Chrome upgrades a profile forward and won't open one written by a newer build. One Chromium, one profile, no version skew.
Being a good citizen
This drives a real site as a real signed-in user, and it's deliberately
unhurried — a POLITE_DELAY between navigations, no parallelism, one browser
at a time. It touches your own shelves and the search page, nothing else. It
is not a crawler and shouldn't be turned into one.
Setup
cp .env.example .env # fill in MCP_BEARER_TOKEN
docker build -t goodreads-mcp .
docker run -p 8005:8000 --env-file .env -v goodreads-profile:/profile goodreads-mcpPoint the Pebble app at https://<your-host>/mcp with the bearer token, then
sign in with authenticate.py.
Environment variables
Variable | Default | Meaning |
| — | Static token Pebble sends as |
|
| Persistent Chromium profile — the signed-in session |
|
| Queued actions |
|
| Seconds the sign-in window waits for you |
|
| Port inside the container |
This server cannot be deployed
Maintenance
Related MCP Connectors
Web search, data extraction and controlled browser automation for AI assistants via OAuth.
Control a real browser from AI agents: navigate, click, type, screenshot, read the page.
The media memory layer for AI agents and their humans. Your AI client can search your collection, add and log what you've finished, update ratings and lists, and find patterns across everything you've read, watched, played, and listened to.
Web search, page reading, site crawling, data extraction and cited research. OAuth sign-in.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to help users manage their reading experience by searching books, tracking reading progress, managing bookmarks, and generating personalized recommendations and summaries.-
- AlicenseAqualityAmaintenanceConnects AI assistants to the Hardcover book library, enabling natural language book searches, reading status updates, list management, and library exploration.28470 PyPI10MIT
- AlicenseAqualityAmaintenanceA read-only MCP server for Goodreads that enables LLMs to search for books, retrieve detailed book info with ratings and reviews, and explore recommendations, series, and author bibliographies using public data sources without requiring authentication.126MIT
- AlicenseAqualityDmaintenanceEnables searching, managing library, wishlist, and credits on Audible through browser automation.68 npmMIT