Quran Gallery MCP
REMOTE · QURANGALLERY.COM
Classical Islamic library (Shamela, 8,594 books): verbatim Arabic cited by volume and page. No key.
Available components
Last scanned (6 hours ago)
Scores higher than 59% of remote servers
Reachable. Last reached 24 Oct 2026.
Category Education and Research
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security74
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- No authorisation is required to call this server. Every tool declares its destructiveHint and none is destructive, so open access doesn't expose one. See how to fix → View diagnostics → Partial
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- HSTS check failed: the Strict-Transport-Security header is absent. See how to fix → View diagnostics → Fail
- DNSSEC check failed: this domain isn't protected by DNSSEC. See how to fix → View diagnostics → Fail
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability71
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 13768 tokens (~917/item across 15 items; 14 tools + 1 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management0
- Stability check failed: schema churn in the 9 days we've observed: 37 tool removals, 0 breaking changes, 0 auth/transport breaks, 12 additions. See how to fix → Fail
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 14 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 16 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 16 Oct 26 −1
- Stability: unverified → fail ▼ security
- Tool “search_library” was removed ▼ security
- Tool “shamela_books_by_period” was removed ▼ security
- Tool “shamela_brief” was removed ▼ security
- Tool “shamela_get_author” was removed ▼ security
- Tool “shamela_get_aya” was removed ▼ security
- Tool “shamela_get_book” was removed ▼ security
- Tool “shamela_get_book_parts” was removed ▼ security
- Tool “shamela_get_book_section” was removed ▼ security
- Tool “shamela_get_books_for_hadith” was removed ▼ security
- Tool “shamela_get_citation” was removed ▼ security
- Tool “shamela_get_isnad” was removed ▼ security
- Tool “shamela_get_narrator” was removed ▼ security
- Tool “shamela_get_page” was removed ▼ security
- Tool “shamela_get_page_services” was removed ▼ security
- Tool “shamela_get_pages_range” was removed ▼ security
- Tool “shamela_get_tafseer_of_aya” was removed ▼ security
- Tool “shamela_get_tafseer_texts” was removed ▼ security
- Tool “shamela_get_toc” was removed ▼ security
- Tool “shamela_list_categories” was removed ▼ security
- Tool “shamela_list_tafsirs_for_aya” was removed ▼ security
- Tool “shamela_recon” was removed ▼ security
- Tool “shamela_resolve” was removed ▼ security
- Tool “shamela_resolve_printed_page” was removed ▼ security
- Tool “shamela_resolve_work” was removed ▼ security
- Tool “shamela_root_stats” was removed ▼ security
- Tool “shamela_search_authors” was removed ▼ security
- Tool “shamela_search_batch” was removed ▼ security
- Tool “shamela_search_books” was removed ▼ security
- Tool “shamela_search_boolean” was removed ▼ security
- Tool “shamela_search_exact” was removed ▼ security
- Tool “shamela_search_hadith” was removed ▼ security
- Tool “shamela_search_isnad” was removed ▼ security
- Tool “shamela_search_narrators” was removed ▼ security
- Tool “shamela_search_pages” was removed ▼ security
- Tool “shamela_search_phrase” was removed ▼ security
- Tool “shamela_search_quran” was removed ▼ security
- Tool “shamela_search_titles” was removed ▼ security
- The server rewrote its instructions, which are the text every model session reads security
- Tool “fetch” rewrote its description, which is the text the model reads security
- Tool “search” rewrote its description, which is the text the model reads security
- Schema quality: 535 → 917 ▼ functional
- Tool coverage: 18% → 100% ▲ functional
- Stability: unverified → 0.03 ▲ functional
- Server version: 0.2.0 → 0.3.0 functional
- New tool “shamela_cite” functional
- New tool “shamela_find” functional
- New tool “shamela_get_brief” functional
- New tool “shamela_get_details” functional
- New tool “shamela_lookup_hadith” functional
- New tool “shamela_lookup_quran” functional
- New tool “shamela_lookup_rijal” functional
- New tool “shamela_lookup_tafsir” functional
- New tool “shamela_read” functional
- New tool “shamela_search” functional
- New tool “shamela_search_library” functional
- New tool “shamela_survey_topic” functional
- “fetch” reworded the description of “id” cosmetic
- “search” reworded the description of “query” cosmetic
- Tool “search” changed its title: Search the whole library (deep research) → Quick generic search of the whole library cosmetic
- 15 Oct 26 71
First indexed and scored.
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 24 Oct 2026 · Probed https://qurangallery.com/mcp/shamela
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=qurangallery.com | CN=WE1,O=Google Trust Services,C=US | 8 Sept 2026 | 7 Dec 2026 | ECDSA 256 | ECDSA-SHA256 | 263dd67787229dac0edaab06e4ce7542 |
| SANs: qurangallery.com, rt.qurangallery.com, *.rt.qurangallery.com | ||||||
| CN=WE1,O=Google Trust Services,C=US (CA) | CN=GTS Root R4,O=Google Trust Services LLC,C=US | 13 Dec 2023 | 20 Feb 2029 | ECDSA 256 | ECDSA-SHA384 | 7ff31977972c224a76155d13b6d685e3 |
| CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) | CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE | 15 Nov 2023 | 28 Jan 2028 | ECDSA 384 | SHA256-RSA | 7fe530bf331343bedd821610493d8a1b |
Background: What to check on a remote MCP endpoint →
DNSSEC insecure
Validation of qurangallery.com. — Not signed
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | trust_anchor | 20326, 38696 | 8, 8 | Verified |
| com. | present | 19718 | 13 | Verified |
| qurangallery.com. | absent | Unsigned (proven) parent-signed NSEC/NSEC3 proves an unsigned delegation |
Authentication No authorisation required
The endpoint answered without asking for a token. Anyone who knows the URL can reach it.
| Result | No authorisation required |
|---|---|
| HTTP status | 200 |
| Header | Value |
|---|---|
| x-content-type-options | nosniff |
| x-frame-options | SAMEORIGIN |
| referrer-policy | strict-origin-when-cross-origin |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://qurangallery.com/mcp/shamela | Verified | 200 | |
| http (plaintext) | http://qurangallery.com/mcp/shamela | HTTPS enforced | 301 | https://qurangallery.com/mcp/shamela |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
fetch Read a library page ~227
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.
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | yes | Page id "{bookId}:{pageId}", e.g. "1681:10" — Shamela internal ids from a `search` result, not printed page numbers. Malformed or unknown ids return a tool error. |
| Name | Type | Req | Description |
|---|---|---|---|
| id | string | – | "{bookId}:{pageId}", normalised. |
| metadata | object | – | – |
| text | string | – | Main text, then the footnotes under their own label (the editor's words). When metadata.complete is false it ends with the shamela_read(unit='page') call that continues it. |
| title | string | – | "{book} — {author} ({volume}/{page})". |
| url | string | – | The same page on shamela.ws. |
No examples provided.
search Quick generic search of the whole library ~284
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.
| Name | Type | Req | Description |
|---|---|---|---|
| query | string | yes | Arabic search text, e.g. "إنما الأعمال بالنيات"; 2-6 words work best. Quote the wording if known, else name the topic. |
| Name | Type | Req | Description |
|---|---|---|---|
| results | array | – | At most 10 pages; empty when no page carries the words. |
No examples provided.
shamela_cite Format a citation or resolve a printed page ~864
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. mode=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.
| Name | Type | Req | Description |
|---|---|---|---|
| book_id | integer | – | [mode=citation] The book id, from shamela_find(kind='book'), shamela_find(kind='work') or shamela_find(kind='name'). [mode=printed_page] The book. Resolve a cited title with shamela_find(kind='work')… |
| mode | string | – | Selects what the call does: citation | printed_page. Default citation. |
| page | integer | – | The PRINTED page number as the citation gives it (e.g. 405). Example: {book_id:6910, part:'4', page:405}; {book_id:1681, part:'1', page:6}. (mode=printed_page only.) |
| page_id | integer | – | Optional page_id. When omitted, the citation references the book without a specific page and page_resolved is null. A page id that is missing, has no printed number, or belongs to a book whose text i… |
| part | string | – | The volume/part label as the book uses it, usually a bare number ('4'). Omit when the citation names no volume or the work is single-volume: the search then runs across every part and the response re… |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| style | string | – | Citation style. 'shamela' replicates Shamela's UI copy-with-citation format (default). 'short' is a one-line inline reference. 'full' is the long form including author death year and book year, with… |
| text | string | – | Optional quoted text. Used by the 'shamela' style only, which then prints a two-line block: «<book>» (<part>/ <page>): «<text>». Other styles ignore it. (mode=citation only.) |
| Name | Type | Req | Description |
|---|---|---|---|
| available_parts | array | – | On part_not_found: the part labels the book uses. (mode=printed_page only.) |
| book_id | number|null | – | Catalogue book id. (mode=printed_page only.) |
| book_name | string|null | – | Catalogue title of the book (Arabic). (mode=printed_page only.) |
| citable | boolean|null | – | False when the numbers are Shamela's own, not a printed edition's. (mode=printed_page only.) |
| components | object | – | The parts the citation was built from. (mode=citation only.) |
| formatted | string|null | – | The citation text in the requested style. (mode=citation only.) |
| matches | array | – | One row per page id. (mode=printed_page only.) |
| notes | array | – | [mode=citation] Missing citation fields and fallbacks; never fill them in. [mode=printed_page] Guidance on reading the result. |
| page_ids | array | – | Every page id carrying the printed page, in reading order; read them all. Shamela splits a long printed page across records, so one page routinely has several ids (part '1', page 6 of book 1681 = ids… |
| page_range | object | – | On page_not_in_part: the printed range that exists in that part. (mode=printed_page only.) |
| page_resolved | boolean|null | – | True when the page and its printed number were found; false when the citation fell back to book level (see notes) and must not be presented as a page reference; null when no page_id was given. (mode=… |
| parts_matched | array | – | Distinct parts matched; more than one means the number is ambiguous across volumes. (mode=printed_page only.) |
| requested_page | number|null | – | Printed page requested. (mode=printed_page only.) |
| requested_part | string|null | – | Part label requested; null when omitted. (mode=printed_page only.) |
| rows_dropped | array | – | – |
| status | string|null | – | 'ok', 'book_not_downloaded', 'no_printed_pagination' (Shamela paginates this entry itself: no printed page exists), 'part_not_found' or 'page_not_in_part'. (mode=printed_page only.) |
| style | string|null | – | 'shamela', 'short', 'full', 'bibtex' or 'ris'. (mode=citation only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
No examples provided.
shamela_find Find books, headings, authors, categories or names ~2,234
Catalogue lookup — which books, headings, authors and shelves exist, not page text. `kind`: - 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. - 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'). - author: names and biographies → author_id, Hijri death year, book count; no scope. Empty is not absence: retry kunya, nisba or shuhra (ابن قدامة / الموفق / المقدسي). - 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. - work: verify a cited title (optional author, edition); refuses rather than guesses; catalogue only, text need not be installed. - name: fuzzy best guess over book/author names, for an id; always answers, so never use it to verify a citation. - period: books by Hijri window, bounds ANDed (scope.period_* on searches unions them). Rules: 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').
| Name | Type | Req | Description |
|---|---|---|---|
| author | string | – | The author as cited, when known. This is a FILTER, not a hint: a candidate whose author cannot be reconciled with it is rejected rather than ranked down, because that is exactly how a commentary gets… |
| category_id | integer | – | Optional: restrict to one category (use shamela_find(kind='category') for IDs). Categories are flat in master.db. Example: {died_from:600, died_to:700, category_id:17}. (kind=period only.) |
| composed_from | integer | – | Hijri year, inclusive LOWER bound on book.book_date — Shamela's «تاريخ الكتاب». NOT an independent composition year: it holds the main author's death year on 98.5% of dated books (8,461/8,587), so pa… |
| composed_to | integer | – | Hijri year, inclusive UPPER bound on book.book_date («تاريخ الكتاب»; see composed_from — it is not a composition year). Pair with composed_from. (kind=period only.) |
| died_from | integer | – | Hijri year, inclusive LOWER bound on the MAIN AUTHOR's death year (author.death_number). A different column from composed_*, but the same number on 98.5% of dated books. Pair with died_to. At least o… |
| died_to | integer | – | Hijri year, inclusive UPPER bound on the MAIN AUTHOR's death year (author.death_number). Pair with died_from. (kind=period only.) |
| downloaded_only | boolean | – | [kind=category] If true, list only categories with at least one book installed on this server. Useful to see where the installed library is concentrated across the 41 categories. Default: false. [kin… |
| edition | string | – | A specific printing, as the catalogue names it: 'ط السلطانية', 'ت البغا', 'ط التأصيل'. If no entry carries it you get status='not_found' with reason='edition_not_found' and the editions that DO exist… |
| include_counts | boolean | – | If true (default), include book_count for each category; false returns book_count 0. Costs nothing either way — counts are precomputed. downloaded_count is always filled. (kind=category only.) |
| kind | string | – | Selects what the call does: book | heading | author | category | work | name | period. Default book. |
| limit | integer | – | [kind=book|heading|author|period] Maximum number of results to return (1-100, default 20). [kind=work] Maximum candidates to report (1-50, default 20). [kind=name] Maximum results per list (1–20, def… |
| offset | integer | – | Number of results to skip for pagination. Use with `limit` to page through large result sets. The response includes `has_more` and `next_offset` to drive paging. Default: 0. (kind=book|heading|author… |
| options | object | – | [kind=book] morphology / wildcards / sort / relax_when_empty. [kind=heading] morphology / wildcards / sort ('chronological' = earliest author first); headings are matched in folded form only. [kind=a… |
| query | string | – | [kind=book] Arabic words matched against book name + author + bibliography and the editorial subject description; each hit's `matched_in` says which. 1,729 entries carry a description (~1,500 charact… |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| scope | object | – | [kind=book] Restrict to authors, categories, a Hijri period (period_from/period_to) or downloaded_only (books whose text is installed); scope.book_ids is not accepted. E.g. {query:'فقه', scope:{categ… |
| title | string | – | The work's title as cited, e.g. «صحيح البخاري», «المغني», «فتح الباري». Leading words only — the title, not a description of it. You may include the catalogue's own edition tail, with the « - » («صحي… |
| type | string | – | 'book' matches catalogue titles only, 'author' author names only, 'any' (default) both, returned as separate books[] and authors[] lists. Reads the s_book/ and s_author/ n-gram indexes (fast partial… |
| Name | Type | Req | Description |
|---|---|---|---|
| ambiguity | string|null | – | When ambiguous: 'edition' — one work in several printings: search them as one scope, cite one; 'work' — different books that nothing may choose between («المغني»: al-Dhahabi's book of weak narrators… |
| author | string|null | – | Author filter applied; null when none. (kind=work only.) |
| authors | array | – | Author matches, best first. (kind=name only.) |
| available_editions | array | – | When edition_not_found: the printings the catalogue does carry, shaped like candidates. (kind=work only.) |
| book_ids | array | – | This page's ids, ready for scope.book_ids. (kind=period only.) |
| books | – | – | [kind=name] Book matches, best first. [kind=period] book_id, book_name, main author + death year, book_date, category, downloaded; sorted by book_id. (kind=name|period only.) |
| candidates | array | – | Entries that carry the requested title. (kind=work only.) |
| categories | array | – | Categories by id. (kind=category only.) |
| coverage | object | – | Hits rolled up by_category and by_century. (kind=book only.) |
| downloaded_total | number|null | – | Books installed on this server, whole library. (kind=category only.) |
| edition | string|null | – | Edition requested; null when none. (kind=work only.) |
| filter | object | – | Echo of the applied constraints. (kind=period only.) |
| has_more | boolean | – | [kind=book|heading|author] True when another page exists; call again with `next_offset`. [kind=period] True when more rows exist past this page. (kind=book|heading|author|period only.) |
| match | object | – | The single entry, when status is 'exact'. (kind=work only.) |
| next_offset | number | – | [kind=book|heading|author] Offset of the next page. Absent on the last page. [kind=period] Offset for the next page; present only when has_more is true. (kind=book|heading|author|period only.) |
| no_confident_match | object | – | Present when nothing reached score 800 (no name carries the whole query): treat the hits as suggestions. (kind=name only.) |
| no_title_match | boolean | – | True when no returned title carries every query word: hits match by some words or by description, not proof the book is held. (kind=book only.) |
| normalized_tokens | array | – | [kind=book|heading|author] The query after Arabic folding, as actually searched. [kind=name] Tokens after Arabic normalisation. (kind=book|heading|author|name only.) |
| notes | array | – | Guidance on using the result. (kind=work only.) |
| offset | number | – | [kind=book|heading|author] Offset this page started at. [kind=period] Rows skipped before this page. (kind=book|heading|author|period only.) |
| paging_ceiling | number | – | Deepest offset paging can reach. Present only when the request went past it: narrow the scope instead of paging further. (kind=book|heading|author only.) |
| query | string|null | – | The query as received. (kind=book|heading|author|name only.) |
| reason | string|null | – | When not_found: 'no_title_match', 'author_mismatch' or 'edition_not_found'. (kind=work only.) |
| rejected | array | – | Entries that matched the words but are not the cited work. (kind=work only.) |
| relaxed_min_match | number | – | Set when no entry held every word: hits carry at least this many of `relaxed_of_terms`. (kind=book only.) |
| relaxed_of_terms | number | – | Word count the relaxed match is measured against. (kind=book only.) |
| results | array | – | [kind=book] Catalogue entries: book_id, book_name, author_name, category, book_date, downloaded (false = text not installed on this server), snippet, matched_in ('bibliography' | 'description' | null… |
| returned | number | – | [kind=book|heading|author] Rows in `results` on this call. [kind=period] Rows in this response. (kind=book|heading|author|period only.) |
| rows_dropped | array | – | – |
| status | string|null | – | 'exact' — use `match`; 'ambiguous' — see `ambiguity`; 'not_found' — read `reason` (and available_editions for an unknown edition). (kind=work only.) |
| terms_truncated | boolean | – | True when the query had more words than are searched. (kind=book|heading|author only.) |
| title | string|null | – | Title as parsed from the request. (kind=work only.) |
| total | number|null | – | [kind=category] Categories listed. [kind=period] Books satisfying every bound. (kind=category|period only.) |
| total_hits | number | – | Every match in scope, not just the rows returned. (kind=book|heading|author only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
No examples provided.
shamela_get_brief Server capabilities and search pitfalls ~249
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'}.
| Name | Type | Req | Description |
|---|---|---|---|
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| Name | Type | Req | Description |
|---|---|---|---|
| brief_hash | string | – | Digest of every other field; re-fetch only when it changes. |
| capabilities | array | – | Arguments and response fields this build supports; gate new arguments on these. |
| limits | object | – | Numeric server limits by name. |
| rows_dropped | array | – | – |
| server_version | string | – | This build's version. |
| tool_aliases | object | – | Retired tool names mapped to their replacement and argument changes. |
| traps | array | – | – |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
No examples provided.
shamela_get_details Get book or author details ~540
Catalogue record for one book (kind=book, default) or one author (kind=author), installed or not. - 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. - author: name, Hijri death year (null = unknown or living) and every catalogued book they wrote or co-wrote, each flagged installed or not. Volumes → shamela_read(unit='parts'); a book by title or subject → shamela_find(kind='book'). Errors: BOOK_NOT_FOUND, AUTHOR_NOT_FOUND.
| Name | Type | Req | Description |
|---|---|---|---|
| author_id | integer | – | The author id (e.g. 474 for Ibn Qudama, 57 for Ibn Uthaymeen), from shamela_find(kind='name') with type 'author' or a book's authors[]. A catalogue id, not a death year or book id; shamela_find(kind=… |
| book_id | integer | – | The book id (e.g. 9942). (kind=book only.) |
| include_books | boolean | – | If true (default), include every catalogued book by this author, main or co-author, ordered by book_id. False returns name and death year only. (kind=author only.) |
| include_cover | boolean | – | Attach the book's cover image as an MCP image block when Shamela ships one (1,368 of 8,594 books). The picture is a ~310x460 thumbnail of the scanned printing's title page, so it costs roughly 190 im… |
| kind | string | – | Selects what the call does: book | author. Default book. |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| Name | Type | Req | Description |
|---|---|---|---|
| author_id | number|null | – | Author id. (kind=author only.) |
| author_name | string|null | – | Author name. (kind=author only.) |
| authors | array | – | Authors, main author first. (kind=book only.) |
| available | boolean|null | – | True when Shamela offers the book for download. (kind=book only.) |
| book_count | number|null | – | Number of catalogue books (main or co-author). (kind=author only.) |
| book_date | number|null | – | Shamela «تاريخ الكتاب», Hijri; on 98.5% of dated books the main author's death year, not a composition year: never cite it as one. (kind=book only.) |
| book_id | number|null | – | Catalogue book id. (kind=book only.) |
| book_name | string|null | – | Catalogue title of the book (Arabic). (kind=book only.) |
| book_type | number|null | – | Numeric book type. (kind=book only.) |
| book_type_label | string|null | – | Book type in Arabic: printed, manuscript, journal, thesis, electronic or audio. (kind=book only.) |
| books | array | – | The author's books by ascending book_id; empty when include_books is false. (kind=author only.) |
| category | string|null | – | Category name. (kind=book only.) |
| category_id | number|null | – | Category id (see shamela_find(kind='category')). (kind=book only.) |
| content_status | string|null | – | 'readable', 'downloaded_no_pages' or 'not_downloaded'. (kind=book only.) |
| cover | – | – | Title-page thumbnail of the scanned printing; null when none. Says nothing about the real binding or whether a scan exists (377 books have a `scan` but no cover): read `scan`. (kind=book only.) |
| death_text | string|null | – | Death date as display text. (kind=author only.) |
| death_year | number|null | – | Hijri death year; null when unknown or living. (kind=author only.) |
| downloaded | boolean|null | – | True only when the text is installed on this server and has pages. (kind=book only.) |
| edition | string|null | – | Edition read from the book's front matter; null when absent. Never invent one. (kind=book only.) |
| editor | string|null | – | Editor (محقق) from the front matter; null when absent. (kind=book only.) |
| notes | array | – | Caveats, including citation fields the catalogue lacks. (kind=book only.) |
| pdf_links | string|null | – | Raw scan descriptor from the catalogue; prefer `scan`. (kind=book only.) |
| printed | number|null | – | 1 when page numbers follow a printed edition; otherwise Shamela numbers the pages itself. (kind=book only.) |
| publication_date | string|null | – | Hijri publication date, DDMMYYYY, from meta_data, when recorded. (kind=book only.) |
| publisher | string|null | – | Publisher from the front matter; null when absent. (kind=book only.) |
| rows_dropped | array | – | – |
| same_group | array | – | Other catalogue entries of the same work (editions, abridgments: Sahih al-Bukhari is 8, five editions and three abridgments). Quotes from two of them are one source. (kind=book only.) |
| scan | – | – | The scanned printing Shamela holds; null when none. (kind=book only.) |
| sub_books | array | – | Catalogue ids of books bound inside this one. (kind=book only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
No examples provided.
shamela_lookup_hadith Find a hadith or the books that carry it ~846
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. mode=sources: every book recording one hadith_key, with its page_id, one row per book in index order. A 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').
| Name | Type | Req | Description |
|---|---|---|---|
| downloaded_only | boolean | – | If true (default), only return books whose text is installed on this server. false also lists catalogue-only editions (downloaded:false); `total` counts both either way. (mode=sources only.) |
| hadith_key | integer | – | Numeric hadith key (the normalized identifier Shamela uses across collections — e.g. 1234). Different collections of the same hadith share this key. Take it from shamela_lookup_hadith(mode='search'),… |
| limit | integer | – | Maximum number of results to return (1-100, default 20). (mode=search only.) |
| max_pages_scanned | integer | – | How many top text matches (by relevance) to scan for hadith service keys. This is the only result window: `matches` never exceeds it whatever `limit` says, and there is no offset. Default: 20. Raise… |
| mode | string | – | Selects what the call does: search | sources. Default search. |
| query | string | – | The hadith text (or a distinctive part of it). AND-combines words across matn + footnotes. Hadith keys come from each matching page's service annotations, takhrij from hadeeth.db. E.g. {query:'إنما ا… |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| search_all_categories | boolean | – | Search the ENTIRE library instead of the hadith shelves (كتب السنة، شروح الحديث، التخريج، علوم الحديث). Off by default because unscoped ranking buries the collections under works that merely quote th… |
| Name | Type | Req | Description |
|---|---|---|---|
| books_searched | number | – | Books the text search covered: the hadith shelves (كتب السنة، شروح الحديث، التخريج والأطراف، علوم الحديث), 1,957 here. (mode=search only.) |
| hadith_key | integer | – | (mode=sources only.) |
| index_entries | integer | – | Raw index rows behind `total`. (mode=sources only.) |
| key_index_books | number | – | Books hadeeth.db indexes hadith keys for (ten here); takhrij can only come from these, so a hadith on 1,746 pages can still yield takhrij from ten books. (mode=search only.) |
| matches | array | – | Matching pages, key-bearing first: book_id, book_name, page_id, snippet (often showing the printed takhrij, «رواه البخاري ومسلم»), snippet_source ('matn' | 'footnote'), matched_in, hadith_keys (read… |
| pages_scanned | number | – | Top matches read for hadith keys (<= max_pages_scanned). (mode=search only.) |
| query | string | – | The query as received. (mode=search only.) |
| relaxed | object | – | Present when the full text matched nothing and one word was dropped. (mode=search only.) |
| results | array | – | One row per book, in index order, with its first page for the hadith. (mode=sources only.) |
| returned | integer | – | Rows in `results` after downloaded_only. (mode=sources only.) |
| rows_dropped | array | – | – |
| searched | string | – | 'hadith_shelves' (default) or 'whole_library' (search_all_categories). (mode=search only.) |
| takhrij | array | – | Cross-collection takhrij per hadith key. Drawn only from key_index_books, so few rows is not proof of a weak or rare hadith. (mode=search only.) |
| takhrij_from_key_index | boolean | – | True when the matched pages carried no hadith key and takhrij came from re-running the query inside the key-indexed books. (mode=search only.) |
| total | integer | – | Distinct books carrying the key, installed or not. (mode=sources only.) |
| total_text_matches | number | – | Every page matching the text in the searched shelves. (mode=search only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
No examples provided.
shamela_lookup_quran Search the Quran or get an ayah ~958
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. mode=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. Commentary → shamela_lookup_tafsir; the words inside books → shamela_search(match='words').
| Name | Type | Req | Description |
|---|---|---|---|
| aya | integer | – | Aya number within the surah, 1..N. Pair with `surah`. (mode=aya only.) |
| aya_id | integer | – | Cumulative aya id, 1..6236. Mutually exclusive with surah/aya. E.g. 1 = al-Fatiha 1 (the basmala). (mode=aya only.) |
| count | integer | – | How many consecutive verses to return, starting at the one resolved above (1-20, default 1). Use it for a passage — «the last two verses of al-Baqara» is surah=2, aya=285, count=2, and a short surah… |
| limit | integer | – | Maximum number of results to return (1-100, default 20). (mode=search only.) |
| mode | string | – | Selects what the call does: search | aya. Default search. |
| offset | integer | – | Number of results to skip for pagination. Use with `limit` to page through large result sets. The response includes `has_more` and `next_offset` to drive paging. Default: 0. (mode=search only.) |
| options | object | – | Currently only the `wildcards` flag is honored. The Quranic index ships pre-built and zero-config. `*` stands for any letters, `?` for one: {query:'الرحم*', options:{wildcards:true}} finds 57 verses.… |
| query | string | – | Arabic text of a verse or part of one. Matched against all 6,236 verses in BOTH orthographies — the Egyptian إملائي spelling a user types from memory AND the Uthmani rasm that mushaf apps, quran.com… |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| surah | integer | – | Surah number 1..114. Pair with `aya`. E.g. {surah:55, aya:1} = Ar-Rahman 1. (mode=aya only.) |
| Name | Type | Req | Description |
|---|---|---|---|
| amiri | string|null | – | Uthmani-script rendering (Amiri), for display to the reader. (mode=aya only.) |
| aya | integer | – | Verse number within the surah. (mode=aya only.) |
| aya_id | integer | – | Cumulative verse id, 1..6236. (mode=aya only.) |
| body | string|null | – | Standard Egyptian imla'i spelling, Hafs from Asim — the form text search matches. (mode=aya only.) |
| has_more | boolean | – | True when another page exists; call again with `next_offset`. (mode=search only.) |
| majma | string|null | – | KFQPC Mushaf rendering. (mode=aya only.) |
| next_offset | number | – | Offset of the next page. Absent on the last page. (mode=search only.) |
| normalized_tokens | array | – | The query after Arabic folding, as actually searched. (mode=search only.) |
| offset | number | – | Offset this page started at. (mode=search only.) |
| paging_ceiling | number | – | Deepest offset paging can reach. Present only when the request went past it: narrow the scope instead of paging further. (mode=search only.) |
| query | string | – | The query as received. (mode=search only.) |
| query_form_hits | number | – | Verses matching the word as typed (or its prefixed forms) rather than the stem: «الملك» returns 60 verses, 28 of them this way. (mode=search only.) |
| results | array | – | Verses in mushaf order: aya_id (1-6236), surah, surah_name, aya, body (full verse), snippet_body (<mark>…</mark> around matches), matched_orthography, matched_form (single-word queries: the searched… |
| returned | number | – | [mode=search] Rows in `results` on this call. [mode=aya] Number of verses in `verses`. |
| rows_dropped | array | – | – |
| stem_expanded_to | array | – | Single-word queries: the extra forms searched beyond the word as typed. (mode=search only.) |
| surah | integer | – | Surah number, 1..114. (mode=aya only.) |
| surah_ayat | integer | – | Total verses in the first verse's surah, so you can ask for the rest with `count`. (mode=aya only.) |
| surah_name | string | – | Arabic surah name. (mode=aya only.) |
| terms_truncated | boolean | – | True when the query had more words than are searched. (mode=search only.) |
| total_hits | number | – | Every match in scope, not just the rows returned. (mode=search only.) |
| total_hits_complete | boolean | – | False when total_hits is a lower bound. (mode=search only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
| verses | array | – | The requested run in order; the top-level fields repeat verses[0]. (mode=aya only.) |
No examples provided.
shamela_lookup_rijal Narrators and isnads ~1,778
Hadith narrators and isnad chains, from Shamela's rijal register and isnad index. `mode`: - 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. - 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. - 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. - 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. Rules: 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). Instead: book authors → shamela_find(kind='author'); a hadith by its text → shamela_lookup_hadith(mode='search').
| Name | Type | Req | Description |
|---|---|---|---|
| book_id | integer | – | Book id from a search hit (e.g. 1681, Sahih al-Bukhari). Chains exist only for the ten isnad-indexed books listed under shamela_lookup_rijal(mode='isnad_search'); other books answer no_isnad_indexed:… |
| contains | array | – | Narrator ids that must ALL appear in the chain, at any position and in any order. Use for «which reports pass through both X and Y». Ids from shamela_lookup_rijal(mode='narrators'). BAD_ARG when cont… |
| include_network | boolean | – | Include the transmission network computed from the isnād index: how many chains this narrator carries, in which books, and their most frequent teachers and students. Set false to skip it when you onl… |
| include_variants | boolean | – | Also return the other routes (طرق) of the same ḥadīth from the other indexed books, matched on Shamela's ḥadīth key. This is what shows whether a report rests on one thread or many. Default: true. (m… |
| limit | integer | – | [mode=narrators] Maximum narrators to return (1-50, default 10). [mode=narrator] How many CRITICS of al-jarḥ wa-l-taʿdīl to return (1-100, default 10) — the only part of the dossier that is paged. al… |
| max_results | integer | – | Chains to return per page (1-100, default 20). Chains come in index order. (mode=isnad_search only.) |
| max_variants | integer | – | Cap on returned variant routes (1-200, default 20). `variants.truncated` reports when more exist. (mode=isnad only.) |
| mode | string | – | Selects what the call does: narrators | narrator | isnad_search | isnad. Default narrators. |
| narrator_id | integer | – | The narrator id, as returned by shamela_lookup_rijal(mode='narrators') or inside a chain from shamela_lookup_rijal(mode='isnad'). Example: {narrator_id:4677}. (mode=narrator only.) |
| offset | integer | – | [mode=narrators] Narrators to skip, for paging. Common names match in the thousands — «محمد بن» matches 4,271 — so page with this or narrow the query. Default: 0. [mode=narrator] Critics to skip, for… |
| page_id | integer | – | Shamela page id within that book (not the printed page number), from the same hit. An id the book lacks is PAGE_NOT_FOUND. (mode=isnad only.) |
| query | string | – | Part of the narrator's name, in Arabic. Matched against the short name, the full lineage, and the register's الشهرة / اللقب / الكنية / النسب — so «الزهري» and «الأعمش» reach the men known by those ni… |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| scope_book_ids | array | – | Restrict to these books. The isnād index covers only ten: صحيح البخاري (1681), صحيح مسلم (711), سنن أبي داود (654), سنن الترمذي (7895), سنن النسائي (829), موطأ مالك (28107), مسند الطيالسي (1456), الم… |
| top_n | integer | – | How many teachers and how many students to return, most frequent first (1-100, default 15). (mode=narrator only.) |
| transmission | array | – | Pairs [teacher_id, student_id] that must appear ADJACENT and in that order — direct transmission, the student having heard from the teacher with nobody in between. This is the question «did X really… |
| Name | Type | Req | Description |
|---|---|---|---|
| absent_from_isnad_index | boolean|null | – | True when no indexed chain names this narrator; null when not computed. (mode=narrator only.) |
| book_id | integer | – | (mode=isnad only.) |
| chains | array | – | Chains printed on this page. (mode=isnad only.) |
| chains_truncated | boolean | – | (mode=isnad only.) |
| contains | array | – | (mode=isnad_search only.) |
| death_year | – | – | (mode=narrator only.) |
| full_name | string | – | (mode=narrator only.) |
| grade_dhahabi | string|null | – | (mode=narrator only.) |
| grade_ibn_hajar | string|null | – | (mode=narrator only.) |
| hadeeth_keys | array | – | (mode=isnad only.) |
| hadith_notes | array | – | Fawa'id on audition, irsal and implicit tawthiq: the evidence for whether a chain is connected. (mode=narrator only.) |
| has_more | boolean | – | True when more rows exist past this page. (mode=narrators|narrator|isnad_search only.) |
| jarh_tadil | array | – | This page of critics' verdicts, grouped by critic, each verbatim with book and volume/page (e.g. «تهذيب التهذيب (1/ 101)»). 15,160 of the 18,989 narrators carry verdicts, from 2,821 named critics. (m… |
| name | string | – | (mode=narrator only.) |
| narrator_id | integer | – | (mode=narrator only.) |
| network | – | – | Isnad-index network; null when include_network is false. (mode=narrator only.) |
| next_offset | integer | – | Offset for the next page; present only when has_more is true. (mode=narrators|narrator|isnad_search only.) |
| no_isnad_indexed | boolean | – | (mode=isnad only.) |
| no_isnad_reason | string|null | – | no_marker_on_page (the page's own service annotations carry no isnad marker) | marked_but_unindexed | null. (mode=isnad only.) |
| note | string|null | – | (mode=narrator only.) |
| offset | integer | – | Rows skipped before this page. (mode=narrators|narrator|isnad_search only.) |
| page_id | integer | – | (mode=isnad only.) |
| page_isnad_markers | integer | – | (mode=isnad only.) |
| paging_ceiling | integer | – | Present when offset passed the deepest reachable row. (mode=isnad_search only.) |
| query | string | – | (mode=narrators only.) |
| results | – | – | [mode=narrators] Most-documented narrator first, earliest death year breaking ties. [mode=isnad_search] Chains in index order. (mode=narrators|isnad_search only.) |
| returned | integer | – | Rows in this response. (mode=narrators|narrator|isnad_search only.) |
| rows_dropped | array | – | – |
| summary | array | – | kunya, nasab, cities, relations — whatever the register holds. (mode=narrator only.) |
| tabaqa | string|null | – | Generation, per Taqrib al-Tahdhib. (mode=narrator only.) |
| total_chains_on_page | integer | – | (mode=isnad only.) |
| total_critics | integer | – | (mode=narrator only.) |
| total_hits | integer | – | Chains matching, before paging. (mode=isnad_search only.) |
| total_matches | integer | – | (mode=narrators only.) |
| total_verdicts | integer | – | (mode=narrator only.) |
| transmission | array | – | (mode=isnad_search only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
| variants | – | – | Other routes of the same hadith, following its key outward: the route count shows one thread (gharib, غريب) or many (mashhur, مشهور). Null when none or not requested. (mode=isnad only.) |
No examples provided.
shamela_lookup_tafsir Tafsir coverage and texts for an ayah ~630
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. mode=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]}.
| Name | Type | Req | Description |
|---|---|---|---|
| aya | integer | – | Verse number within the surah, 1..N; requires `surah`. |
| aya_id | integer | – | Cumulative verse id, 1..6236 (e.g. 262 = 2:255). Give this OR surah + aya, not both; a reference that disagrees with surah/aya is BAD_ARG. |
| book_ids | array | – | Restrict to these tafsir books, read in the order given (omit it and the installed indexed books are read earliest author first). Books not present in the curated index for this aya are reported with… |
| downloaded_only | boolean | – | If true (default), list only books whose text is installed on this server. false also lists books the curated index maps to this aya whose text is not installed (downloaded:false) — still useful as c… |
| max_sources | integer | – | Maximum number of sources to fetch text for (1-10, default 5). The response-size budget can stop earlier; `remaining_book_ids` lists the sources not read, to pass as book_ids next. (mode=texts only.) |
| mode | string | – | Selects what the call does: coverage | texts. Default coverage. |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| surah | integer | – | Surah number 1..114; requires `aya`. Alternative to aya_id. |
| Name | Type | Req | Description |
|---|---|---|---|
| _display | string|null | – | (mode=texts only.) |
| aya | integer | – | – |
| aya_id | integer | – | Cumulative verse id, 1..6236. |
| books | array | – | Every tafsir-shelf book plus index hits, ordered by status, installed first, then book_id; a long list is cut (rows_dropped). (mode=coverage only.) |
| coverage_note | string | – | (mode=coverage only.) |
| fetched | integer | – | Sources whose text was read. (mode=texts only.) |
| index_entries | integer | – | Raw index rows; exceeds `total` when commentary spans pages. (mode=coverage only.) |
| note | string | – | Caveat: the index is curated, so unknown status is not absence. |
| remaining_book_ids | array | – | Indexed sources not read in this call; pass as book_ids to continue. (mode=texts only.) |
| results | array | – | The index hits alone, repeating books[] rows; filtered by downloaded_only (false adds hits whose text is not installed, downloaded:false). (mode=coverage only.) |
| returned | integer | – | Rows in `results`. (mode=coverage only.) |
| rows_dropped | array | – | – |
| sources | array | – | Read only from pages the curated service/tafseer.db maps to this verse; there is no text-search fallback, which misattributes verses through shared phrases and the basmala. (mode=texts only.) |
| surah | integer | – | – |
| surah_name | string | – | – |
| total | integer | – | Distinct books the index maps to this verse, installed or not. (mode=coverage only.) |
| total_indexed | integer | – | Books the curated index maps to this verse. (mode=texts only.) |
| totals | object | – | Count of books in each coverage status. (mode=coverage only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
No examples provided.
shamela_read Read pages, sections and tables of contents ~1,282
Read an installed book's text and structure by internal ids. `unit`: - page (default): one page_id → body (author's matn), foot (editor's footnotes), printed page label, prev/next page ids, enclosing headings. - 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. - section: one chapter by title_id with its sub-headings, up to the next heading outside it. - toc: headings with their title_ids; top level by default, parent_id/depth expand, containing_page_id gives the chain enclosing a page. - parts: volumes — part label, page count, first/last page_id. - 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'). Rules: 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). Instead: 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').
| Name | Type | Req | Description |
|---|---|---|---|
| body_part | integer | – | For long pages: when the body exceeds ~4000 characters it is split into parts. Pass the 1-based part to read (default 1). The response reports body_part/body_total_parts/body_has_more; request the ne… |
| book_id | integer | – | The book id, from shamela_find(kind='book'), shamela_find(kind='work') or shamela_find(kind='name'). Installed ids: shamela_list_downloaded_books. |
| containing_page_id | integer | – | Page id. Switches to ancestor-chain mode: returns the headings that enclose this page, root to leaf, in `ancestor_chain`; parent_id and depth are then ignored. E.g. containing_page_id:17 gives the ch… |
| count | integer | – | How many consecutive pages to fetch (1–20, default 5). Fewer come back when the ~12,000-character budget is reached; has_more then stays true. Use shamela_read(unit='section') for full chapter reads.… |
| depth | integer | – | Levels below parent_id to include (1–5, default 1); deeper levels arrive nested in `children`. Ignored when containing_page_id is set. E.g. {unit:'toc', book_id, depth:1} lists the top-level chapters… |
| keep_html | boolean | – | [unit=page] If true, preserve inline HTML markers (e.g. <span data-type='title'>). Default false strips them for plain Arabic display. [unit=range|section] If true, keep Shamela's inline markup: <spa… |
| max_pages | integer | – | Cap on pages to read (1–100, default 30). The ~12,000-character budget can stop the read earlier; either way truncated:true and next_start_page_id say where to resume with shamela_read(unit='range').… |
| page_id | integer | – | [unit=page] Internal page id, as search hits, shamela_read(unit='toc') and shamela_cite(mode='printed_page') return it; not the printed page number. Ids have gaps, so take neighbours from prev_page_i… |
| parent_id | integer | – | Title id whose children to list; 0 (default) = top-level chapters. Ignored when containing_page_id is set. (unit=toc only.) |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| start_page_id | integer | – | First page id to read (inclusive). To continue a range that was cut short, pass the previous response's next_start_page_id. (unit=range only.) |
| title_id | integer | – | The title id of the chapter / section to fetch, from shamela_read(unit='toc') or shamela_find(kind='heading'). Its sub-headings are included. (unit=section only.) |
| unit | string | – | Selects what the call does: page | range | section | toc | parts | services. Default page. |
| Name | Type | Req | Description |
|---|---|---|---|
| _display | string|null | – | Advice on presenting a long text (show in parts, or ask the user how); null when the text is short. (unit=page|range|section only.) |
| ancestor_chain | array | – | ancestor_chain mode: headings enclosing the page, root to leaf. (unit=toc only.) |
| author_name | string|null | – | Main author name. (unit=page|range|section only.) |
| ayat | array | – | Cumulative aya ids (1-6236, 262 = 2:255) cited on the page, as stored; pass to shamela_lookup_quran(mode='aya'). (unit=services only.) |
| body | string|null | – | Main text (matn), or the requested body_part of it. (unit=page only.) |
| body_has_more | boolean|null | – | True when another body_part follows. (unit=page only.) |
| body_part | number|null | – | 1-based part of the body returned. (unit=page only.) |
| body_total_parts | number|null | – | How many parts the body is split into. (unit=page only.) |
| book_id | number|null | – | Catalogue book id. |
| book_name | string|null | – | Catalogue title of the book (Arabic). (unit=page|range|section|toc|parts only.) |
| category_path | array | – | Category names, broadest first. (unit=page only.) |
| comment | string|null | – | User annotation; returned with body_part 1 only. (unit=page only.) |
| containing_titles | array | – | Chapter headings enclosing the page, root to leaf. (unit=page only.) |
| count | number|null | – | Pages actually returned (may be fewer than requested). (unit=range only.) |
| depth | number|null | – | Levels expanded in subtree mode; null in ancestor_chain mode. (unit=toc only.) |
| end_page_id | number|null | – | Last page id of the section. (unit=section only.) |
| esnad | array | – | Raw isnad markers, one string per chain: «<zero-padded hadith key> s <narrator ids, Companion first, collector last>». Ids, not names; resolve with shamela_lookup_rijal(mode='isnad'). (unit=services… |
| esnad_count | number|null | – | Number of isnad markers. (unit=services only.) |
| foot | string|null | – | Footnotes (editor's words, not the author's); returned with body_part 1 only. (unit=page only.) |
| hadeeth | array | – | Numeric hadith keys, as stored; pass to shamela_lookup_hadith(mode='sources'). (unit=services only.) |
| has_more | boolean|null | – | True when pages exist after the last one returned. (unit=range only.) |
| has_services | boolean|null | – | False when the page carries no markers (common outside hadith works). (unit=services only.) |
| is_multi_volume | boolean|null | – | True when the pages carry more than one part label. (unit=parts only.) |
| mode | string|null | – | 'subtree' (parent_id/depth) or 'ancestor_chain' (containing_page_id). (unit=toc only.) |
| next_page_id | number|null | – | Next existing page id; null at the end. (unit=page only.) |
| next_start_page_id | number|null | – | [unit=range] Where to continue when the size budget cut the range short; null otherwise. [unit=section] Continue with shamela_read(unit='range') from here; null when the section is complete. (unit=ra… |
| page_id | number|null | – | [unit=page] Internal page id that was read. [unit=services] Page id. (unit=page|services only.) |
| pages | array | – | Pages in reading order. (unit=range|section only.) |
| parent_id | number|null | – | Parent expanded in subtree mode; null in ancestor_chain mode. (unit=toc only.) |
| part | string|null | – | Volume/part label, e.g. '4'; null for single-volume books. (unit=page only.) |
| parts | array | – | Volumes in reading order: whether a citation needs a part designator. Empty for a single-volume book unless its pages carry one part label (kept: citations print it). (unit=parts only.) |
| prev_page_id | number|null | – | Previous existing page id (ids have gaps); null at the start. (unit=page only.) |
| printed_page | string|null | – | Printed page label as Shamela renders it, e.g. '4/ 405'; null when the page has no printed number. (unit=page only.) |
| raw | – | – | The raw service record, for debugging. (unit=services only.) |
| rows_dropped | array | – | – |
| start_page_id | number|null | – | [unit=range] First page id requested. [unit=section] First page id of the section. (unit=range|section only.) |
| title_id | number|null | – | Heading that was read. (unit=section only.) |
| title_text | string|null | – | Heading text. (unit=section only.) |
| titles | array | – | Subtree mode: the headings, nested via children. Empty under a leaf. (unit=toc only.) |
| total_pages | number|null | – | Page records in the book. (unit=parts only.) |
| total_pages_in_section | number|null | – | Pages the whole section spans. (unit=section only.) |
| truncated | boolean|null | – | True when fewer pages were returned than the section has. |
| truncation_message | string | – | – |
No examples provided.
shamela_search Search page text (words, phrase, exact, boolean, batch) ~2,254
Full-text search inside the pages (matn and footnotes) of installed books. `match` picks how the query is read: - 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). - phrase: the words consecutively (a quotation). near: all words within `distance`, any order. Both verified in the full page text. - exact: diacritics, hamza/alef forms or digit systems kept distinct («أحمد» not «احمد», «عِلْم» not «عَلَم», ٢٥٥ not 255); set at least one `preserve` flag. - 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. - batch: 1–24 scoped `queries` run at once, merged and deduped by page (probe_ids); no paging, cut at max_total_passages. Rules: 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. Instead: 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'). Example: {query:'استصناع', scope:{category_ids:[17]}}.
| Name | Type | Req | Description |
|---|---|---|---|
| all_of | array | – | The three lists are ONE Lucene BooleanQuery over the whole index: all_of MUST, any_of SHOULD (at least one), none_of MUST_NOT. AND — terms that must ALL appear on the page; a multi-word term is itsel… |
| any_of | array | – | OR — at least ONE of these terms must appear on the page. Union of every term's hit set, then intersected with the all_of result. Leave empty to rely on all_of. (match=boolean only.) |
| deadline_ms | integer | – | Wall-clock budget for the whole batch. Probes still running when it expires are reported with status='timeout' and contribute nothing. A timeout is NOT a negative finding — it means the question was… |
| distance | integer | – | For match='near': maximum word span from the FIRST to the LAST query word, counted inclusively — 1 = adjacent, 2 allows one word between two query words. Ignored for match='phrase'. Suits fiqh terms… |
| exclude_author_ids | array | – | Exclude every book by these authors. (match=words|phrase|near only.) |
| exclude_book_ids | array | – | Book ids to keep out of the results entirely. (match=words|phrase|near only.) |
| exclude_category_ids | array | – | Exclude every book on these shelves. (match=words|phrase|near only.) |
| exclude_pages | array | – | Exact pages to keep out — the pages a previous round already returned. Excluding these rather than whole books is what lets a follow-up search find MORE evidence in a book that has already contribute… |
| exclude_work_group_ids | array | – | Exclude every catalogue entry of these works — all printings at once. This is the one to use after a round returned «صحيح البخاري - ط السلطانية»: excluding that book_id alone leaves the other seven e… |
| limit | integer | – | Maximum number of results to return (1-100, default 20). (match=words|phrase|near|exact|boolean only.) |
| match | string | – | Selects what the call does: words | phrase | near | exact | boolean | batch. Default words. |
| max_total_passages | integer | – | Hard cap on merged rows returned. Rows are ordered by match quality then probe agreement before the cut, so the cap drops the weakest evidence rather than an arbitrary tail. `truncated` says whether… |
| none_of | array | – | NOT — pages containing ANY of these terms are excluded, across the whole index (a MUST_NOT clause, not a subtraction inside a sampled window). Optional. (match=boolean only.) |
| offset | integer | – | Number of results to skip for pagination. Use with `limit` to page through large result sets. The response includes `has_more` and `next_offset` to drive paging. Default: 0. (match=words|phrase|near|… |
| options | object | – | Search options: morphology, wildcards, sort, search_in (body/foot), relax_when_empty. Defaults to body+foot, no toggles. preserve_* redirect to shamela_search(match='exact'). E.g. {query:'كلم', optio… |
| preserve | object | – | Which distinctions to enforce when each candidate is verified; at least one must be true (none = BAD_ARG), and every unset feature folds. E.g. {query:'أحمد', preserve:{preserve_hamza:true}}, {query:'… |
| queries | array | – | Several wordings of one question, run concurrently to assemble its evidence; results are merged, deduped by (book_id, page_id) and attributed to the probes that found each page (`probe_ids`): a page… |
| query | string | – | [match=words] Arabic words, ANDed; each may match in body or footnotes, e.g. {query:'الكلام'}. A word the library lacks in your spelling is searched in the spelling the books use and reported in `res… |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| scope | object | – | Restrict to books, authors, categories, a Hijri period or the other filters below; get ids from shamela_find(kind='category') or shamela_find(kind='name'). Strongly recommended on common words for ma… |
| search_in | array | – | [match=phrase|near] Which page sections to verify the phrase in: body (matn), foot (footnotes). Default both; a hit's `matched_in_section` says where it was found. [match=boolean] Which page sections… |
| shape | string | – | How much of each hit to return. 'full' (default): every field, snippets included — ask for it when the answer will QUOTE the page. 'brief': book_id/page_id, printed_page, match_quality and matched_in… |
| Name | Type | Req | Description |
|---|---|---|---|
| all_of | array | – | AND terms, as searched. (match=boolean only.) |
| any_of | array | – | OR terms, as searched. (match=boolean only.) |
| books | object | – | shape 'brief' only: book metadata keyed by book_id, hoisted off the rows. (match=words|phrase|near|batch only.) |
| by_book | object | – | Returned rows per book name. (match=batch only.) |
| candidate_cap_hit | boolean | – | True when the candidate window filled up: more matches may exist outside it; narrow the scope. (match=phrase|near|exact only.) |
| coverage | object | – | Roll-up of hits by_category and by_century (the whole sample), by_book and by_author (the largest top_n only, so they do not sum to it) and edition_groups (one work under several catalogue entries: o… |
| distance | number | – | Word span used for mode 'near'. (match=phrase|near only.) |
| edition_groups | array | – | Works present under several catalogue entries in these rows: read each as one source. (match=batch only.) |
| exclusion | object | – | What the `exclude_*` parameters removed. Present only when used. (match=words|phrase|near only.) |
| has_more | boolean | – | True when another page exists; call again with `next_offset`. (match=words|phrase|near|exact|boolean only.) |
| incomplete | boolean | – | True when any probe errored or timed out: a thin result is then not the library being silent. (match=batch only.) |
| mode | string | – | 'phrase' or 'near', as searched. (match=phrase|near only.) |
| morphology_expanded_to | object | – | options.morphology only: exactly what was searched, per word. Roots are ambiguous and every reading is kept («كتب» also searches تبب/توب/وتب, perdition and repentance), so results are a SUPERSET of t… |
| morphology_fallback | boolean | – | True when the literal search found nothing and was re-run with morphology (root forms). (match=words only.) |
| next_offset | number | – | Offset of the next page. Absent on the last page. (match=words|phrase|near|exact|boolean only.) |
| none_of | array | – | NOT terms, as searched. (match=boolean only.) |
| normalized_tokens | array | – | The query after Arabic folding, as actually searched. (match=words only.) |
| notes | array | – | Caveats about how the expression was evaluated. (match=boolean only.) |
| offset | number | – | Offset this page started at. (match=words|phrase|near|exact|boolean only.) |
| paging_ceiling | number | – | Deepest offset paging can reach. Present only when the request went past it: narrow the scope instead of paging further. (match=words|boolean only.) |
| preserve | object | – | The preserve_* flags enforced on this call. (match=exact only.) |
| probes | array | – | One report per probe, in request order. (match=batch only.) |
| query | string | – | The query as received. (match=words|phrase|near|exact only.) |
| relaxed_min_match | number | – | Set when no page held every word: hits carry at least this many of `relaxed_of_terms`. (match=words only.) |
| relaxed_of_terms | number | – | Word count the relaxed match is measured against. (match=words only.) |
| respelled_terms | array | – | {typed, searched_instead, hits}: a word absent as typed was searched in the spelling the books use. (match=words only.) |
| results | array | – | [match=words|phrase|near] Matching pages. shape 'full': book_id, book_name, author_name, category, book_date, work_group_id, madhab fields, page_id, printed_page, matched_in, match_quality ('exact_ph… |
| returned | number | – | Rows in `results` on this call. (match=words|phrase|near|exact|boolean only.) |
| rows_dropped | array | – | – |
| scope_count | number | – | Books in the resolved scope; -1 when unscoped. (match=words|phrase|near|boolean only.) |
| scope_resolution | object | – | Requested book_ids split into resolved and `dropped` (not in the catalogue, never searched). (match=words|phrase|near only.) |
| terms_truncated | boolean | – | True when the query had more words than are searched. (match=words only.) |
| total_candidates_scanned | number | – | Candidate pages verified against the page text. (match=phrase|near|exact only.) |
| total_hits | number | – | [match=words] Every match in scope, not just the rows returned. [match=boolean] Exact count of pages matching the whole expression. (match=words|boolean only.) |
| total_unique_passages | number | – | Distinct pages found across all probes, before the max_total_passages cut. (match=batch only.) |
| total_verified | number | – | Matches confirmed within the scanned window, not a library total. (match=phrase|near|exact only.) |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
| unattributable_books | number | – | Books excluded by scope.madhab because no school can be established for them. (match=words|phrase|near only.) |
| zero_due_to_exclusion | boolean | – | True when pages matched but every one was excluded: not evidence of absence. (match=words|phrase|near only.) |
| zero_hit_terms | array | – | Query words with no entry in the library as spelled. A zero then reflects spelling, not the topic. (match=words|phrase|near|exact|boolean only.) |
No examples provided.
shamela_search_library Search the classical Islamic library ~432
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.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Maximum passages to return (max 10). |
| query | string | yes | Arabic search text. A quoted wording works best; a topic also works. |
| scope | string | yes | hadith-primary — The eight primary hadith collections, edition-pinned; tafsir-canonical — Canonical tafsir — Ibn Kathir, al-Tabari, Ibn al-Jawzi first; fiqh-hanafi — Hanafi fiqh (+ usul, comparative)… |
| Name | Type | Req | Description |
|---|---|---|---|
| booksSearched | integer|null | – | Books in the searched scope, or null when the library did not say. |
| note | string | – | Present only when the result needs a caveat; carry it with the passages. |
| passages | array | – | Best evidence first: exact phrase before word matches, main text before footnote, the school's own shelf before the wider one. Empty when nothing in the scope matched. |
| relaxedToTokens | boolean | – | True when the exact phrase was not found and a looser word search answered. |
| scope | string | – | The scope searched, as sent. |
| totalMatches | integer|null | – | Matching pages the library verified in the scope before the limit, or null. |
No examples provided.
shamela_survey_topic Survey a topic across the library ~580
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}}.
| Name | Type | Req | Description |
|---|---|---|---|
| mode | string | – | 'literal' counts pages carrying the WORD as written (plus the ordinary spelling folds). 'morphological' expands it to every AlKhalil root reading and counts those — which is far broader than most cal… |
| response_format | string | – | Format of the human-readable text: 'markdown' (default) for display; 'json' the same data as one JSON code block; 'none' only a one-line pointer, leaving structuredContent as the whole answer. struct… |
| scope | object | – | Restrict the profile to specific books, authors, categories, or a Hijri date range. Use shamela_find(kind='category') / shamela_find(kind='name') to find IDs. Omit to profile the whole library instal… |
| term | string | yes | Arabic word or root to profile (e.g. «الاستصناع»، «صبر»، «رحم»). Under mode='literal' (default) only the word as written is counted; under mode='morphological' it is matched via the AlKhalil analyzer… |
| Name | Type | Req | Description |
|---|---|---|---|
| accuracy_note | string | – | Morphological counts: the analyzer is ~0.80 accurate on classical Arabic, so read them as reach, not exact tallies. |
| books_matched | integer | – | – |
| by_author | array | – | Top 15 authors. |
| by_book | array | – | Top 15 books by matching pages. |
| by_category | array | – | Category names (no ids), top 15. Reflects corpus size as well as topic, never authority: التفسير tops nearly every profile because tafsir is the largest body of text here. |
| by_century | array | – | Hijri century, top 15. |
| coverage_cap | integer | – | – |
| coverage_capped | boolean | – | True when the distribution is a top-coverage_cap sample: bucket counts are floors and shares indicative. |
| mode | string | – | literal | morphological. |
| normalized_tokens | array | – | – |
| root | string | – | Same as `term`, for older callers. |
| rows_dropped | array | – | – |
| scope_count | integer | – | Books in scope; -1 when no scope was given. |
| term | string | – | – |
| total_counted | integer | – | Hits folded into the distribution. |
| total_hits | integer | – | EXACT number of matching pages. |
| truncated | boolean | – | – |
| truncation_message | string | – | – |
No examples provided.
How do I install the Quran Gallery MCP server?
Quran Gallery MCP is a hosted endpoint at https://qurangallery.com/mcp/shamela, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · qurangallery.com
claude mcp add --transport http com-qurangallery-mcp 'https://qurangallery.com/mcp/shamela'
What is the Quran Gallery MCP server?
Quran Gallery MCP is listed in the public MCP registry as com.qurangallery/mcp. Classical Islamic library (Shamela, 8,594 books): verbatim Arabic cited by volume and page. No key. This page covers its hosted endpoint (https://qurangallery.com/mcp/shamela).
Is the Quran Gallery MCP server safe to use?
Quran Gallery MCP scores 70 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the Quran Gallery MCP server expose?
Quran Gallery MCP exposes 14 tools: shamela_search_library, search, fetch, shamela_search, shamela_find, and 9 more. Their descriptions and schemas cost roughly 13,158 tokens of context every time the server is loaded.
Does the Quran Gallery MCP server require authentication?
No. We connected to Quran Gallery MCP without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.
Is the Quran Gallery MCP server still maintained?
Quran Gallery MCP is still listed as active in the MCP registry. We last reached this channel on 24 October 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.