goodreads-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GOODREADS_TELEMETRY | No | Set to '0' to disable telemetry entirely. | 1 |
| GOODREADS_TRANSPORT | No | Transport mode: 'stdio' (default) or 'http'. | stdio |
| GOODREADS_BQ_DATASET | No | Override for the BigQuery dataset name. | |
| GOODREADS_BQ_PROJECT | No | Override for the Google Cloud project containing the BigQuery dataset. | |
| GOODREADS_BQ_LOCATION | No | Override for the BigQuery location. | |
| GOODREADS_TELEMETRY_PATH | No | File path where telemetry JSONL entries are written. | |
| GOODREADS_MAX_BYTES_BILLED | No | Maximum bytes billed for each BigQuery job. Default is 20 GiB. | 20 GiB |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": true
} |
| logging | {} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| dataset_overviewA | Shape, coverage and known defects of the Goodreads dataset. Call this before answering anything substantive. It reports live row and population counts for every column that has a coverage problem, and returns the full caveat list, including three defects measured from the loaded tables that the project's own DATA_NOTES.md does not mention. |
| rating_distributionA | How book ratings are distributed: a histogram of per-book mean ratings, plus the pooled share of 1-5 star ratings across every rating in scope. Answers "are ratings clustered high?", "what does a typical rating look like?", "how unusual is a 4.5?". |
| top_books_by_ratingA | Highest- or lowest-rated books, subject to a minimum-ratings threshold. The threshold is the whole point: raise it for a result about well-known books, lower it to reach the long tail. Ties break toward the more heavily rated book. Under the default unit="editions" a work with several editions can take several places in the list -- all with the same rating, since editions of one work largely share a rating pool. Pass unit="works" for a list of distinct works. |
| stats_by_languageA | Rating statistics grouped by language. Grouped on language_normalised, never the raw |
| stats_by_yearA | Rating statistics and publication volume per publication year. publish_year is the only reliable temporal field in this dataset -- use this rather than publish_month for any real time series. Always ordered chronologically. |
| stats_by_publisherA | Rating statistics grouped by publisher string.
|
| stats_by_authorA | Rating statistics grouped by author string.
|
| page_count_statsA | Book length against rating: page-count quartiles overall, and rating statistics for each band of book length. Answers "do longer books rate higher?". Books with a NULL pages_number are excluded and counted separately -- 11,216 implausible values were nulled during cleaning. |
| publish_month_seasonalityA | Coarse publishing seasonality by month, plus per-month rating averages. January is inflated -- it holds 17.72% of rows against a uniform 8.3% because unknown dates were recorded as January 1. The January row is flagged in the output. Prefer stats_by_year for real time-series work. |
| user_ratings_overviewA | Shape of the user_ratings table: how the 1-5 stars are distributed, and how active the users are. This describes 4,154 users only. It is a separate dataset from |
| top_titles_by_user_ratingsA | Best- or worst-liked titles among the 4,154 users in user_ratings. Stays entirely inside user_ratings -- no join, so no title-matching loss. These are the opinions of a small user panel, not the books table. |
| compare_user_vs_book_ratingsA | Where the 4,154-user panel disagrees with the wider Goodreads rating. This is the only tool that crosses the two tables, and the join is on normalised title text because user_ratings carries no book ID. It reaches 52,016 of 98,686 rated titles (52.7%) -- roughly half the panel's ratings have no book row to match and are simply absent. Editions of the same title are pooled, so book rating counts are summed across up to 36 rows. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 12 tools
Each tool targets a distinct analytical question, and the detailed descriptions make the boundaries fairly clear. However, top_books_by_rating and top_titles_by_user_ratings, plus dataset_overview and user_ratings_overview, are similar enough at name level that an agent could initially pick the wrong one.
All tool names use snake_case and the stats_by_* family is a recognizable pattern for grouped summaries. But descriptive names like dataset_overview, user_ratings_overview, and publish_month_seasonality break the otherwise consistent pattern.
Twelve tools is a well-scoped size for a dataset-analysis server. Each tool covers a meaningful slice of the data, and none feel redundant or purely decorative.
The server covers the dataset's core analytical needs: overview, rating distributions, top lists, grouping by language/year/publisher/author, page-count effects, seasonality, and cross-table comparison. There are no obvious dead ends or missing operations for the declared purpose.