MCP server for BiblioCommons-powered public libraries — search, place holds, manage your account
Project description
bibliocommons-mcp
MCP server for BiblioCommons-powered public libraries — Seattle, San Francisco, ~190 others. Search the catalog, place holds, manage checkouts, all from any MCP-capable client (Claude, Cursor, etc.).
Built because placing a hold on a CD shouldn't take seven clicks.
What it does
| Tool | What it does |
|---|---|
search |
Search the catalog. Optional format filter (MUSIC_CD, BK, EBOOK, EAUDIOBOOK, DVD, etc.) and sort |
availability |
Per-branch availability for a specific bib |
place_hold |
Place a physical hold (CD/book/DVD/etc.) with pickup branch |
borrow_digital |
Check out an immediately-available digital item |
list_holds |
All your current holds (physical + digital) |
cancel_hold |
Cancel one of your holds |
list_loans |
Current checkouts with due dates |
list_branches |
All branches at your configured library |
library_health |
Login probe + hold counts/quotas |
Not yet supported (v1.1): placing a digital hold on an unavailable digital item (joining a waitlist). Available digital items work via borrow_digital. Use the Libby app directly for digital waitlists in the meantime.
Install
pip install -e .
Requires Python 3.11+.
Configure
Create ~/.config/bibliocommons-mcp/config.toml:
library = "seattle" # your BiblioCommons subdomain
default_pickup_branch = "Lake City" # branch name or 3-letter code
default_format = "MUSIC_CD" # optional default for search
[credentials]
card = "1234567890"
pin = "1234"
chmod 600 it. Or set everything via environment variables:
BIBLIOCOMMONS_LIBRARY=seattle
BIBLIOCOMMONS_CARD=1234567890
BIBLIOCOMMONS_PIN=1234
BIBLIOCOMMONS_PICKUP_BRANCH="Lake City"
Finding your library subdomain
If your library uses BiblioCommons, the URL will be {your-library}.bibliocommons.com. Common examples:
- Seattle:
seattle - San Francisco:
sfpl - Vancouver (BC):
vpl - Boston:
bpl
If you visit {name}.bibliocommons.com and see a catalog, that's your subdomain.
Run
Console script:
bibliocommons-mcp
Or via Python:
python -m bibliocommons_mcp
The server speaks MCP over stdio.
Add to Claude Desktop
In ~/Library/Application Support/Claude/claude_desktop_config.json (Mac) or the equivalent on your OS:
{
"mcpServers": {
"bibliocommons": {
"command": "bibliocommons-mcp"
}
}
}
Restart Claude Desktop. Then ask Claude to "search the library for Mudhoney CDs" or "what holds do I have?"
Format codes
Common values for the format parameter of search:
| Code | Meaning |
|---|---|
MUSIC_CD |
Music CD |
BK |
Book |
EBOOK |
Ebook |
EAUDIOBOOK |
E-audiobook |
AUDIOBOOK_CD |
Audiobook on CD |
DVD |
DVD |
BLU_RAY |
Blu-ray |
LARGEPRINT |
Large print book |
MN |
Music notation / printed music |
The full facet list is available from a search response under entities.bibs[*].briefInfo.format.
How it works
- Authenticates via the standard SPL/BiblioCommons login form (
POST /user/login). - Talks to the modern gateway at
gateway.bibliocommons.com/v2/libraries/{your-library}/using your session cookies. - Wraps and corrects the
python-bibliocommonsclient — same auth, more endpoints (search, place hold, cancel hold, branches, availability).
The hold POST body shape we eventually figured out (see commit history for the saga):
POST /v2/libraries/{library}/holds?locale=en-US
{
"metadataId": "S30C...",
"materialType": "PHYSICAL",
"accountId": 1234567890,
"enableSingleClickHolds": false,
"materialParams": {
"branchId": "LCY",
"expiryDate": null,
"errorMessageLocale": "en-US"
}
}
errorMessageLocale is the killer field — without it, the gateway 500s with a generic Internal Server Error.
Limitations
- Digital queue holds (joining a waitlist for an unavailable ebook/audiobook) aren't supported yet — only
borrow_digitalfor items currently available. Use Libby for waitlists. - No suspend/unsuspend holds in v1. Cancel works.
- No renewals in v1. Use the library website to renew.
- One library per server instance. Run two servers if you have cards at multiple libraries.
Acknowledgments
python-bibliocommonsby William Jackson — handles the modern login flow.SFPLby kaijchang — first sighting of the BiblioCommons place-hold endpoint pattern.bibliophile-backendby DavidCain — proof that this approach generalizes across ~190 libraries.
License
MIT
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 bibliocommons_mcp-0.1.0.tar.gz.
File metadata
- Download URL: bibliocommons_mcp-0.1.0.tar.gz
- Upload date:
- Size: 206.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3bc75c9070a48a99db0a9fa4d28fbbc23d2eb729fa4f4c7d3a428200599c7bdd
|
|
| MD5 |
db63ece4e3b1b3cc8b109e1a64b904a6
|
|
| BLAKE2b-256 |
0afcc8e9808007690315d4b821cd6297ec2ee94cc24faf114f04acbe73c18036
|
Provenance
The following attestation bundles were made for bibliocommons_mcp-0.1.0.tar.gz:
Publisher:
publish.yml on pdugan20/bibliocommons-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bibliocommons_mcp-0.1.0.tar.gz -
Subject digest:
3bc75c9070a48a99db0a9fa4d28fbbc23d2eb729fa4f4c7d3a428200599c7bdd - Sigstore transparency entry: 1646060998
- Sigstore integration time:
-
Permalink:
pdugan20/bibliocommons-mcp@623c6139c91644f9a9f55fb1a8f9d7fee3405d6b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/pdugan20
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@623c6139c91644f9a9f55fb1a8f9d7fee3405d6b -
Trigger Event:
push
-
Statement type:
File details
Details for the file bibliocommons_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: bibliocommons_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 13.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 |
087a9ef36ecdcd43440b31f7858367a7a7631da22e001703de8feec49039e650
|
|
| MD5 |
aa69ce483a24d770751608c969527071
|
|
| BLAKE2b-256 |
740e869661d6e8e64cd9420c9070f7937677e21fb0826c45ede27794f2e4fc70
|
Provenance
The following attestation bundles were made for bibliocommons_mcp-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on pdugan20/bibliocommons-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
bibliocommons_mcp-0.1.0-py3-none-any.whl -
Subject digest:
087a9ef36ecdcd43440b31f7858367a7a7631da22e001703de8feec49039e650 - Sigstore transparency entry: 1646061120
- Sigstore integration time:
-
Permalink:
pdugan20/bibliocommons-mcp@623c6139c91644f9a9f55fb1a8f9d7fee3405d6b -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/pdugan20
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@623c6139c91644f9a9f55fb1a8f9d7fee3405d6b -
Trigger Event:
push
-
Statement type: