adisweb
Click on "Install 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., "@adiswebsearch for 'Clean Code' and show availability at ZLB"
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.
adisweb-client
Python client for aDISWeb OPAC systems (a|S|tec / OCLC BIBLIOTHECAplus) —
a port of the Adis.java adapter from
opacapp/opacclient (GPL-3.0) to Python.
Das Repo enthält zusätzlich einen MCP-Server (Model Context Protocol,
stdio) für Bibliotheks-Katalog, Konto und Bestellungen — nutzbar aus jedem
MCP-Client (Hermes, Claude Desktop, …) mit 12 Tools.
Authorship: this repository was written by an AI agent (Hermes Agent, by Nous Research) on behalf of its user, with human review of every change. It builds on prior art in two places:
opacapp/opacclient — the Android OPAC client whose
Adis.javaadapter this project ports to Python. The session/state handling, search flow and detail parsing follow its design (GPL-3.0).noestreich/voebbar — a Swift macOS menu-bar + iOS app for VÖBB account operations. Its login flow (OIDC via
oidcp/logincheckwith theReferer: oidcp/authorizeheader, bypassing the F5 WAF) and itsrequestCount/scriptEnabledPOST conventions were verified against and incorporated here.
aDISWeb-based library systems (VÖBB Berlin, München, Stuttgart, Zürich, and the whole Baden-Württemberg BSZ consortium, …) expose no public SRU/DAIA/REST API. The only way to query their catalogues programmatically is to drive the stateful aDISWeb web frontend: session bootstrap, form POSTs, HTML parsing. This library does exactly that — generically, across all aDISWeb generations and layouts.
Features
Session bootstrap — auto-detects both aDISWeb generations: URL-embedded session tokens (
/aDISWeb/_<token>/app, VÖBB) and cookie-session instances (/aDISWeb/app+ JSESSIONID, Zürich/Stuttgart/…)Search — free-text search (
search_simple) and advanced-form search (search), with pagination (search_get_page)Result parsing — both hit-list layouts: modern
ul.rList(Berlin) and legacytable.rTable_table; ids fromdata-ajax,sp=SAK…orhtmlOnLinkDetail view — metadata table, cover, per-branch holdings/availability (status + return date), reservable flag
Account (cookie-session or OIDC login) — account overview (validity, fees, loans, reservations), renewal, reservation placement (
get_account,prolong,reserve, …)Availability-by-query —
get_availability_by_query()searches and fetches every hit's holdings in a single session and filters copies by branch (e.g. "which One Piece volumes are available at ZLB tomorrow?")Library-agnostic — 46 aDISWeb library configs included, all verified working (see COMPATIBILITY.md)
Related MCP server: Primo MCP Server
Install
python -m venv .venv
.venv/bin/pip install -e ".[dev]"Usage
from adisweb import AdisClient, load_library
client = AdisClient(load_library("Berlin"))
# search the catalogue
results = client.search_simple("Berlin", area="Bibliotheksbestand")
print(results.total_result_count) # 1190992
for hit in results.results[:5]:
print(hit.id, hit.type.name, hit.status.name, hit.innerhtml)
# page 2
page2 = client.search_get_page(2)
# detail view
detail = client.get_result_by_id(results.results[0].detail_url)
print(detail.title)
for copy in detail.copies:
print(copy.branch, copy.location, copy.status, copy.return_date)
# availability of a query's hits, filtered by branch (single session)
avail = client.get_availability_by_query("One Piece 86", branch_filter="ZLB")
for record in avail:
print(record["title"], [(c["branch"], c["status"]) for c in record["copies"]])CLI scan over all configured libraries:
.venv/bin/python scripts/scan_libraries.py --jsonMCP server
The client ships as an MCP (Model Context Protocol) stdio server — usable from any MCP client (Hermes, Claude Desktop, …):
.venv/bin/pip install -e ".[mcp]"
.venv/bin/python -m adisweb.mcp_serverTools (12):
list_libraries— all configured librariessearch(query, library="Berlin", area="Bibliotheksbestand")— hit list as JSONsearch_availability(query, branch_filter=None, library="Berlin", area="Bibliotheksbestand")— hit list with per-copy availability (branch, location, signature, status, return date), optionally filtered by branch substring (e.g. "ZLB", "Else Ury", "Namik Kemal"). Runs search + all detail fetches in ONE session (aDISWeb form state is session-bound)get_detail(record_id_or_url, library="Berlin")— full record detail as JSONget_availability(record_id_or_url, library="Berlin")— per-copy availabilityget_account(ausweis, password, library="Berlin")— account overview: pending fees, card validity, loans, reservationsget_loans(ausweis, password, library="Berlin")— currently borrowed items: title, author, media_type, return_date, prolongableget_orders(ausweis, password, library="Berlin")— pending orders:{"orders": [...], "magazine_orders": [...]}(Bestellwünsche via *SZW, Magazin-Bestellungen via *SZB, each with branch/title/order timestamp)reserve(record_id_or_url, ausweis, password, pickup_branch=None, express=False, notify=True, confirm=False, max_fee=None)— place an order / Vormerkungpickup_branch: delivery branch as shown in the order form, e.g."Friedrichshain-Kreuzberg: Familienbibliothek Else Ury"express: check Expressbestellung (fast delivery, may incur transport fees)notify: notify on availability (default True)confirm: must be True to submit the cost-bearing final button ("kostenpflichtig bestellen / vormerken"); otherwise the quoted cost is returned and nothing is orderedmax_fee: refuse the order when the quoted cost exceeds this amount (even with confirm=True). Cost detection covers both live phrasings: "Gebühren in Höhe von 2.00 Euro" (order fee) and "Transport kostet bei Bereitstellung 1.00 Euro" (magazine transport)
prolong(media_key, ausweis, password)— renew a single loan (key from get_loans/get_account)prolong_all(ausweis, password)— renew all prolongable loanscancel_reservation(media_key, ausweis, password)— cancel a reservation
Each tool call creates a fresh client session (stateless, safe for concurrent calls). Account/order tools need the credentials of the patron.
⚠️ Teststatus: Die kompletten Konto-/Bestell-Funktionen (get_account, get_loans, get_orders, reserve, prolong, cancel_reservation) sind nur für die VÖBB (Berlin) live getestet — alle anderen Bibliotheken sind nur für Suche/Detail/Verfügbarkeit verifiziert. Handshake + tools verified via
scripts/mcp_handshake_test.py.🤝 Mitwirken: Wir freuen uns über Pull Requests und Verifikationen der Konto-/Bestell-Funktionen für andere Bibliotheken! Wenn du eine aDISWeb-Bibliothek nutzt (z.B. Stuttgart, München, Zürich, Herne, …) und die Account-Funktionen dort testest, reiche gerne einen PR ein — mit Config-Update (falls nötig), Testergebnis und ggf. Code-Anpassungen für abweichende Layouts. Siehe CONTRIBUTING.md.
Register in Hermes:
hermes mcp add adisweb --command /abs/path/to/.venv/bin/python --args -m adisweb.mcp_serverClaude Desktop / Claude Code / ChatGPT: Schritt-für-Schritt-Anleitungen für diese Clients (inkl. Remote-MCP für ChatGPT) findest du in MCP_CLIENTS.md.
MCP example workflow
A full order cycle over the MCP tools (verified live on VÖBB):
Search a title:
search(query="One Piece 86")→ hits withid(e.g.AK34063780)Check availability per branch:
search_availability(query="One Piece 86", branch_filter="Else Ury")→ copies with branch/location/ signature/status/return datePlace an order (costs shown first, nothing ordered without
confirm=True):reserve(record_id_or_url="AK34063780", ausweis=…, password=…, pickup_branch="Friedrichshain-Kreuzberg: Familienbibliothek Else Ury", express=True, confirm=False)→ returns the quoted fee (e.g. "Kostenpflichtige Bestellung (2.00 EUR)"); re-run withconfirm=True(+ optionalmax_fee=5.0) to actually orderVerify in the account:
get_orders(ausweis=…, password=…)→{"orders": [...], "magazine_orders": [...]};get_loans(…)for borrowed items;get_account(…)for fees/validity
Library configs
Each library is a JSON file under libraries/:
{
"name": "Berlin",
"baseurl": "https://www.voebb.de/aDISWeb/app",
"startparams": "service=direct/0/Home/$DirectLink&sp=SPROD00",
"encoding": "UTF-8"
}Configs were imported from
opacapp/opacapp-config-files
(MIT) and updated with current endpoints discovered via web search
(BSZ symbolic sp=SOPACxx names, itk-rheinland, …). Add your own library by
dropping a JSON file into libraries/.
Library compatibility
All 46 bundled library configs were live-verified against the real OPACs
(see COMPATIBILITY.md and libraries-scan.json for the
full report):
BSZ consortium (Baden-Württemberg, ~24): Aalen_HS, Esslingen_HS, Freiburg_UB, Furtwangen_HS, Heidelberg_PH, Heilbronn_HS, Karlsruhe_BLB, Karlsruhe_Muho, Konstanz_HTWG, Loerrach_DHBW, Ludwigsburg_PH, Mannheim_Duale_Hochschule, Mannheim_HS, Mannheim_Muho, Mosbach_DHBW, Nuertingen_HfWU, Offenburg_HS, Pforzheim_HS, Ravensburg_DHBW, Reutlingen_Hochschulbibliothek, Schwaebisch_Gmuend_Paedagogische_Hochschule, Stuttgart, Stuttgart_Duale_Hochschule, Stuttgart_HdM, Stuttgart_HfT, Stuttgart_Muho, Stuttgart_Rathaus, Stuttgart_Uni, Stuttgart_WLB, Trossingen_Muho, Tuebingen_Uni, Ulm_Uni, Weingarten_HS
itk-rheinland: Dormagen, Dortmund, Duesseldorf, Grevenbroich, Meerbusch, Neuss
Other: Berlin (VÖBB), Herne, Muenchen, Nuernberg, Nuremberg_Bibliothek_des_Germanischen_Nationalmuseums, Regensburg, Zuerich
Feature coverage:
Search / detail / availability — verified on all 46 libraries.
Account (login, loans, orders, reservations, renewal) und Bestellungen (Express/Magazin/Ausgabeort) — nur für die VÖBB (Berlin) live getestet und verifiziert; für alle anderen Bibliotheken sind diese Funktionen nicht getestet (die aDISWeb-Layouts können abweichen). Andere Bibliotheken nutzen Cookie-Session oder klassischen Login.
Tests
# offline tests (recorded VÖBB fixtures)
.venv/bin/python -m pytest tests/ -q
# live scan of all 46 libraries (opt-in, hits the real OPACs)
ADISWEB_LIVE=1 .venv/bin/python -m pytest tests/test_live_scan.py -vOpenSpec
Capability specs and the change proposal live in openspec/.
License
GPL-3.0 (derived from opacapp/opacclient). Library configs under libraries/
are MIT (from opacapp/opacapp-config-files).
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
MCP server for Open Archives: Dutch genealogical records and historical page transcriptions.
Remote MCP server for OFAC screening, EDD memos, exposure forecasts, queues, and reports.
MCP server for Russian books search, details, and recommendation candidates.
Remote MCP server for product discovery catalog and retrieving product details.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables searching OpenAleph entities and documents using natural language queries through the MCP protocol.191MIT
- AlicenseAqualityDmaintenanceMCP server for searching Ex Libris Primo library catalogues and subscribed databases, enabling search, record retrieval, autocomplete, citation generation, and export to BibTeX, RIS, or CSV.57MIT
- AlicenseAqualityDmaintenanceA library management MCP server supporting book search, member management, and loan operations through natural language commands.134MIT
- FlicenseNot gradedqualityFmaintenanceAn MCP server that searches library catalogs worldwide using the SRU protocol, enabling bibliographic search without API keys.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/tilllt/adisweb-client'
If you have feedback or need assistance with the MCP directory API, please join our Discord server