Skip to content

Latest commit

 

History

History
126 lines (102 loc) · 13.3 KB

INTEGRATIONS.md

File metadata and controls

126 lines (102 loc) · 13.3 KB

Integrations — developer surfaces, the landscape, and what Basira adds

§1 and §3 describe what is shipped. §2 is a survey of the developer surfaces of established Islamic platforms; every external claim was read from the linked page on the date given, not from memory.

1. What Basira exposes (verified against /openapi.json on 2026-10-05)

Surface Path Notes
OpenAPI 3.1 document GET /openapi.json generated by FastAPI; title «Basira API», version = backend/app/__init__.py
Interactive docs (Swagger UI) GET /docs on unless BASIRA_DOCS=0; ReDoc disabled
Health gate GET /health 503 with error envelope until index loaded; counts, rss, build sha, provider names
Check text POST /v1/check {text ≤ 5000, ui_lang, source_modality, options} → CheckResponse
Check image POST /v1/check/image multipart image (+ ui_lang); returns ocr_text so the user can verify what was read (ADR-003)
Sources manifest GET /v1/sources name, version/commit, licence + URL, record count
Message catalogue GET /v1/messages/{ar|en} single source of all user-facing strings
Guard an AI answer POST /v1/guard clear / flagged / no_quotes with fixed summaries (docs/GUARD.md)
Verification receipt POST /v1/receipt, GET /v/{token}?h= stateless token; replay answers verified_now or stale (§3.3)
Grounding rules GET /v1/rules the red lines and the four states, AR/EN, with safety_sha256
Model configuration GET /v1/models, PUT/DELETE /v1/models/config measured catalog; key stored server-side, always masked (docs/MODELS.md)
MCP server /mcp six tools when BASIRA_MCP=1 (§3.1)

Guards: CORS allow-list, rate limit 30/min per client (X-Eval-Key bypass), error envelope {error:{code,message_ar,message_en}}, class-only logging, no persistence.

The frontend links to /docs; in development Vite proxies /docs and /openapi.json to :8000, and in production the single container serves both from the same origin.

2. Survey — strong Islamic platforms, developer surfaces (read 2026-10-01)

