Skip to main content
Glama

annas-mcp

Tests Release npm annas-mcp MCP server

An MCP server and command-line tool for searching Anna's Archive for books and papers and downloading the file you pick. Use annas-cli in your terminal or connect annas-mcp to Claude, Cursor, Codex and other AI clients.

A paid Anna's Archive membership is required.

Anna's Archive membership

Search through the MCP

Download by file hash or book-page URL

No paid membership

❌

❌

Brilliant Bookworm (cheapest tier)

❌

✅

Lucky Librarian or higher (recommended)

✅

✅

We recommend Lucky Librarian or higher so the AI can both search and download for you. With the basic tier you'll need to manually paste each book download URL.

Disclaimer: I'm not affiliated with Anna's Archive. They were forced to introduce strict anti-scraping limits in 2026 due to massive DDoS attacks, with only paying members exempt.

MCP setup · CLI setup · Go SDK

It signs in with your membership's secret key and renews the session by itself, so you never copy cookies from a browser. If you're coming from iosifache/annas-mcp, switching is a one-line change.

Tool

What it does

book_search

Finds books, textbooks, manuals and standards by title, author or topic, filtered by format, language, source or year; can include file activity counts

article_search

Finds journal articles by keyword, author or year, or looks one up by DOI; can include file activity counts

metadata_search

Searches library catalogs such as Open Library, WorldCat and ISBNdb for editions and ISBNs

book_details

Shows a result's ISBNs and other identifiers, edition, description and reported file problems

account_status

Shows your membership and how many fast downloads are left

book_download

Downloads a book using a file hash or Anna's Archive book-page URL

article_download

Downloads an article by DOI or hash

Use it only for material you are entitled to obtain, under the laws and terms that apply to you.

Go SDK

Go applications can import github.com/SokolskyNikita/annas-mcp/anna for the same search, metadata, account and verified-download operations. See the SDK guide and examples for explicit configuration, errors, timeouts and concurrency. The SDK and applications share this module’s release tags. Requires Go 1.26 or newer; install with go get github.com/SokolskyNikita/annas-mcp/anna@v0.7.0.

Related MCP server: annas-archive-download-mcp

Setup

You need Node.js 18 or newer and an active paid Anna's Archive membership. Lucky Librarian or higher is recommended so both search and downloads work.

Get your secret key

Copy the secret key you log in with from your Anna's Archive account page. It is also your API key (API FAQ).

MCP setup

After getting your secret key, add the server to your client:

Claude Code

claude mcp add annas-mcp \
  --env ANNAS_SECRET_KEY=your-secret-key \
  -- npx -y annas-mcp

On native Windows (not WSL), end the command with -- cmd /c npx -y annas-mcp.

Claude Desktop, one click

Download annas-mcp.mcpb and open it, or drag it onto Settings → Extensions. Claude Desktop asks for your secret key and lets you pick a different download folder.

Claude Desktop or Cursor, by hand

Add this to Claude Desktop's config (Settings → Developer → Edit Config) or to Cursor's ~/.cursor/mcp.json:

{
  "mcpServers": {
    "annas-mcp": {
      "command": "npx",
      "args": ["-y", "annas-mcp"],
      "env": {
        "ANNAS_SECRET_KEY": "your-secret-key"
      }
    }
  }
}

Codex

Add this to ~/.codex/config.toml:

[mcp_servers.annas-mcp]
command = "npx"
args = ["-y", "annas-mcp"]

[mcp_servers.annas-mcp.env]
ANNAS_SECRET_KEY = "your-secret-key"

Gemini CLI

gemini extensions install https://github.com/SokolskyNikita/annas-mcp

Gemini CLI asks for your secret key, which it keeps in the system keychain, then for two optional settings; press Enter to skip them. Change them later with gemini extensions config annas-mcp.

Docker

Build the image straight from this repository:

docker build -t annas-mcp https://github.com/SokolskyNikita/annas-mcp.git

Then have your client run it, mounting your download folder at /downloads:

{
  "mcpServers": {
    "annas-mcp": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "-e", "ANNAS_SECRET_KEY", "-v", "/absolute/path/to/downloads:/downloads", "annas-mcp"],
      "env": { "ANNAS_SECRET_KEY": "your-secret-key" }
    }
  }
}

On Linux, add "--user", "1000:1000" with your own user and group IDs before "annas-mcp", so the container can write to the folder.

Try it

Restart your client and ask something like "Find the EPUB of Pride and Prejudice and download it." The AI searches, picks a copy and tells you where it saved the file: annas-archive in your home folder unless you chose another.

CLI setup

Install both commands with one package:

npm install -g annas-mcp
export ANNAS_SECRET_KEY="your-secret-key"

annas-cli --help
annas-cli book-search "pride and prejudice" --format epub

Both commands support the same operations. With no arguments, annas-cli shows help and annas-mcp starts MCP. See Configuration for settings and Command line for all commands.

Or run without installing globally:

npx -y --package=annas-mcp annas-cli book-search "pride and prejudice" --format epub

Switching from iosifache/annas-mcp

This server keeps the same four tools, adds three more and reads the same ANNAS_SECRET_KEY, ANNAS_DOWNLOAD_PATH and ANNAS_BASE_URL variables. In your client's config, replace the path to the old binary with npx:

-      "command": "/path/to/annas-mcp",
-      "args": ["mcp"],
+      "command": "npx",
+      "args": ["-y", "annas-mcp"],

What changes:

  • Searches run as your signed-in member account, so they aren't turned away with 403 by the archive's browser check. Searching needs Lucky Librarian or higher.

  • The server picks a working official mirror by itself. Set ANNAS_AUTO_BASE_URL=false to use only ANNAS_BASE_URL.

  • Downloads are checked against the archive's MD5 hash.

  • npx picks up new releases without a manual download.

Signing in

Anna's Archive only lets signed-in members search. The server signs in with your secret key before its first request and again whenever the archive ends the session, about once a week. The session is saved between runs.

If signing in fails, the error says what each mirror answered and how to give the server a browser session instead:

  1. Sign in to Anna's Archive in your browser, open its developer tools and go to Application (Chrome, Edge) or Storage (Firefox, Safari) → Cookies.

  2. Copy the value of aa_account_id2 into ANNAS_ACCOUNT_COOKIE and restart the MCP server from your client.

The server uses that cookie until it expires, then signs in with the secret key again. Keep the secret key and cookie private.

Configuration

Variable

Needed for

Description

ANNAS_SECRET_KEY

Everything

Your Anna's Archive secret key. The server signs in with it and uses it for downloads.

ANNAS_DOWNLOAD_PATH

Optional

Folder for downloaded files. Defaults to annas-archive in your home folder. See Choosing the download folder.

ANNAS_ACCOUNT_COOKIE

Optional

An aa_account_id2 cookie to use before signing in. See Signing in.

ANNAS_BASE_URL

Optional

Mirror to try first; the official mirrors stand in for it while it fails. Defaults to annas-archive.gl. Language versions such as es.annas-archive.gl are refused, since the server reads the archive in English.

ANNAS_AUTO_BASE_URL

Optional

Set to false to always use ANNAS_BASE_URL instead of picking a mirror automatically.

ANNAS_MCP_CACHE_DIR

Optional

Where the server saves its session and npx caches release binaries. See The cache folder.

The server and CLI also read a .env file from their working directory. Variables already set in the environment take precedence.

The server only uses ANNAS_BASE_URL and the official mirrors annas-archive.gl, .pk and .gd; Choosing a mirror explains how it picks one. Whatever host you set in ANNAS_BASE_URL receives your credentials, so only use one you trust.

Choosing the download folder

Downloads go to ~/annas-archive (%USERPROFILE%\annas-archive on Windows), which is created on the first download. Set ANNAS_DOWNLOAD_PATH to use another folder. It must be an absolute path, except that a leading ~ stands for your home folder.

On macOS, Desktop, Documents, Downloads and iCloud Drive are protected: the first download there makes macOS ask whether your MCP client may access the folder. If that access is denied, downloads fail with [CONFIG] cannot write to the download folder; allow your client in System Settings → Privacy & Security → Files and Folders, or pick a folder directly in your home folder. Avoid /tmp, which the operating system clears.

Tools

The AI fills in each tool's options from your request. HOW-IT-WORKS.md lists them and what each tool returns, and --help shows them on the command line.

Before downloading, the server checks completed regular files directly in your download folder against the full MD5 hash. If one matches, it returns that file's path and size regardless of its name or extension, without downloading it or making a fresh account request; downloads_left is omitted. For article downloads by DOI, the DOI is resolved to a hash first. If no local file matches, the server downloads a verified copy and chooses a unique filename without overwriting an existing file. A fast download may use your membership's allowance, which Anna's Archive counts over a rolling 18- or 24-hour window. Downloading a file again within that window is free, and account_status shows how many are left.

Troubleshooting

Errors start with a code:

Code

What to do

[CONFIG]

A variable is missing or invalid, Anna's Archive rejected the secret key or the download folder can't be written to. Check Configuration.

[UPSTREAM_BLOCKED]

The archive refused access. Check that your membership allows searching. If the error says no fast downloads are left, wait for the window to roll over; account_status shows the allowance. If signing in itself failed, see Signing in.

[NOT_FOUND]

Nothing matched, or that copy has no fast download. Try another query, or another copy from the search results.

[INVALID_ARGUMENT]

Fix the hash, DOI, id, filter, sort, page, limit or timeout.

[REQUEST_TIMEOUT]

Retry, or raise timeout_seconds.

[UPSTREAM]

The archive or a download server failed. The error says which one and why; retry later.

A failed download lists every server it tried and why each one failed. The server only checks your credentials when you search or download, not when it starts.

If the server doesn't start at all, run npx -y annas-mcp --version in a terminal to see the error. The launcher unpacks releases with the system's tar, which macOS, most Linux distributions and Windows 10 or later include.

Command line

Every tool is also a command. Follow CLI setup, set the same variables (or put them in a .env file), then:

annas-cli book-search "pride and prejudice" --language en --format epub --include-stats
annas-cli book-search --author "Jane Austen" --year 1813 --sort oldest
annas-cli article-search 10.1038/nature14539
annas-cli metadata-search 9780141439518
annas-cli book-details <hash>
annas-cli account-status
annas-cli book-download <hash> "Pride and Prejudice.epub"
annas-cli article-download 10.1038/nature14539

Add --include-stats to a book or article search to include per-file download, list, quality-vote, report and comment counts when available. Add --json for machine-readable output, --timeout 10m to change the timeout and --help to any command for all of its options.

Privacy

annas-mcp runs on your machine and has no telemetry. It sends your secret key (and cookie, if you set one) only to Anna's Archive, and downloads files from the servers Anna's Archive points it to. DOI lookups may contact doi.org. The npx launcher and the MCP Bundle contact GitHub to fetch and verify release binaries. Apart from downloaded files, it stores only the release binary, the saved session and recent mirror health, all in the cache folder. Questions: open an issue.

Contributing

See CONTRIBUTING.md for building from source, tests and releases.

Credits

The idea for this project comes from iosifache/annas-mcp, which first exposed Anna's Archive as an MCP server. This repository is a complete rewrite and shares no code with it.

License

MIT

Available Tools

7 tools
account_statusAccount statusA
Read-only

Show the account's membership and how many fast downloads it has left in its rolling window. Check it before downloading many files.

NameRequiredDescriptionDefault
timeout_secondsNoTotal operation timeout in seconds, including retries. Defaults to 60; maximum 86400

Output Schema

NameRequiredDescription
memberYes
membershipsNo
window_hoursNo
downloads_leftYes
downloads_limitNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is covered. The description adds value by disclosing the returned content (membership plus quota) and the rolling-window semantics, which explains why idempotentHint=false for a read. It omits auth requirements and rate-limit behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler. The capability is front-loaded and the usage cue follows, so a scanning agent gets both the what and the when in minimal reading time.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, the description need not enumerate return fields, and it does note the two key outputs anyway. For a no-required-parameter read-only tool this is essentially complete, with only auth/rate-limit context missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% and there is only one optional parameter (timeout_seconds), so the schema carries the semantics. The description adds no parameter-level information. Baseline 3 applies when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Show') and two concrete resources: the account's membership and its remaining fast downloads in a rolling window. An agent can immediately distinguish this status/quota tool from the sibling download and search tools 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly gives the trigger condition: 'Check it before downloading many files.' That is actionable guidance tied to the sibling download tools. It stops short of naming alternatives or stating when not to call it (e.g., it is cheap/safe to call anytime), so it is clear context rather than a full when/when-not rubric.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

article_downloadDownload articleA

Download a selected paper by exactly one of doi or hash. The hash field accepts a bare MD5 or an Anna's Archive /md5/ page URL. Resolves a DOI to its hash, then returns an existing file in ANNAS_DOWNLOAD_PATH if its full MD5 matches, otherwise downloads under a unique name. Returns path and bytes; downloads_left is omitted on local reuse. Optional title and format control a new file's name.

NameRequiredDescriptionDefault
doiNoDOI, doi: identifier or https://doi.org/ URL. Supply exactly one of doi or hash
hashNo32-character MD5 hash or Anna's Archive /md5/ page URL. Supply exactly one of doi or hash
titleNoOptional title override for the saved filename
formatNoOptional filename extension such as pdf. Inferred when omitted; does not convert the file
timeout_secondsNoTotal operation timeout in seconds, including retries. Defaults to 1800; maximum 86400

Output Schema

NameRequiredDescription
pathYes
bytesYes
downloads_leftNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare the mutation/openWorld profile (readOnlyHint=false, destructiveHint=false, idempotentHint=false, openWorldHint=true). The description goes well beyond that, disclosing the resolution flow (DOI to hash), the local-reuse behavior when the full MD5 matches, the fallback of downloading under a unique name, and that downloads_left is omitted on reuse — exactly the operational detail an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the identifier constraint, then the resolution/reuse flow, then the parameter caveat. Dense but each clause carries information; the only cost is that the third sentence reads as a run-on, slightly hurting scannability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a download tool with a full output schema, the description covers everything an agent needs: identifier rules, resolution and reuse behavior, naming effects of optional params, and the fact that downloads_left is conditionally present. Nothing material is left to inference.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds value by tying title and format to the reuse path ('control a new file's name'), implying they are ignored when an existing file is reused. That is meaningful semantics not spelled out in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Download a selected paper') and immediately constrains the identifier to 'exactly one of doi or hash'. Combined with the word 'paper', an agent can distinguish it from the sibling book_download and from article_search 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear selection conditions: use exactly one of doi or hash, and the hash field accepts either a bare MD5 or an Anna's Archive /md5/ page URL. It does not explicitly name a sibling alternative (e.g., book_download for non-article items), so it stops short of full when/when-not routing, but the implied scope is unambiguous.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

article_searchSearch articlesA
Read-only

Find a paper by DOI (including DOI URLs), or search journal articles by keywords, author, title or year. DOI lookup returns one paper; keyword search returns one page. Set include_stats to add public per-file downloads, quality votes, reports, lists and comments. Compare metadata before downloading by hash or DOI.

NameRequiredDescriptionDefault
pageNoResult page starting at 1. Defaults to 1
sortNoOptional order: relevance (default), newest or oldest (publication year), largest or smallest (file size), newest_added or oldest_added (date added to the archive), or random
yearNoOptional publication year, for example 2008
limitNoMaximum results from this page. Defaults to 10; raise this before requesting another page
queryNoWords to look for in titles, authors, publishers and other metadata. For article_search, also a DOI, doi: identifier or https://doi.org/ URL. Optional when title, author, publisher or year is set
titleNoOptional phrase the title must contain
authorNoOptional phrase the author must contain
formatNoOptional file extensions, comma-separated, such as epub, pdf, mobi, azw3, djvu, fb2 or cbz. Prefix one with - to exclude it, as in -pdf
sourceNoOptional source libraries, comma-separated, such as lgli (Libgen.li), lgrs (Libgen.rs), zlib, ia, scihub, nexusstc or upload. Prefix one with - to exclude it
contentNoOptional content types, comma-separated: book_nonfiction, book_fiction, book_unknown, book_comic, magazine, standards_document, musical_score, audiobook or other. Prefix one with - to exclude it
languageNoOptional language codes, comma-separated, for example en or en,de. Prefix one with - to exclude it
publisherNoOptional phrase the publisher must contain
include_statsNoInclude public per-file community counts (downloads, quality votes, reports, lists and comments). Adds a statistics lookup for returned file hashes
timeout_secondsNoTotal operation timeout in seconds, including retries. Defaults to 60; maximum 86400
downloadable_onlyNoOnly return files the download tools can fetch: fast downloads, and for article_search also SciDB
search_descriptionsNoAlso match query against descriptions and metadata comments

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover the safety profile (readOnly, openWorld, non-destructive), so the description's job is to add context — and it does: DOI lookup returns a single paper, keyword search returns one page, and include_stats triggers a per-file statistics lookup. It does not mention auth or rate limits, but it adds meaningful behavioral detail 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.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the two core modes, then scoping options, then the downstream workflow hint. Every sentence carries information, though the closing 'compare metadata' sentence is advisory rather than definitional.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 16-parameter search tool with no output schema, the description covers return cardinality, the stats side-effect, and the download-comparison workflow. Pagination behavior and result shape are only lightly touched, leaving a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 16 parameters. The description restates include_stats and alludes to hashes, but adds little syntax or format detail beyond what the schema provides — the baseline of 3 fits.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

