mcpField
A
AskSakina Islamic Knowledge

AskSakina Islamic Knowledge

远程服务
asksakina.com科研与教育03 天前更新

关于 AskSakina Islamic Knowledge

AskSakina Islamic Knowledge 是供 AI Agent 和客户端查阅精选伊斯兰文本的参考服务,提供《古兰经》经文、祈祷词和真主的 99 个尊名,并附呈现指引及危机处理。它是资料库,不提供宗教咨询。

主要功能

  1. 01按章节经文编号或主题查经文
  2. 02按生活情境查找祈祷词
  3. 03查询真主的 99 个尊名
  4. 04提供学习提示词和参考资源
  5. 05附带呈现指引与危机资源

适用场景

  1. 01检索含阿拉伯文和译文的经文
  2. 02查找适合某种生活情境的祈祷词
  3. 03在学习过程中了解真主的尊名
  4. 04对危机相关查询仅返回求助资源

MCP 相关

通过 MCP 提供四种查询工具、四个学习旅程提示词和七项资源。响应附带元数据及供调用 Agent 使用的呈现指引。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://sakina-mcp.fly.dev/mcp
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

安装包
npm@asksakina/islamic-knowledge-mcp2.5.1

工具

4
参数类型必填说明
ayahinteger是苏拉中的阿耶(经文)编号
surahinteger是苏拉编号,1–114
localeenum否译文区域设置;默认值为 "en"(Pickthall)。目前尚无乌尔都语和印度尼西亚语译文:"ur" 和 "id" 会返回附带说明的 Pickthall 英语译文。en | id | ur | ar
audienceenum否可选:curious、revert 或 practising。有可用内容时,返回预先编写的教学背景;省略时返回标准记录。curious | revert | practising

详细介绍

AskSakina 伊斯兰知识 MCP 服务

npm version License MCP Registry

经专业 AI 审核的伊斯兰知识,供 AI Agent 使用。 古兰经经文、精选的祈祷词语料库,以及安拉的 99 个尊名——由 AskSakina 的结构化专业 AI 审核链依据逊尼派四大主流学派(哈乃斐派、马立克派、沙斐仪派、罕百里派)进行审核,但这不能替代合格学者的指导。每条回复都附带展示约定,防止 Agent 在不知不觉中歪曲内容。

架构理念: “AskSakina 提供记录,Agent 给出答案。” 该服务是参考资料库,而非顾问。每条回复都包含一个 _sakina_meta 信封,其中含有免责声明、大模型指令、展示约定和教育背景。调用该服务的 Agent 如何处理记录,由其自行负责:每条回复都附带明确的处理说明,但服务无法让其他 AI 遵循这些说明。


提供的内容

通过模型上下文协议提供四个查询工具、四个学习旅程提示词和七项资源。所有记录均来自 AskSakina 主应用(asksakina.com),因此每个 MCP 版本都与其构建时公开应用所呈现的内容一致。

工具功能
get_quran_verse按 surah:ayah 查询古兰经经文原文
get_dua按生活情境(焦虑、早晨、旅行等)查询精选祈祷词语料库
get_name_of_allah按编号(1–99)或字符串查询 99 个尊名之一
find_verses根据主题关键词,从 AskSakina 的主题经文索引中查找古兰经经文
understand_a_verse(提示词)按 surah 和 ayah 获取一节经文,然后结合其教学注释(如有)进行介绍
explore_names_of_allah(提示词)按编号获取一个尊名(未提供编号时默认为 1),然后介绍该尊名并提供下一个尊名
what_muslims_believe(提示词)古兰经《忠诚章》、尊名 Ar-Rahman、经审核的信仰纲要与五功介绍,以及古兰经 2:256
first_steps_new_muslim(提示词)为新穆斯林提供循序渐进的指引(1-4):独一的真主与祂的慈悯、过去的罪过已获宽恕、一步步学习礼拜、你的社群
sakina://about(资源)阅读一次即可的简报——七项核心指令,以及三篇经 Gem 审核的宣教文本(古兰经的保存、圣训分级、学派归属)
sakina://learn/...(资源,2.5.0)提供两段学习旅程所用的六篇经审核文本原文

工具

get_quran_verse

按 surah:ayah 查询古兰经经文原文。返回标准 AskSakina 信封,包含阿拉伯语文本、译文、章名(阿拉伯语和英语),以及 quran 展示约定;该约定指示 Agent 不得改述、必须注明 surah:ayah,并将译文标注为“意义译文”。

参数

名称类型必填说明
surah1..114是章编号
ayah1..286是章内经文编号
locale'en' | 'id' | 'ur' | 'ar' | 'tr'否,默认为 en译文语言。ar 返回阿拉伯语原文及匹克索尔英语译文。乌尔都语、印度尼西亚语和土耳其语译文尚未提供(等待授权):ur、id 和 tr 会返回匹克索尔英语译文、translation_language: "en",以及说明这一情况的 translation_note

响应示例(已截断)

{
  "_sakina_meta": {
    "version": "1.0",
    "content_type": "quran_verse",
    "presentation_contract": {
      "quran": {
        "no_paraphrase": true,
        "require_citation": "surah:ayah",
        "translation_label": "Translation of the Meaning"
      }
    }
    /* … */
  },
  "content": {
    "surah": { "number": 2, "name_arabic": "البقرة", "name_english": "Al-Baqarah" },
    "ayah": 186,
    "arabic": "وَإِذَا سَأَلَكَ عِبَادِي عَنِّي فَإِنِّي قَرِيبٌ ۖ …",
    "translation": "And when My servants ask you concerning Me — indeed I am near. …"
  }
}
get_dua

返回与生活情境(焦虑、悲伤、清晨、旅行等)匹配的 du'a。系统会根据规范类别 slug、别名映射和标签维度解析情境。自然语言短语(“失去母亲后的悲伤”)也能解析:服务会对其进行标准化,并以确定性方式匹配其中已知的类别、别名、标签和同义词,以及少量多词短语,不使用 AI。content.matched_by 会说明解析方式。**悲伤(WO#386):**查询提及提问者自身的悲伤(“我失去了母亲”“失去母亲后的悲伤”“我父亲去世了”“丧亲”)时,会解析为情境 bereaved;葬礼仪式或已故者(“葬礼”“为亡者祈祷”“去我母亲的坟前探望”)则仍解析为 deceased。**父母(WO#430):**查询同时提及父母(mother、mum、mom、father、dad、parent、parents)和死亡相关词语(late、dead、passed、grave、burial、janaza、janazah、cemetery、funeral、died、death、deceased、lost)时,会采用此悲伤解析路径,绝不返回 mothers 或 fathers;查询中有父母和 “miss” 但没有死亡相关词语时,只返回适用于在世或已故父母的 du'a;普通的父母查询(“我母亲”“父母”)保持不变。单独出现死亡相关词语(例如 “grave”)时,不会解析出任何结果。bereaved 会按照 fiqh 审核者(Gem 4)裁定的顺序返回七条 du'a,并附带一条关于阿拉伯语中阳性形式的 teaching_note,且始终至少附带一条温和的支持提示。危机检测会先对完整原始输入进行。自残和虐待会分别使用独立的区块(crisis_type):虐待区块包含家庭暴力相关内容和针对虐待情境的指示。出现任何严重危机(自残或虐待)时,均不返回 du'a:content_type 为 crisis_resource_only,且危机资源构成完整响应。每个区块都先列出全天候热线,并注明任何服务时间有限的热线的开放时间。如果情境中包含危机关键词(根据主应用的 detectCrisis 关键词列表匹配),响应会包含必需的 crisis_resource 区块,其中提供适当的热线和亲社会指示。

参数

名称类型必填说明
contextstringcontext 或 id 二选一自由格式的生活情境
idstringcontext 或 id 二选一从先前响应中的 related 引用获取的 du'a ID(WO#390)
locale'en' | 'id' | 'ur' | 'ar' | 'tr'否,默认为 en无论 locale 为何,du'a 记录均为英文;危机资源使用请求中的 locale(2.2.1);省略 locale 或设为 en 时,严重危机资源使用匹配到的危机关键词所对应的语言(id、ur、ar 或 tr;2.2.2)
audience'curious' | 'revert' | 'practising'否仅根据用户对自身情况的描述填写。会作为 teach.audience 原样返回;若省略,教学区块会显示 unknown(2.2.0)
limit整数,1 到 10否,默认为 3情境查询返回的记录数量(2.2.0)。bereaved 集合和虐待白名单始终完整返回。与 id 一起使用时忽略
offset整数,0 或更大否,默认为 0使用 limit 分页时,指定本页之前要跳过的记录数(2.2.0)。与 id 一起使用或用于 bereaved 时忽略

**结果处理(2.2.0)。**情境查询会从 offset 开始,按该路径现有顺序(数据包顺序;bereaved 使用 Gem 4 固定的顺序)返回 limit 条记录。如果后面还有记录,content.total_available 会给出总数,content.truncated 为 true,且 content.more 会包含提示:“此情境还有 N 条 du'a;调用 get_dua 并设置 offset 和 limit 查看。”CRITICAL_RULES 中也会包含相同的提示。content.offset 仅在其值不为 0 时出现。某个类别中的每条记录都可以通过分页获取。

响应示例(已截断)

{
  "_sakina_meta": {
    "content_type": "dua_collection",
    "presentation_contract": {
      "hadith": { "require_grading": "per_record" /* true when every record is graded */ }
    }
    /* … */
  },
  "content": {
    "context": "stress-anxiety",
    "duas": [
      {
        "dua_block": "Arabic: …\nTransliteration: …\nTranslation: …\nOrigin: Quran 21:87\nSource: Quran 21:87\nGrading: Quranic",
        "title": "Dua to Deal with Distress & Depression",
        "arabic": "وَذَا ٱلنُّونِ إِذ ذَّهَبَ …",
        "source": "Quran 21:87",
        "grading": "Quranic",
        "grading_status": "quranic",
        "origin": "quran",
        "quran_citation": "Quran 21:87"
      },
      {
        "title": "Dua to Remove Sorrow & Grief:",
        "source": "Source not recorded in AskSakina corpus",
        "grading": "Not graded in AskSakina corpus",
        "grading_status": "not_recorded"
        /* … */
      }
      /* … */
    ],
    "total_results": 3,
    "total_available": 12,
    "truncated": true,
    "more": "9 more du'as for this context; call get_dua with offset and limit to see them.",
    "grading_summary": { "quranic": 2, "graded": 0, "not_a_narration": 0, "not_recorded": 1 }
  }
  // crisis_resource block added if context triggers the crisis keyword list
}

分级状态。 每条 du'a 记录都带有 grading_status:quranic(文本是《古兰经》经文或经文片段)、graded(已记录圣训分级)、not_a_narration(一般祈祷词,并非先知传述;记录中带有说明这一点的 grading_directive),或 not_recorded(AskSakina 语料库没有该条内容的分级记录)。目前语料库的大部分记录均为 not_recorded;Source 和 Grading 行会如实说明,而不会暗示存在分级。已核实《古兰经》出处的 du'a 带有 origin: "quran" 和 quran_citation,其阿拉伯语文本是在打包时通过 AskSakina 的经文模块解析得到的 Tanzil Uthmani 文本。

get_name_of_allah

按编号(1–99)或字符串(转写、阿拉伯语或英文释义)查询。返回阿拉伯语、转写、本地化释义、默想内容和《古兰经》出处。

参数 — 以下二选一:

