{"server":{"name":"com.qurangallery/mcp","title":"Quran Gallery MCP","$schema":"https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json","remotes":[{"url":"https://qurangallery.com/mcp/shamela","type":"streamable-http","headers":[{"name":"Authorization","value":"Bearer {api_key}","isSecret":true,"variables":{"api_key":{"isSecret":true,"description":"Optional Quran Gallery API key (starts with qg_sk_).","placeholder":"qg_sk_..."}},"description":"Optional. Free Quran Gallery API key as a bearer token: 60 tool calls a minute with no daily cap, instead of the keyless 10 a minute and 200 a day. Create one at https://accounts.qurangallery.com/developers. Omit the header to use the server with no account."}]}],"version":"0.3.0","websiteUrl":"https://qurangallery.com/mcp","description":"Classical Islamic library (Shamela, 8,594 books): verbatim Arabic cited by volume and page. No key."},"_meta":{"io.modelcontextprotocol.registry/official":{"status":"active","isLatest":true,"updatedAt":"2026-10-16T09:18:29.842747Z","publishedAt":"2026-10-16T09:18:29.842747Z","statusChangedAt":"2026-10-16T09:18:29.842747Z"},"dev.protogrid/connectability":{"class":"R0","autonomous":true,"human_steps":[],"preferred":{"kind":"remote","idx":0},"remotes":[{"idx":0,"url":"https://qurangallery.com/mcp/shamela","transport":"streamable-http","templated":false,"headers":[{"name":"Authorization","required":false,"secret":true,"value":"Bearer {api_key}","secret_names":["api_key"]}],"auth":{"type":"none","location":null,"secret_name":null,"oauth":null},"protocol":{"supported_versions":["2026-07-28","2025-11-25","2025-06-18"],"stateless":true},"health":{"reachable":true,"uptime_30d":1,"latency_ms_p50":310,"consecutive_failures":0,"last_probe_at":"2026-10-19T12:08:55.887Z","last_ok_at":"2026-10-19T12:08:55.887Z"}}],"packages":[]},"dev.protogrid/tools":[{"name":"fetch","title":"Read a library page","description":"Read one library page whole by the id `search` returned: main text, then its footnotes under their own label (the editor's words, never the author's), with book, author, printed volume/page, edition data and the shamela.ws link. Use shamela_read instead to read one body part at a time (unit \"page\"), a run of pages (unit \"range\") or a whole chapter (unit \"section\"), and shamela_cite (mode \"printed_page\") to turn a printed volume and page into ids. Not a search. Long pages are cut at 4 body parts of about 4,000 characters (2 without an API key): metadata.complete false, ending with the shamela_read call that continues it. A malformed id, or a page the library does not hold, returns a tool error.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"search","title":"Quick generic search of the whole library","description":"Search the whole classical Islamic library (8,594 works, no scope) and get up to 10 pages as {id, title, url}; pass an id to `fetch` to read the page. This is the generic one-argument entry (the standard search/fetch pair); the scoped tools answer research questions better. Use shamela_search_library for a hadith, tafsir or fiqh question: unscoped ranking is by term frequency, so a poetry anthology can outrank Sahih al-Bukhari. Use shamela_search (match \"words\", \"phrase\", \"near\", \"exact\" or \"boolean\") to pin books, categories or a madhhab, match an exact or diacritized phrase, or page further; use shamela_cite (mode \"printed_page\") for printed-page citations. Exact phrase first; only when it finds nothing are the words matched separately. Title flags: [footnote match] = only an editor's footnote; [token match] = words occur apart; [near match] = only some words or their roots. Empty results mean no page carries the words. A query without Arabic words returns a tool error.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_cite","title":"Format a citation or resolve a printed page","description":"Citations. mode=citation (default): build one for a book, optionally a page and quoted text — Shamela's copy format, short inline, full with death year, or BibTeX/RIS. Call it whenever you attribute a quote; it needs only the catalogue, plus the installed text for a page's printed number. Read page_resolved, components.auto_numbered and notes[] before presenting.\nmode=printed_page: map a printed citation («vol. 4, p. 405») to the page_ids carrying it — no arithmetic relates the two, and one printed page often spans several ids: read them all, in order, with shamela_read(unit='page'). Resolve the work with shamela_find(kind='work') first; holding a page_id already, skip this. Failures come back as `status`; citable:false = Shamela's own numbering. Error: BOOK_NOT_FOUND.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_find","title":"Find books, headings, authors, categories or names","description":"Catalogue lookup — which books, headings, authors and shelves exist, not page text. `kind`:\n- book (default): titles, authors, publication lines, subject descriptions → book_ids, installed or not. no_title_match: not proof the book is held. downloaded:false → another edition (shamela_get_details(kind='book') same_group) or catalogue metadata only.\n- heading: chapter/section headings, i.e. where books treat a topic; open with shamela_read(unit='section', book_id, title_id). No hits = no heading carries the words: drop words or use shamela_search(match='words').\n- author: names and biographies → author_id, Hijri death year, book count; no scope. Empty is not absence: retry kunya, nisba or shuhra (ابن قدامة / الموفق / المقدسي).\n- category: the 41 flat shelves with catalogue and installed counts → scope.category_ids. A subject spans ids (Qur'anic studies 3 tafsir, 4 Qur'anic sciences/usul al-tafsir, 5 tajwid/qira'at; fiqh 14–17 by madhab): pass all that apply. downloaded_only:true when choosing shelves to search or read.\n- work: verify a cited title (optional author, edition); refuses rather than guesses; catalogue only, text need not be installed.\n- name: fuzzy best guess over book/author names, for an id; always answers, so never use it to verify a citation.\n- period: books by Hijri window, bounds ANDed (scope.period_* on searches unions them).\nRules: a parameter of another kind is refused; book/heading/author/period page with limit/offset until has_more is false. Instead: page text → shamela_search; a printed page → shamela_cite(mode='printed_page'); one book's headings → shamela_read(unit='toc').","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_get_brief","title":"Server capabilities and search pitfalls","description":"Return this server's machine-readable capability handshake: capabilities, numeric limits, retired tool names with their replacements, and traps (ways a result misleads, each with the response field that proves it fired). Call it first from a programmatic client: inputs are strict, so an argument an older build lacks (e.g. `shape`, response_format:'none') is a hard validation error that fails the whole call, and tools/list cannot reveal argument support — gate each new argument on its capability string. Cache by brief_hash and re-fetch only when it changes. Constants only: needs no library access and does not fail. Example: {} or {response_format:'json'}.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_get_details","title":"Get book or author details","description":"Catalogue record for one book (kind=book, default) or one author (kind=author), installed or not.\n- book: authors, category, type, printed-edition flag, whether the text is installed here, the scanned printing and the other editions of the same work (same_group). When a reader tool says BOOK_NOT_DOWNLOADED, pick an installed entry from same_group or answer from this record. Read book_date, edition, editor and publisher per their field notes: never supply a missing one.\n- author: name, Hijri death year (null = unknown or living) and every catalogued book they wrote or co-wrote, each flagged installed or not.\nVolumes → shamela_read(unit='parts'); a book by title or subject → shamela_find(kind='book'). Errors: BOOK_NOT_FOUND, AUTHOR_NOT_FOUND.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_lookup_hadith","title":"Find a hadith or the books that carry it","description":"Hadith. mode=search (default): find a hadith by its wording and trace its takhrij — searches the hadith shelves (Sunnah collections, commentaries, takhrij, hadith sciences) in matn and footnotes, reads hadith keys off the matching pages and lists every collection indexing the same hadith. No offset; if the full text matches nothing, one word is dropped and named in `relaxed`. Takhrij covers only key_index_books, so few rows is not proof of a weak or rare hadith.\nmode=sources: every book recording one hadith_key, with its page_id, one row per book in index order.\nA downloaded:false book is catalogued but not installed: use another edition (shamela_get_details(kind='book') same_group). Narrator chains → shamela_lookup_rijal(mode='isnad_search'); general text → shamela_search(match='words').","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_lookup_quran","title":"Search the Quran or get an ayah","description":"Qur'an text. mode=search (default): find verses by Arabic words, typed in إملائي spelling or pasted in Uthmani rasm; words ANDed, results in mushaf order (aya_id 1–6236), not relevance. Zero hits usually means a misspelling: drop a word or use options.wildcards.\nmode=aya: fetch verses you can already cite, by aya_id OR surah + aya (never both or neither: BAD_ARG); `count` gives a run that continues across surahs and stops at the last verse. Each verse in three renderings (body = the spelling search matches, amiri for display). AYA_NOT_FOUND names the valid range.\nCommentary → shamela_lookup_tafsir; the words inside books → shamela_search(match='words').","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_lookup_rijal","title":"Narrators and isnads","description":"Hadith narrators and isnad chains, from Shamela's rijal register and isnad index. `mode`:\n- narrators (default): a narrator by name → narrator_id, most-documented first, then earliest death year. Names collide: confirm the death year before using an id.\n- narrator: one dossier by narrator_id — lineage, death year, tabaqa, Ibn Hajar's and al-Dhahabi's grades, critics' jarh wa-ta'dil verdicts verbatim with source (the only paged part), hadith_notes on audition and irsal; include_network adds isnad-index counts per book and top teachers/students. Quote verdicts as worded; never synthesize a grade.\n- isnad_search: chains by the narrators in them — `contains` (anywhere) or `transmission` [teacher_id, student_id] pairs that must be adjacent (direct audition, the stronger test) — each hit with book, page, hadeeth_key and the chain.\n- isnad: the chain(s) printed on one page (book_id/page_id from a search hit) with names and death years, plus the same hadith's other routes — one thread or many.\nRules: a parameter of another mode is refused. Chains run ascending (Companion first, collector last). Only ten hadith books are isnad-indexed (see scope_book_ids): an empty isnad_search means no such chain in those ten, not in all literature; most pages answer no_isnad_indexed:true with a no_isnad_reason, not an error. Errors: RIJAL_UNAVAILABLE (register not installed), NARRATOR_NOT_FOUND (search the name again), BOOK_NOT_FOUND, PAGE_NOT_FOUND, BOOK_NOT_DOWNLOADED (try shamela_get_details(kind='book') same_group).\nInstead: book authors → shamela_find(kind='author'); a hadith by its text → shamela_lookup_hadith(mode='search').","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_lookup_tafsir","title":"Tafsir coverage and texts for an ayah","description":"Tafsir on one verse (aya_id OR surah + aya, else BAD_ARG). mode=coverage (default): which tafsir books cover it, fetching no text — shelves 3 (tafsir) and 4 (Qur'anic sciences; not 5, tajwid and qira'at) crossed with Shamela's curated tafsir index, plus index hits from other shelves (in_tafsir_categories:false). Status per book: indexed_covers (with page_id), indexed_no_entry_for_this_aya, or not_indexed_coverage_unknown — NOT evidence the book is silent.\nmode=texts: the commentary from several books in one call, each attributed (book, author, death year, printed page), read only from pages the index maps to the verse, never a text-search guess. Each source's `note` names the next call when its text continues. Example: {surah:2, aya:255, book_ids:[1503, 639]}.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_read","title":"Read pages, sections and tables of contents","description":"Read an installed book's text and structure by internal ids. `unit`:\n- page (default): one page_id → body (author's matn), foot (editor's footnotes), printed page label, prev/next page ids, enclosing headings.\n- range: up to 20 consecutive pages from start_page_id, each with text, footnotes, printed page — to read on past a hit or through a span.\n- section: one chapter by title_id with its sub-headings, up to the next heading outside it.\n- toc: headings with their title_ids; top level by default, parent_id/depth expand, containing_page_id gives the chain enclosing a page.\n- parts: volumes — part label, page count, first/last page_id.\n- services: what one page cites (aya ids, hadith keys, isnad markers, as stored) → shamela_lookup_quran(mode='aya'), shamela_lookup_hadith(mode='sources'), shamela_lookup_rijal(mode='isnad').\nRules: a parameter of another unit is refused. page_id is not the printed page and ids have gaps: step with prev_page_id/next_page_id, not ±1; for a printed «vol./page» call shamela_cite(mode='printed_page') first. A size budget cuts long text: follow body_has_more (body_part+1) or next_start_page_id. Errors: PAGE_NOT_FOUND (also a range start past the end), TITLE_NOT_FOUND, BOOK_NOT_FOUND, BOOK_NOT_DOWNLOADED (catalogued, not installed: use an installed edition from shamela_get_details(kind='book') same_group).\nInstead: a heading by its words → shamela_find(kind='heading'); books of untitled «فصل» headings → shamela_search(match='words') scoped to the book; any catalogued book's metadata → shamela_get_details(kind='book').","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_search","title":"Search page text (words, phrase, exact, boolean, batch)","description":"Full-text search inside the pages (matn and footnotes) of installed books. `match` picks how the query is read:\n- words (default): every word required, ranked by relevance; options add morphology, wildcards, chronological sort. An all-words miss retries with fewer words (relaxed_min_match).\n- phrase: the words consecutively (a quotation). near: all words within `distance`, any order. Both verified in the full page text.\n- exact: diacritics, hamza/alef forms or digit systems kept distinct («أحمد» not «احمد», «عِلْم» not «عَلَم», ٢٥٥ not 255); set at least one `preserve` flag.\n- boolean: every all_of term, one or more any_of, no none_of (الوقف with المسجد or المقبرة, without البيع); one query over the whole index, so total_hits is exact and exclusion exhaustive.\n- batch: 1–24 scoped `queries` run at once, merged and deduped by page (probe_ids); no paging, cut at max_total_passages.\nRules: a parameter of another match value is refused. Page with limit/offset until has_more is false. scope.madhab drops books of unknown school: omit it for comparative questions; set scope.citable_only before quoting a page number. Follow-up rounds: exclude_pages / exclude_work_group_ids keep out pages already used and other printings of the same work. EMPTY_SCOPE: the scope matched no book.\nInstead: chapter headings → shamela_find(kind='heading'); titles → shamela_find(kind='book'); verses → shamela_lookup_quran(mode='search'); a hadith's wording → shamela_lookup_hadith(mode='search').\nExample: {query:'استصناع', scope:{category_ids:[17]}}.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_search_library","title":"Search the classical Islamic library","description":"Search one named shelf of the classical Islamic library (8,594 works) for quotable passages: verbatim Arabic with book, author, printed volume/page, edition and a shamela.ws link. The default first search for hadith, tafsir, fiqh or creed. Not for isnads, narrators or diacritic-exact wording. Use shamela_search (match \"words\") to pin books or categories or to page past 10 results, shamela_read (unit \"page\") to read a whole page. Scope is one shelf per call; call again with another shelf to widen. Ranking: exact phrase first, then all the words; a madhhab scope asks that school's own books first; main text before footnote. relaxedToTokens and note flag a weaker match; no passages means absent from that scope, not from the library. A non-Arabic query or unknown scope returns a tool error naming the fix.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"},{"name":"shamela_survey_topic","title":"Survey a topic across the library","description":"Count how much the library holds on a term and where: the exact matching-page total plus its distribution by category, Hijri century, book and author (top 15 each). Statistics only, never passages — use shamela_search(match='words') instead to retrieve and read the pages. Run it before searching to size a topic and pick scope.category_ids (map by_category names to ids with shamela_find(kind='category')). mode 'literal' (default, 6–9 ms) counts the word as written; 'morphological' counts every derived form of its root (seconds) and is often far broader. coverage_capped:true means the breakdown is a top-5,000 sample whose counts are floors; total_hits stays exact. No match = total_hits 0; EMPTY_SCOPE when scope matches no book. Example: {term:'الاستصناع', scope:{category_ids:[14,15,16,17]}}; {term:'التيمم', scope:{citable_only:true}}.","annotations":{"readOnlyHint":true,"openWorldHint":false,"idempotentHint":true,"destructiveHint":false},"source":"probe","observed_at":"2026-10-19T12:08:55.887Z"}],"dev.protogrid/trust":{"score":83,"components":{"hygiene":80,"liveness":100,"freshness":100,"provenance":55},"drivers":["+dns-namespace","+website","+reachable","+uptime-100%","+updated-3d-ago","-no-repository"],"flags":["no-repository"],"blocked":false,"computed_at":"2026-10-19T14:14:19.044Z","disclaimer":"Derived from observable signals (official registry feed and our own credential-free probes); no code audit performed."},"dev.protogrid/quality":{"score":92,"label":"new","components":{"auth":null,"hygiene":86,"protocol":100,"stability":null,"dependencies":null},"checks":[{"id":"protocol.modern","detail":"supports 2026-07-28 (server/discover)","status":"pass","category":"protocol"},{"id":"protocol.stateless","detail":"answers without a session","status":"pass","category":"protocol"},{"id":"protocol.transport","detail":"streamable HTTP","status":"pass","category":"protocol"},{"id":"protocol.list_ttl","detail":"tool list is cacheable (ttlMs 300000)","status":"pass","category":"protocol"},{"id":"auth.prm","detail":"no remote uses OAuth","status":"na","category":"auth"},{"id":"auth.as_metadata","detail":"no remote uses OAuth","status":"na","category":"auth"},{"id":"auth.cimd","detail":"no remote uses OAuth","status":"na","category":"auth"},{"id":"auth.secret_in_url","detail":"no templated URL","status":"na","category":"auth"},{"id":"tools.descriptions","detail":"every tool has a description","status":"pass","category":"hygiene"},{"id":"tools.description_length","detail":"4 tools have descriptions over 1,024 characters, which crowds the context","status":"warn","category":"hygiene"},{"id":"tools.schemas","detail":"every tool has an object input schema","status":"pass","category":"hygiene"},{"id":"tools.annotations","detail":"14 of 14 tools declare readOnlyHint or destructiveHint","status":"pass","category":"hygiene"},{"id":"tools.directory_hints","detail":"every tool declares readOnlyHint, destructiveHint, idempotentHint and openWorldHint","status":"pass","category":"hygiene"},{"id":"tools.token_cost","detail":"about 20,035 tokens to load every tool","status":"warn","category":"hygiene"},{"id":"tools.api_dump","detail":"tools are not a one-to-one API dump","status":"pass","category":"hygiene"},{"id":"stability.changes","detail":"tool history recorded for 4 of the 7 days needed","status":"na","category":"stability"},{"id":"stability.rug_pull","detail":"tool history recorded for 4 of the 7 days needed","status":"na","category":"stability"},{"id":"deps.known_vulns","detail":"no npm or PyPI package","status":"na","category":"dependencies"},{"id":"deps.mcp_sdk_version","detail":"no npm or PyPI package","status":"na","category":"dependencies"},{"id":"deps.resolvable","detail":"no npm or PyPI package","status":"na","category":"dependencies"}],"drivers":["~tools.description_length","~tools.token_cost"],"flags":[],"tool_count":14,"token_estimate":20035,"tools_hash":"4bdce49bbf3548b3e3d49c5d14fa4375","tools_changed_at":"2026-10-16T06:47:56.475Z","computed_at":"2026-10-19T14:10:15.286Z","disclaimer":"Checks run on what our credential-free, read-only probes observe; tools are never called and no code audit is performed."},"dev.protogrid/identity":{"canonical_id":"com.qurangallery/mcp","aliases":[],"alias_count":0,"repository_key":null,"owner":{"verified":false,"method":null,"since":null}}},"next_actions":[{"action":"list_tools","description":"Every current tool with input schemas","href":"/v1/servers/com.qurangallery%2Fmcp/tools","arguments":{"name":"com.qurangallery/mcp"}},{"action":"get_connection","description":"Minimal connection block for the preferred remote or package","href":"/v1/servers/com.qurangallery%2Fmcp/connection?target=mcpServers","arguments":{"name":"com.qurangallery/mcp","target":"mcpServers"}},{"action":"search","description":"Find other servers by intent","href":"/v1/search?q={query}","arguments":{"q":"{query}"}}]}