It states specific verbs and resources — DOI lookup and keyword search over journal articles — and clearly delineates the two modes. The 'article' scope implicitly separates it from book_search, but no sibling is named, so the differentiation is inferential rather than explicit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear context for choosing between the two modes (DOI vs keyword) and notes that include_stats and downloadable_only shape results. It stops short of naming alternatives like metadata_search or book_search, so there is no explicit when-not guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

book_detailsBook detailsA
Read-only

Get the full record for a search hit: ISBNs, DOI, OCLC and other identifiers, edition, year, full description, subjects, alternative titles, problems reported for the file, and download and quality counts. Accepts a hash from book_search or article_search, or an id from metadata_search.

NameRequiredDescriptionDefault
idYesA 32-character hash from book_search or article_search, or a record id such as isbndb:9780521879286 from metadata_search
timeout_secondsNoTotal operation timeout in seconds, including retries. Defaults to 60; maximum 86400

Output Schema

NameRequiredDescription
idYes
urlYes
hashNo
yearNo
statsNo
titleYes
formatNo
authorsNo
contentNo
editionNo
sourcesNo
problemsNo
subjectsNo
languagesNo
publisherNo
added_dateNo
size_bytesNo
descriptionNo
identifiersNo
fast_downloadYes
classificationsNo
original_filenameNo
alternative_titlesNo
alternative_authorsNo
recently_downloadedNo
alternative_editionsNo
alternative_publishersNo

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true, so the safety profile is covered. The description adds useful context about record contents, including volatile data (problems reported, download and quality counts), which loosely explains the idempotentHint=false. However, it says nothing about error behavior for missing hashes, auth needs, or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action, and the identifier-source sentence is placed last where it is most actionable. The field enumeration is slightly long, but each listed item is real content rather than filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values need not be explained, yet the description still orients the agent on what the record holds. Combined with the id-sourcing guidance, an agent has enough to call the tool correctly; only edge-case behavior (invalid/expired hash, missing record) is unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both parameters (id and timeout_seconds) are already fully documented in the schema. The description restates the id sources but adds no syntax, format, or failure-mode detail beyond what the schema provides, so the baseline of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("Get the full record") and then enumerates exactly what the record contains: identifiers, edition, year, description, subjects, problems, counts. It is clearly the detail-lookup counterpart to the sibling search tools, so an agent can tell it apart from book_search/article_search/metadata_search 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.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says the tool takes a hash from book_search or article_search, or an id from metadata_search, which tells the agent this is the follow-up call after a search. It gives clear context but no explicit exclusions or when-not-to-use conditions, so it stops 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.

book_downloadDownload bookA

Download the selected book using its MD5 hash or Anna's Archive /md5/ page URL in hash. Returns an existing file in ANNAS_DOWNLOAD_PATH if its full MD5 matches, otherwise downloads a verified copy under a unique name. Returns path and bytes; downloads_left is omitted on local reuse. Format sets the extension; it does not convert the file.

NameRequiredDescriptionDefault
hashYes32-character MD5 hash or Anna's Archive /md5/ page URL
titleYesBook title used for the filename
formatNoOptional filename extension such as pdf or epub. Inferred when omitted; does not convert the file
timeout_secondsNoTotal operation timeout in seconds, including retries. Defaults to 1800; maximum 86400

Output Schema

NameRequiredDescription
pathYes
bytesYes
downloads_leftNo

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond annotations by disclosing the local-reuse behavior (returns an existing file when the full MD5 matches), verified downloading under a unique name, that path and bytes are returned, and that downloads_left is omitted on local reuse. This is the kind of behavioral detail an agent could not get from the structured fields alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads the core action and inputs in the first sentence, then layers return behavior and the format caveat. Every sentence carries distinct information with no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists so return values needn't be enumerated, yet the description still usefully characterizes the response and its conditional field. It omits failure modes (unavailable book, exhausted quota, timeout expiry), which is the only meaningful gap for a tool with retries and a 24h max timeout.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description restates the hash input forms and the format-does-not-convert rule already present in the schema, but adds no syntax or edge-case detail (e.g. timeout behavior or format inference rules) beyond it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (download) and resource (the selected book) and specifies the exact input forms accepted (32-char MD5 or Anna's Archive /md5/ page URL). This clearly separates it from siblings like article_download and book_search without needing schema inspection.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'the selected book' implies a prior selection step (e.g. book_search/book_details) must happen first, but no alternative tool is named and no explicit when-not condition is given. Usage is inferable but not spelled out.

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.

  1. 7 tool updatesv0.7.0
    • Addedaccount_status
    • Changedarticle_download3 fields changed
      • changedInput schema / properties / doi / description
        Previous value: -"DOI, doi: identifier, or https://doi.org/ URL. Supply exactly one of doi or hash"New value: +"DOI, doi: identifier or https://doi.org/ URL. Supply exactly one of doi or hash"
      • changedInput schema / properties / hash / description
        Previous value: -"32-character MD5 hash from search. Supply exactly one of doi or hash"New value: +"32-character MD5 hash or Anna's Archive /md5/ page URL. Supply exactly one of doi or hash"
      • addedOutput schema / properties / downloads_left
        Added value: +{
        +  "type": [
        +    "null",
        +    "integer"
        +  ]
        +}
    • Changedarticle_search14 fields changed
      • addedInput schema / properties / author
        Added value: +{
        +  "description": "Optional phrase the author must contain",
        +  "type": "string"
        +}
      • changedInput schema / properties / content / description
        Previous value: -"Optional content filter: book_fiction, book_nonfiction, book_unknown, book_comic, magazine, or standards_document"New value: +"Optional content types, comma-separated: book_nonfiction, book_fiction, book_unknown, book_comic, magazine, standards_document, musical_score, audiobook or other. Prefix one with - to exclude it"
      • addedInput schema / properties / downloadable_only
        Added value: +{
        +  "description": "Only return files the download tools can fetch: fast downloads, and for article_search also SciDB",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / format
        Added value: +{
        +  "description": "Optional file extensions, comma-separated, such as epub, pdf, mobi, azw3, djvu, fb2 or cbz. Prefix one with - to exclude it, as in -pdf",
        +  "type": "string"
        +}
      • addedInput schema / properties / include_stats
        Added value: +{
        +  "description": "Include public per-file community counts (downloads, quality votes, reports, lists and comments). Adds a statistics lookup for returned file hashes",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / language / description
        Previous value: -"Optional two-letter ISO 639-1 language code, for example en"New value: +"Optional language codes, comma-separated, for example en or en,de. Prefix one with - to exclude it"
      • addedInput schema / properties / publisher
        Added value: +{
        +  "description": "Optional phrase the publisher must contain",
        +  "type": "string"
        +}
      • changedInput schema / properties / query / description
        Previous value: -"Title, author, topic, or (for article_search) a DOI, doi: identifier, or https://doi.org/ URL"New value: +"Words to look for in titles, authors, publishers and other metadata. For article_search, also a DOI, doi: identifier or https://doi.org/ URL. Optional when title, author, publisher or year is set"
      • addedInput schema / properties / search_descriptions
        Added value: +{
        +  "description": "Also match query against descriptions and metadata comments",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / sort
        Added value: +{
        +  "description": "Optional order: relevance (default), newest or oldest (publication year), largest or smallest (file size), newest_added or oldest_added (date added to the archive), or random",
        +  "type": "string"
        +}
      • addedInput schema / properties / source
        Added value: +{
        +  "description": "Optional source libraries, comma-separated, such as lgli (Libgen.li), lgrs (Libgen.rs), zlib, ia, scihub, nexusstc or upload. Prefix one with - to exclude it",
        +  "type": "string"
        +}
      • addedInput schema / properties / title
        Added value: +{
        +  "description": "Optional phrase the title must contain",
        +  "type": "string"
        +}
      • addedInput schema / properties / year
        Added value: +{
        +  "description": "Optional publication year, for example 2008",
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "query"
        -]
    • Addedbook_details
    • Changedbook_download2 fields changed
      • changedInput schema / properties / hash / description
        Previous value: -"32-character MD5 hash from search"New value: +"32-character MD5 hash or Anna's Archive /md5/ page URL"
      • addedOutput schema / properties / downloads_left
        Added value: +{
        +  "type": [
        +    "null",
        +    "integer"
        +  ]
        +}
    • Changedbook_search27 fields changed
      • addedInput schema / properties / author
        Added value: +{
        +  "description": "Optional phrase the author must contain",
        +  "type": "string"
        +}
      • changedInput schema / properties / content / description
        Previous value: -"Optional content filter: book_fiction, book_nonfiction, book_unknown, book_comic, magazine, or standards_document"New value: +"Optional content types, comma-separated: book_nonfiction, book_fiction, book_unknown, book_comic, magazine, standards_document, musical_score, audiobook or other. Prefix one with - to exclude it"
      • addedInput schema / properties / downloadable_only
        Added value: +{
        +  "description": "Only return files the download tools can fetch: fast downloads, and for article_search also SciDB",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / format
        Added value: +{
        +  "description": "Optional file extensions, comma-separated, such as epub, pdf, mobi, azw3, djvu, fb2 or cbz. Prefix one with - to exclude it, as in -pdf",
        +  "type": "string"
        +}
      • addedInput schema / properties / include_stats
        Added value: +{
        +  "description": "Include public per-file community counts (downloads, quality votes, reports, lists and comments). Adds a statistics lookup for returned file hashes",
        +  "type": "boolean"
        +}
      • changedInput schema / properties / language / description
        Previous value: -"Optional two-letter ISO 639-1 language code, for example en"New value: +"Optional language codes, comma-separated, for example en or en,de. Prefix one with - to exclude it"
      • addedInput schema / properties / publisher
        Added value: +{
        +  "description": "Optional phrase the publisher must contain",
        +  "type": "string"
        +}
      • changedInput schema / properties / query / description
        Previous value: -"Title, author, topic, or (for article_search) a DOI, doi: identifier, or https://doi.org/ URL"New value: +"Words to look for in titles, authors, publishers and other metadata. For article_search, also a DOI, doi: identifier or https://doi.org/ URL. Optional when title, author, publisher or year is set"
      • addedInput schema / properties / search_descriptions
        Added value: +{
        +  "description": "Also match query against descriptions and metadata comments",
        +  "type": "boolean"
        +}
      • addedInput schema / properties / sort
        Added value: +{
        +  "description": "Optional order: relevance (default), newest or oldest (publication year), largest or smallest (file size), newest_added or oldest_added (date added to the archive), or random",
        +  "type": "string"
        +}
      • addedInput schema / properties / source
        Added value: +{
        +  "description": "Optional source libraries, comma-separated, such as lgli (Libgen.li), lgrs (Libgen.rs), zlib, ia, scihub, nexusstc or upload. Prefix one with - to exclude it",
        +  "type": "string"
        +}
      • addedInput schema / properties / title
        Added value: +{
        +  "description": "Optional phrase the title must contain",
        +  "type": "string"
        +}
      • addedInput schema / properties / year
        Added value: +{
        +  "description": "Optional publication year, for example 2008",
        +  "type": "string"
        +}
      • removedInput schema / required
        Removed value: -[
        -  "query"
        -]
      • addedOutput schema / properties / more_pages
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / partial_matches
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "authors": {
        +        "type": "string"
        +      },
        +      "content": {
        +        "type": "string"
        +      },
        +      "description": {
        +        "type": "string"
        +      },
        +      "doi": {
        +        "type": "string"
        +      },
        +      "edition": {
        +        "type": "string"
        +      },
        +      "fast_download": {
        +        "type": "boolean"
        +      },
        +      "format": {
        +        "type": "string"
        +      },
        +      "hash": {
        +        "type": "string"
        +      },
        +      "language": {
        +        "type": "string"
        +      },
        +      "possible_issues": {
        +        "type": "boolean"
        +      },
        +      "publisher": {
        +        "type": "string"
        +      },
        +      "size": {
        +        "type": "string"
        +      },
        +      "sources": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": [
        +          "null",
        +          "array"
        +        ]
        +      },
        +      "stats": {
        +        "additionalProperties": false,
        +        "properties": {
        +          "comments": {
        +            "type": "integer"
        +          },
        +          "downloads": {
        +            "type": "integer"
        +          },
        +          "great_quality": {
        +            "type": "integer"
        +          },
        +          "lists": {
        +            "type": "integer"
        +          },
        +          "reports": {
        +            "type": "integer"
        +          }
        +        },
        +        "required": [
        +          "downloads",
        +          "great_quality",
        +          "reports",
        +          "lists",
        +          "comments"
        +        ],
        +        "type": [
        +          "null",
        +          "object"
        +        ]
        +      },
        +      "title": {
        +        "type": "string"
        +      },
        +      "url": {
        +        "type": "string"
        +      },
        +      "year": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "title",
        +      "authors",
        +      "publisher",
        +      "language",
        +      "format",
        +      "size",
        +      "fast_download",
        +      "hash",
        +      "url"
        +    ],
        +    "type": [
        +      "null",
        +      "object"
        +    ]
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedOutput schema / properties / results / items / properties / content
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / edition
        Added value: +{
        +  "type": "string"
        +}
      • addedOutput schema / properties / results / items / properties / fast_download
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / results / items / properties / possible_issues
        Added value: +{
        +  "type": "boolean"
        +}
      • addedOutput schema / properties / results / items / properties / sources
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": [
        +    "null",
        +    "array"
        +  ]
        +}
      • addedOutput schema / properties / results / items / properties / stats
        Added value: +{
        +  "additionalProperties": false,
        +  "properties": {
        +    "comments": {
        +      "type": "integer"
        +    },
        +    "downloads": {
        +      "type": "integer"
        +    },
        +    "great_quality": {
        +      "type": "integer"
        +    },
        +    "lists": {
        +      "type": "integer"
        +    },
        +    "reports": {
        +      "type": "integer"
        +    }
        +  },
        +  "required": [
        +    "downloads",
        +    "great_quality",
        +    "reports",
        +    "lists",
        +    "comments"
        +  ],
        +  "type": [
        +    "null",
        +    "object"
        +  ]
        +}
      • addedOutput schema / properties / results / items / properties / year
        Added value: +{
        +  "type": "string"
        +}
      • changedOutput schema / properties / results / items / required
        Previous value: -[
        -  "title",
        -  "authors",
        -  "publisher",
        -  "language",
        -  "format",
        -  "size",
        -  "hash",
        -  "url"
        -]New value: +[
        +  "title",
        +  "authors",
        +  "publisher",
        +  "language",
        +  "format",
        +  "size",
        +  "fast_download",
        +  "hash",
        +  "url"
        +]
      • addedOutput schema / properties / total
        Added value: +{
        +  "type": "integer"
        +}
      • addedOutput schema / properties / total_is_lower_bound
        Added value: +{
        +  "type": "boolean"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "page",
        -  "language",
        -  "matched",
        -  "limit",
        -  "results"
        -]New value: +[
        +  "page",
        +  "language",
        +  "total",
        +  "more_pages",
        +  "matched",
        +  "limit",
        +  "results"
        +]
    • Addedmetadata_search
  2. 4 tool updatesv0.1.0
    • First observedarticle_download
    • First observedarticle_search
    • First observedbook_download
    • First observedbook_search