名称类型说明
number1..99主要查询方式
namestring转写、阿拉伯语或英文释义

另有可选参数 locale(tr 会返回英文释义和默想内容)。

响应示例(已截断)

{
  "_sakina_meta": { "content_type": "name_of_allah" /* … */ },
  "content": {
    "number": 29,
    "arabic": "الحَكَم",
    "transliteration": "Al-Hakam",
    "meaning": "The Judge",
    "reflection": "Allah is the absolute Judge…",
    "quran_references": ["6:114", "13:41"]
  }
}
find_verses

按主题查询,与 get_quran_verse 的出处查询并列(WO#386)。系统会规范化查询内容,并将其中每个词与 AskSakina 主题经文索引中的主题(anxiety、gratitude、patience、trust、grief、hope、forgiveness、morning、friday、ramadan、encouragement)进行匹配,匹配方式为主题名称或固定同义词列表。结果是确定性的:不使用嵌入,也不调用 AI。

2.5.0(WO#495)新增了十五个主题,每个主题的经文均按规则顺序排列:companionship、family_and_marriage、hereafter、parents、night_and_rest、character、justice、protection、quran_and_knowledge、faith_and_guidance、prophets_and_creation、seasons、provision、healing 和 certainty。companionship(孤独)与 grief 一样,带有温和支持内容块,不包含教导内容。healing 还带有一条额外指示:这些经文提供精神慰藉,不能替代医疗护理。若查询中含有危机检测器无法单独识别的虐待词语("abuse"、"abusive"、"violence" 及其变体),则不会匹配这十五个主题中的任何一个,响应方式与 2.4 相同。自 2.5.1(WO#500)起,以这些词语构成的披露短语("abusing me"、"abusive husband"、"my father is violent",以及 Gem 3 中以乌尔都语、阿拉伯语、印度尼西亚语、孟加拉语和波斯语写出的短语)属于危机关键词:系统会在匹配任何主题前返回虐待资源内容块。

每节经文都包含 reference(章:节)、arabic(经文模块提供的完整经文,Tanzil Uthmani 文本,逐字节一致)、translation(完整经文的 Pickthall 译文,获取方式与 get_quran_verse 相同)、章名,以及说明该经文列于哪些主题中的 relevance_note。该说明不是注释。如果上游服务无法访问,仍会提供阿拉伯语文本,而 translation 会为 null,并附带说明。

如果没有匹配项,则返回 content_type: "not_found"、verses: []、no_results: true 以及可用主题列表,而不是错误。危机检测优先运行,与 get_dua 一样:任何严重危机(自残或虐待)都会返回 crisis_resource_only,不包含经文或主题列表。

参数

名称类型必填说明
querystring是主题或关键词,例如 patience、grief、gratitude
limit1..10否,默认 5经文数量
locale'en' | 'id' | 'ur' | 'ar' | 'tr'否,默认 en选择当地危机资源。译文为 Pickthall 英文译文;ur、id 和 tr 会附带暂未提供译文的说明
资源:sakina://about

使用工具前请先阅读此资源。它包含七条核心指示,以及三篇经 Gem 审核通过的教育性 dawah 文本。大多数 MCP 客户端会在首次连接时自动获取此资源。

服务端 instructions(2.2.0)

初始化结果包含 instructions(1,529 个字符,低于 1,801 个字符的限制):引文和教学规则、2026 年 10 月 20 日裁定的宣教礼仪条款(原文照录),以及附带条件的敞开之门表述(仅当用户对伊斯兰本身感兴趣时才提及,每次对话最多一次,用户陷入困境时绝不提及,绝不将其作为回答的条件,用户拒绝后绝不提及)。会呈现 instructions 的客户端会在每个会话中向其模型提供这些规则一次;无论客户端是否呈现,_sakina_meta.llm_directives 中的逐条响应规则都适用。

教学(2.2.0,“教学,不转手”)

如果某条记录有对应的教学条目(src/teach/entries.ts;目前有六条记录),记录就会包含 teach 区块和 related 列表,audience 字段则可有可无。指令规定了教学顺序:先逐字引用记录(阿拉伯语、译文、出处、等级);然后仅依据 teach 区块进行解释,并说明内容来自 AskSakina 的笔记,而非经注或教法裁定;笔记未涉及之处,应明确说明并指向公认的经注或合格的学者;原文提供反思问题,但不得作答;最多提供一个相关的后续步骤。支持区块、哀伤流程或危机响应中不会附加任何内容;指令还要求,只有在用户已透露自己陷入困境、哀伤或危机后,Agent 才能引用记录。如果没有提供 teach 区块,Agent 只能依据记录自身提供的字段进行解释,并注明内容来自 AskSakina 的笔记,然后以相同方式转介。

提示词:学习旅程(2.4.0)

两个提示词,适用于会显示 MCP 提示词的客户端(例如将其显示为斜杠命令的客户端)。每个提示词都会返回一条用户消息,告知 Agent 调用一个工具,然后依照该响应自带的规则呈现响应(_sakina_meta.llm_directives.CRITICAL_RULES 和 presentation_contract,只要提供了 teach 区块,其中就包含教学顺序),并遵循服务端逐字照录的宣教礼仪。提示词不会增加任何宗教内容:用户看到的所有内容都来自工具的记录,以及其中可能存在的、经 Gem 批准的教学条目。

提示词参数调用的工具后续步骤
understand_a_versesurah(1-114)、ayah(1-286),均为必填get_quran_verseteach 区块自身提供的相关步骤(如果有)
explore_names_of_allahnumber(1-99),可选;未提供时默认为 1get_name_of_allah名称 number + 1,仅提供一次(99 之后不再提供)
  • 参数必须为数字字符串,提示词运行前会进行检查;其他任何输入都会以 -32602 拒绝,且不会回显该值。某节经文是否存在于其章中,由工具通过 not_found 响应告知,与直接调用时相同。
  • 如果响应包含 crisis_resource 区块(危机或温和支持),消息会告知 Agent 遵循该区块的指令,不添加任何内容:不提供反思问题,也不提供后续步骤。
  • 提示词参数绝不会被记录或计数。/stats 只按名称统计每个提示词被获取的次数。
提示词:两种使用流程(2.5.0)
提示词参数要求 Agent 执行的操作
what_muslims_believeaudience(curious、revert 或 practising),可选;未提供时为 curious阅读 sakina://about;获取 112:1-4、第 1 个真主尊名、资源 sakina://learn/what-muslims-believe 和 2:256;后续内容只能来自这些记录;提供一个下一步;至多出现一次开放邀请,不得出现在危机提示或困扰之后
first_steps_new_muslimstep(1 到 4),可选;未提供时为 1每次获取一个步骤,audience 始终为 revert:1 念作证词(不得要求用户念诵)、112:1-4、第 1 和第 2 个真主尊名;2 8:38、关于宽恕的资源、第 34 个真主尊名、39:53 和 du'a Sahih al-Bukhari 744(get_dua id D00234);3 小净和第一次礼拜、1:1;4 寻找社群。不得提供开放邀请。
  • 提示词运行前会检查参数;其他任何值都会被拒绝,并返回 -32602,且不会回显该值。
  • 这些资源(sakina://learn/what-muslims-believe、sakina://learn/first-steps#shahada、#forgiven、#wudu、#first-prayer、#community)由脚本根据应用自身经过审核的种子模块和 Gems 的裁定生成(scripts/wo495-learn-content.ts);如果提交的文本不一致,构建将失败。
  • 给新穆斯林的说明(audience_note)。 当 audience: "revert" 时,有六条记录包含 AskSakina 给新穆斯林的说明(112:1、1:1、第 1、第 2 和第 34 个真主尊名,以及 du'a D00234),并附有各自的引文和必须原样引用的 note_block。凡是 teach 被禁止的情况(危机、支持提示、悲伤、非英语区域设置),均不提供此说明。

响应封装

每个工具都会返回相同结构:

{
  "_sakina_meta": {
    "version": "1.0",
    "source": "AskSakina Islamic Knowledge Server (asksakina.com)",
    "content_type": "quran_verse" | "dua_collection" | "name_of_allah" | "not_found" | "crisis_resource_only",
    "disclaimer": "AskSakina provides curated Islamic reference content for educational purposes. …",
    "llm_directives": { "CRITICAL_RULES": ["…"] },
    "presentation_contract": {
      "quran":         { "no_paraphrase": true, "require_citation": "surah:ayah" /* … */ },
      "hadith":        { "require_grading": true, "require_source": true /* … */ },
      "name_of_allah": { "no_paraphrase_arabic": true /* … */ }
    },
    "educational_context": "…"
  },
  "content": { /* tool-specific record; a record with a teaching entry also carries "teach" and "related" (2.2.0) */ },
  // get_dua and find_verses, when crisis keywords detected:
  "crisis_resource": { "level": "hard" | "soft", "crisis_type": "self-harm" | "abuse", "locale": "…", "directive": "…", "text": "…" }
}

该封装是约定:_sakina_meta.presentation_contract 会告知 Agent 如何呈现记录,disclaimer 会说明 Agent 不能凭自身权威作出哪些声明,而 crisis_resource 要求当用户的困扰达到安全阈值时,Agent 必须优先提供危机资源。这些是给客户端 AI 的指令;服务端无法强制另一个 AI 遵循这些指令。

结构化输出(2.4.2)

每个工具都会发布一个 outputSchema,并以两种形式返回封装:作为对象的 structuredContent,以及作为文本内容的 JSON 文本(与早期版本相同,未经更改)。两者始终包含相同的数据。各工具的架构见 src/contracts/output-schemas.ts:

工具content_typecontent
get_quran_versequran_verse、not_found经文(苏拉编号和名称、阿亚、arabic_text、translation、translation_source、translation_language;可选的 teach、related),或 { requested, reason }
get_duadua_collection、not_found、crisis_resource_only{ context, matched_by, duas[], total_results, total_available, truncated, grading_summary },或 { requested, reason },或 { requested, withheld, reason }
get_name_of_allahname_of_allah、not_found、crisis_resource_only真主尊名(name_block、number、arabic、transliteration、english_meaning、reflection、quranic_references;可选的 teach、related),或 { requested, reason },或 { requested, withheld, reason }
find_versesverse_collection、not_found、crisis_resource_only{ query, matched_themes[], verses[], total_results, no_results },或未匹配时的结构(available_themes),或 { requested, withheld, reason }

每个响应都包含 _sakina_meta(version、source、content_type、disclaimer、可选的 disclaimer_locale、llm_directives.CRITICAL_RULES、presentation_contract、educational_context);如果适用危机提示或轻度支持提示,还会包含 crisis_resource(level、可选的 crisis_type、locale、directive、text)。每个对象都允许扩展:后续版本添加字段时,不会导致验证对象的客户端失败。

快速开始

通过 npx 运行(无需安装)
npx -y @asksakina/islamic-knowledge-mcp --stdio

使用 --stdio 时,程序会通过标准输入/输出使用 MCP;将其接入任意 MCP 客户端即可。不带此标志时,程序会在 $PORT 上启动 Streamable HTTP 服务(默认端口为 3030,提供 POST /mcp 和 GET /health),与托管端点的运行方式相同。在 2.1.0 之前,sakina-mcp 命令会直接退出,不会启动任何服务(WO#444)。

通过远程 Streamable HTTP 连接
https://sakina-mcp.fly.dev/mcp

适用于更倾向使用托管端点而非本地子进程的 Agent。工具、消息封装和速率限制均相同。

Claude Desktop

将以下内容添加到 ~/Library/Application Support/Claude/claude_desktop_config.json(macOS)或 %APPDATA%/Claude/claude_desktop_config.json(Windows):

{
  "mcpServers": {
    "sakina": {
      "command": "npx",
      "args": ["-y", "@asksakina/islamic-knowledge-mcp", "--stdio"]
    }
  }
}

重启 Claude Desktop。工具选择器中会显示这四个工具和 sakina://about 资源。

Cursor

将以下内容添加到 ~/.cursor/mcp.json(或工作区的 .cursor/mcp.json):

{
  "mcpServers": {
    "sakina": {
      "command": "npx",
      "args": ["-y", "@asksakina/islamic-knowledge-mcp", "--stdio"]
    }
  }
}
VS Code(搭配支持 MCP 的扩展)

将以下内容添加到工作区中的 .vscode/mcp.json:

{
  "servers": {
    "sakina-islamic-knowledge": {
      "command": "npx",
      "args": ["-y", "@asksakina/islamic-knowledge-mcp", "--stdio"]
    }
  }
}
通过远程 HTTP 使用通用 MCP 客户端
{
  "mcpServers": {
    "sakina": {
      "type": "streamable-http",
      "url": "https://sakina-mcp.fly.dev/mcp"
    }
  }
}

使用场景

此 MCP 服务面向任何需要精选伊斯兰来源资料的 Agent 或应用,并会明确指示其原文引用,不得改述。

  • 构建带有出处引用的伊斯兰聊天机器人。 将 get_quran_verse 和 get_dua 接入对话流程;呈现约定会指示 Agent 原文引用并保留等级标注,每条回复还会注明内容类型;对于祈祷词,则会注明每条记录的等级。
  • 为 Agent 添加结合礼拜时间的灵性内容。 将《古兰经》和祈祷词工具与礼拜时间 API 结合,在一天中恰当的时刻呈现真主的话语。
  • 根据用户情境推荐祈祷词。 get_dua 中的危机关键词过滤器可处理危险的边缘情况(自残相关措辞、虐待),确保在遇到涉及安全的紧急消息时,助手不会以通用祈祷词作答。
  • 回答有关 99 个尊名的问题。 get_name_of_allah 可通过编号或名称查询,并返回规范阿拉伯语、转写、含义和释义,以及《古兰经》出处。
  • 保持神学包容性。 此服务旨在避免将有争议的教法裁决当作普遍适用的答案。

内容完整性

新的和已更改的内容在发布前,都会经过 AskSakina 的“Gem”专业 AI 审核链审核。其中 4 位审核者负责把关每次伊斯兰知识内容的发布:

  1. 《古兰经》与译文核验。 经文准确性、苏拉/经文引文正确性、圣训等级判定、来源审核。
  2. 教法多元性(多学派)。 跨学派准确性、对有争议的主题不采用单一学派视角、语言包容。
  3. 伊斯兰心理学与牧灵关怀。 安慰窗口的安全性、危机过滤覆盖范围、不以愧疚感作为激励。
  4. 探索者/伊斯兰信仰新手易用性。 为非穆斯林读者解释阿拉伯语术语、通俗易懂的教法内容、不预设信仰背景的反思。

已在代码中实现的架构行为:

  • 每个数据加载器边界都会将 Unicode 先知祝福语(U+FDFA,ﷺ)替换为 (peace be upon him)。响应构建器会拒绝任何包含该符号的输出。
  • 每条 du'a 记录都带有 grading_status(quranic、graded、not_a_narration、not_recorded)。只有当每条返回记录都经过等级判定或属于《古兰经》内容时,hadith 呈现契约才会设置 require_grading: true;否则会设为 "per_record",确保响应信封不会声称数据中并不存在的等级判定。
  • 每次 get_dua 请求都会进行危机关键词检测,使用的关键词列表与主应用安全关卡所用的列表相同。

神圣用途许可证。 本服务根据神圣用途许可证分发(参见 LICENSE)。允许的用途主要包括宣教、教育、个人礼拜,以及以尊重的方式集成到服务穆斯林的应用中。该许可证禁止将伊斯兰知识包装成稀缺或付费墙内容来变现。许可证条款的公开摘要位于 https://www.asksakina.com/en/mcp。

隐私。 请参见 隐私与分析。


本地运行以进行开发

cd mcp-server
npm install
npm run bundle-data     # snapshot data from main repo into data/
npm run typecheck       # tsc --noEmit
npm run start           # HTTP server on :3030 via tsx
npm run test:tools      # exercise each tool, prints sample JSON

# Or build + run from compiled output:
npm run build           # tsc -> dist/, postbuild adds shebang + dist/package.json
npm run start:dist      # node dist/server.js

POST /mcp 接受标准 MCP JSON-RPC 2.0。GET /health 返回 { "status": "ok", "name", "version" }。

速率限制

默认值:每个 IP 每分钟 60 个请求。

  • 设置 UPSTASH_REDIS_REST_URL + UPSTASH_REDIS_REST_TOKEN → 使用分布式 Upstash Redis 固定窗口。
  • 否则 → 使用进程内存令牌桶。

响应包含 X-RateLimit-Limit、X-RateLimit-Remaining、X-RateLimit-Reset。超出限制时返回状态码为 429、错误码为 -32029 的响应。

身份验证

v1 版本无需身份验证即可使用。v1 会接受可选的 X-Sakina-App-Id 标头,但不会强制要求或记录该标头。v2 将要求提供该标头。

隐私与分析

本服务采用仅汇总数据的模型(WO#360;每日总计 WO#456;教学计数器 WO#477)。对于每个工具,服务器都会持续统计不同结果(ok、not_found、error)的调用次数、处理程序耗时总和(用于报告运行平均值),以及包含教学区块的响应数量。对于所有工具,服务器还会统计每个可选 audience 参数值(curious、revert、practising、unknown 或无)的调用次数,以及每条学习提示词被获取的次数。这些都只是总计,通过 /stats 端点报告。

  • 不进行持久化跟踪: 应用不会将单次请求日志或客户端标识符写入磁盘或任何数据库。
  • 临时处理 IP: 客户端 IP 地址仅用于执行速率限制。每个地址都会在速率限制窗口(60 秒)内作为速率限制键保存在 Upstash Redis 中,之后过期。如果 Upstash 不可用,内存回退机制会在同一窗口内将其保存在进程内存中,随后丢弃。应用绝不会持久化原始 IP 地址,也绝不会将其写入日志。
  • 不记录载荷: 不会捕获或记录请求参数(例如上下文值、经文引用、Name 编号、提示词参数或区域设置)及响应载荷。唯一会计数的参数是 audience,且仅按其四个固定值和“无”进行计数;该值本身绝不会与调用、工具或其他任何内容一同存储。
  • 启动以来的计数器: /stats 在 by_tool 下报告的总计仅存在于 RAM 中,服务器进程重启时会重置。
  • 服务器本地磁盘上的每日总计: 在托管服务器上,每个 UTC 日对各工具的调用次数(按结果 ok、not_found、error 分类)、处理程序耗时总和、包含教学区块的数量、audience 值的计数,以及每条学习提示词的获取次数,都会写入服务器本地磁盘,以便在重启后保留。数据最多保留 90 天;更早的数据会被删除。数据不包含 IP 地址、用户代理、客户端标识符、单次调用时间、参数或载荷,也无法关联到任何请求或个人。只有在设置了 MCP_USAGE_DIR 时才会写入这些数据:本地运行 npx 或 --stdio 时不会写入任何数据。
  • 不按个人计数: 不会针对客户端、会话、用户或对话单独保存任何计数器。教学、audience 和提示词计数器与各工具的调用次数属于同一类数字:所有调用者的累计总数。

法规说明(英国 GDPR):由于超出速率限制窗口后不会保留任何可识别个人身份的信息,因此不存在可供访问或删除的记录。请注意,虽然应用本身不会持久化个人数据,但我们的基础设施提供商(Fly.io)会在边缘层临时处理 IP 地址,以进行标准网络路由和平台安全保护。

/stats 端点

需要身份验证的摘要端点:

curl -H "Authorization: Bearer $MCP_STATS_TOKEN" https://sakina-mcp.fly.dev/stats

必须设置 MCP_STATS_TOKEN 环境变量(否则端点会返回 503,并拒绝提供未经身份验证的服务)。令牌比较采用恒定时间算法。

负载结构:

{
  "privacy": "aggregate-only counters; no per-request records, no IPs, no user-agents, no client identifiers, no geolocation, no params beyond a tally of audience values, no payloads; since-start totals reset on restart; daily totals (per tool: ok, not_found, error, summed duration, teach served; plus audience tally and prompt fetches by name) kept on the server's own disk for at most 90 days",
  "since": "2026-09-25T…",
  "total_requests": N,
  "by_tool": {
    "get_quran_verse":   { "total": N, "ok": N, "not_found": N, "error": N, "avg_response_ms": N, "teach_served": N },
    "get_dua":           { "total": N, "ok": N, "not_found": N, "error": N, "avg_response_ms": N, "teach_served": N },
    "get_name_of_allah": { "total": N, "ok": N, "not_found": N, "error": N, "avg_response_ms": N, "teach_served": N },
    "find_verses":       { "total": N, "ok": N, "not_found": N, "error": N, "avg_response_ms": N, "teach_served": N }
  },
  "audience": { "curious": N, "revert": N, "practising": N, "unknown": N, "absent": N },
  "prompts": { "understand_a_verse": N, "explore_names_of_allah": N, "what_muslims_believe": N, "first_steps_new_muslim": N },
  "rate_limiter": {
    "state": "upstash",
    "upstash_configured": true,
    "upstash_failures": 0,
    "last_failure": null,
    "last_failure_at": null,
    "last_success_at": "2026-09-25T…",
    "startup_check": "Upstash reachable (PING ok, 12 ms); state: upstash"
  },
  "basmala_prefix_mismatch": 0,
  "daily": {
    "retention_days": 90,
    "days": [
      { "date": "2026-10-12", "total": N,
        "by_tool": { "get_dua": { "total": N, "ok": N, "not_found": N, "error": N, "avg_response_ms": N, "teach_served": N }, … },
        "audience": { "curious": N, "revert": N, "practising": N, "unknown": N, "absent": N },
        "prompts": { "understand_a_verse": N, "explore_names_of_allah": N, "what_muslims_believe": N, "first_steps_new_muslim": N } }
    ]
  }
}

daily 列出已存储的日期,按时间从近到远排列,并包含今天尚未写入的调用;未设置 MCP_USAGE_DIR 时,其值为 null,此时 privacy 行仅列出内存中的计数器(“仅聚合的内存计数器,包括按工具统计的 teach-served、受众值的计数,以及按名称统计的提示词获取次数;……重启后重置”)。

teach_served 统计包含 teach 块的响应(WO#488)。audience 按四个固定值统计每次工具调用可选的 audience 参数;对于未发送该参数的调用,记为 absent。这是所有工具的总计,绝不会与某个工具、某次调用或精度高于 UTC 日的时间关联。prompts 按名称统计每个学习提示词的获取次数;不会读取提示词参数。

rate_limiter.state 的值为 upstash(Upstash 正常响应)、degraded(已配置 Upstash,但出现故障:请求由内存备用方案限流,绝不会放行)或 memory(未配置 Upstash)。故障原因会包含 HTTP 状态码或错误,但绝不包含客户端 IP。basmala_prefix_mismatch 统计上游提供的第 1 节经文文本既不以记录的两种 basmala 形式开头、又未经更改直接提供的次数。这只是聚合计数;对应的日志行不包含经文引用。

在 Fly 上进行一次性设置
fly secrets set MCP_STATS_TOKEN=$(openssl rand -hex 32)
fly deploy

服务器只会向 fly.toml 挂载的 /data 卷写入一类内容:每日总计,每个 UTC 日期在 /data/usage(MCP_USAGE_DIR)中对应一个文件,每 5 分钟写入一次,并在 Fly 停止机器时写入。自 WO#360 起,LOG_DIR(/data/logs)便未再使用。

数据源

工具来源
get_quran_verse英语(2.1.0,WO#444): AskSakina 修订后的 Pickthall 译本,作为 data/pickthall.json 打包,来源为应用的 public/quran/en.pickthall(全部 6,236 节经文,包含针对 1930 年文本的 WO#442 修订,不含经文末尾标点,与应用阅读器中的显示一致),适用于所有区域设置:ur 和 id 会附带说明(其译文因许可问题暂缓提供;1.4.1)。阿拉伯语和苏拉名称: 运行时从 alquran.cloud 获取(源自 Tanzil 的 Uthmani 版本)。会移除开头的字节顺序标记。上游还会在除第 1 和第 9 章之外的每章第 1 节经文前添加太斯米。根据 Gem 2(太斯米仅在 1:1 中属于第 1 节经文),会从第 2–8 章和第 10–114 章的第 1 节经文中移除该确切前缀,并匹配上游发送的两种字节形式。经文其余部分按原始字节提供。无法识别的开头会原样提供,并在 /stats 中计数(basmala_prefix_mismatch)。所有内容均按节逐条获取(/ayah/{surah}:{ayah})。不提供 Saheeh International 译本(已于 1.2.0 移除,WO#245)。每节经文 + 版本在进程内缓存 24 小时。
get_duaAskSakina 的祈祷词语料库(2.1.0 版共 440 条),在 npm run bundle-data 时从 ../src/data/duas 快照到 data/duas.json。带有已核实《古兰经》出处的祈祷词,会在同一步从 scripture 模块(../src/lib/scripture,Tanzil Uthmani 版本)获取阿拉伯语文本。
get_name_of_allahAskSakina 的真主 99 个尊名,在 npm run bundle-data 时从 ../src/lib/data/99-names 快照。
find_versesAskSakina 的主题经文索引(../src/lib/data/thematic-verses),在 npm run bundle-data 时快照到 data/thematic-verses.json。仅从索引中获取每节经文的出处和主题;阿拉伯语文本在同一步从 scripture 模块获取,Pickthall 译文则从打包的 data/pickthall.json 获取(2.1.0;苏拉名称仍在运行时从 alquran.cloud 获取,与 get_quran_verse 使用相同缓存)。

祈祷词和尊名数据是主应用数据文件的快照,因此任何更新都会在下次运行 npm run bundle-data 时同步到此处(部署工作流会运行该命令)。已发布的软件包包含构建时的快照。


v1 暂不包含

根据 Phase 3 规划文档:

  • 语义搜索 / search_islamic_guidance — 需要由 Gem 审核的评估集。(find_verses 是索引查找,不是语义搜索。)
  • explain_islamic_concept — 在 Architect 级别作出裁定之前,与 CLAUDE.md 中“AI 绝不提供精神或教法建议”的规则直接冲突。
  • get_pastoral_guidance — Gem 3 的表述依赖 AskSakina 控制的界面;未经单独审核,不能通过 MCP 发布。
  • check_halal_ingredient — 因 WO#61 恢复工作受阻。
  • HMAC 签名强制执行 — v1 会接受 X-Sakina-App-Id 标头,但会忽略它。

部署

发布时无需依赖主应用:npm run bundle-data 会将祈祷词语料库、99 个尊名以及规范安全模块从主 AskSakina 单体仓库快照到 data/ 和 src/safety/_synced/。编译后的 dist/ 和打包的 data/ 目录在运行时不依赖主应用。

bundle-data 会通过 prebuild 脚本自动运行(WO#138),因此在全新检出后,npm run build 即可独立完成,无需手动打包。src/safety/_synced/ 目录已提交到 git,因此主应用安全模块的任何偏差都会显示在不同提交之间的 git diff 中。

docker build 不会运行 prebuild(它只复制 mcp-server/ 目录,而不复制单体仓库)。在运行 docker build 前,请先在主机上运行 npm run bundle-data,以填充 data/。从全新克隆构建时也一样——运行 docker build 前先执行 npm install && npm run bundle-data。

CI 部署(规范流程 — WO#249)

所有 MCP 版本发布都通过 MCP Server Deploy GitHub Actions 工作流 (.github/workflows/mcp-deploy.yml)进行——开发者的机器上无需保存 flyctl 或 npm 身份验证信息。架构师在仓库的 Actions 选项卡中通过 workflow_dispatch 触发此工作流,并设置两个布尔输入:

  • deploy_fly(默认值 true)——构建并通过 flyctl deploy 部署到 sakina-mcp.fly.dev。
  • sync_mirror(默认值 true)——将构建好的软件包推送到公开镜像 (github.com/yserrag/asksakina-mcp),并在那里创建 v<version> 标签。镜像自身的 工作流随后会通过可信发布和来源证明(WO#444)将 @asksakina/islamic-knowledge-mcp 发布到 npm;本仓库不保存 npm 令牌。

该作业会在 main 上运行完整的 Gem 10 操作手册:npm ci → npm run bundle-data (关键步骤)→ flyctl deploy → 轮询 /health → 实时 Pickthall 字节检查 2:255 和 9:129 → 实时 Dhun-Nun 检查 → 速率限制器探测(仅警告)→ 实时发布防护检查 → Agent 评测(仅警告;自 WO#386 起放在防护检查之后,因此阻止发布的防护检查会优先获得速率限制预算)→ 镜像同步和打标签(由镜像执行发布)。字节检查会对实时端点运行 MCP initialize 握手 + tools/call get_quran_verse:"save Him"(Pickthall)通过;"except Him"(Saheeh International)或无法访问的 /mcp 都会导致作业失败,且不会执行镜像同步, 同时输出 flyctl status + 日志,并打印手动回滚命令。9:129 必须显示 "There is no God save Him",只有已打包的修正文案包含这一内容。 密钥 FLY_API_TOKEN 和 ASKSAKINA_MCP_DEPLOY_KEY 保存在仓库设置中,绝不会回显。

自动回滚到上一镜像是 Gem 10 的最终目标,但目前暂缓实施:当前的线上镜像本身有问题,因此暂时没有已知正常的镜像可供自动恢复。首次运行只会在失败时明确报错,并仅支持手动回滚。

Fly.io(手动 / 紧急处理)

优先使用上面的 CI 工作流。以下命令是底层操作方式,适用于已完成 flyctl 身份验证的机器:

cd mcp-server
fly launch              # first time only — picks up fly.toml
fly secrets set \
  UPSTASH_REDIS_REST_URL=... \
  UPSTASH_REDIS_REST_TOKEN=...
npm run bundle-data     # load-bearing: docker build copies host data/
fly deploy
fly status
curl https://<app>.fly.dev/health

生产应用:sakina-mcp.fly.dev。应用 sakina-mcp,区域 lhr,内部端口 3030,强制使用 HTTPS,每 30 s 在 /health 上执行健康检查,空闲时自动停止,1 个共享 CPU,256 MB RAM。

部署后验证和回滚

每次执行 fly deploy 后,都要从线上端点检查一节《古兰经》经文的字节,并与锁定的 Pickthall 表(docs/wo-cert/si-pickthall-LOCKED-final.json)进行比对,以确认译本是 Pickthall,而不是 Saheeh International:

curl -s https://sakina-mcp.fly.dev/mcp ... # call get_quran_verse for a known ref
# compare the returned translation to the locked Pickthall text for that ref

如果字节检查失败(提供的是 SI 文本,或译文与 Pickthall 不匹配),先回滚,再诊断。在进行任何进一步调查或修复之前,立即重新部署上一镜像:

fly releases --app sakina-mcp                 # find the last-good release / image
fly deploy --app sakina-mcp --image <previous-image-ref>

线上出现 SI 回归问题时,不要尝试直接向前修复——先恢复已知正常的镜像,确认该镜像通过字节检查,然后在离线环境中诊断有问题的构建。

本地容器测试
docker compose up --build
curl http://localhost:3030/health
其他目标平台

该软件包只是一个 Node.js HTTP 服务端,因此可运行在任何支持 Dockerfile 或 Node 进程的平台上:Railway、Render、小型 VPS、Cloudflare Workers(使用 streamable-http 传输)、Vercel Functions(使用轻量适配器)。如果未配置 Upstash,内存速率限制器会自动回退。


npm 发布

发布通过 MCP Server Deploy 工作流进行(参见 CI 部署),并设置 publish_npm: true——架构师从 Actions 选项卡触发该工作流;NPM_TOKEN 保存在仓库设置中。手动等效操作(紧急处理,需要本地 npm 身份验证):

cd mcp-server
npm login                                    # to the @asksakina org
npm publish --access public

prepublishOnly 会依次运行 bundle-data → build → test:tools,确保发布的 tarball 始终包含最新数据且构建干净。files 字段会将文件范围限制为 dist/、data/、README.md、LICENSE 和 .mcp/server.json。

先运行 npm pack --dry-run,检查将要发布的 tarball 内容。

MCP Registry 提交

mcp-server/.mcp/server.json 声明了 AskSakina 在官方 MCP Registry 中的身份:

  • 服务名称:com.asksakina/islamic-knowledge
  • 软件包:@asksakina/islamic-knowledge-mcp(npm,stdio 传输)
  • 远程服务:https://sakina-mcp.fly.dev/mcp(Streamable HTTP)

发布流程:MCP Registry Publish GitHub Actions 工作流(主仓库中的 .github/workflows/mcp-registry-publish.yml,手动触发)。该工作流会检查 server.json、package.json 和 npm 是否一致,然后运行:

mcp-publisher login dns --domain asksakina.com --private-key <KEY>   # or: login http
mcp-publisher publish .mcp/server.json
curl "https://registry.modelcontextprotocol.io/v0/servers?search=com.asksakina"

com.asksakina 的域名所有权证明使用 Ed25519 密钥:公钥位于 asksakina.com 的 DNS TXT 记录中(v=MCPv1; k=ed25519; p=<base64>,自 2026 年 5 月起),或位于 https://asksakina.com/.well-known/mcp-registry-auth;私钥位于仓库密钥 MCP_REGISTRY_PRIVATE_KEY 中。

Smithery 重新发布(版本升级后)

版本号分布在三个位置,升级时需同时更新:

  1. package.json("version")
  2. mcp-server/.mcp/server.json(顶层 version 以及 packages[0].version)
  3. mcp-server/src/server.ts(SERVER_VERSION 常量——显示在 /health 和 /.well-known/mcp/server-card.json 中)

升级版本时的重新发布检查清单:

cd mcp-server
npm run typecheck && npm run test:tools && npm run test:analytics
npm run bundle-data
npm publish                                       # npm registry
mcp-publisher publish .mcp/server.json            # MCP Registry
fly deploy                                        # Smithery scanner picks up the new card via /.well-known/mcp/server-card.json

Smithery 会自动扫描 /.well-known/mcp/server-card.json,并在几分钟内重新编入索引——无需手动调用 Smithery API。


链接

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。