apple-books-mcp
This MCP server lets Claude browse, search, and analyze your Apple Books library, annotations, and reading progress, and optionally edit collections.
List and search books by title, author, genre, and reading status (in-progress, finished, unstarted, recently read).
Describe books with metadata, progress, annotation counts, readable-text status, and Open in Books links.
Browse, search, and describe annotations, highlights, and notes; filter by color, date range, or text; get surrounding context for a highlight.
Read non-DRM EPUB chapter content, table of contents, and current reading position, including
chapter_id="current".List, search, and describe collections; with writes enabled, create, rename, delete collections, and add/remove books.
Get library stats and attach a Currently Reading resource.
Use prompts such as weekly_digest, library_snapshot, and revisit_book for guided workflows.
Provides tools for interacting with Apple Books, allowing access to book collections, detailed book information, and annotation management including highlights and notes.
Provides support for the developer through donation links to Buy Me A Coffee platform.
Facilitates contribution to the project through the GitHub repository, including issue reporting and pull request submission.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@apple-books-mcpwhat are my recent highlights from 'Dune'?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Apple Books MCP
Model Context Protocol (MCP) server for Apple Books.
At a glance
Pick up where you left off — Claude sees the book you're reading, your progress and the chapter you're on, and pulls that chapter's text (
chapter_id="current") and your highlights when it needs them.Find any book — by title or author, ignoring case, accents and curly quotes, with a link that opens it in Apple Books.
Expand on any highlight — get the surrounding paragraph explained in context, with the exact anchor you marked shown in
«...».Revisit a book — pull your highlights, cluster them by theme, and quote you back to yourself.
Reflect on your reading — patterns across books, recurring ideas in your highlights, what you're actually drawn to.
https://github.com/user-attachments/assets/77a5a29b-bfd7-4275-a4af-8d6c51a4527e
And much more!
Related MCP server: Co-Reading MCP
Available Tools
List and search tools return one page at a time: 50 annotations or 200 books by default, limit between 1 and 500, and offset for the next page. When there is more, the output says so and names the next offset.
How results work:
Ids are integers: every row starts with one, as in
[175] Title by Author, to pass on asbook_id,annotation_idorcollection_id. A numeric string such as"175"is accepted too;true,falseand fractions are not ids.A failure (an unknown id, a book that isn't downloaded, a bad
color) comes back as an MCP error (isError) whose message names what to do next, often another tool to call. An empty result ("No books matched …") is a normal answer, not an error.Text taken from your books (chapter text, the passage around a highlight, a table of contents, a book's description) is wrapped in
<book_text>…</book_text>. The server's instructions tell Claude that this text is untrusted data from the book, never instructions to follow.Highlights from books you've removed from the library are kept by Apple Books. They are shown per removed book, as "Removed book (asset 3F2A1B2C…)", after the books still in your library.
Collections
Tool | Description | Parameters |
list_all_collections | List all collections | limit?: int (default: 200), offset?: int |
get_collection_books | Get all books in a collection | collection_id: int |
describe_collection | Get details of a collection | collection_id: int |
search_collections_by_title | Search for collections by title | title: str |
Editing collections (opt-in)
Off by default. Enable by adding --enable-writes to the server args:
"args": ["apple-books-mcp", "--enable-writes"]With the Claude Desktop extension, turn on Allow editing collections in the extension's settings instead.
Apple provides no automation API for collections, so these write directly to the library database — behind guard rails: every write refuses while Books is open, takes an automatic WAL-safe backup first (~/.py_apple_books/backups/), validates the schema and aborts on drift, and only touches user-created collections (plus "Want to Read" membership). Deleting a collection never deletes the books in it.
⚠️ If iCloud sync for collections is enabled, direct edits may not propagate to other devices and can be reverted by a cloud re-sync.
Tool | Description | Parameters |
create_collection | Create a new collection | title: str, details?: str |
rename_collection | Rename a user-created collection | collection_id: int, new_title: str |
delete_collection | Delete a user-created collection (books untouched) | collection_id: int |
add_book_to_collection | Add a book to a collection (idempotent) | collection_id: int, book_id: int |
remove_book_from_collection | Remove a book from a collection (idempotent) | collection_id: int, book_id: int |
Books
Tool | Description | Parameters |
list_all_books | List all books | limit?: int (default: 200), offset?: int |
search_books | Find books whose title or author contains the query, ignoring case, accents and quote/dash style | query: str, limit?: int (default: 200), offset?: int |
search_books_by_title | Search for books by title (same matching, titles only) | title: str, limit?: int (default: 200), offset?: int |
describe_book | Get details of a particular book (metadata, progress, annotation count, description), whether its text is readable (see below) and an "Open in Books" link | book_id: int |
list_annotations | Annotations for a book in reading order (id + text + chapter per row, with your notes) | book_id: int, limit?: int (default: 50), offset?: int |
get_books_by_genre | Get books by genre (substring match) | genre: str, limit?: int (default: 200), offset?: int |
describe_book has a Readable text line saying whether the chapter tools can read the book, and if not why: yes (EPUB), a PDF, DRM-protected, not downloaded (in iCloud only, an Apple Books Store title, or never downloaded) or a missing file. It is worked out from the library's records and file metadata, without opening the book: reading a file that is only in iCloud would make macOS download it.
Open in Books links (ibooks://assetid/…) open the book in Apple Books. They appear in describe_book, describe_annotation, get_current_reading_position and the Currently Reading resource.
Reading Status
Tool | Description | Parameters |
get_books_in_progress | Get books currently being read | limit?: int (default: 200), offset?: int |
get_finished_books | Get books that have been finished | limit?: int (default: 200), offset?: int |
get_unstarted_books | Get books not yet started | limit?: int (default: 200), offset?: int |
get_recently_read_books | Get the most recently read books | limit?: int (default: 10), offset?: int |
Annotations
Tool | Description | Parameters |
list_all_annotations | Browse every annotation grouped by book, newest first, with your notes | limit?: int (default: 50), offset?: int |
recent_annotations | Get most recent annotations (flat, with date + book per row) | limit?: int (default: 10), offset?: int |
describe_annotation | Get full details of a single annotation, with the book's "Open in Books" link | annotation_id: int |
get_annotation_context | Text window around a highlight (the paragraph it's in), with the highlight marked | annotation_id: int, chars_before?: int (default: 500), chars_after?: int (default: 500) |
get_highlights_by_color | Highlights of a particular color, grouped by book | color: yellow|green|blue|pink|purple, limit?: int (default: 50), offset?: int, order_by?: newest|oldest |
search_notes | Search user notes (shows highlight + note inline) | note: str, limit?: int (default: 50), offset?: int, order_by?: newest|oldest |
search_annotations | Search across highlights + notes + surrounding text (shows notes inline) | text: str, limit?: int (default: 50), offset?: int, order_by?: newest|oldest |
get_annotations_by_date_range | Annotations within a date range, inclusive of the | after?: YYYY-MM-DD, before?: YYYY-MM-DD, limit?: int (default: 50), offset?: int, order_by?: newest|oldest |
Library Stats
Tool | Description | Parameters |
get_library_stats | Get library summary with reading stats | None |
Book Content
Only works for non-DRM EPUBs downloaded to this Mac (imported books, Project Gutenberg, Standard Ebooks, etc.). Apple Books Store purchases are usually FairPlay-protected and return a clear error, and iCloud-only books a "not downloaded" hint; describe_book's "Readable text" line tells in advance.
Tool | Description | Parameters |
list_book_chapters | Table of contents for a book (chapter titles, order, nesting) | book_id: int |
get_chapter_content | Plain-text content of a chapter, with optional | book_id: int, chapter_id?: str (default: "current"), offset?: int, max_chars?: int |
get_current_reading_position | The chapter the user last left off reading (via Apple Books' auto-bookmark CFI), with an "Open in Books" link | book_id: int |
Available Resources
Attachable data objects accessible from Claude Desktop's resource picker.
Resource | URI | Description |
Currently Reading |
| A short pointer to the book you're reading right now (the most recently opened in-progress book): title, author, book id, progress, an "Open in Books" link, the chapter you left off on with its chapter id (for non-DRM EPUBs; otherwise why its text can't be read), and how many highlights you have in it. It carries no chapter text or highlights; Claude fetches those on demand with |
Available Prompts
One-click workflows, accessible from Claude Desktop's prompt picker.
Prompt | Description | Arguments |
weekly_digest | Summarize what I've read and highlighted in the past week | days?: int (default: 7) |
library_snapshot | A reflection on my whole reading life | None |
revisit_book | Revisit your notes and highlights from a specific book | book_title: str |
Installation
Requirements
macOS, with Apple Books opened at least once (it creates the library the server reads).
Python 3.10 or newer. uvx and the Claude Desktop extension provide one if needed.
Installed with the server:
mcp>= 1.12 (< 2) andpy-apple-books>= 1.10 (< 2).
Using uv (recommended)
uvx runs apple-books-mcp without a separate install step.
brew install uv # for macos
uvx apple-books-mcp --versionThe first run downloads about 14 MB of dependencies and can take up to a minute, which is close to how long Claude waits for a server to start. Running the command above once in Terminal warms uv's cache before you add the server to Claude. --version prints the apple-books-mcp, mcp and py-apple-books versions uvx resolved.
Then add the server to Claude with the JSON config or the Claude Code command below.
Claude Desktop extension (.mcpb)
Claude Desktop can also install apple-books-mcp as an extension, without editing its config: download apple-books-mcp-<version>.mcpb from the latest GitHub release, double-click it (or open Settings → Extensions → Install Extension… and pick the file), and click Install. Desktop installs uv and the locked dependencies itself. Allow editing collections in the extension's settings does the same as --enable-writes.
On organization-managed Claude (Team/Enterprise), admins can limit Desktop Extensions to an allowlist or turn them off. If the .mcpb install is refused, use the JSON config below. If user-added MCP servers are also disabled by policy, ask your admin to approve the extension.
Using pip
Needs Python 3.10 or newer (the python3 that ships with macOS is 3.9). Install into a virtual environment:
python3 -m venv ~/.venvs/apple-books-mcp
~/.venvs/apple-books-mcp/bin/pip install apple-books-mcp
~/.venvs/apple-books-mcp/bin/apple-books-mcp --versionUpgrade later with ~/.venvs/apple-books-mcp/bin/pip install -U apple-books-mcp.
Using Docker (deprecated)
⚠️ The Docker image is deprecated and only partly works: a Linux container can't be granted the macOS permission, can't reach book files stored in iCloud Drive (so the tools that read book text fail), and can't tell whether Books is running (so collection writes are unsupported). Use uvx instead.
It can still serve library metadata and annotations. Mount the Apple Books container read-only and keep stdin open with -i. The image runs as an unprivileged user and reads the library from the same mount path as before:
docker run -i --rm -v ~/Library/Containers/com.apple.iBooksX/Data/Documents:/root/Library/Containers/com.apple.iBooksX/Data/Documents:ro ghcr.io/vgnshiyer/apple-books-mcp:latestIn a Claude config, spell out your home directory: Claude doesn't expand ~.
{
"mcpServers": {
"apple-books-mcp": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-v", "/Users/YOU/Library/Containers/com.apple.iBooksX/Data/Documents:/root/Library/Containers/com.apple.iBooksX/Data/Documents:ro",
"ghcr.io/vgnshiyer/apple-books-mcp:latest"
]
}
}
}First-run permission prompt (macOS)
The first time the server reads your library, macOS asks whether the program that started it may "access data from other apps", because Apple Books keeps its library in its own app container (~/Library/Containers/com.apple.iBooksX/). Click Allow.

macOS asks about the program Claude launches, not about apple-books-mcp itself:
uvxwith the recommended Claude Desktop config (the prompt above);the Python interpreter with the pip config;
claudewhen the server is configured in Claude Code;your terminal app when you run the server by hand.
The permission belongs to that program, so anything else it launches can use it too. apple-books-mcp only reads the library, plus the book files for chapter text; it changes nothing unless you pass --enable-writes.
To check, run uvx apple-books-mcp --doctor in Terminal: it reports whether the program running it may read the library and, if not, how to fix it. Run that way it checks your terminal app's permission, which macOS asks about separately from uvx or Claude.
Asked again after an update? Homebrew's uv/uvx and Homebrew or uv-managed Python builds aren't signed by a registered developer, so after brew upgrade uv (or a Python upgrade) macOS treats them as a new program and asks again. Click Allow.
Clicked "Don't Allow"? Tools then fail with "macOS denied access to the Apple Books library". (Older releases failed at startup instead, with "No sqlite files found in … Please open Apple Books at least once".) This permission has no switch in System Settings. To be asked again, run:
tccutil reset SystemPolicyAppDataThis clears the "data from other apps" decisions for all apps. Then quit and reopen Claude, and click Allow. Adding the program (e.g. /opt/homebrew/bin/uvx) to Full Disk Access in System Settings > Privacy & Security also works, but grants far more access.
Configuration
Claude Desktop Setup
Quit Claude Desktop (Cmd+Q) before editing ~/Library/Application Support/Claude/claude_desktop_config.json: Desktop rewrites the file while it runs, so edits made while it's open can be lost.
Using uvx (recommended)
{
"mcpServers": {
"apple-books-mcp": {
"command": "uvx",
"args": [ "apple-books-mcp" ]
}
}
}Plain apple-books-mcp still picks up new releases: uv checks PyPI for a newer version whenever its cached copy of the package index is more than 10 minutes old, which is usually the case when Claude starts. apple-books-mcp@latest gains nothing over that and makes uv build a fresh environment on every launch (3–12 s instead of about 1 s).
Faster or offline startup
Because uvx checks PyPI at launch, the server won't start while PyPI is unreachable. To avoid that:
Run
uv tool install apple-books-mcponce. The same uvx config then uses the installed copy and starts in about a second without contacting PyPI. Installed copies don't update themselves: runuv tool upgrade apple-books-mcpto get new releases.Or use
"args": ["--offline", "apple-books-mcp"]to run whatever version uv has already cached (after at least one online run), without any network access.
Using pip
Point Claude at the script inside the virtual environment from Using pip, with your home directory spelled out:
{
"mcpServers": {
"apple-books-mcp": {
"command": "/Users/YOU/.venvs/apple-books-mcp/bin/apple-books-mcp"
}
}
}Claude Code Setup
Claude Code doesn't read the Claude Desktop config. Add the server with:
claude mcp add --scope user apple-books-mcp -- uvx apple-books-mcpand check it with /mcp.
Environment variables
Set these in the server's "env" in the Claude config (e.g. "env": {"APPLE_BOOKS_MCP_THREADS": "4"} next to "args"), or with claude mcp add -e NAME=value.
Variable | Default | What it does |
| off |
|
|
| How many tool calls run at once. |
| Apple Books' own folder | The Apple Books |
|
| Seconds a library query may run before it is stopped; |
Troubleshooting
Where to look
uvx apple-books-mcp --doctorin Terminal checks the versions, finds the library, explains macOS permission problems and prints counts of what it read. It only reads, and never prints titles or text.~/Library/Logs/Claude/mcp-server-apple-books-mcp.log(named after yourmcpServerskey) has the server's own output, including Python tracebacks. For more detail, add"-v"to the args: the server then logs its version, the mcp and py-apple-books versions it runs with, and each request.~/Library/Logs/Claude/mcp.loglists failures. Its "Server started and connected successfully" line only means the process was launched, not that it works.~/Library/Logs/Claude/main.logrecords "Connected to apple-books-mcp (N tools)" when a Claude Code or Cowork session in Desktop loaded the tools.uvx apple-books-mcp --versionin Terminal shows which versions uvx resolves.
Common problems
"Connection closed", "Server disconnected" or "Server transport closed unexpectedly": the server exited at startup. Read the last error in the traceback in
mcp-server-apple-books-mcp.log.No module named 'mcp.server.fastmcp': uv picked an apple-books-mcp release older than 0.8.1 together with mcp 2.x, which removed the API those releases were built on (on Python 3.12 and older, uvx could even fall back to 0.1.2). 0.8.1 and newer work with Python 3.10+ and stay on mcp 1.x. Runuv cache clean apple-books-mcp, check thatuvx apple-books-mcp --versionreports 0.8.1 or newer, then quit and reopen Claude.A
No module named 'server'error in front of the real one is noise from releases before 0.8.4.
"Not ready after 60 seconds" or "Request timed out" at startup: the first launch was still downloading and installing dependencies. Run
uvx apple-books-mcp --versiononce in Terminal, then reopen Claude."macOS denied access to the Apple Books library" (older releases: "No sqlite files found in …"): see First-run permission prompt.
"No Apple Books library store found": Apple Books hasn't created its library for this macOS user yet. Open Books once, then try again.
Stopping a response while a tool runs: since 0.9 a stopped tool call is answered immediately and the server keeps serving other sessions; the call's remaining work finishes in the background (a write that had already started still completes; one that hadn't started never runs).
"Extension apple-books-mcp not found in installed extensions" in
main.logis harmless.
Getting Claude to retry
Claude Desktop chats: quit Claude completely (Cmd+Q) and reopen it. A server that failed to start isn't retried otherwise.
Claude Code and Cowork sessions in Desktop: start a new session; each new session retries the server.
Claude Code: run
/mcpand reconnect apple-books-mcp, or restart Claude Code.
Upcoming Features
Highlight export: a book's highlights and notes in reading order, with chapter headings
Fewer, broader tools in 1.0, where today several overlap
Titles for removed books, where Apple Books' caches still hold them
PDF content access (currently EPUB-only)
Contribution
Thank you for considering contributing to this project!
Development
Clone the repository and let uv create the virtual environment and install the package with its dependencies:
uv sync
uv run apple-books-mcp --version
uv run pytestTo build the Claude Desktop extension locally, install the pinned packer, then build:
npm ci --ignore-scripts --prefix mcpb
uv run python scripts/build_mcpb.pyThis writes dist/apple-books-mcp-<version>.mcpb and the registry's dist/server.json (--out DIR picks another folder). python scripts/build_mcpb.py --smoke dist/apple-books-mcp-<version>.mcpb installs the bundle the way Claude Desktop does and checks the server it starts.
Maintainers: publishing a GitHub release runs the release workflow, which checks the tag against every version field, publishes to PyPI, attaches the .mcpb to the release and publishes to the MCP Registry.
Debugging
Logs go to stderr, which Claude Desktop writes to ~/Library/Logs/Claude/mcp-server-<name>.log. Without flags the server logs only warnings and errors; -v adds startup details (versions, whether writes are enabled) and a line per request; -vv adds debug output from the MCP SDK.
With Claude Desktop
{
"mcpServers": {
"apple-books-mcp": {
"command": "uv",
"args": [
"--directory",
"/path/to/apple-books-mcp/",
"run",
"apple-books-mcp",
"-v"
]
}
}
}With inspector
npx @modelcontextprotocol/inspector uv --directory /path/to/apple-books-mcp run apple-books-mcpOpening Issues
If you encounter a bug, have a feature request, or want to discuss something related to the project, please open an issue on the GitHub repository. When opening an issue, please provide:
Bug Reports: Describe the issue in detail. Include steps to reproduce the bug if possible, along with any error messages or screenshots.
Feature Requests: Clearly explain the new feature you'd like to see added to the project. Provide context on why this feature would be beneficial.
General Discussions: Feel free to start discussions on broader topics related to the project.
Contributing
1️⃣ Fork the GitHub repository https://github.com/vgnshiyer/apple-books-mcp
2️⃣ Create a new branch for your changes (git checkout -b feature/my-new-feature).
3️⃣ Make your changes and test them thoroughly.
4️⃣ Push your changes and open a Pull Request to main.
Please provide a clear title and description of your changes.
License
Apple Books MCP is licensed under the Apache 2.0 license. See the LICENSE file for details.
Available Tools
31 toolsadd_book_to_collectionAdd a book to a collectionCIdempotent
Add a book to a collection (user-created collections and "Want to Read"). Idempotent. Requires write access and Books to be quit.
Args: collection_id: The collection's numeric ID. book_id: The book's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| book_id | Yes | ||
| collection_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already carry idempotentHint=true, destructiveHint=false, readOnlyHint=false, so "Idempotent" is redundant. The description does add the write-access authorization requirement, which is genuine behavioral context beyond annotations. However, the garbled phrase "Books to be quit" is confusing and adds no usable trait.
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?
Front-loaded with the core purpose and reasonably short, but the broken "Books to be quit" fragment wastes a sentence and undercuts clarity. The Args block duplicates information already in the schema.
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-param mutation with no output schema, the description covers the authorization prerequisite and idempotency, which is the essential gap-fill. But the garbled clause and lack of failure/edge-case behavior (e.g. what happens if the book is already present) leave it only partially 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 0%, so the description must compensate. It only restates each parameter as a "numeric ID", which is already implied by the integer type in the schema; no format, valid range, or how to obtain the IDs is given. Minimal value added over the structured fields.
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+resource ("Add a book to a collection") and clarifies the scope of "collection" by naming user-created collections and "Want to Read". It implicitly contrasts with remove_book_from_collection, though it never names the sibling. Clear purpose, but no explicit sibling differentiation.
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 a prerequisite ("Requires write access") but gives no guidance on when to use this versus alternatives, no preconditions on states (e.g. already-in-collection), and no exclusions. The agent is left to infer usage entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_collectionCreate a collectionA
Create a new collection in the user's Apple Books library. Requires write access and Books to be quit; a backup is taken automatically.
Args: title: Name for the new collection. details: Optional description.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes | ||
| details | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this is a non-read-only, non-destructive, non-idempotent write, so the bar is lower. The description still adds meaningful context the annotations cannot convey: it requires write access, requires Books to be quit, and takes a backup automatically. It omits duplicate-title behavior and the creation response, keeping it out of the top band.
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?
Purpose and preconditions are front-loaded in two tight sentences, then the Args block. The Args section largely restates the schema, which is mildly redundant but conventional and not wasteful.
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, no annotations beyond the safety hints, and a trivial two-parameter schema, the description covers what an agent needs: purpose, permissions, required app state, and backup behavior. Minor gaps (duplicate handling, return value) are acceptable given the tool's simplicity.
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 0%, so the description carries the full burden and does document both parameters: title as the collection name and details as an optional description. It compensates for the empty schema, though it adds no constraints such as uniqueness or length limits.
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 specific verb ("Create") and resource ("collection") scoped to the user's Apple Books library, which cleanly distinguishes it from siblings like rename_collection and delete_collection. It stops short of explicitly contrasting with those siblings, so it is 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?
It supplies real preconditions (write access required, Books must be quit, automatic backup) that tell the agent when the tool is usable. However, it never routes the agent among alternatives (e.g., rename vs create, or what to do if the collection already exists), so usage guidance is implied rather than explicit.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_collectionDelete a collectionADestructiveIdempotent
Delete a user-created collection (built-in collections are refused). The books inside are NOT deleted — only the collection. Requires write access and Books to be quit.
Args: collection_id: The collection's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| collection_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true, idempotentHint=true and readOnlyHint=false, so safety is covered. The description adds valuable non-obvious context: the contained books survive the deletion, built-in collections are rejected, and the app must be closed. That is meaningful disclosure beyond the structured hints.
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?
Front-loads the destructive action and the safeguard about books, then the prerequisites, then the arg. The Args line is slightly redundant with the sentence but does carry the numeric-ID detail.
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 destructive tool with no output schema, the description covers effect scope, prerequisites, and refusal behavior. Return value is trivially implied (success/failure), so nothing critical is missing.
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 0% for the single parameter, so the description must compensate; it states the parameter is a numeric collection ID, which clarifies type and meaning. It adds no format or lookup guidance beyond that, so it is adequate rather than rich.
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 (delete) and resource (user-created collection), and immediately scopes it by excluding built-in collections. An agent can distinguish this from create_collection and rename_collection without opening any 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?
Gives explicit preconditions (requires write access, Books must be quit) and an exclusion (built-in collections are refused). It doesn't name a sibling alternative, but the when/when-not guidance is clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_annotationDescribe an annotationARead-only
Describe a specific annotation in detail — text, note, book (with
an Open in Books: link), chapter, color, creation date. For the
passage around the highlight, call get_annotation_context
instead.
Args: annotation_id: The annotation's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| annotation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds valuable context beyond that by disclosing the fields returned (text, note, book with an Open in Books link, chapter, color, creation date), which matters since there is no output schema. It does not discuss auth or rate limits, but those are minor for a simple read.
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 content is front-loaded in the first sentence with the alternative routing in the second, which is efficient. The trailing 'Args:' block restating the single obvious parameter is mild redundancy but conventional and not harmful.
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 read-only describe tool with no output schema, the description is nearly complete: it names the fields returned and routes to the correct sibling. It stops short of noting any error behavior for an unknown ID, but the core need to call it correctly is met.
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 0%, so the description must carry the parameter burden, and it does identify annotation_id as 'the annotation's numeric ID'. That clarifies type and target, but adds little beyond the obvious given the tool name. Adequate but thin for the single parameter.
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 (describe), resource (a specific annotation), and enumerates what detail is returned: text, note, book link, chapter, color, creation date. It also distinguishes itself from get_annotation_context, so an agent can tell the two apart without opening either 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 names an explicit alternative (get_annotation_context) and the condition that selects it ('for the passage around the highlight'). This is exactly the when-to-use-the-other routing an agent needs to choose correctly between the two sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_bookDescribe a bookARead-only
Describe a specific book in detail — metadata (title, author, genre,
page count), reading status (progress, last opened, finished date),
and annotation count. Also whether the chapter tools can read its
text (Readable text:, and why not), and an Open in Books:
link (ibooks://assetid/...) that opens it in Apple Books.
Args: book_id: The book's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| book_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuine context beyond that: the specific categories of returned data, a 'Readable text:' field explaining whether chapter tools can extract the text (and why not), and the ibooks:// link format. It stops short of describing any limits, but for a read-only lookup this is solid additional value.
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?
Front-loaded with the core purpose, then details of the return content, then args. Every sentence contributes, particularly given there is no output schema. The Args section is slightly mechanical but not wasteful.
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 carries the full burden of explaining return values, and it does so thoroughly (metadata fields, reading progress, annotation count, readability, link). For a one-parameter read tool nothing essential is missing.
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 0%, so the description must compensate. It documents the single parameter as 'the book's numeric ID', which clarifies identity but largely restates what the integer type in the schema already conveys. Adequate but minimal.
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 (describe) and resource (a specific book), then enumerates exactly what the description returns: metadata, reading status, annotation count, text readability, and an Open in Books link. This clearly separates it from list/search siblings like list_all_books and search_books.
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 phrase 'Describe a specific book' implies it is used when you already have a book_id and want full detail on one book, but there is no explicit when-to-use, when-not-to-use, or named alternative (e.g., versus search_books or list_all_books). Usage is implied rather than guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
describe_collectionDescribe a collectionBRead-only
Describe a specific collection in detail — title, details text, and the books contained in it.
Args: collection_id: The collection's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| collection_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds that the result includes title, details text, and contained books, which is useful content context but not deeper behavioral detail (no pagination, size, or error notes).
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?
Front-loaded with the purpose, then lists what is returned and the single argument. No wasted sentences, though the 'Args:' block format is boilerplate rather than flowing 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 single-parameter, read-only lookup with no output schema, the description tells the agent what it does and what it returns. Only the missing routing against sibling list/get tools keeps it from being fully 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 0%, so the description must carry the parameter. It contributes 'The collection's numeric ID', clarifying the type/format beyond the bare 'Collection Id' title, but offers nothing further such as where to obtain the ID.
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 ('Describe') and resource ('collection'), plus the fields returned (title, details text, books contained). It does not distinguish itself from the sibling get_collection_books, whose name suggests overlapping content, so sibling differentiation is missing.
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 use this versus get_collection_books, list_all_collections, or search_collections_by_title. The agent must infer usage 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.
get_annotation_contextGet the passage around a highlightARead-only
Return the passage around a specific highlight — the text before
and after, with the highlight itself wrapped in «...». Use
this to expand on a highlight without fetching the whole chapter.
Works for non-DRM EPUBs downloaded to this Mac; fails with a clear message for DRM-protected books, iCloud-only books, or older annotations that lack the chapter hint.
Args: annotation_id: The annotation's numeric ID. chars_before: Chars of context before the highlight (0–5000). Default 500. chars_after: Chars of context after the highlight (0–5000). Default 500.
| Name | Required | Description | Default |
|---|---|---|---|
| chars_after | No | ||
| chars_before | No | ||
| annotation_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnlyHint and openWorldHint. The description adds substantial behavioral context beyond that: the «...» output formatting convention and explicit failure modes (DRM-protected, iCloud-only, or older annotations lacking the chapter hint) with promises of a clear error message.
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 limitation notes are front-loaded and earn their place; the Args block is warranted given 0% schema coverage. Slightly verbose in formatting but no wasted sentences.
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 correctly explains the return format (surrounding text with the highlight marked) plus failure modes. For a 3-param read tool with annotations covering safety, nothing essential is missing.
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 0%, so the description bears full burden, and it delivers: annotation_id is identified as the numeric ID, and both chars_before and chars_after are documented with bounds (0–5000) and a default of 500. This fully compensates for the schema gap.
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 ('Return the passage around a specific highlight') and clarifies the scope (text before/after with the highlight wrapped in «...»). This clearly distinguishes it from siblings like describe_annotation or get_chapter_content, which fetch metadata or full chapters.
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 explicit usage context: 'Use this to expand on a highlight without fetching the whole chapter.' This tells the agent when to prefer this over a heavier fetch, though it does not name a specific sibling alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_annotations_by_date_rangeAnnotations by date rangeARead-only
Annotations created within a date range, newest first by default. Flat rows with the creation time and book name inline. Dates and times are in the Mac's local time zone, named in the header.
Row format::
YYYY-MM-DD HH:MM [id] text — chapter · Book TitleArgs:
after: Only include annotations created on or after this date
(YYYY-MM-DD, or YYYY-MM-DDTHH:MM).
before: Only include annotations created on or before this
date (YYYY-MM-DD covers the whole day, or YYYY-MM-DDTHH:MM).
limit: Max annotations to return (1–500, default 50).
offset: Annotations to skip, for paging.
order_by: newest (default) or oldest first.
| Name | Required | Description | Default |
|---|---|---|---|
| after | No | ||
| limit | No | ||
| before | No | ||
| offset | No | ||
| order_by | No | newest |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, covering safety. The description adds genuinely non-obvious behavior: timestamps are in the Mac's local time zone, 'newest' is the default order, and the exact row rendering (date, id, text, chapter, book title). No pagination limits or error behavior for malformed dates are disclosed.
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?
Front-loaded with the one-line purpose, then the return format, then a compact Args block — a sensible order for an agent. Slightly verbose in the repeated 'Only include annotations created on or after/before this date' phrasing, but nothing is wasted.
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 correctly compensates by documenting the row format and time zone, and it covers all five optional parameters. It is complete enough to call correctly; the missing pieces are sibling routing and what happens on invalid or inverted date ranges.
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 0%, so the description carries the full burden and does so: it documents accepted formats for after/before (YYYY-MM-DD vs YYYY-MM-DDTHH:MM, including the whole-day rule for before), the limit range 1–500 with default 50, offset as a paging skip, and the order_by semantics. Every parameter is meaningfully specified beyond its bare schema type.
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+resource with scope: annotations filtered by creation date range, ordered newest first. That scope distinguishes it from unfiltered siblings like list_all_annotations, but the description never names an alternative, so the agent must infer the split from sibling names alone.
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 when-to-use or when-not-to-use guidance is given, and no alternative is named despite several overlapping siblings (search_annotations, recent_annotations, list_all_annotations, list_annotations). The date-range framing implies a use case but the agent is left to infer routing entirely.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_books_by_genreFind books by genreARead-only
Get books whose genre matches the given string (substring match).
Output is one row per match: [id] title by author (genre).
Args: genre: The genre to search for (e.g. "Romance", "Philosophy"). limit: Max books to return (1–500, default 200). offset: Books to skip, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| genre | Yes | ||
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description meaningfully adds the substring-match semantics, the exact output row shape, and the 1-500 limit range, which go beyond structured 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?
Well front-loaded: purpose first, then output format, then args. Every line earns its place with no filler, though the prose is slightly verbose in the arg section.
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 supplies the return row format, and it documents all parameters plus pagination. Read-only behavior is covered by annotations. Adequate and nearly complete for this tool.
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 0%, so the description must carry the load, and it documents all three parameters: genre with concrete examples, limit with max and default (1-500, default 200), and offset as a paging offset. It adds constraints not present in 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+resource ('Get books whose genre matches') and clarifies it is a substring match, which is more precise than the bare name. It does not explicitly name a sibling such as search_books or list_all_books to differentiate, so it falls 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?
Usage is implied by the genre-search framing, but there is no explicit when-to-use guidance or when to prefer this over search_books / list_all_books. No exclusions or alternative routing are provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_books_in_progressBooks in progressARead-only
Get books currently being read (progress > 0% and < 100%). Output
per row: [id] title by author with a progress summary below.
Args: limit: Max books to return (1–500, default 200). offset: Books to skip, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds useful return-format detail ('[id] title by author' rows plus a progress summary) that the annotations do not provide. It stops short of describing ordering or pagination edge 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?
Three short lines, purpose front-loaded, then output shape, then args. No filler or restated title.
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 read-only filtered list with no output schema, the description supplies the filter semantics, the return row format, and both parameters' meaning. Nothing an agent needs to call it correctly is missing.
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 0%, so the description carries the burden, and it does explain both parameters: limit with its 1–500 range and 200 default, and offset framed as paging. The schema only lists names and defaults, so this adds real meaning, though it omits what happens when offset exceeds the result count.
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 ('Get books currently being read') and pins the scope precisely with the progress filter (>0% and <100%), which cleanly separates it from siblings like get_finished_books, get_unstarted_books, and get_recently_read_books. It also previews the output shape.
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 inclusion criteria make the when-to-use condition clear: books with partial progress. However, it never names an alternative tool (e.g. use get_finished_books for completed items) or states exclusions, so routing is inferred from the filter rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_chapter_contentGet chapter textARead-only
Return the plain-text content of a chapter, paginated by default
to protect the context window. Get chapter_id from
list_book_chapters or from the (ch=...) suffix on
annotation listing rows, or pass "current" (the default) for
the chapter the user is reading in Apple Books. Works for non-DRM
EPUBs downloaded to this Mac.
Default max_chars=10000 (~2500 words) fits most chapters in
one call. Longer chapters return a slice with a footer naming
the exact offset to pass next. At most 50000 chars are
returned per call.
Every response ends with a footer like one of::
(full chapter returned: 4,872 chars.)
…(returned chars 0–10000 of 24,311 [10000 chars]. Call again with
offset=10000 to continue; 14,311 chars remaining.)
(returned chars 20000–24311 of 24311 [4311 chars]. End of chapter.)Args:
book_id: The book's numeric ID.
chapter_id: Chapter identifier, the 1-based chapter order as a
string (e.g. "5"), or "current" (the default): the
chapter of the user's reading position. A chapter whose id
is literally "current" wins.
offset: Character offset to start from. Defaults to 0.
max_chars: Max chars to return (1–50000). Default 10000.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | ||
| book_id | Yes | ||
| max_chars | No | ||
| chapter_id | No | current |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations only cover readOnlyHint and openWorldHint; the description adds substantial behavior beyond that: default pagination, the 50000-char hard cap, what the footer looks like and how to continue, the 'current' reading-position semantics, and the non-DRM EPUB limitation. These are exactly the traits an agent needs to call it correctly.
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?
Front-loaded with purpose, then pagination behavior, then args. Slightly long due to three footer examples, but each illustrates a distinct return state (full, mid-chapter, end-of-chapter), so the space is largely earning 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?
No output schema exists, yet the description documents the return shape via footer examples and continuation semantics, and contextualizes input sources. Nothing an agent needs to call this correctly is missing.
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 0%, so the description carries the load — and it does: book_id, chapter_id (1-based order, "current" default, literal-'current' edge case), offset (start position), and max_chars (1–50000 range, 10000 default). All four parameters are meaningfully documented.
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+resource: 'Return the plain-text content of a chapter.' It also scopes itself immediately via 'paginated by default' and 'Works for non-DRM EPUBs,' which distinguishes it from the listing/routing siblings like list_book_chapters.
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?
Gives clear routing context: 'Get chapter_id from list_book_chapters or from the (ch=...) suffix on annotation listing rows, or pass "current".' This tells the agent where inputs come from, but stops short of stating when to avoid this tool or an alternative to prefer.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_collection_booksList a collection's booksARead-only
List the books in a collection as lean rows: [id] title by author. Descriptions are intentionally omitted — collections
with many books would otherwise emit tens of thousands of chars of
marketing blurb. Use describe_book(id) for details on any
specific book.
Args: collection_id: The collection's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| collection_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuine behavioral value by disclosing the return format (lean rows) and the deliberate omission of descriptions, explaining the tradeoff. It stops short of noting pagination or ordering.
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?
Front-loaded with the core behavior, then a justified sentence on the omitted descriptions, then the alternative. No wasteful padding; the explanation of the lean-row design 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?
No output schema exists, but the description compensates by specifying the exact return shape ('[id] title by author') and pointing to describe_book for richer data. Nothing needed to call or interpret the result is missing.
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 0%, so the description must carry parameter meaning, and it does document collection_id as 'the collection's numeric ID'. With a single, simple required parameter this is sufficient, though it adds little beyond the schema's integer type.
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 ('List the books in a collection') and even specifies the exact output shape ('[id] title by author'). It clearly distinguishes itself from siblings like list_all_books and describe_book.
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 routes the agent: use describe_book(id) when details on a specific book are needed, and implies a lightweight listing here. The condition for choosing the alternative is stated, not left to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_current_reading_positionCurrent reading positionARead-only
Return where the user last left off reading a book — chapter
title and chapter_id, no text — and an Open in Books: link to
the book. Follow up with get_chapter_content for the text.
Works for non-DRM EPUBs downloaded to this Mac. If Apple Books hasn't recorded a position, falls back to inferring from the user's most recent highlight (labeled as such in the output).
Args: book_id: The book's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| book_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnlyHint=true, openWorldHint=false), yet the description adds real behavioral context: a platform/format limitation, and a fallback path that infers position from the most recent highlight and labels it as such. The only omitted details are error behavior for a missing/invalid book_id.
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?
Front-loaded with the core return value, then the follow-up action, then applicability limits, then the arg. Every sentence carries new information with no filler.
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 appropriately describes the returned fields and the fallback labeling, so an agent knows what it will receive. Missing only failure-mode guidance (unknown book_id, DRM books) for full completeness.
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 0%, so the description carries the burden, and it does: 'book_id: The book's numeric ID' clarifies the expected type beyond the bare integer title. It adds little else (no ID discovery pointer), so it is helpful but not exhaustive.
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 ('Return where the user last left off reading a book') and enumerates exactly what comes back (chapter title and chapter_id, no text) plus an Open in Books link. Combined with the routing hint to get_chapter_content, an agent can distinguish this from sibling chapter/annotation tools 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?
The description gives an explicit chaining instruction ('Follow up with get_chapter_content for the text') and scopes applicability ('Works for non-DRM EPUBs downloaded to this Mac'). It stops short of naming sibling alternatives such as get_books_in_progress, but the use condition is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_finished_booksFinished booksARead-only
Get books that have been finished. Output per row: [id] title by author with a progress summary below.
Args: limit: Max books to return (1–500, default 200). offset: Books to skip, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds genuinely new behavioral context beyond the annotations: the exact per-row output shape ('[id] title by author') plus a progress summary, which an agent needs to parse results. It stops short of describing ordering or the progress summary's contents.
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 first sentence front-loads the purpose and output format, and the Args block is compact. It is well-sized for a two-parameter list tool, though the bare 'Args:' block is slightly boilerplate.
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 usefully compensates by specifying the return row format, and it covers both parameters. Missing pieces are sort order and what the 'progress summary' contains, which would matter for an agent assembling a reading-status answer.
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 0%, so the description must carry parameter meaning and it largely does: limit is documented with its range (1–500) and default (200), and offset is explained as a paging skip count. The only gap is that offset's bounds and the meaning of the default are not stated.
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 ('Get books that have been finished'), which is immediately distinguishable from in-progress/unstarted siblings by the status qualifier. It does not, however, explicitly name or contrast with the nearest siblings (get_books_in_progress, get_recently_read_books), so it falls short of the top score.
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 when-to-use or when-not-to-use guidance is given; the agent must infer from the tool name that this is the status-filtered list and not, say, get_recently_read_books. Usage is implied rather than stated, and no exclusions or alternatives are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_highlights_by_colorHighlights by colorARead-only
Browse highlights of a particular color, grouped by book.
Output is one row per highlight: [id] text — chapter. The
book's name is shown once in the header, with a count of matching
highlights on this page.
Args:
color: yellow, green, blue, pink, or purple.
limit: Max annotations to return (1–500, default 50).
offset: Annotations to skip, for paging.
order_by: newest (default) or oldest first.
| Name | Required | Description | Default |
|---|---|---|---|
| color | Yes | ||
| limit | No | ||
| offset | No | ||
| order_by | No | newest |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description still earns credit by disclosing the actual return shape (one row per highlight as [id] text — chapter, book name in header with a page count) and by explaining that limit/offset drive paging, which is real behavioral context for a tool with no output schema.
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?
Purpose is front-loaded in the first line, followed by a compact output-format explanation and a clean Args block. Every sentence carries information and nothing is padded.
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 helpfully describes the rendered result and documents all four parameters, so an agent has enough to call it correctly. It stops short of routing between this tool and the other annotation-listing siblings, which is the one remaining gap.
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 0%, so the description carries the burden and largely does: it names the color values, gives the limit range (1–500) and default, explains offset as paging, and lists the order_by options with defaults. Only minor value is added beyond the enum lists already present in 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 (browse) and resource (highlights) scoped by color and grouping by book, so the agent knows exactly what it returns. It does not, however, contrast itself with near-siblings like list_annotations, search_annotations, or recent_annotations, so differentiation relies on the name alone.
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?
Usage is only implied: an agent can infer it is the tool for pulling highlights of one color, but there is no explicit when-to-use statement, no mention of when a sibling like search_annotations would be preferable, and no prerequisite or exclusion guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_library_statsLibrary statsARead-only
Get a summary of your Apple Books library with reading stats.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds only the hint that output is a 'summary ... with reading stats', without saying what is aggregated, whether counts are lifetime or filtered, or whether the result is cheap to call repeatedly.
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 or redundancy. Nothing could be trimmed without losing information.
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 present, the description carries the burden of describing the return value, and 'summary ... with reading stats' is too vague to tell an agent what fields or metrics come back. Given the tool is a zero-param, low-risk read, this is adequate but leaves an information gap.
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?
The tool takes zero parameters, so the baseline of 4 applies. There is nothing in the schema for the description to clarify, and it correctly does not invent 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?
States a clear verb (Get) and resource (summary of Apple Books library with reading stats). It is implicitly distinct from the many list/search siblings because it is the only aggregate/summary tool, but the description never explicitly contrasts itself with the per-book or per-collection listing 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?
Usage is only implied: an agent can infer you call this for an overview rather than a filtered list, but no when-to-use or when-not-to-use condition is stated, and no alternative sibling is named (e.g. get_books_in_progress, get_finished_books).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recently_read_booksRecently read booksARead-only
Get the most recently read books, newest first (by when each was
last opened or read, whichever is later).
Output per row: [id] title by author with a progress summary
below.
Args: limit: Max books to return (1–500, default 10). offset: Books to skip, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds value beyond that by disclosing the return shape per row ('[id] title by author' plus a progress summary) and the exact sort key, which annotations cannot express.
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?
Purpose and ordering come first, the output format follows, and the two parameters are listed compactly. Every sentence carries information with no padding or repetition of the title.
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 correctly compensates by describing the per-row format and progress summary, and it documents both parameters. It lacks interaction notes (e.g., behavior when offset exceeds results or how progress is computed), so it is strong but not exhaustive.
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 0%, so the description must carry the parameters, and it does: limit is documented with its 1-500 range and default of 10, and offset is identified as the paging offset. The offset explanation ('Books to skip, for paging') is thin and omits its default, keeping this under a 5.
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 ('Get the most recently read books') and pins down the ordering rule (last opened or read, whichever is later), which separates it from siblings like get_books_in_progress or get_finished_books. It doesn't explicitly name an alternative tool, 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?
The sort semantics imply when this tool is appropriate (surfacing recent activity), but there is no explicit when-to-use/when-not guidance and no mention of alternatives such as list_all_books or get_books_in_progress. Usage is inferable but not directed.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_unstarted_booksUnstarted booksARead-only
Get books that haven't been started yet (0% progress). Output per
row: [id] title by author with a progress summary below.
Args: limit: Max books to return (1–500, default 200). offset: Books to skip, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description goes beyond them by disclosing the return shape per row ('[id] title by author' with a progress summary) and that offset exists for paging — real behavioral context, especially useful with no output schema.
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?
Front-loaded summary sentence followed by a compact Args block; no filler. The Args section partially restates schema defaults, but the added range and output format justify the length.
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 and no annotation coverage of results, the description supplies the output format itself, plus the result cap and paging mechanism. Nothing essential for calling this read-only list tool is missing.
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 0%, so the description must carry the parameters, and it does: both limit and offset are explained. It adds the 1–500 bound for limit, which the schema omits (only a default of 200 is present), and clarifies offset's paging role.
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+resource ('get books') and pins the scope with a precise filter: 'haven't been started yet (0% progress)'. That filter implicitly separates it from get_books_in_progress and get_finished_books, though those siblings are never named 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?
The 0%-progress filter implies when to reach for this tool versus the in-progress/finished variants, but there is no explicit when-to-use, when-not-to-use, or named alternative. Usage must be inferred from the scope definition alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_all_annotationsList all annotationsARead-only
Browse all annotations grouped by book, most recent first. Rows:
[annotation_id] <text> — <chapter title> (ch=<id>), with the
user's note, if any, on a second line prefixed with ↳ note:.
Pass ch=<id> to get_chapter_content for the chapter, or
call get_annotation_context(annotation_id) for the passage
around a specific highlight.
Args: limit: Max annotations to return (1–500, default 50). offset: Annotations to skip, for paging; a footer names the next offset when there are more.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuine value beyond that: the exact row rendering, the note prefix convention, and the footer that names the next offset, all of which shape how the agent consumes results.
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?
Front-loaded with purpose and output shape, then arguments. Dense but every element (row template, note prefix, paging footer, range) informs correct invocation; nothing is padding.
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?
No output schema exists, so the description rightly specifies the return format and paging footer. Combined with the argument docs, an agent has enough to call and interpret the tool; only the lack of explicit alternative-routing keeps it from full marks.
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 0%, so the description must carry the parameters, and it does: 'limit' is given a range (1-500) and default (50), and 'offset' is explained as the skip count for paging. The 1-500 range is information found nowhere in 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+resource ('Browse all annotations') plus grouping ('by book') and ordering ('most recent first'), which distinguishes it from filtered siblings like search_annotations. It does not explicitly contrast against the closely-named list_annotations or recent_annotations, so it stops short of full sibling differentiation.
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 downstream workflow context (pass ch=id to get_chapter_content, call get_annotation_context for a passage) and paging behavior, but never states when to choose this over search_annotations, recent_annotations or get_annotations_by_date_range. Usage is implied rather than framed against alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_all_booksList all booksARead-only
List all books in my Apple Books library. Output is one row per
book: [id] title by author. Use describe_book(id) for
details on any book.
Args: limit: Max books to return (1–500, default 200). offset: Books to skip, for paging; a footer names the next offset when there are more.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered; the description adds useful behavior beyond that, disclosing the exact row format and the pagination footer that names the next offset. It stops short of stating auth needs or ordering guarantees, but adds real value over 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?
Front-loaded with the core action, followed by output shape, the alternative tool, then args. Three compact blocks with no filler sentences.
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?
No output schema exists, yet the description supplies the return format and paging semantics, and parameters are fully specified. Nothing an agent needs to call this correctly is missing.
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 0%, so the description must carry the parameter burden and does: limit is bounded (1–500, default 200) and offset is explained as paging with a footer naming the next offset when more results exist. This is meaning well beyond the bare integer properties in 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 and resource ('List all books in my Apple Books library') and the scope word 'all' implicitly separates it from filtered siblings such as search_books, get_books_by_genre, and get_books_in_progress. The one-line output format ('[id] title by author') further pins down what this tool returns.
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 routes the agent onward: 'Use describe_book(id) for details on any book.' However, it never states when to prefer this over search_books or get_collection_books, so it gives a clear follow-up path but no exclusions among the many list/search siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_all_collectionsList collectionsARead-only
List all collections in my Apple Books library. Output is one row
per collection: [id] title. Use describe_collection(id) for
details or get_collection_books(id) to list its books.
Args: limit: Max collections to return (1–500, default 200). offset: Collections to skip, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so safety is covered. The description adds genuinely new behavioral context: the row-per-collection output format (`[id] title`) and that offset enables paging, which the annotations do not convey.
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?
Front-loaded with purpose, then output shape, then alternatives, then args — a logical order with no wasted prose. The Args block slightly duplicates defaults already in the schema, but the added range justification 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 read-only list tool with no output schema, the description supplies the missing return-format detail (`[id] title`), pagination guidance, and sibling routing. Nothing an agent needs to invoke it correctly is absent.
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 0%, so the description must carry the burden, and it does: it explains limit (range 1–500, default 200) and offset ('collections to skip, for paging'). The 1–500 range is meaningful added detail not present in the bare integer schema, though the default values merely repeat 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 (List) and resource (all collections in the Apple Books library) with an explicit scope of 'all'. This cleanly distinguishes it from filtered siblings like search_collections_by_title and the detail-oriented describe_collection.
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?
Names the follow-up alternatives explicitly ('describe_collection(id) for details', 'get_collection_books(id) to list its books'), giving clear routing context. It does not state when to prefer search_collections_by_title over this enumeration, so it stops short of the full when/when-not bar.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_annotationsList a book's annotationsARead-only
List annotations within a specific book in reading order (their
position in the book). Rows are lean —
[annotation_id] <text> — <chapter> (ch=<id>) — with the user's
note, if any, on a second line prefixed with ↳ note:.
Args: book_id: The book's numeric ID. limit: Max annotations to return (1–500, default 50). offset: Annotations to skip, for paging; a footer names the next offset when there are more.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No | ||
| book_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
readOnlyHint=true and openWorldHint=false already establish the safety profile, so the bar is lower. The description adds real value beyond them: the exact row layout, the second-line note prefix, and the pagination-footer behavior ('a footer names the next offset when there are more') are behavioral details not available in 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?
The purpose is front-loaded and the Args block is tightly scoped. The inline row-format snippet is slightly heavy but earns its place by telling the agent what the return text looks like.
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 lean, no-output-schema, read-only list tool, the description is complete: it covers the return format, note handling, and the pagination contract an agent needs to page correctly.
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 0%, so the description carries full burden and does: book_id as numeric ID, limit as 1-500 with default 50, and offset explained as a skip count for paging. All three parameters gain meaning beyond the bare schema types.
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 with an explicit scope: 'List annotations within a specific book in reading order'. The 'within a specific book' qualifier implicitly separates it from list_all_annotations, but it never names a sibling, 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?
Usage is only implied by the per-book scoping. The description never says when to prefer this over list_all_annotations, search_annotations, recent_annotations, or get_annotations_by_date_range, nor does it state prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_book_chaptersList a book's chaptersARead-only
List the table of contents for a book — chapter titles, order, and nesting depth. Only works for non-DRM EPUBs that have been downloaded to this Mac.
Args:
book_id: The book's numeric ID (from list_all_books or similar).
| Name | Required | Description | Default |
|---|---|---|---|
| book_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuinely useful context beyond that: the DRM and local-download constraints that determine success or failure. It stops short of describing failure behavior for nested/edge-case EPUBs, so not a 5.
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, the return contents, and the key constraint all appear in the first two lines, followed by a compact Args block. No filler.
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?
No output schema exists, so the description is responsible for the return shape, and it does describe the TOC fields. Combined with the precondition note, an agent has enough to call it correctly, though nothing is said about empty results or chapters-without-TOC cases.
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 0% on a single parameter, so the description must carry the burden — and it does, stating the ID is numeric and pointing to list_all_books as the source. It is slightly under-specified on whether the ID is a library ID versus an external identifier.
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 ('List the table of contents for a book') and immediately enumerates the returned fields (titles, order, nesting depth), which cleanly separates it from the sibling get_chapter_content that fetches chapter bodies.
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?
Gives a clear precondition — only non-DRM EPUBs already downloaded to this Mac — which tells the agent when the tool will fail. It does not name an alternative tool or explicitly route the agent elsewhere, so it falls short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
recent_annotationsRecent annotationsARead-only
Most recent annotations, newest first. Flat rows with the creation time (the server's local time zone) and book name inline so Claude can see chronology across books at a glance.
Row format::
YYYY-MM-DD HH:MM [id] text — chapter · Book TitleArgs: limit: Max annotations to return (1–500, default 10). offset: Annotations to skip, for paging.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true and openWorldHint=false, and the description usefully adds that timestamps are in the server's local time zone plus the exact row layout returned. It does not cover edge behavior such as what happens with an out-of-range offset or an empty result set, keeping it below a 5.
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?
Front-loaded with the one-line summary, then a format block, then args. Every element is relevant, though the multi-line row-format example is slightly more elaborate than needed for a two-parameter read 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?
With no output schema, describing the row format is the right call, and both parameters are fully documented. Minor gaps remain around empty-result and paging-limit behavior, but an agent has enough to invoke the tool correctly.
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 0%, so the description carries the full burden, and it does: 'limit' is documented with a range (1-500) and default (10) that the schema lacks, and 'offset' is explained as a paging skip count.
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 resource ('annotations') with a clear recency scope and ordering ('Most recent ... newest first'). This distinguishes it in spirit from list_all_annotations and search_annotations, though it never names those siblings explicitly, so it falls 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?
The phrase 'so Claude can see chronology across books at a glance' implies the browsing use case, but there is no explicit when-to-use or when-not-to-use guidance relative to list_annotations, list_all_annotations, or search_annotations. Usage is inferable but not stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_book_from_collectionRemove a book from a collectionADestructiveIdempotent
Remove a book from a collection (the book stays in the library). Idempotent. Requires write access and Books to be quit.
Args: collection_id: The collection's numeric ID. book_id: The book's numeric ID.
| Name | Required | Description | Default |
|---|---|---|---|
| book_id | Yes | ||
| collection_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare destructiveHint=true and idempotentHint=true, so 'Idempotent' repeats structured data. However, the description adds value the annotations don't carry: the precondition 'Requires write access and Books to be quit' and the scope note that the book survives the removal. These are genuine behavioral context beyond the structured fields.
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?
Front-loads the core action and its key scope caveat in the first sentence, then layers idempotence and prerequisites. The Args block restates parameter names already present in the schema, which is mildly redundant but keeps the definition self-contained and scannable.
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 2-param destructive tool with no output schema, the description covers the essentials: what happens (unlink, not delete), the precondition (write access, Books quit), and idempotence. Nothing critical for correct invocation is missing, though return/error behavior is unstated.
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 0%, so the description must carry parameter meaning, and it does document both required params (collection_id and book_id) as numeric IDs. This compensates for the schema gap, though the detail is thin – no format, bounds, or example values beyond 'numeric ID'.
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 ('Remove a book from a collection') and immediately disambiguates scope with '(the book stays in the library)'. This distinguishes it from delete_collection and from destructive library-level operations, so an agent can place it correctly without opening a sibling 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?
The parenthetical clarifies what the tool does NOT do (the book isn't deleted), which implicitly contrasts with destructive siblings, but there is no explicit when-to-use guidance or named alternative (e.g., add_book_to_collection or delete_collection). Usage is implied rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
rename_collectionRename a collectionADestructiveIdempotent
Rename a user-created collection (built-in collections are refused). Requires write access and Books to be quit.
Args: collection_id: The collection's numeric ID. new_title: The new name.
| Name | Required | Description | Default |
|---|---|---|---|
| new_title | Yes | ||
| collection_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the safety profile (readOnly=false, idempotent=true, destructive=true). The description adds operational context beyond them: write access required, the app must be quit, and built-in collections are rejected. It does not describe reversibility or return behavior, keeping it below top marks.
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?
Front-loaded first sentence carries the key scope, followed by prerequisites and a compact Args block. Slight redundancy between the title/name and the Args labels, but nothing wasteful.
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 two-param mutation with annotations covering safety and no output schema, the description supplies the needed preconditions and both parameter meanings. Only minor gaps remain (no statement of what happens to the old title or 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 description coverage is 0%, so the description must carry the params. It documents both: collection_id as the numeric ID and new_title as the new name, which meaningfully clarifies semantics the bare schema titles do not.
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+resource ('Rename a ... collection') and immediately scopes it ('user-created ... built-in collections are refused'). This clearly separates it from siblings like create_collection, delete_collection, and describe_collection.
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?
Gives a clear exclusion (built-in collections are refused) plus prerequisites (write access, Books must be quit). It does not name alternative tools, but the operation's context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_annotationsSearch annotationsARead-only
Search across every annotation field — selected (highlighted) text,
the surrounding paragraph, and the user's note body. Grouped by
book; a row's note, if any, is on a second line prefixed with
↳ note:. Use search_notes when you only want to find your
own written notes.
Args:
text: Substring to match anywhere in an annotation.
limit: Max annotations to return (1–500, default 50).
offset: Annotations to skip, for paging.
order_by: newest (default) or oldest first.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | ||
| limit | No | ||
| offset | No | ||
| order_by | No | newest |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description adds genuine behavioral context beyond that: results are grouped by book and a row's note appears on a second line prefixed with '↳ note:'. It doesn't state whether a total count is returned for paging, a minor gap.
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?
Purpose and output format are front-loaded before the alternative and the Args block. Every sentence carries information, though the docstring-style Args section duplicates what a well-documented schema would hold, adding slight 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 read-only search tool with no output schema, the description covers purpose, result grouping/format, the sibling alternative, and all four parameters. It stops short of noting pagination totals or result-size expectations, but nothing critical to correct invocation is missing.
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 0%, so the description carries the full burden and does so completely: text is 'Substring to match anywhere', limit is '1–500, default 50', offset is 'Annotations to skip, for paging', and order_by is 'newest (default) or oldest'. All four parameters gain meaning not present in the bare 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 (search) and resource (annotations) plus the scope of the search: 'across every annotation field — selected text, the surrounding paragraph, and the user's note body.' It also explicitly distinguishes itself from the sibling search_notes, so an agent can tell them apart without opening either 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?
Names the key alternative with a selecting condition: 'Use search_notes when you only want to find your own written notes.' However, it gives no guidance relative to other annotation siblings like list_annotations, recent_annotations, or get_annotations_by_date_range, so routing is only partial.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_booksSearch books by title or authorARead-only
Search for books whose title or author contains query, ignoring
case, accents and quote/dash style ("don't" finds "Don’t", "godel"
finds "Gödel"). Output is one row per book, by book id:
[id] title by author. Use describe_book(id) for details.
Args: query: Text to find in the title or the author's name. limit: Max books to return (1–500, default 200). offset: Books to skip, for paging; a footer names the next offset when there are more.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| query | Yes | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish this as a safe read (readOnlyHint=true, openWorldHint=false), so the bar for added context is met by real substance: case/accent/quote-dash-insensitive matching, the one-row-per-book output shape, and the paging footer behavior. This discloses matching semantics and return behavior that no annotation or schema field conveys.
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?
Purpose and matching behavior are front-loaded in the first sentence, then output format, then the sibling pointer, then per-arg docs. Slight redundancy between the prose output note and the Args block, but with 0% schema coverage the Args section earns its space.
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, so the description correctly compensates by describing the return format (``[id] title by author``) and the paging footer. Combined with full parameter docs and the describe_book handoff, an agent has everything needed to call and interpret this tool.
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 0%, so the description carries the full parameter burden and does so completely: ``query`` semantics (matched against title or author), ``limit`` bounds and default (1–500, default 200), and ``offset`` meaning plus the footer hint that reveals the next offset. Every parameter gets meaning and constraints absent from 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?
The description states a specific verb and resource plus scope: books whose title OR author contains the query, with normalization rules spelled out. It implicitly separates itself from the title-only sibling, but never names ``search_books_by_title``, so an agent must infer which of the two overlapping search tools to pick.
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 clear routing guidance for the follow-up step ('Use ``describe_book(id)`` for details') and explains when paging applies (the footer names the next offset when there are more). What it lacks is an explicit when-not statement against the near-identical sibling ``search_books_by_title`` or the broader ``list_all_books``.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_books_by_titleSearch books by titleARead-only
Search for books by title (substring match, ignoring case, accents
and quote/dash style). Output is one row per match: [id] title by author. Use describe_book(id) for details, and
search_books to match authors too.
Args: title: The title to search for. limit: Max books to return (1–500, default 200). offset: Books to skip, for paging; a footer names the next offset when there are more.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| title | Yes | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, but the description adds non-obvious behavior: substring matching that ignores case, accents, and quote/dash style; one-row-per-match output format; and paging via a footer that names the next offset. These details meaningfully exceed the annotation coverage.
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?
Front-loads purpose, match semantics, and output format before alternatives and parameters. No redundant or filler sentences; the Args block is compact.
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?
Complete for a read-only search tool with no output schema: return row format, match rules, paging, and alternative tools are all specified. Nothing an agent needs to call correctly is missing.
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 0%, so the description carries the full burden. It documents all three parameters: title (what to search), limit (range 1–500, default 200), and offset (paging behavior with footer guidance). The added range and paging semantics are valuable beyond the bare schema types.
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?
Starts with a specific verb and resource ('Search for books by title'), details the matching semantics (substring, case/accent/quote-dash insensitive), and names the output shape. It distinguishes itself from the sibling search_books by noting that tool also matches authors.
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 directs to describe_book(id) for details and search_books for author matching, giving clear alternative tools. However, it does not state when not to use this tool (e.g., for genre or status filtering) or provide broader when-to-use beyond title lookup.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_collections_by_titleSearch collections by titleARead-only
Search for collections by title (substring match). Output is one
row per match: [id] title.
Args: title: The title to search for.
| Name | Required | Description | Default |
|---|---|---|---|
| title | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false, so the safety profile is covered. The description goes further by disclosing the exact output shape ('one row per match: [id] title'), which is valuable because no output schema exists. It omits matching behavior details like case sensitivity or result limits.
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?
Front-loaded with the core action and matching mode, then a compact output-format statement. The Args block is largely redundant given the single obvious parameter, but it is brief and causes little 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?
With no output schema, the description responsibly covers the return format, and with one simple required parameter the input side needs little more. Missing case-sensitivity, empty-result behavior, and result-count limits are minor gaps for a simple lookup tool.
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 0% and the Args line merely restates the parameter name ('The title to search for'), which is tautological. The body does contribute one real semantic detail — that matching is substring-based rather than exact — which compensates partially for the empty 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?
The description states a specific verb and resource ('Search for collections by title') and adds the matching mode ('substring match'), which meaningfully disambiguates it from list_all_collections and search_books_by_title. It does not explicitly name sibling tools, 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?
There is no statement of when to use this tool versus alternatives such as list_all_collections or search_books_by_title, and no preconditions are given. The agent must infer usage from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_notesSearch notesARead-only
Search user notes (not highlights) by substring, grouped by book.
Output shows the highlighted passage on the primary row and the
matching note on a second line prefixed with ↳ note:.
Args:
note: Substring to find inside note bodies.
limit: Max annotations to return (1–500, default 50).
offset: Annotations to skip, for paging.
order_by: newest (default) or oldest first.
| Name | Required | Description | Default |
|---|---|---|---|
| note | Yes | ||
| limit | No | ||
| offset | No | ||
| order_by | No | newest |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover the read-only safety profile (readOnlyHint=true, openWorldHint=false), so the bar is lower. The description adds genuine behavioral value by disclosing the return layout: highlighted passage on the primary row and matching note on a second line prefixed with '↳ note:'. It does not discuss pagination limits or result caps beyond the limit arg.
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?
Front-loaded purpose followed by output format and then a compact args list; every sentence carries information. The docstring-style arg block with literal backticks is slightly awkward but not wasteful.
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, so the description appropriately steps in to describe the returned row structure, and all parameters are documented. Combined with annotations covering read-only behavior, this is largely complete, though grouping/paging semantics of the output could be clearer.
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 0%, so the description must carry semantics, and it documents all four params: note (substring inside note bodies), limit (1-500, default 50), offset (paging), and order_by (newest/oldest). The 1-500 range and default are constraints the bare schema does not convey, though the note param adds little beyond its name.
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 (search) and resource (notes), scope ('by substring, grouped by book'), and explicitly excludes highlights ('not highlights'), which separates it from the sibling search_annotations. An agent can identify the tool and its boundary 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?
The '(not highlights)' parenthetical hints at the boundary versus other annotation-searching tools, but there is no explicit when-to-use/when-not guidance, no named alternative, and no prerequisites. Usage is only implied.
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.
12 tool updates
v0.9.0- Changed
create_collection2 fields changed- added
Input schema / properties / details / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / details / typeRemoved value: -"string"
- Changed
describe_annotation1 field changed- changed
Input schema / properties / annotation_id / typePrevious value: -"string"New value: +"integer"
- Changed
describe_book1 field changed- changed
Input schema / properties / book_id / typePrevious value: -"string"New value: +"integer"
- Changed
describe_collection1 field changed- changed
Input schema / properties / collection_id / typePrevious value: -"string"New value: +"integer"
- Changed
get_annotations_by_date_range5 fields changed- added
Input schema / properties / after / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / after / typeRemoved value: -"string" - added
Input schema / properties / before / anyOfAdded value: +[ + { + "type": "string" + }, + { + "type": "null" + } +] - removed
Input schema / properties / before / typeRemoved value: -"string" - added
Input schema / properties / order_by / enumAdded value: +[ + "newest", + "oldest" +]
- Changed
get_chapter_content2 fields changed- added
Input schema / properties / chapter_id / defaultAdded value: +"current" - changed
Input schema / requiredPrevious value: -[ - "book_id", - "chapter_id" -]New value: +[ + "book_id" +]
- Changed
get_collection_books1 field changed- changed
Input schema / properties / collection_id / typePrevious value: -"string"New value: +"integer"
- Changed
get_highlights_by_color2 fields changed- added
Input schema / properties / color / enumAdded value: +[ + "yellow", + "green", + "blue", + "pink", + "purple" +] - added
Input schema / properties / order_by / enumAdded value: +[ + "newest", + "oldest" +]
- Changed
search_annotations1 field changed- added
Input schema / properties / order_by / enumAdded value: +[ + "newest", + "oldest" +]
- Added
search_books - Changed
search_books_by_title2 fields changed- added
Input schema / properties / limitAdded value: +{ + "default": 200, + "title": "Limit", + "type": "integer" +} - added
Input schema / properties / offsetAdded value: +{ + "default": 0, + "title": "Offset", + "type": "integer" +}
- Changed
search_notes1 field changed- added
Input schema / properties / order_by / enumAdded value: +[ + "newest", + "oldest" +]
30 tool updates
v0.8.4- First observed
add_book_to_collection - First observed
create_collection - First observed
delete_collection - First observed
describe_annotation - First observed
describe_book - First observed
describe_collection - First observed
get_annotation_context - First observed
get_annotations_by_date_range - First observed
get_books_by_genre - First observed
get_books_in_progress - First observed
get_chapter_content - First observed
get_collection_books - First observed
get_current_reading_position - First observed
get_finished_books - First observed
get_highlights_by_color - First observed
get_library_stats - First observed
get_recently_read_books - First observed
get_unstarted_books - First observed
list_all_annotations - First observed
list_all_books - First observed
list_all_collections - First observed
list_annotations - First observed
list_book_chapters - First observed
recent_annotations - First observed
remove_book_from_collection - First observed
rename_collection - First observed
search_annotations - First observed
search_books_by_title - First observed
search_collections_by_title - First observed
search_notes
TDQS
Scored across 31 tools
Most tools target distinct resources or actions (collections, books, annotations, chapters), and descriptions clarify differences like search_books vs search_books_by_title or list_annotations vs list_all_annotations. However, several listing/searching tools for the same resource overlap somewhat, requiring careful reading to pick the right one.
Names are predominantly snake_case with a clear verb_noun structure (list_, get_, describe_, search_, create_, rename_, delete_, add_, remove_). Minor inconsistencies include 'recent_annotations' lacking a verb prefix and filtered book lists using 'get_' while full lists use 'list_', but the overall pattern is readable.
31 tools is heavy for the domain; many could be consolidated (e.g., the four reading-status book filters, the multiple book search tools, the several annotation listing tools). While the domain is complex, the rubric flags 25+ as too many, and several tools feel redundant.
Read coverage is extensive (books, collections, annotations, chapters, stats), but there are notable gaps in write operations: no tools to create/update/delete annotations or notes, no book metadata editing, no reading progress updates, and no ability to add/remove books from the library. Collection CRUD exists, suggesting write support is intended, so these gaps limit full lifecycle coverage.
Maintenance
Related MCP Connectors
MCP server unifying ERPs, CRMs, APIs and knowledge base for Claude, ChatGPT and Gemini.
Your memory, everywhere AI goes. Build knowledge once, access it via MCP anywhere.
Official Bookmax MCP server: search and save bookmarks, read notes and docs from AI assistants.
1The CustomGPT.ai MCP server is a fully managed, RAG-powered endpoint that connects large language models with private knowledge bases and external data sources. It provides tools for retrieval-augmented generation queries (send_message), data ingestion (upload_file), and source listing, enabling AI agents to query private documents like PDFs with high accuracy and real-time citations.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceEnables AI clients to read and write local Apple Books library, collections, and annotations. Supports searching, exporting, and modifying books and highlights via MCP tools.1MIT
- AlicenseBqualityBmaintenanceA local MCP server that gives Claude a durable reading room for EPUB and plain text books, enabling chunk-by-chunk navigation, annotations, progress tracking, and shared margin cards.26115MIT
- FlicenseNot gradedqualityDmaintenanceMCP server for processing raw book notes into structured, searchable knowledge using embeddings and semantic search.-

Books Mandala MCPofficial
FlicenseNot gradedqualityCmaintenanceMCP server enabling AI assistants to search, browse, and discover books from Books Mandala's live catalog of 50,000+ titles.2-