Goodreads MCP
Provides tools for Goodreads book search, metadata extraction, author and review lookup, book enrichment, and authenticated shelf/rating write-back using a Goodreads browser session, cookie, or JWT.
Goodreads CLI (goodreads)
A command-line tool and MCP server for Goodreads book search, metadata extraction, and authenticated shelf/rating write-back, built by Sameer Bajaj.
It uses public Goodreads pages for read-only metadata and the logged-in Goodreads web GraphQL endpoint for shelf changes. Goodreads no longer issues new public API keys, so authenticated writes use your own browser session, GOODREADS_COOKIE, or GOODREADS_JWT.
Install
go install github.com/sameerbajaj/goodreads-cli/cmd/goodreads@latestVerify:
goodreads doctor
goodreads --helpRelated MCP server: anna-book-search
Quick Start
goodreads search dune
goodreads book 44767458-dune --json
goodreads enrich "Dune" --json --select metadata.title,metadata.rating,metadata.ratings_countShelf Write-Back
On macOS, goodreads can use your local Brave or Chrome Goodreads cookies automatically. It reads only Goodreads cookies, decrypts them locally through Keychain, and does not print or store them.
goodreads shelf auth-check --json
goodreads shelf set --book-id 44767458-dune --shelf currently-reading --yes --json
goodreads shelf set "Dune" --shelf read --rating 5 --tags sci-fi,classics --yes --json
goodreads shelf rate --book-id 44767458-dune --rating 5 --yes --json
goodreads shelf unrate --book-id 44767458-dune --yes --json
goodreads shelf unshelve --book-id 44767458-dune --yes --jsonSupported shelves are to-read, currently-reading, and read; aliases include want-to-read, reading, completed, and done.
Started/finished date writes are intentionally rejected for now because the current Goodreads web client did not expose a verified date mutation.
Auth Options
Automatic macOS browser auth tries Brave first, then Chrome. You can force a browser or disable auto browser auth:
GOODREADS_BROWSER=brave goodreads shelf auth-check --json
GOODREADS_BROWSER=chrome goodreads shelf auth-check --json
GOODREADS_NO_BROWSER_AUTH=1 goodreads shelf auth-check --jsonManual auth also works:
export GOODREADS_COOKIE='_session_id2=...; other_cookie=...'
goodreads shelf auth-check --json
export GOODREADS_JWT='...'
goodreads shelf auth-check --jsonYou can store config at ~/.config/goodreads-cli/config.toml:
goodreads_browser = "brave"
# or:
goodreads_cookie = "_session_id2=...; other_cookie=..."
# or:
goodreads_jwt = "..."Agent Usage
The CLI is designed for LLM and automation use:
--agentsets JSON, compact output, non-interactive mode, no color, and--yes.--dry-runpreviews writes without sending them.Mutating commands are grouped under
shelf.Write commands require
--yesunless--dry-runis used.Secrets are redacted from dry-run output.
Example for another LLM or local agent:
goodreads shelf set "The Left Hand of Darkness" --shelf currently-reading --agent
goodreads enrich "The Left Hand of Darkness" --agent --select metadata.title,metadata.rating,metadata.ratings_count,book_idMCP
Build the MCP server:
go build -o bin/goodreads-mcp ./cmd/goodreads-mcpManual Claude Desktop config:
{
"mcpServers": {
"goodreads": {
"command": "goodreads-mcp"
}
}
}Commands
goodreads search "left hand of darkness"
goodreads book 44767458-dune --json
goodreads author 58.Frank_Herbert --json
goodreads review <user_id> --json
goodreads enrich "Dune" --json
goodreads shelf auth-check --jsonRun goodreads <command> --help for command-specific flags.
Build From Source
git clone https://github.com/sameerbajaj/goodreads-cli.git
cd goodreads-cli
go test ./...
go build -o bin/goodreads ./cmd/goodreadsNotes
This project was initially scaffolded with a CLI generator, then customized for Goodreads' current public web and logged-in web behavior.
👤 Author
Developed by Sameer Bajaj, a Product Manager & Software Builder. Explore more developer tools at sameerbajaj.com/tools.
📄 License
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Available Tools
16 toolsauthor_getBRead-only
Fetch a public Goodreads author page. Required: author_id.
| Name | Required | Description | Default |
|---|---|---|---|
| author_id | Yes | Author id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds the useful detail that the page is 'public' (implying no auth or private-access path), but says nothing about rate limits, failure modes (e.g., unknown author_id), or what the returned page contains. With annotations carrying the safety profile, this is an adequate but thin contribution.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action and resource, with nothing superfluous. It is perhaps slightly too terse — a single clause about what the fetch returns would earn its place — but there is no padding or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read-only tool whose annotations and schema are both fully populated, the definition is serviceable. However, with no output schema and no note about return content or error behavior for invalid author_id, an agent still has to guess at the result shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the single parameter is documented, so the schema does the heavy lifting. The description only restates that author_id is required, adding no format, source, or example beyond what the schema provides — baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Fetch a public Goodreads author page'), which is clear enough for an agent to identify the operation. It does not explicitly differentiate from book_get or the goodreads-search_books siblings, but the resource noun (author page) does most of that work implicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus siblings like book_get or goodreads-search_books, nor on how to obtain a valid author_id. The word 'public' hints that no authentication is needed, but no conditions, prerequisites, or exclusions are stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
book_getBRead-only
Fetch a public Goodreads book page. Required: book_id.
| Name | Required | Description | Default |
|---|---|---|---|
| book_id | Yes | Book id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, openWorldHint, destructiveHint=false, so the safety profile is covered. The description adds only 'public', which usefully implies no authentication is required. It says nothing about rate limits, failure modes for missing ids, or whether the result is raw HTML versus parsed data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with the action first and the requirement second. Nothing is wasted or buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description should indicate what a 'page' fetch returns (parsed fields, raw HTML, or a summary). As written, an agent can call it but cannot anticipate the response shape.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single parameter is documented as 'Book id'. The description merely restates that book_id is required, adding no format, sourcing, or example detail beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb ('Fetch') and resource ('public Goodreads book page'), which is enough to tell it apart from author_get or review_get-shelf by resource noun alone. It stops short of explicitly contrasting itself with those siblings, but the resource is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance on when to call this versus goodreads-search_books (to find a book_id first) or the enrich/sync tools. The agent must infer the lookup-to-fetch workflow entirely on its own.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
contextARead-only
Get API domain context: resource taxonomy, auth requirements, query tips, and unique capabilities. Call this first.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already disclose readOnly and openWorld. Description adds what the context contains but does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two concise sentences, no wasted words. Front-loaded with action and resource.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given zero parameters and no output schema, the description fully covers what the tool does and when to use it.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
No parameters exist; baseline 4 per instructions. Description adds no parameter info, but none needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool retrieves API domain context including specific items (resource taxonomy, auth requirements, etc.). Distinct from sibling action tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'Call this first', providing clear temporal guidance. Does not explicitly name alternatives but context implies using siblings for subsequent actions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
enrichCDestructive
Resolve a title or Goodreads book ID to metadata suitable for syncing into Notion.
| Name | Required | Description | Default |
|---|---|---|---|
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| args | No | Additional positional arguments or raw CLI flags to append to the command. | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| book-id | No | Goodreads book id or slug, e.g. 44767458-dune | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| no-details | No | Only return the search match, without fetching the book page (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, yet the description frames the tool as a benign 'resolve ... to metadata' operation. Nothing in the text warns that this may mutate or destroy data, what the destructive action targets, or that authentication/open-world network access is involved, so the described behavior conflicts with the declared safety profile.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
It is a single front-loaded sentence with no filler, which is structurally sound. The brevity is not wasteful per se, but it leaves the one sentence doing too little work for a 23-parameter tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, open-world tool with 23 parameters, no output schema, and Notion-sync implications, one sentence is seriously incomplete. An agent gets no warning about writes, no interaction with the idempotent/dry-run flags, and no explanation of how 'enrich' differs from 'sync' or 'book_get'.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 23 parameters are documented at 100% schema coverage, so the schema already carries the semantics and a baseline of 3 applies. The description adds no extra meaning about the key input (book-id or title) or how the output-control flags interact with the sync purpose.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description gives a clear verb ('Resolve') and resource ('a title or Goodreads book ID') plus the output ('metadata'). However, it never distinguishes itself from close siblings like book_get or goodreads-search_books, so an agent cannot tell from the text alone why it should pick this tool over those.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use guidance, no mention of alternatives, and no preconditions. With siblings such as book_get and goodreads-search_books performing overlapping lookups, the description offers no routing help at all.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
goodreads-search_booksCRead-only
Search public Goodreads book pages. Required: q.
| Name | Required | Description | Default |
|---|---|---|---|
| q | Yes | Q |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered structurally. The phrase 'public Goodreads book pages' loosely corroborates the open-world nature, but the description does not explain the notable idempotentHint=false, whether results come from live scraping, or whether rate limits apply.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the action. The second sentence is largely redundant with the schema's required array, so it does not fully earn its place, but there is no bloat.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter search tool with no output schema, the definition is minimally viable but thin. It says nothing about result shape, result count, or whether the search hits the live site versus a cached index, all of which an agent would want before calling.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is nominally 100%, but the only schema description is the single character 'Q', which conveys nothing. The description's 'Required: q' merely repeats requiredness, leaving the agent with no idea what the query string should contain or how it is matched.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: search public Goodreads book pages. That is enough to separate it from book_get and author_get, which retrieve a single known entity, but it never explicitly states the distinction or what the search matches on (title, author, ISBN).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no when-to-use or when-not-to-use guidance, and no mention of when to prefer book_get or enrich instead. 'Required: q' is a parameter constraint, not usage guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
importBDestructive
Import data from a JSONL file by issuing POST requests for each record. Each line must be a valid JSON object. Failed records are logged to stderr but do not stop the import.
| Name | Required | Description | Default |
|---|---|---|---|
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| args | No | Additional positional arguments or raw CLI flags to append to the command. | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| input | Yes | Input JSONL file path (use - for stdin) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Preview import without sending requests (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| batch-size | No | Records per batch (future: batch API support) (default: 1) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already flag destructiveHint=true, openWorldHint=true and idempotentHint=false, so the safety profile is covered. The description adds genuinely useful non-obvious behavior: per-record POSTs and partial-failure semantics (failed records logged to stderr, import continues). It does not mention confirmation prompts, the idempotent or dry-run flags that mitigate destructiveness, or rate limiting, which matter a lot for a destructive bulk-write.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the action and mechanism, followed by the file format constraint and failure behavior. Nothing is padded, though the format constraint partially restates the schema description of `input`.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive bulk-write with 23 params and no output schema, the description covers the core semantics an agent needs: the input format, the write mechanism, and non-atomic failure handling. What's missing is where records land and how to preview safely (dry-run), but those gaps are partly bridged by the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so each of the 23 parameters is already documented in the input schema. The description only clarifies the format expectation for the required `input` file (one JSON object per line), adding little beyond the schema baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb+resource: import records from a JSONL file via per-record POST requests. That distinguishes it from read-oriented siblings like book_get or sql, but it never names the target resource (presumably Goodreads shelves) nor contrasts with sync or enrich, which are the closest alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No statement of when to use import versus sync, enrich, or workflow_* tools, and no mention of prerequisites such as auth or a prior sync. The agent must infer usage entirely from the name and schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
review_get-shelfBRead-only
Fetch a public Goodreads user shelf page. Required: user_id. Optional: shelf.
| Name | Required | Description | Default |
|---|---|---|---|
| shelf | No | Shelf | |
| user_id | Yes | User id |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, destructiveHint=false, and idempotentHint=false, so the safety profile is covered. The description adds that the shelf is public, which is useful context about access scope, but it does not mention authentication, rate limits, pagination, or default shelf behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with zero waste, front-loading the main action and then the parameter requirements. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read tool with annotations covering safety, the description is adequate but incomplete. It does not say what shelf is fetched by default when 'shelf' is omitted, nor does it describe pagination or return shape, and there is no output schema to compensate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents both parameters. The description reiterates required/optional status and adds no format, valid values, or default behavior for 'shelf' or 'user_id,' so the baseline of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Fetch') and resource ('public Goodreads user shelf page'), which is clearer than a generic shelf tool. It does not explicitly distinguish itself from siblings like shelf_auth_check or goodreads-search_books, so it stops short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It lists required and optional parameters but gives no guidance on when to use this tool versus alternatives such as shelf_auth_check or goodreads-search_books. The closest thing to usage context is the word 'public,' which implies access to public shelves only, but this is not developed into explicit when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shelf_auth_checkCDestructive
Validate Goodreads write authentication.
| Name | Required | Description | Default |
|---|---|---|---|
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=false, destructiveHint=true, openWorldHint=true, and idempotentHint=false. The description adds no behavioral context about what validation actually does, whether it sends a real write request, what side effects are possible, or what credentials are needed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no filler, and the purpose is front-loaded. It is terse for a 20-parameter tool, but that is a completeness issue rather than wasted prose.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 20 optional parameters, open-world access, a destructive hint, and no output schema, the description is too thin. It does not explain the validation result, required auth context, or how it relates to write siblings such as shelf_set and shelf_rate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
All 20 parameters have schema descriptions (100% coverage), so the schema carries the parameter semantics. The description adds no parameter-level meaning, which is acceptable at the baseline 3 but leaves the generic CLI flags entirely to the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (validate) and resource (Goodreads write authentication). It distinguishes the check from read-oriented siblings like book_get, but does not clarify what 'authentication' entails or name related write tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides no explicit when-to-use guidance, prerequisites, or alternatives. The description only implies that it should be run before write operations; the agent must infer that context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shelf_rateCDestructive
Set a Goodreads rating for a book.
| Name | Required | Description | Default |
|---|---|---|---|
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| args | No | Additional positional arguments or raw CLI flags to append to the command. | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| rating | Yes | Rating from 1 to 5 (default: 0) | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| book-id | No | Goodreads book id/slug or GraphQL kca://book id | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false and idempotentHint=false, so the safety profile is known. The description adds nothing beyond that: it doesn't say whether an existing rating is overwritten, whether auth is required, or what the result looks like, despite this being a destructive mutation with 23 parameters.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One short, front-loaded sentence with no filler. It is efficient, though the brevity edges into under-specification rather than genuine concision.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive, non-idempotent mutation with 23 parameters and no output schema, the description is far too thin. It should at minimum cover overwrite behavior, auth requirements, and the relationship to shelf_set/shelf_unrate.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so parameters such as rating (1 to 5) and book-id are already documented in the schema. The description adds no syntax or format detail beyond that, which is acceptable given full coverage — baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: set a Goodreads rating for a book. That is unambiguous about what the tool does, but it never distinguishes itself from close siblings such as shelf_unrate or shelf_set, so an agent must guess which one applies.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this versus shelf_set or shelf_unrate, nor any prerequisites such as authentication or whether the book must already be on a shelf. Usage has to be inferred entirely from the name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shelf_setCDestructive
Mark a book as to-read, currently-reading, or read.
| Name | Required | Description | Default |
|---|---|---|---|
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| args | No | Additional positional arguments or raw CLI flags to append to the command. | |
| json | No | Output as JSON (default: false) | |
| tags | No | Optional comma-separated tags to apply | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| shelf | Yes | Shelf: to-read, currently-reading, or read | |
| config | No | Config file path | |
| rating | No | Optional rating from 1 to 5 (default: 0) | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| book-id | No | Goodreads book id/slug or GraphQL kca://book id | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| started-at | No | Reserved for Goodreads started date writes; currently unsupported | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| finished-at | No | Reserved for Goodreads finished date writes; currently unsupported | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=false, and openWorldHint=true, so the description should add context such as whether re-shelving overwrites a prior shelf, whether auth is required, that it makes a live network call, or that it prompts for confirmation. None of that is present; the description adds nothing beyond the annotations and leaves the destructive overwrite semantics unexplained.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no wasted words. It is efficient, though the brevity borders on under-specification given the 27-parameter surface.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a destructive, non-idempotent mutation with a very large parameter surface, no output schema, and no stated return format or auth requirements. One sentence cannot adequately prepare an agent to invoke it safely.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% across all 27 parameters, so the schema carries the burden and baseline 3 applies. The description does not clarify the required 'book-id'/'shelf' pairing or note that 'started-at' and 'finished-at' are unsupported no-ops, but repeating schema text is not required.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
A specific verb ('Mark') and resource ('a book') plus the three target shelves, so the action is unambiguous. However it never names a sibling it differs from, and the closest neighbor, shelf_unshelve, removes books from a shelf — the description does not help an agent tell these apart.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The sentence describes what the tool does but gives no guidance on when to prefer it over shelf_unshelve or shelf_rate, no prerequisites (authentication, existing shelf state), and no mention of the confirmation behavior implied by the 'yes' and 'no-input' parameters.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shelf_unrateBDestructive
Remove your Goodreads rating for a book.
| Name | Required | Description | Default |
|---|---|---|---|
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| args | No | Additional positional arguments or raw CLI flags to append to the command. | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| book-id | No | Goodreads book id/slug or GraphQL kca://book id | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, readOnlyHint=false, and idempotentHint=false, so the safety profile is covered. The description adds nothing beyond that: it doesn't say what happens if no rating exists, whether a confirmation prompt fires (relevant given the 'yes' parameter), or whether the removal is reversible.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with zero filler. It is efficient, though the brevity comes at the cost of the targeting detail (book-id) an agent actually needs to invoke it.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive mutation tool with 22 parameters, no required fields, and no output schema, the description is too thin. It should at minimum identify the book-id as the targeting input and note confirmation behavior, neither of which is stated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 22 parameters are documented in the schema and the baseline is 3. The description adds no parameter guidance, notably omitting that 'book-id' is the essential input despite no required parameters being marked.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (remove) and resource (your Goodreads rating for a book), which is clear enough to distinguish from shelf_rate and shelf_set by implication. It stops short of naming those siblings explicitly or noting the shelf scope, so it's clear but not maximally differentiating.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The verb 'remove' implies the inverse-of-rate use case, so an agent can infer when to reach for it. There is no explicit guidance on when to use this versus shelf_set, shelf_unshelve, or shelf_rate, and no mention of prerequisites such as the book needing an existing rating.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shelf_unshelveCDestructive
Remove a book from your Goodreads shelves.
| Name | Required | Description | Default |
|---|---|---|---|
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| args | No | Additional positional arguments or raw CLI flags to append to the command. | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| book-id | No | Goodreads book id/slug or GraphQL kca://book id | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare destructiveHint=true, idempotentHint=false, readOnlyHint=false, and openWorldHint=true, so the safety profile is covered structurally. The description adds essentially no behavioral context beyond those annotations: it does not mention that a confirmation prompt may appear, what gets removed, whether it affects multiple shelves, or how the operation behaves if the book is not on the shelf. Given the destructive nature, this is thin.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. It is appropriately sized for conciseness, though that conciseness comes at the cost of useful detail for a destructive tool with 22 parameters.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a destructive 22-parameter tool with no output schema, the description is insufficiently complete. It does not mention the likely required book identifier, confirmation prompts, dry-run behavior, or whether removal applies to all shelves. The schema covers the parameters, but the description should still prepare the agent for the destructive nature of the call.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 22 parameters are documented in the schema itself. The description adds no parameter-level meaning, so the baseline 3 is appropriate. It does not explain which parameters matter most for this specific operation, such as book-id, yes, or dry-run.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: remove a book from Goodreads shelves. It clearly distinguishes itself in intent from shelf_set, shelf_rate, and shelf_unrate. It does not explicitly name its siblings or clarify whether it removes from a specific shelf versus all shelves, which keeps it from a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives like shelf_set or shelf_unrate, nor any mention of prerequisites such as authentication or confirmation handling. The description only restates what the tool does, leaving selection conditions for the agent to infer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sqlARead-only
Run read-only SQL against local database. Use for ad-hoc analysis, aggregations, and joins across synced resources. Requires sync first.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | SQL query (SELECT or WITH...SELECT). Tables match resource names. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is carried by structured data. The description adds a real prerequisite ('Requires sync first') not present in annotations, but says nothing about row limits, timeouts, cost, or what happens for invalid/non-SELECT queries.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action, then use case, then prerequisite. No filler; every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an open-ended SQL tool with no output schema, the description covers what it does, when to use it, and the sync prerequisite. The main remaining gap is table/schema discovery guidance (which sibling to call to learn available tables and columns) before writing a query.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With a single parameter at 100% schema description coverage, the schema already explains the query string and the SELECT/WITH...SELECT restriction, so baseline is 3. 'Tables match resource names' is useful but duplicated in the schema, adding no new meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Run read-only SQL against local database') plus the intended use case (ad-hoc analysis, aggregations, joins). It is clearly distinguishable from the CRUD-style siblings (author_get, book_get, review_get-shelf), though it never names those siblings explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Use for ad-hoc analysis, aggregations, and joins across synced resources' gives clear positive guidance, and 'Requires sync first' states a prerequisite. It stops short of naming alternatives (e.g., the context tool for schema discovery) or when-not-to-use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
syncADestructive
Sync data from the API into a local SQLite database. Supports resumable incremental sync (only fetches new data since last sync) and full resync. Once synced, use the 'search' command for instant full-text search.
Exit codes & warnings: Resources the API denies access to (HTTP 403, or HTTP 400 with an access-policy body) are reported as warnings rather than failing the run. In --json mode each is emitted as a {"event":"sync_warning",...} line carrying status, reason, and message fields, and a final {"event":"sync_summary",...} aggregates the run.
Exit 0 when at least one resource synced and no resource flagged in the spec as critical (x-critical: true) failed; non-critical failures emit {"event":"sync_warning","reason":"exit_policy_default_changed", ...} so callers can detect that a partial failure was tolerated. Pass --strict to exit non-zero on any per-resource failure. Exit is always non-zero when every selected resource failed, regardless of --strict.
| Name | Required | Description | Default |
|---|---|---|---|
| db | No | Database path (default: ~/.local/share/goodreads-cli/data.db) | |
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| full | No | Full resync (ignore previous checkpoint) (default: false) | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| since | No | Incremental sync duration (e.g. 7d, 24h, 1w, 30m) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| strict | No | Exit non-zero on any per-resource failure (default: only critical failures or all-resource failure exit non-zero). (default: false) | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| max-pages | No | Maximum pages to fetch per resource (0 = unlimited; cap-hit emits a sync_warning event) (default: 100) | |
| resources | No | Comma-separated resource types to sync | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| concurrency | No | Number of parallel sync workers (default: 4) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| latest-only | No | Refresh head of each resource only; clears resume cursor and caps pages at 1. Mutually exclusive with --since (--since wins). (default: false) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds substantial behavior beyond the annotations: denied resources are warnings rather than hard failures, JSON warning/summary events are emitted, and exit status depends on critical-resource policy and --strict. This is exactly the kind of operational context an agent needs for a non-idempotent, open-world sync.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core purpose and search handoff are front-loaded, and the exit-code section is organized under a clear heading. The exit-policy prose is dense and quite long, but it remains relevant for a sync tool whose failure semantics matter.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich schema and annotations, the description covers the essential sync model, incremental/full behavior, warnings, and exit codes. It does not explicitly restate destructive local-write implications or authentication requirements, but the destructive and open-world annotations already signal those risks.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 100% schema description coverage across 28 parameters, the schema already carries most parameter meaning. The description adds useful context for 'since', 'full', 'strict', and '--json' behavior, but it does not systematically explain the many output, routing, cache, concurrency, and resource-selection parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: syncing API data into a local SQLite database. It also distinguishes the post-sync query path by naming the 'search' command, so an agent can tell what this tool is for without opening the schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It clearly frames the tool as populating local data for later search and explains incremental vs. full resync and when to use --strict. It does not explicitly exclude or compare against siblings such as 'import' or 'sql', so it stops short of full when/when-not guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workflow_archiveADestructive
Archive fetches all syncable resources from the API and stores them in a local SQLite database. Supports incremental sync (only new data since last run) and full resync. After archiving, use 'search' for instant full-text search.
| Name | Required | Description | Default |
|---|---|---|---|
| db | No | Database path (default: ~/.local/share/goodreads-cli/data.db) | |
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| full | No | Full re-archive (ignore previous sync state) (default: false) | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare destructiveHint=true and openWorldHint=true, so the agent knows this is a mutating, network-bound operation; the description adds useful detail that it writes to a local SQLite database and supports incremental sync. But it never explains what the destructive flag means in practice—whether existing archived data is overwritten or merged, whether confirmation is required (the 'yes' param implies it), or that the run may be long due to remote fetching.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences, front-loaded with the core action before the incremental/full variants. The trailing pointer to 'search' is efficient but references a command not present among siblings, slightly diluting the value of that sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 22 flags, no output schema, and destructive/open-world annotations, the description covers the essential 'what it does and how it differs across modes' story. It leaves out return-value shape and confirmation behavior, but for an archival command whose flags are fully in the schema, this is reasonably complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 22 parameters are already documented, establishing the baseline of 3. The description reinforces the semantics of the 'full' flag (full resync vs incremental) but does not mention any parameter by name or clarify the interaction of 'agent', 'yes', 'dry-run', or 'data-source' with this command.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource: fetch all syncable resources from the API and persist them into a local SQLite database. The incremental-vs-full distinction is spelled out. It does not, however, distinguish itself from close siblings like 'sync' and 'import', leaving the agent to infer which one performs the local archive.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies a workflow (archive first, then use 'search' for full-text search), which is useful routing, but 'search' is not one of the actual sibling tools (the closest are 'sql' and 'goodreads-search_books'). No guidance is given on when to choose this over 'sync' or 'import', or on prerequisites such as authentication.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
workflow_statusBRead-only
Show local archive status and sync state for all resources
| Name | Required | Description | Default |
|---|---|---|---|
| db | No | Database path | |
| csv | No | Output as CSV (table and array responses) (default: false) | |
| yes | No | Skip confirmation prompts (for agents and scripts) (default: false) | |
| json | No | Output as JSON (default: false) | |
| agent | No | Set all agent-friendly defaults (--json --compact --no-input --no-color --yes) (default: false) | |
| plain | No | Output as plain tab-separated text (default: false) | |
| quiet | No | Bare output, one value per line (default: false) | |
| config | No | Config file path | |
| select | No | Comma-separated fields to include in output (e.g. --select id,name,status) | |
| compact | No | Return only key fields (id, name, status, timestamps) for minimal token usage (default: false) | |
| deliver | No | Route output to a sink: stdout (default), file:<path>, webhook:<url> | |
| dry-run | No | Show request without sending (default: false) | |
| profile | No | Apply values from a saved profile (see 'goodreads profile list') | |
| timeout | No | Request timeout (default: 30s) | |
| no-cache | No | Bypass response cache (default: false) | |
| no-color | No | Disable colored output (default: false) | |
| no-input | No | Disable all interactive prompts (for CI/agents) (default: false) | |
| idempotent | No | Treat already-existing create results as a successful no-op (default: false) | |
| rate-limit | No | Max requests per second (0 to disable) (default: 0) | |
| data-source | No | Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default: auto) | |
| human-friendly | No | Enable colored output and rich formatting (default: false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds that the scope is local archive status and sync state across all resources, but it does not elaborate on auth, rate limits, caching, or what the returned status includes. It adds some scope context without contradicting the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. It communicates the core scope immediately and is appropriately sized for a status command.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
There is no output schema, and the description does not explain what 'status' or 'sync state' contains. For a 21-parameter status tool, the minimal description is adequate to identify the command but leaves output expectations and practical usage context under-specified.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 21 parameters already have structured descriptions. The tool description adds no parameter-level meaning beyond that, which makes the baseline score of 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Show local archive status and sync state for all resources.' This is clearly a read-only status tool, distinguishable in kind from siblings like workflow_archive and sync, though it does not explicitly name those alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives no explicit guidance on when to use this tool versus workflow_archive, sync, or other siblings. The scope 'for all resources' is stated, but there are no usage conditions, prerequisites, or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
16 tool updates
v0.1.0- First observed
author_get - First observed
book_get - First observed
context - First observed
enrich - First observed
goodreads-search_books - First observed
import - First observed
review_get-shelf - First observed
shelf_auth_check - First observed
shelf_rate - First observed
shelf_set - First observed
shelf_unrate - First observed
shelf_unshelve - First observed
sql - First observed
sync - First observed
workflow_archive - First observed
workflow_status
TDQS
Scored across 16 tools
Most tools target distinct Goodreads resources or actions, but sync and workflow_archive are near-duplicates: both fetch API resources into a local SQLite database with incremental/full resync. enrich also overlaps somewhat with book_get, so an agent cannot reliably distinguish the intended choice from descriptions alone.
Tool names mix noun_verb (author_get, book_get, shelf_rate), verb_noun (workflow_archive), single-word commands (context, sync, sql), a hyphenated namespace (goodreads-search_books), and an internal hyphen (review_get-shelf). They are readable but do not follow a predictable convention.
At 16 tools, the set is just above the ideal 3–15 range and feels slightly heavy, especially with the duplicate sync/workflow_archive pair and a separate workflow_status tool. The count is not extreme, but the redundancy inflates the surface.
Core read, search, shelf-write, and local sync/SQL operations are present, but there are notable gaps: no standalone review retrieval/write, no author search, and no current-user/profile tool. The sync and workflow_archive descriptions also reference a 'search' command that is not exposed as a tool, leaving a dead end.
Maintenance
Related MCP Connectors
MCP server for Russian books search, details, and recommendation candidates.
Gutendex MCP — wraps Gutendex API for Project Gutenberg books (free, no auth)
Books MCP — wraps Open Library API (free, no auth)
MCP server for Project Gutenberg: 78,000+ public-domain ebooks with full plain-text retrieval.
Related MCP Servers
- 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.125MIT
- AlicenseNot gradedqualityCmaintenanceSelf-hosted MCP server for searching and discovering books using Anna's Archive and Goodreads datasets, enabling full-text search, ISBN/md5 lookup, similarity matching, and optional download URL retrieval.12 npm4MIT
- AlicenseAqualityAmaintenanceMCP server in Go to search and download books, papers, comics and more from Library Genesis — three focused tools, one static binary, no account required.424MIT
- AlicenseNot gradedqualityBmaintenanceA Go MCP server for inspecting and safely operating Audiobookshelf libraries.1MIT