Platform What they offer developers What is worth adopting What we must NOT copy
Quran Foundation / quran.com — api-docs.quran.foundation Developer Console (app registration), Content APIs GET /content/api/v4/… with OAuth2 client-credentials, official JS/TS SDK (@quranjs/api) and Python SDK (quran-foundation-api on PyPI), User APIs (bookmarks…) behind OIDC Clear two-tier docs: «Quickstart in 5 minutes» + reference generated from the OpenAPI spec; typed SDK as the first-class path User accounts / OAuth — Basira stores nothing, so there is no user data to protect; adding login would contradict SAFETY
quran/quran-mcp (github.com/quran/quran-mcp, remote https://mcp.quran.ai) Remote streamable-HTTP MCP server; tools fetch_quran, search_tafsir, …; MCP resources and prompts; a middleware layer for rate limiting, grounding, logging; one-line client config for Claude Desktop / ChatGPT Remote-first MCP (no install), a grounding middleware that tells the model how to cite, and a documentation site served by the same process Tafsir/translation tools — out of scope and would require us to serve interpretive text
hadith-mcp.org Six read-only tools incl. fetch_grounding_rules (returned once per session: citation rules + limitations), fetch_hadith, search_hadith, fetch_cross_references, show_hadith (MCP app UI); a companion web app «verify AI citations quickly» with shareable proof links; explicit disclaimer that provenance tags are heuristics, not rulings fetch_grounding_rules pattern (we have the equivalent text in SAFETY §1.3 and transparency_notice); shareable, stateless proof links; the honesty of labelling algorithmic output as algorithmic Semantic (embedding) search as a verification primitive — non-deterministic; our matching stays deterministic (I1–I9)
sunnah.com — sunnah.com/developers REST API documented on Stoplight; API key by GitHub issue; community reports slow/unanswered key requests (reddit, issue #2849, 2026-03) Public OpenAPI reference Gate-kept keys — Basira's check endpoint is public with rate limiting; eval key is for benchmarks only
dorar.net — article 389 «خدمة واجهة الموسوعة الحديثية API» JSON(P) search widget for site owners; third parties wrap it (dorar-hadith-api) because the official one needs jQuery/JSONP The idea of an embeddable widget for other sites (§3.3) Scraping or wrapping dorar — we only link to dorar search (referral URLs are built in backend/app/links.py)
hadeethenc.com Bulk download page (used by us under their redistribution terms) — Showing the full HadeethEnc text by default; Basira ships HADEETHENC_MODE=link (grade + link)

Conclusion of the survey. Every existing MCP/API in this space is a retrieval surface («give me ayah 2:255», «search hadith about …»). None offers a deterministic verification primitive («here is a text someone wrote — tell me byte-exactly where it departs from the Mushaf / the matn, without rewriting it»). That is the gap Basira fills, and it is what would make the MCP tool unique: an AI assistant can draft, then call Basira to check its own quotes before showing them to a user.

3. What Basira adds

3.1 MCP server — shipped (E-049)

Status: live at /mcp when BASIRA_MCP=1 (otherwise a plain 404). backend/app/mcp_server.py, mounted inside the FastAPI process, reads app.state.pipeline per call — one pipeline object serves REST and MCP (no second index load, E-038). Streamable HTTP, stateless_http=True, JSON responses, SDK mcp 2.3.0 (MCPServer; the v1 FastMCP import no longer exists). Tool errors reuse the API envelope {code, message_ar, message_en}; nothing internal leaks; nothing is stored.

tool input output
verify_text text, ui_lang compact verdicts per quotation + notices as sentences + determinism_hash
verify_quote text, claimed_ref? («2:255», «البقرة: 255», «البخاري 1», «رواه مسلم»), ui_lang status, claimed_source_mismatch, the matched record verbatim
guard_answer answer, ui_lang clear / flagged / no_quotes + counts + fixed summaries (docs/GUARD.md)
list_sources — manifest: id, version, licence, sha256 (incl. the 18 OHD files), live counts
grounding_rules ui_lang fixed AR/EN instructions from SAFETY.md + safety_sha256
issue_receipt text, ui_lang stateless verification receipt (§3.3); same token as POST /v1/receipt

Names deliberately differ from the design (check_text → verify_text) to read as verification next to the association's retrieval tools. Tests: backend/tests/test_mcp.py (21, real MCP client over ASGI; REST and MCP verdicts byte-equal).

Client config: {"mcpServers":{"basira":{"url":"https://<host>/mcp","type":"http"}}} · local: http://localhost:8000/mcp.

Complementing mcp.islamiccontent.org (verified live 2026-10-05). Their server offers 11 tools, all retrieval (search, fetch, get_quran_verses, list_quran_translations, get_quran_audio, get_hadith, browse_hadith_categories, browse_library, get_library_item, list_library_categories, list_languages); none takes user text and verifies it. The intended loop for an assistant: fetch with theirs → answer → verify/guard with ours. scripts/mcp_demo.py does exactly that; its unedited output:

$ cd backend && BASIRA_MCP=1 .venv/bin/uvicorn app.main:app --port 8000     # terminal 1
$ backend/.venv/bin/python scripts/mcp_demo.py                               # terminal 2
== Part 1: Basira MCP at http://localhost:8011/mcp
  server: basira v0.2.0
  tools/list: ['verify_text', 'verify_quote', 'guard_answer', 'list_sources', 'grounding_rules', 'issue_receipt']
  grounding_rules: states=['found', 'partial_match', 'needs_review', 'not_found'] safety_sha256=4d5256783de4…
  verify_text('قال تعالى: ﴿إن الله مع الصابرين﴾') → hash 5785aa4af67b…
    • found         quran        reason=None  سورة البقرة، الآية 153
      source_text: يَٰٓأَيُّهَا ٱلَّذِينَ ءَامَنُوا۟ ٱسْتَعِينُوا۟ بِٱلصَّبْرِ وَٱلصَّلَو…
      notice: النص المنقول جزء من الآية لا الآية كاملة؛ نص الآية كاملًا معروض بجانب نصك.
  verify_text('قال تعالى: ﴿قل هو HELLO الله أحد﴾.') → hash 5a70649c0a33…
    • needs_review  quran        reason=foreign_material  سورة الإخلاص، الآية 1
      source_text: بِسْمِ ٱللَّهِ ٱلرَّحْمَٰنِ ٱلرَّحِيمِ قُلْ هُوَ ٱللَّهُ أَحَدٌ
      notice: داخل الاقتباس كلمات أو أرقام أو رموز ليست من النص (مظلّلة في نصك). أزلها ثم أعد الفحص.
  verify_text('قال ﷺ: «الدين المعاملة»') → hash a4d5b77d78e2…
    • not_found     hadith_matn  reason=None  —
  determinism: second call hash equal = True
  guard_answer → flagged {'quotes': 3, 'found': 1, 'flagged': 2, 'by_status': {'found': 1, 'needs_review': 1, 'not_found': 1}}
    The answer contains 3 quotation(s); 2 of them need review before publishing (not found verbatim in Basira's sources, or differing from the source text). Basira is a deterministic aid; "not found in our sources" is not a verdict on the text. Consult qualified scholars when in doubt.
== Part 2: integration with https://mcp.islamiccontent.org/mcp
  remote tools (11): ['search', 'fetch', 'get_quran_verses', 'list_quran_translations', 'get_quran_audio', 'get_hadith', 'browse_hadith_categories', 'browse_library', 'get_library_item', 'list_library_categories', 'list_languages']
  get_quran_verses input schema keys: ['surah', 'ayah', 'through', 'translation_key', 'language']
  calling get_quran_verses({'surah': 2, 'ayah': 153, 'through': 153, 'translation_key': 'english_saheeh'})
  remote returned 1036 chars: ["──────── RETRIEVED FROM QURANENC — published text ────────\n\n[Surah 2, translation \"english_saheeh\"]\n\n[EXACT] the verses and their published translation …
  verse text → Basira: 'يَٰٓأَيُّهَا ٱلَّذِينَ ءَامَنُواْ ٱسۡتَعِينُواْ بِٱلصَّبۡرِ …'
    • found         quran        reason=None  Surah Al-Baqarah (2:153)
      source_text: يَٰٓأَيُّهَا ٱلَّذِينَ ءَامَنُوا۟ ٱسْتَعِينُوا۟ بِٱلصَّبْرِ وَٱلصَّلَو…
  determinism_hash 195a15343a45…

Reading: the verse text returned by get_quran_verses (QuranEnc's Uthmani encoding: U+06E1 small high dotless head of khah for sukun, plain U+0652 sukun elsewhere, U+0653 madda) is confirmed found 2:153 by Basira against Tanzil's encoding — the strict tier's canonical composition (E-023/E-024) is what makes two faithful encodings of the Mushaf agree. remote returned 1036 chars is their framed payload (header

  • Arabic + Saheeh International translation); only the Arabic span is sent to verify_text.

3.2 API documentation — shipped

  • docs/API.md: quickstart, one example per endpoint captured from the real corpus, the four states, the error envelope, rate limits and the red lines (what the API never returns).
  • /developers page in the SPA: the quickstart, the MCP client config and a link to the OpenAPI reference.
  • OpenAPI examples are real request/response pairs (backend/app/openapi_examples.json), never invented text.
  • Every response carries the corpus block and X-Basira-Determinism-Hash: the reproducibility contract.

3.3 Proof links — shipped (E-052) · embeddable widget — not planned yet

  • Stateless verification receipt: POST /v1/receipt {text, ui_lang} → {receipt_id, determinism_hash, corpus, index_sha256, build_sha, issued_at, summary, quotes, token}; GET /v/{token}?h=<hash> re-runs the whole pipeline and answers verified_now / stale. token = base64url(zlib(json{v:1,t,l})) — the receipt is the input; nothing is stored (dorar/hadith-mcp «shareable link» idea without their database). MCP tool issue_receipt. JSON only — the design agent renders /v/{token} later. docs/API.md §3.8.
  • <script> widget for publishers: paste-box that posts to /v1/check and renders the same QuoteCard. Needs CORS allow-list per publisher and a size budget; not before the deploy target is known.

3.4 Explicitly rejected

  • OAuth / user accounts (nothing to protect; contradicts «لا نحفظ شيئًا»).
  • Semantic/embedding search as a verification primitive (non-deterministic; I7 reproducibility).
  • Serving tafsir, translations or any interpretive text (red line: never generate or curate religious text beyond the pinned corpora).

4. Telegram bot

@BasiraCheckBot — integrations/telegram/ (README there). Forward any text or image; the bot calls POST /v1/check or POST /v1/check/image and renders the response with messages/ar.json only: status, verbatim source_text, reference, bold differences from diff, links, transparency line. No model in the bot, nothing stored. Run: docker compose --profile bot up. Decision: E-059.