MCP server for the Hardcover GraphQL API — library tracking and list management.
Project description
hardcover-mcp
Talk to your Hardcover library from any AI assistant.
hardcover-mcp connects your Hardcover library to AI assistants like Claude and Copilot. Search for books, update your reading status, manage lists, explore series — all through natural conversation instead of clicking through menus.
What you can say
"What's on my currently reading list?"
"Add Project Hail Mary to my library as currently reading"
"Search for books by Brandon Sanderson"
"Look up ISBN 9780547928227"
"Create a list called 'Summer Reading' and add The Hobbit to it"
"Show me the Stormlight Archive series in reading order"
"Move Project Hail Mary and The Martian to currently reading"
"What books has Andy Weir written? Add any I haven't read to my want-to-read list"
"Compare my rating of Dune with the Hardcover average"
What's covered
- Library tracking — status, ratings, reading dates
- List management — create, edit, add/remove books
- Discovery — search books, authors, series, editions, and more
- Account info — your profile and reading stats
Safety & control
- You control your API key — it stays on your machine, never shared with third parties
- Runs locally through your MCP client — no external server involved
- Actions only happen when explicitly requested — nothing runs in the background
- You review prompts and outputs in your client before anything is sent
Quick Start
- Install uv (a fast Python package runner — the setup takes seconds).
- Get an API token from hardcover.app/account/api.
- Add the config below to your MCP client — no manual install needed,
uvxhandles it.
VS Code
Add to .vscode/mcp.json:
{
"servers": {
"hardcover": {
"command": "uvx",
"args": ["hardcover-mcp"],
"env": {
"HARDCOVER_API_TOKEN": "<your token>"
}
}
}
}
Claude Desktop
Add to claude_desktop_config.json:
{
"mcpServers": {
"hardcover": {
"command": "uvx",
"args": ["hardcover-mcp"],
"env": {
"HARDCOVER_API_TOKEN": "<your token>"
}
}
}
}
Tools
Browse & discover
| What you can do | Tool |
|---|---|
| Search for books, authors, series, and more | search_books |
| Look up a book by title or ID | get_book |
| Look up a specific edition by ISBN or ASIN | get_edition |
| Explore a series in reading order | get_series |
| Browse an author's catalogue | get_author |
Your library
| What you can do | Tool |
|---|---|
| See your profile and book count | me |
| Get reading statistics (totals, ratings, books read per year) | get_reading_stats |
| Browse your library, filter by reading status | get_user_library |
| Check your status/rating for a specific book (includes privacy setting) | get_user_book |
| List your reviews | get_user_reviews |
| List books you own, with edition details | get_owned_books |
| Add a book or update its status, rating, review, notes, privacy, and edition | set_user_book |
| Mark an edition as owned or not owned | set_edition_owned |
| Log reading dates and progress (pages, audiobook time) | add_user_book_read / update_user_book_read |
| Remove a book or reading entry | delete_user_book / delete_user_book_read |
Lists
| What you can do | Tool |
|---|---|
| View all your lists | get_my_lists |
| View a specific list with its books | get_list |
| Create, rename, or delete a list | create_list / update_list / delete_list |
| Add or remove books from a list | add_book_to_list / remove_book_from_list |
Development
git clone https://github.com/kristianedlund/hardcover-mcp.git
cd hardcover-mcp
uv sync
Lint and format checks (using Ruff):
uv run ruff check src/
uv run ruff format --check src/
Run tests:
uv run pytest tests/ -v
Integration Tests
Integration tests hit the live Hardcover API and require a valid token. They are skipped automatically in CI and when the token is absent.
To run them locally, create a .env file with your token:
HARDCOVER_API_TOKEN=your_token_here
Then run:
uv run pytest tests/integration/ -v
Write tests follow a create → verify → delete lifecycle so the account is left unchanged.
Contributing
Contributions are welcome! Please:
- Open an issue first to discuss the change.
- Fork the repo and create a branch (
feature/short-descriptionorfix/short-description). - Run lint and tests before submitting:
uv run ruff check src/ uv run ruff format --check src/ uv run pytest tests/ -v
- Keep PRs focused — one change per PR.
- Use conventional commit prefixes:
feat:,fix:,chore:,docs:.
Rate Limiting
The Hardcover API allows 60 requests per minute. The server handles this automatically — it queues requests and retries if needed. You shouldn't hit this in normal use.
Troubleshooting
| Problem | Fix |
|---|---|
| "API token is not set" | Add your token to the config (see Quick Start above) |
| "Access is denied" on Windows | Add "UV_LINK_MODE": "copy" to the env block in your config |
| Slow or repeated errors | The server retries automatically — wait a moment and try again |
| Unexpected results | Check for a newer version: the Hardcover API may have changed |
Disclaimer
Unofficial project. Not affiliated with Hardcover.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hardcover_mcp-0.3.0.tar.gz.
File metadata
- Download URL: hardcover_mcp-0.3.0.tar.gz
- Upload date:
- Size: 22.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
05b5eed31d8afc06e48da17471d644db633e7babb0d3edb8dafabb370b1164fa
|
|
| MD5 |
2997b4890e77190fdc8dcd6b9442344b
|
|
| BLAKE2b-256 |
a19879ada7ccc182856063456e2d014bb460cbc89f1cf3ae1548e30c3357a211
|
Provenance
The following attestation bundles were made for hardcover_mcp-0.3.0.tar.gz:
Publisher:
publish.yml on kristianedlund/hardcover-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hardcover_mcp-0.3.0.tar.gz -
Subject digest:
05b5eed31d8afc06e48da17471d644db633e7babb0d3edb8dafabb370b1164fa - Sigstore transparency entry: 1418054963
- Sigstore integration time:
-
Permalink:
kristianedlund/hardcover-mcp@58762f5a7e09b3b69bf9cb5b2b2131d9e2d8a122 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/kristianedlund
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@58762f5a7e09b3b69bf9cb5b2b2131d9e2d8a122 -
Trigger Event:
push
-
Statement type:
File details
Details for the file hardcover_mcp-0.3.0-py3-none-any.whl.
File metadata
- Download URL: hardcover_mcp-0.3.0-py3-none-any.whl
- Upload date:
- Size: 30.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4492403df8fbd8f5096305289aceb894e32493524610a2dcd85fdcd040e76809
|
|
| MD5 |
f5656d09a0f2835e64bd3ca42455a65a
|
|
| BLAKE2b-256 |
a0f0d15f62fbaa8868e6266fa62c4fb3ea37b2aee4f58cfb140c6b1a6ebcfd35
|
Provenance
The following attestation bundles were made for hardcover_mcp-0.3.0-py3-none-any.whl:
Publisher:
publish.yml on kristianedlund/hardcover-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
hardcover_mcp-0.3.0-py3-none-any.whl -
Subject digest:
4492403df8fbd8f5096305289aceb894e32493524610a2dcd85fdcd040e76809 - Sigstore transparency entry: 1418054969
- Sigstore integration time:
-
Permalink:
kristianedlund/hardcover-mcp@58762f5a7e09b3b69bf9cb5b2b2131d9e2d8a122 -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/kristianedlund
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@58762f5a7e09b3b69bf9cb5b2b2131d9e2d8a122 -
Trigger Event:
push
-
Statement type: