Skip to content

edwinavalos/aud2sg

Repository files navigation

aud2sg

An MCP server that gives Claude tools to sync your Audible library to StoryGraph.

What this is

aud2sg exposes your Audible listening history and StoryGraph read shelf as tools that Claude can use. You can ask Claude to:

  • Fetch your Audible library with completion data
  • Search StoryGraph for books
  • Mark books as read (with finish dates) on StoryGraph
  • Bulk-import your Audible history into StoryGraph

Tools

Tool Description
setup_audible Initialize the Audible client from a local auth file
setup_storygraph Initialize the StoryGraph client from credentials stored in the system keychain. No parameters — credentials must be saved first via CLI (setup_storygraph_auth.py or make credentials)
get_audible_library Fetch your Audible library. Returns slim list: asin, title, author, percent_complete, is_finished, finished_at. Params: min_percent (int, default 0), only_unfinished (bool, default false). Call get_audible_book for full detail.
get_audible_book Fetch full detail for a single book by ASIN. Returns: asin, isbn, title, author, narrator, percent_complete, is_finished, finished_at, purchase_date
get_storygraph_read_books Fetch all books marked as read on StoryGraph. Returns list of book_id, title, author, finished_on
search_storygraph Search StoryGraph by title/author. Returns list of book_id, title, url. Param: best_match (bool) to return only the top canonical result
get_storygraph_book Get a book's current status on StoryGraph. Returns book_id, title, status where status is "read", "currently-reading", "to-read", or null
mark_storygraph_read Mark a book as read (with optional finish date)
mark_storygraph_currently_reading Mark a book as currently reading

Requirements

  • Python 3.11 or later — the code uses union type hints (str | None, introduced in Python 3.10) and the declared minimum is 3.11+
  • macOS, Linux, or Windows
  • An Audible account (for Audible tools)
  • A StoryGraph account (for StoryGraph tools)

Setup

1. Install dependencies

make install

This creates .venv/ and installs all dependencies into it.

2. Set up Audible auth

Run the interactive setup script. It prompts for your Amazon email and password using getpass so the password is never echoed or stored in shell history. It saves a token file to ~/.audible/auth.json:

.venv/bin/python setup_audible_auth.py

Security: ~/.audible/auth.json contains long-lived Amazon OAuth tokens with access to your full Amazon account — not just Audible. Keep it private. The file is written with chmod 600 permissions. Never copy it into the repo directory.

Once done, tell Claude to call setup_audible (or it will auto-initialize on server start).

Supported locales

The default locale is us. To use a different locale, edit both setup_audible_auth.py and setup_credentials.py and change locale="us" to your region code (e.g., "uk", "de", "au"). Both files hardcode this value — if you use make credentials without changing setup_credentials.py, it will create a US-locale token regardless.

Tip: Instead of running steps 2 and 3 separately, you can run both in one go:

make credentials

This runs setup_credentials.py, which checks whether each credential is already set up and only prompts for what's missing. Safe to run multiple times.

3. Set up StoryGraph auth

Run the interactive setup script. It prompts for your credentials using getpass so the password is never echoed or stored in shell history:

.venv/bin/python setup_storygraph_auth.py

Credentials are stored in the OS keychain (macOS Keychain, Windows Credential Manager, or a Linux Secret Service backend — see Linux keyring note below). The server auto-initializes on start using these stored credentials.

Security: The setup_storygraph MCP tool reads credentials from the keychain only — it does not accept a password as an argument. Passwords never pass through the LLM context window.

4. Configure your MCP client

Copy .mcp.json.example to .mcp.json and replace the placeholder paths with the absolute paths on your machine:

cp .mcp.json.example .mcp.json

Then edit .mcp.json. The command must point to the venv Python (which has all dependencies installed), not the system Python:

{
  "mcpServers": {
    "aud2sg": {
      "command": "/Users/yourname/repos/aud2sg/.venv/bin/python",
      "args": ["/Users/yourname/repos/aud2sg/server.py"]
    }
  }
}

Use pwd in the repo directory to get the absolute path:

pwd
# /Users/yourname/repos/aud2sg

Note: .mcp.json is gitignored because it contains machine-specific absolute paths. Each user creates their own.

Claude Code

Place .mcp.json in the repo directory and run claude from that directory. Claude Code discovers .mcp.json automatically.

Claude Desktop

Claude Desktop uses a different config file (~/Library/Application Support/Claude/claude_desktop_config.json on macOS). Add the same mcpServers block to that file instead of using .mcp.json.

5. Verify the server starts

With Claude Code, you can confirm the server loaded by running /mcp and checking that aud2sg appears in the list. If it doesn't, check the MCP server logs — startup errors (e.g., missing auth file, keyring failure) are printed to stderr.


Recommended workflow for bulk import

  1. Ask Claude to fetch your Audible library: get_audible_library(min_percent=90)
  2. Ask Claude to search StoryGraph for each book and collect IDs
  3. Ask Claude to write a local plan file (markdown table: title | finish date | StoryGraph ID) and review it
  4. Ask Claude to execute from the plan sequentially, one book at a time

Building a plan file first prevents duplicates if the session is interrupted and gives you a human-reviewable record before any writes happen.


Development

make install      # create .venv and install dependencies
make credentials  # set up Audible and StoryGraph credentials (idempotent)
make test         # run pytest
make lint         # run ruff
make run          # start the MCP server directly

Agent notes and known quirks

All StoryGraph write calls must be sequential

The StoryGraph client uses a single shared cloudscraper session. Date-setting POSTs follow a per-book edit link resolved from each book's own page — the session must complete each request before starting the next. Parallel calls can corrupt the session state and set dates on the wrong books. Always call one book at a time and wait for each response before the next.

Don't mark a book read twice

Marking a book read twice creates a duplicate entry in StoryGraph that requires manual cleanup in the UI. The tool guards against this, but if you're unsure whether a book is already marked, call get_storygraph_book(book_id) first to check its status.

Search — filter by title cleanliness

search_storygraph returns box sets, dramatized adaptations, and study guides alongside the canonical entry. Pick the result whose title most closely matches just the book title and author. Avoid entries containing: "Boxed Set", "Collection", "Dramatized Adaptation", "Summary", "Study Guide", or titles with "volume " followed by a number. Use best_match=True to have the tool do this automatically.

is_finished vs percent_complete

Trust is_finished as the authoritative completion signal. A book may show percent_complete: 0 but is_finished: true (Audible tracking inconsistency). Conversely, a book at 98% may have is_finished: false — do not assume completion from percent alone.

finished_at can be null for legitimately finished books

Some older Audible books have is_finished: true but finished_at: null. Mark these as read on StoryGraph without a date by calling mark_storygraph_read(book_id) with no finish_date.


Troubleshooting

StoryGraph tools say "not initialized" on startup The server logs the reason to stderr. Check your MCP host's server logs. Common causes: keyring unavailable, wrong stored password, or a network error during auto-login.

setup_storygraph / setup_storygraph_auth.py says "Login failed" Verify your email and password by logging in at app.thestorygraph.com in a browser.

get_audible_library returns an empty list Your Audible auth token may have expired. Re-run python setup_audible_auth.py to get a fresh token.

mark_storygraph_read returns "Failed to mark as read" The StoryGraph session may have expired. The client automatically re-logs in when it detects a session expiry during a request — retry the operation once before intervening. If it continues to fail, call setup_storygraph again (or restart the server, which will auto-login from the keychain).

book_id validation error StoryGraph book IDs look like some-title-by-author-abc123. If you see a validation error, the ID came from an unexpected source — re-run search_storygraph to get a fresh ID.

Linux keyring errors (NoKeyringError) On Linux, keyring requires a Secret Service backend. Install one:

  • GNOME: sudo apt install gnome-keyring libsecret-1-0 (usually already present on GNOME desktops)
  • Headless/CI: pip install keyrings.alt (stores in a file; less secure — not recommended for production use)

License

MIT — see LICENSE

About

MCP server that gives Claude tools to sync your Audible library to StoryGraph

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

No contributors