TDQS

A4.2/5.0

Scored across 7 tools

Disambiguation4/5

Each tool targets a distinct resource+action: account_status for quota, article_search/article_download for papers, book_search/book_download/book_details for books, and metadata_search for catalog lookups. The only real overlap is between book_search and metadata_search, which both find book information, but the descriptions clearly separate file-bearing results from pure metadata.

Naming Consistency5/5

All tools use consistent snake_case noun_action naming (account_status, article_download, article_search, book_details, book_download, book_search, metadata_search). The resource-first convention is predictable and readable throughout.

Tool Count5/5

Seven tools is well within the ideal 3-15 range and each one earns its place, covering quota, search, details, and download for both books and articles plus a metadata path. No redundant or trivial tools.

Completeness4/5

The surface covers the core lifecycle for the domain: check quota, search books and papers, fetch details, and download both resource types. Minor gaps exist, such as no bulk/batch download or browsing recent additions, but core workflows are fully supported without dead ends.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Self-hosted MCP server for searching and discovering books using Anna's Archive and Goodreads datasets, enabling full-text search, ISBN/md5 lookup, similarity matching, and optional download URL retrieval.
    12 npm
    4
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    A local MCP server for managing saved Substack posts. Enables offline reading, searching, bookmarking, and unbookmarking of Substack content via CLI or MCP clients.
    17
    MIT