关于 Doktor
Doktor 是面向土耳其医生的 TypeScript/Node.js MCP 服务框架,用官方法规和有理由的高等法院判决生成有来源依据的法律信息包,不提供定论式法律意见。
主要功能
- 01搜索并获取官方卫生法规
- 02分类医疗法律问题
- 03筛选并去重判例
- 04生成带来源追踪的信息包
- 05支持实时与模拟数据源
适用场景
- 01查询患者知情同意相关法规
- 02查看案件相关的有理由判决
- 03核对引用条文及来源轨迹
MCP 相关
它提供问题分类、法规与判例搜索、判决全文获取以及法律信息包生成和深入查询等工具。响应标注数据来源,法规工具可选择实时或模拟数据源。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
8收录的工具列表 · 更新于 5 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| question | string | 是 | |
| sourceMode | enum | 否 | mock | live | snapshot |
详细介绍
Doktor MCP
Beta 版本 — 当前版本请查看 package.json 和 CHANGELOG.md。
项目页面: avfatihsozer.com/projeler/doktor-mcp · English: README.en.md
doktor-mcp 是一个独立的 TypeScript/Node.js MCP 框架,面向医生生成基于来源的法律信息包。它不会给出一概而论的最终法律意见,也不会告诉医生该怎么做。它会将问题与官方法规文本及附有理由的高等法院判决文本相匹配;在不作确定性断言的前提下,可以提供基于来源的条件性评估(例如,“来源显示出这种倾向”)。
适配器边界为以下来源预留:
legislation(法规)yargitaydanistayaym
一般互联网文章、博客、新闻、律师事务所宣传页面和论坛不是本项目的来源输入。
来源引擎移植(Source Engine Port)
来源引擎层提供了在线适配器所需的可靠性增强:
- Bedesten 请求使用共享的
HttpClient和RateLimiter路径,其中包含有限次数的重试、Retry-After处理、指数退避(backoff)、抖动(jitter)和请求遥测。 - 在线来源错误保持结构化且仅包含 JSON。来源诊断信息可以携带重试次数、backoff 时长、状态和内容类型,且不会向 CLI JSON 输出写入日志。
src/sources/sourceRegistry.ts为法规和判例来源提供精简的来源能力、速率限制和缓存策略元数据。- Bedesten/Yargıtay 适配器会将仅含元数据的判决排除在已验证判例输出之外;如果官方法规的官方搜索、文档获取或条款提取无法支持引文,则会返回结构化的
unavailable结果。
在线法规状态
在线官方法规适配器已连接到可选的 MCP 工具流程:
- 适配器:
LiveOfficialLegislationAdapter - 官方来源:土耳其共和国总统府法规信息系统 —
mevzuat.gov.tr - 搜索能力:官方
MevzuatDatatable搜索请求解析器 - 全文能力:官方
MevzuatMetin文档获取 - 当前提取依据:适用于已匹配法规的 PDF 文本提取和条款解析
医疗法规是首条在线匹配路径。患者权利和知情同意问题使用《患者权利条例》4847 的官方生成 PDF 路径(包括匹配条款 24 和 26)。医疗法匹配还涵盖《医疗伦理条例》、《关于行医及其分支执业方式的法律》和《卫生服务基本法》。KVKK 第 6 条可在医疗专属来源之后,作为个人健康数据和隐私问题的补充一般法规使用。
如果官方文档不是可提取的格式,或无法提取匹配条款,在线适配器会返回结构化的 unavailable 输出,而不是生成结论。
在线来源错误使用以下约定:
{
"status": "unavailable",
"source": "mevzuat.gov.tr",
"errorCode": "provision_not_found",
"message": "Official text was retrieved but the mapped article could not be extracted.",
"retryable": false,
"recommendedNextStep": "Inspect the official text parser before using this provision in an answer."
}
MVP 范围
骨架包含:
- MCP 服务注册和工具处理器骨架
- 正式法规证据、法院判决证据、分类、判例状态和法律信息包的类型契约
- 模拟法规和高等法院适配器
- 用于正式来源验证的实时法规适配器
- 面向实时法规的 MCP
sourceMode路由 - 以医疗健康为优先的法规映射和来源追踪(source trace)元数据
- 医疗健康法律工作流组件:
- 问题分类器
- 法规映射器
- 判例筛选器
- 答案编译器
- 本地 JSON 冒烟测试命令
- 针对首批来源安全规则的 Vitest 覆盖
判例筛选器目前提供以下状态:
precedent_usable:有全文、法律理由和事实相关性limited_value:有全文,但相关性较弱procedural_only:没有实体理由;仅有程序性文本、仅有维持原判或仅有撤销判决metadata_only:没有全文,只有案卷元数据no_reasoning:有全文,但没有法律理由
只有 precedent_usable 记录会进入编译包中的已验证判例部分。
响应契约(Response Contract)
所有工具响应都带有 dataOrigin 字段。该字段用于说明响应的来源:
dataOrigin | 含义 |
|---|---|
"mock" | 响应包含 fixture(虚构)数据。不是真实法规或判决。 |
"live" | 响应来自实时来源(mevzuat.gov.tr、Bedesten、Danıştay)。 |
"snapshot" | 响应是预先保存的实时来源快照。 |
"computed" | 响应仅为计算结果(例如分类器)。不包含来源数据。 |
"client-provided" | 响应基于客户端提供的输入。 |
当 dataOrigin: "mock" 时,响应还带有 mockDataWarning 字段:
{
"dataOrigin": "mock",
"mockDataWarning": "BU YANIT KURGU (FIXTURE) VERİSİDİR. Gerçek mevzuat veya mahkeme kararı DEĞİLDİR. Gerçek kaynaklar için sourceMode: 'live' kullanın."
}
此警告会强制添加,不可遗漏,以防止模拟数据看起来像真实法规引文。不会在 shortAnswer 等面向医生的文本字段前添加额外前缀;顶层的 dataOrigin 和 mockDataWarning 字段已足够。
prepare_doctor_legal_information_pack 响应还带有 packId 字段。这是一个以 "pack-" 为前缀的 6 位十六进制标识符(例如 "pack-3f9a2c")。您可以将 packId 传给 drill_down_pack_item 工具,以便详细查看特定条款或判决,而无需重新生成信息包。packId 会在服务器内存中保存 30 分钟。
结构化信息包围绕所需的面向医生的部分组织:
shortAnswerlegalClassificationcriminalcivilCompensationdisciplinaryAdministrativepatientRightsprivacyKvkkprofessionalEthics
relevantLegislation- 法规名称
- 条款编号
- 从来源条文逐字复制的引文
- 与事件的关联
verifiedHighCourtPrecedents- 法院/庭、日期、案号/判决号
- 事实摘要、法律评估、结果
- 相似/差异说明
missingInformationlawyerReviewPoints
每条法规记录都带有来源文档 ID 和逐字复制的来源引文。每条已验证判例记录都必须通过有理由判例筛选器。
有意不纳入范围
MVP 不包含:
- 实时 AYM 高等法院客户端(AYM 判决信息库是仅提供 HTML 的界面;没有 JSON API — 标记为
synthetic_only) - 缺少来源引用或条件性表述的定性风险等级评分(“风险等级高/低”)
- 紧急行动指示
- 起诉状或辩护文书撰写
- 最终法律结论
- “存在责任”或“不存在责任”等定性表述
- 工具可以提供有来源依据的条件性评估(例如“来源倾向于支持某种观点”),但绝不会给出定性的最终裁决
- 未经 MCP 来源记录验证、仅基于模型的法律主张
v0.44.0 中的新功能
assessmentTone:可选参数("strict"|"grounded-advisory",默认值:"grounded-advisory")。在strict模式下仅返回来源列表(不进行评估)。在grounded-advisory模式下,会添加包含基于来源的条件式评估的preliminaryAssessment。preliminaryAssessment:可选响应字段,包含summary和sentences[]。每个句子都包含text、sourceRef和sourceLabel。句子使用判例中的实际结论/理由以及法规中的原文摘录片段——绝不使用套话。- 法规生效元数据:条款包含
inForce、lastAmendedDate和repealed字段(默认绝不假定条款“有效”)。 - 判决去重:跨来源的重复项(例如,同一判决同时来自 Yargıtay 和 Bedesten)会被去重;保留信息最丰富的版本。
- 完整的土耳其语变音符号策略:所有面向医生的文本均使用正确的土耳其字符(不使用 ASCII 替代字符)。
- 完整版本历史请参阅 CHANGELOG.md。稳定性级别请参阅 COMPATIBILITY.md。
速率限制为实时客户端预留:预期行为是,在发生实际拦截或来源错误后进行自适应退避,以应对正常的公共来源流量;并非在没有压力证据时进行激进限制。
MCP 工具
classify_medical_legal_questionsearch_health_legislationget_legislation_provisionssearch_health_precedentsfilter_reasoned_precedentsprepare_doctor_legal_information_packdrill_down_pack_item— 后续提问:使用packId深入了解特定条款/判决,无需重新生成信息包。示例:{ "packId": "pack-3f9a2c", "followUpQuestion": "madde 24 ne diyor?" }get_decision_full_text— 获取特定法院判决的全文。示例:{ "documentId": "yargitay:99001", "sourceMode": "live" }
响应约定说明
所有工具响应均包含 dataOrigin 字段("mock"、"live"、"snapshot"、"computed"、"client-provided")。在 Mock 模式下会添加 mockDataWarning 字段。
调用 prepare_doctor_legal_information_pack 时,可以添加 includeDiagnostics: true 参数,以获取完整审计跟踪(选择诊断信息、来源跟踪等)。
面向法规的 MCP 输入接受可选的 sourceMode:
{
"question": "kişisel sağlık verisi mahremiyet",
"sourceMode": "live"
}
sourceMode 默认为 "live"(自 0.59.0 起);如需使用 fixture 数据,必须显式指定 "mock"。
search_health_legislation、get_legislation_provisions 和
prepare_doctor_legal_information_pack 可以使用 "live"。实时信息包
保持相同的 MVP 结构,并且仅当官方法规来源无法返回经验证的条款时,才会添加 sourceUnavailable。
Mock 模式使用本地 fixture 条款。实时模式使用来自 mevzuat.gov.tr 的官方法规文本,以及实时 Yargıtay 和 Danıştay 判例适配器。AYM 仅支持 Mock,在实时模式下会被禁用,而不会作为回退选项使用。
健康法规优先级
实时匹配层会将医生的问题归入以下健康法律主题组:
- 知情同意 / 同意
- 医疗干预
- 患者权利
- 患者隐私
- 个人健康数据
- 记录、病历和出院小结
- 紧急干预
- 转诊和会诊
- 医生的注意义务
- 职业道德
每个匹配项都包含目标法规、目标条款编号、搜索词、选择理由和健康法律优先级。匹配到多个主题时,信息包会将主要健康法规排在辅助性通用法规之前。例如,涉及个人健康数据隐私的问题可能会优先返回《患者权利条例》,而不是 KVKK;KVKK 不会被用作与医生问题无关的宽泛回退选项。
来源追踪(Source Trace)
sourceTrace 用于审核实时法规输出,而非提供法律理由。每条追踪记录都展示某项规定如何从医疗法律映射,关联到官方文档和条款提取步骤:
- 原始
query matchedHealthMapping,以及未匹配映射时尝试过的映射候选项officialSearchRequest、官方搜索结果数量和精简的官方结果selectedSearchResult和selectedResultReason- 落地页/详情页 URL,以及直接或生成的 PDF URL
contentType、提取方法、提取的条款编号和获取耗时
实时 search_health_legislation 会在选定的规定旁附带追踪记录。实时
get_legislation_provisions 会在每项返回的规定中附带追踪记录。实时
prepare_doctor_legal_information_pack 会在相关法规条目和包级 sourceTrace 数组中保留追踪记录;因此,汇编的引文可对照同一条提取出的规定进行核验。
即使实时数据包不可用(unavailable),也会保留审核上下文:
{
"sourceUnavailable": [
{
"status": "unavailable",
"source": "mevzuat.gov.tr",
"errorCode": "document_not_found",
"sourceTrace": [
{
"query": "bilinmeyen konu",
"matchedHealthMapping": null,
"attemptedHealthMappings": ["mevzuat:7.5.4847", "mevzuat:1.5.6698"]
}
]
}
]
}
matchedHealthMapping 和 selectedResultReason 会展示主题类别、医疗法律优先级,以及选定映射属于主要医疗法规还是辅助性一般法规。追踪字段仅解释来源选择和提取过程,不会生成法律主张,也绝不能替代官方规定的原文。
规定排序(Provision Ranking)
实时规定排序会在官方条款提取后运行确定性评分。它会为数据包选出一组精简的来源条款;不会生成条款文本、法律建议或定论式法律结论。
排序信号:
- 医生查询词
- 匹配的医疗法律主题类别
- 映射搜索词
- 提取的条款以可用标题开头时的条款标题文本
- 提取条款文本中的关键词匹配
- 匹配条款列表加分
- 医疗法律优先级和主要/辅助角色顺序
实时追踪记录会展示 candidateArticleNumbers、rankedArticleNumbers、rejectedArticleNumbers 和 rankingMethod。每项返回的实时规定还会附带自身的确定性评分、匹配词、排序理由,以及是否来自人工匹配的条款列表。实时适配器会将单份法规文档限制在一组较小的已排序条款内,目前最多三项规定。提取出的匹配条款优先;只有在提取结果中没有匹配条款时,才会考虑高信号的排序备用条款。追踪记录会保留已选中和已拒绝候选项的轨迹。
对于 KVKK、个人健康数据和隐私问题,角色仍为 supporting_general。在排序或数据包排序中,它不会取代主要医疗法规。Yargıtay、Danıştay 和 AYM 适配器仍为模拟适配器。
选择诊断(Selection Diagnostics)
选择诊断提供来源选择的简明审核视图:sourceTrace 仍包含官方请求、文档、提取、候选项、排序和 unavailable 详情;诊断则会概述选中了什么,无需完整查看追踪记录。
精简诊断包括:
- query 和
sourceMode - 选定的法规和规定数量
- 每项选定法规的角色、主题类别、优先级、条款编号、被拒绝条款编号摘要和选择理由
- 每项选定规定的评分、匹配词、最佳排序理由和匹配条款标记
unavailable和警告数量
实时摘要示例:
{
"selectionDiagnostics": {
"query": "kisisel saglik verisi mahremiyet",
"sourceMode": "live",
"selectedLegislationCount": 2,
"selectedProvisionCount": 2,
"selectedLegislations": [
{
"legislationName": "Hasta Haklari Yonetmeligi",
"legislationRole": "health_primary",
"topicCluster": "patient_privacy",
"selectedArticleNumbers": ["21"]
},
{
"legislationName": "Kisisel Verilerin Korunmasi Kanunu",
"legislationRole": "supporting_general",
"topicCluster": "personal_health_data",
"selectedArticleNumbers": ["6"]
}
],
"unavailableCount": 0
}
}
诊断仅为审核元数据。它不能替代官方规定引文,不会生成法律主张,并会将 KVKK 保持在辅助性一般法规角色。Yargıtay、Danıştay 和 AYM 适配器仍为模拟适配器。
判决来源追踪(判决来源追踪)
DecisionSourceTrace 会审计每个候选法院判决的判决处理流程。
它是 LegislationSourceTrace 在判例方面的对应结构。每条追踪记录包含:
- 原始
query source和court(yargitay / danistay / aym)searchRequest(模拟适配器使用 null)searchResultsCount和selectedResultdocumentId/sourceIdfullTextAvailable和fullTextRetrievalMethodretrievedAteligibilityStatus— 判例筛选结果eligibilityReasons— 判决满足的正向标准exclusionReasons— 如有,判决被排除的具体原因- 如果获取失败,则包含
error
判决来源追踪仅包含审计元数据。它们不会生成法律理由,且除非判决通过所有资格标准,否则绝不会将其加入数据包。
附理由判决的资格评估
assessDecisionEligibility(位于 src/health/decisionEligibility.ts)会应用判例筛选规则,并返回结构化的 EligibilityResult,其中包含状态、正向资格理由和排除理由。
如果符合以下任一条件,判决将从已验证判例部分排除:
fullTextAvailable: false— 完整判决文本不可用(→metadata_only)legalReasoning为空或缺失(→no_reasoning)- 判决文本仅包含纯程序性标记:
salt onama、salt bozma、usul karar(→procedural_only) - 法律理由仅为
onama或bozma,且不包含实体内容 (→procedural_only) - 缺少将判决与医疗法律事件关联起来的
relevanceNote(→limited_value)
只有 precedent_usable 判决会进入数据包的 verifiedHighCourtPrecedents 部分。
limited_value、procedural_only、no_reasoning 和 metadata_only 判决将被排除。
判例诊断(判例诊断)
PrecedentSelectionDiagnostics 是用于判决选择的紧凑审计视图,对应法规方面的 LegislationSelectionDiagnostics。它会在每个 prepare_doctor_legal_information_pack 响应以及 filter_reasoned_precedents 工具响应中以 precedentDiagnostics 的形式出现。
诊断信息包含:
query— 原始问题selectedPrecedentCount/excludedDecisionCountselectedPrecedents[]— 法院、审判庭、日期、案号/判决号、状态、匹配的医疗主题和资格理由excludedDecisions[]— 法院、日期、状态和排除理由
诊断信息仅概述选择与排除情况,不提供法律解释,也不会向数据包中添加任何判决。
实时 Yargıtay 适配器
首个实时法院判决适配器:LiveYargitayAdapter
(src/sources/yargitay/liveYargitayAdapter.ts)。Danıştay 和 AYM 仍使用 mock 适配器。
**来源和端点:**目标地址为 https://bedesten.adalet.gov.tr/emsal-karar/searchDocuments,并使用
YARGITAYKARARI 筛选条件。JSON POST 请求体包含健康法搜索词。遇到 429 和 5xx 错误时,
会采用自适应退避策略重试三次。
sourceMode: "live" 下的先例行为:
search_health_precedents使用实时 Yargıtay 适配器;Danıştay 和 AYM 仍使用 mock 适配器。- 使用
sourceMode: "live"时,prepare_doctor_legal_information_pack除实时法规外, 还会搜索实时 Yargıtay 判决。 - 健康法搜索词根据分类后的问题进行匹配:
riza/rıza/onam→"aydınlatılmış rıza",tibbi/müdahale→"tıbbi müdahale",等等。 - 只有
precedent_usable判决会进入verifiedHighCourtPrecedents。其他判决的 排除原因都会记录到precedentDiagnostics.excludedDecisions中。
DecisionSourceTrace 实时示例:
{
"query": "aydınlatılmış rıza",
"source": "yargitay",
"court": "yargitay",
"searchRequest": {
"url": "https://bedesten.adalet.gov.tr/emsal-karar/searchDocuments",
"phrase": "aydınlatılmış rıza",
"pageSize": 5
},
"searchResultsCount": 12,
"selectedResult": { "documentId": "yargitay:99001" },
"selectedResultReason": "Health law term 'aydınlatılmış rıza' matched Yargıtay emsal search.",
"fullTextAvailable": true,
"fullTextRetrievalMethod": "html-text",
"retrievedAt": "2026-05-22T10:00:00.000Z",
"eligibilityStatus": "precedent_usable",
"eligibilityReasons": [
"Tam karar metni mevcut.",
"Hukuki gerekçe alanı dolu.",
"Sağlık hukuku olayıyla bağlantı kurulmuş.",
"Emsal olarak kullanılabilir."
],
"exclusionReasons": []
}
**实时来源错误行为:**如果无法访问 bedesten.adalet.gov.tr,或返回无法解析的
响应,适配器会返回结构化的 unavailable 结果:
{
"status": "unavailable",
"source": "yargitay.gov.tr",
"errorCode": "source_error",
"message": "Yargıtay request failed: fetch failed",
"retryable": true,
"recommendedNextStep": "Retry after checking network access to bedesten.adalet.gov.tr.",
"sourceTrace": [{ "query": "aydınlatılmış rıza", "searchRequest": { ... } }]
}
不会编造任何判决。信息包会继续使用 mock Danıştay 和 AYM 结果,并在 Yargıtay 来源的
precedentDiagnostics 中显示 0 条选中的先例。
Danıştay 和 AYM 适配器仍使用 mock 适配器。
多来源实时先例管线
实时 Danıştay 适配器、集中式健康法查询扩展模块、按来源诊断信息(sourceSummaries)
以及基于文件的结果缓存。
实时 Danıştay 适配器
LiveDanistayAdapter(src/sources/danistay/liveDanistayAdapter.ts)
的目标地址为 https://karararama.danistay.gov.tr/aramalist。它采用与 Yargıtay 适配器相同的
重试、HTML 全文提取和可用性评估模式。court 设置为 "danistay",文档 ID 以
danistay: 为前缀。
适配器使用集中式查询扩展模块中的 pickHealthLawQuery,而不是维护自己的术语映射。
precedentSources 参数
现在,prepare_doctor_legal_information_pack 和 search_health_precedents 在实时模式下均接受可选的
precedentSources 数组,用于选择要查询的法院:
{
"question": "aydınlatılmış rıza",
"sourceMode": "live",
"precedentSources": ["yargitay", "danistay"]
}
有效值为 "yargitay"、"danistay"、"aym"。如果未指定,默认使用全部三个来源。
AYM 仍使用 mock 适配器。
一个来源无法访问时,其他来源会继续运行。信息包绝不会因单个适配器错误而卡住。
assessmentTone 参数(v0.44.0)
prepare_doctor_legal_information_pack 还接受可选的 assessmentTone 参数:
{
"question": "hasta hakları nelerdir",
"sourceMode": "mock",
"assessmentTone": "grounded-advisory"
}
| 值 | 行为 |
|---|---|
"grounded-advisory"(默认) | 信息包包含 preliminaryAssessment,其中含有基于来源的条件性陈述。每条陈述都带有一个 sourceRef。 |
"strict" | 旧行为:仅返回来源列表。不生成评估文本。 |
preliminaryAssessment 字段包含 summary(概述)和 sentences[](单条评估内容)。每条陈述都包含
text、sourceRef 和 sourceLabel。陈述会使用先例中的实际判决结果/理由以及法规中的原文摘录片段——绝不使用
套话。有关稳定性保证,请参阅 COMPATIBILITY.md。
医疗法律查询扩展
src/health/healthLawQueryExpansion.ts 提供确定性的术语映射,由 Yargıtay 和 Danıştay 适配器共享:
riza/onam/aydinlat→"aydınlatılmış rıza"komplikasyon→"komplikasyon tıbbi müdahale"malpraktis→"malpraktis hekim kusur"hekim→"hekimin özen yükümlülüğü"hasta→"hasta hakları"veri/mahrem→"sağlık verisi mahremiyet"kusur→"hizmet kusuru tıbbi müdahale"acil→"acil müdahale hekim yükümlülüğü"
对于已分类的问题,pickHealthLawQuery 会返回优先级最高的映射术语。pickHealthLawQueries 会为多术语搜索返回最多 N 个不重复的术语。
precedentDiagnostics 中的 sourceSummaries
PrecedentSelectionDiagnostics 现在包含 sourceSummaries[],其中提供按来源分类的明细:
{
"precedentDiagnostics": {
"query": "aydınlatılmış rıza",
"selectedPrecedentCount": 1,
"excludedDecisionCount": 2,
"sourceSummaries": [
{
"source": "yargitay",
"mode": "live",
"searched": true,
"searchResultsCount": 5,
"candidateCount": 2,
"selectedCount": 1,
"excludedCount": 1,
"unavailableCount": 0,
"errorCodes": []
},
{
"source": "danistay",
"mode": "live",
"searched": false,
"searchResultsCount": null,
"candidateCount": 0,
"selectedCount": 0,
"excludedCount": 0,
"unavailableCount": 1,
"errorCodes": ["source_error"]
}
]
}
}
selectedPrecedents[] 和 excludedDecisions[] 中的条目现在也包含 source 字段(与 court 的值相同),用于标明生成每项判决的适配器。
基于文件的缓存
PrecedentCache(src/sources/precedentCache.ts)会将实时适配器结果缓存一小时,存储于缓存目录下的 precedents/(默认路径为 ~/.cache/doktor-mcp/precedents/)。缓存文件根据来源、查询和页面大小作为键值。缓存写入失败不会导致致命错误。
smoke:precedents 支持三个缓存标志:
# Önbelleği kullan (varsayılan)
npm run smoke:precedents -- "aydınlatılmış rıza"
# Önbellek okuma ve yazmalarını atla
npm run smoke:precedents -- "aydınlatılmış rıza" --no-cache
# Taze getirmeyi zorla ve önbellek girdisinin üzerine yaz
npm run smoke:precedents -- "aydınlatılmış rıza" --refresh
缓存存储在仓库之外;旧版本使用的 .cache/ 仍保留在 .gitignore 中。
判例来源校准
深入探测分析和标准化器加固。完整校准工作流请参阅
docs/LIVE_SOURCE_CALIBRATION.md。
已验证的端点行为(2026-05-22)
| 来源 | 状态 | 端点 |
|---|---|---|
| Yargitay | reachable_json | bedesten.adalet.gov.tr/emsal-karar/searchDocuments - 通过 Bedesten 代理实现的活动集成。 |
| Danistay | reachable_json | karararama.danistay.gov.tr/aramalist - 活动集成。 |
| Bedesten | reachable_json | bedesten.adalet.gov.tr/emsal-karar/searchDocuments - 活动的统一集成。 |
| AYM | synthetic_only | 无实时端点。仅使用模拟适配器。 |
Probe CLI
# HTML/SOAP analizi ve fixture kaydıyla derin probe
npm run probe:precedents -- "aydınlatılmış rıza" -- --source yargitay --save-fixture
npm run probe:precedents -- "hizmet kusuru tıbbi müdahale" -- --source danistay --save-fixture
Probe 输出包括:HTTP 状态、content-type、HTML/SOAP 分析(标题、表单操作、端点提示、正文长度、验证码/登录检测)、calibrationStatus 和 recommendedNextStep。
非 JSON 响应分类
实时适配器收到非 JSON 响应时,DecisionSourceTrace.error 会包含:
| 代码 | 含义 |
|---|---|
non_json_response:html_shell_response | HTTP 200 + 小型 HTML SPA 外壳 |
non_json_response:unexpected_html_response | 登录页面/大型 HTML |
non_json_response:xml_soap_response | SOAP/XML 服务响应 |
non_json_response:captcha_or_block | 检测到 CAPTCHA |
non_json_response:empty_response | 空正文 |
原始 fixture 策略
fixtures/raw/已添加到 gitignore — 切勿提交原始响应正文。fixtures/live-samples/存放经过清理/合成的 fixture — 可以安全提交。- 清理后的 fixture 格式请参阅
fixtures/live-samples/README.md。
Pack audit 扩展检查
audit:pack 现在还会检查:
sourceSummaries中不可访问的来源 → 发出包含错误代码的警告- 已验证判例中的
decisionSourceTrace.fullTextAvailable === false→ 错误 - 已验证判例中的
decisionSourceTrace.eligibilityStatus !== "precedent_usable"→ 错误
完整检查参考请参阅 docs/PACK_AUDIT.md。
生产环境设置
使用 npm 安装
需要 Node.js 20 或更高版本。无需安装软件包即可通过 npx 运行。要添加到 Claude Code:
claude mcp add doktor -- npx -y doktor-mcp
缓存文件会写入用户的缓存目录:如果设置了 DOKTOR_MCP_CACHE_DIR,则写入该目录;否则写入 $XDG_CACHE_HOME/doktor-mcp 或 ~/.cache/doktor-mcp。
来源模式
sourceMode 默认为 "live"(自 0.59.0 起):如果工具调用中未指定 sourceMode,
查询将访问实时官方来源。若要使用测试夹具数据进行试用,请在调用中传入
sourceMode: "mock",或设置环境变量 DOKTOR_MCP_DEFAULT_SOURCE_MODE=mock;此时
响应中会添加 mockDataWarning 字段。
示例:Claude Desktop 配置
{
"mcpServers": {
"doktor-mcp": {
"command": "npx",
"args": ["-y", "doktor-mcp"]
}
}
}
有效值
| 值 | 含义 |
|---|---|
"mock" | 返回测试夹具数据。并非真实法规或裁决。 |
"live" | 默认值。查询实时官方来源(mevzuat.gov.tr、Yargıtay、Danıştay)。 |
"snapshot" | 使用预先保存的实时来源快照。 |
如果设置了无效值(例如 DOKTOR_MCP_DEFAULT_SOURCE_MODE=production),
系统会向 stderr 写入警告,并使用默认值 "live"。
注意:
DOKTOR_MCP_DEFAULT_SOURCE_MODE是DOKTOR_MCP_SOURCE_MODE的一个 更容易发现的替代变量。两者都会设置sourceMode;如果同时设置, 则优先处理DOKTOR_MCP_DEFAULT_SOURCE_MODE。
开发
npm install
npm test
npm run build
npm run smoke -- "Aydinlatilmis riza kaydi eksikse hangi resmi kaynaklar eslesir?"
npm run smoke:legislation -- "kisisel saglik verisi mahremiyet"
npm run smoke:legislation -- "aydınlatılmış rıza"
# Hem Yargıtay hem Danıştay smoke (varsayılan)
npm run smoke:precedents -- "aydınlatılmış rıza"
# Belirli kaynaklar
npm run smoke:precedents -- "hizmet kusuru" --precedentSources yargitay,danistay
# Önbellek kontrolü
npm run smoke:precedents -- "aydınlatılmış rıza" --no-cache
npm run smoke:precedents -- "aydınlatılmış rıza" --refresh
npm run smoke:mcp -- "kişisel sağlık verisi mahremiyet" -- --sourceMode live
npm run smoke:mcp -- "hasta haklari tibbi mudahale" -- --sourceMode live
npm run smoke:mcp -- "riza belgesi" -- --sourceMode mock
npm run dev:mcp
smoke:precedents 会并行查询实时 Yargıtay 和 Danıştay 适配器,将结果缓存,并以 JSON
格式打印每个候选裁决对应的按来源划分的 results,其中包含 sourceTraces 和
eligibilityStatus。如果某个来源无法访问,其结构化的 unavailable 结果会与另一个
来源的输出一同打印。JSON 始终保持可解析。
smoke:mcp 会调用完整的 prepare_doctor_legal_information_pack 处理器。
使用 sourceMode: "live" 时,它会使用实时法规以及实时 Yargıtay + Danıştay 适配器。
可选参数 precedentSources 用于选择要使用的适配器。
AYM 仅支持 mock,在实时模式下处于禁用状态。
执行 npm run build 后,使用以下命令运行已编译的 stdio MCP 服务:
npm run mcp
医生问题 Benchmark 套件
全面的质量评估和回归测试 Benchmark 套件,专注于典型的以医生为中心的法律问题,并 包含实时来源评估指标。
目的
- 质量衡量:系统评估 15 个独立医疗法律类别中 15-20 个目标问题的表现、法规匹配、先例数量和架构兼容性。
- 防止回归:强制执行严格的安全限制,例如:在非隐私类套件中不得包含
Kisisel Verilerin Korunmasi Kanunu (KVKK);在拒绝情形下,以医生为中心的职业伦理规则优先于一般患者权利;实时模式下不得回退到 mock 先例。
如何运行
使用 Benchmark runner 脚本运行测试并查看报告输出:
# Tam benchmark'ı mock modda çalıştır (varsayılan)
npm run benchmark:doctor-questions
# Canlı modda çalıştır (canlı mevzuat ve emsalleri sorgular, canlı-kaynak metriklerini raporlar)
npm run benchmark:doctor-questions -- --sourceMode live
# Eşdeğer canlı kısayol
npm run benchmark:doctor-questions:live
# Çalıştırmayı ilk N soruyla sınırla
npm run benchmark:doctor-questions -- --limit 5
# Özel bir rapor dizini belirt (varsayılan exports/doctor-benchmark)
npm run benchmark:doctor-questions -- --out exports/my-custom-report
警告
使用
--sourceMode live运行 Benchmark 会向总统府法规服务(mevzuat.gov.tr)和高等法院服务(bedesten.adalet.gov.tr和karararama.danistay.gov.tr)发送真实 HTTP 请求。为避免这些服务器的速率限制(HTTP 429)或 IP 限制,请确保网络连接稳定,并将请求量控制在合理范围内。
Mock 与实时 Benchmark
Mock 模式是确定性的回归保护机制。当预期的法规、优先级、审计或安全不变量发生回归时,它可能会使命令失败。
实时模式则是评估运行。它会保留相同的安全不变量,但会将来源中断、空结果、速率限制和 sourceUnavailable 条目作为指标和警告报告,而不是自动判定失败。使用不安全先例、出现禁止的 MVP 字段、实时模式下回退到 mock,或出现审计错误,仍会被视为严重回归并导致失败。
基准测试报告和导出文件
运行会在 exports/doctor-benchmark/(位于 gitignore 中)生成可解析的 JSON 和 Markdown
报告:
- 模拟模式:
doctor-benchmark-report.jsondoctor-benchmark-report.md
- 实时模式:
live-benchmark-report.jsonlive-benchmark-report.md
报告包含:startedAt、completedAt、durationMs、passedRegressionCount、
failedRegressionCount、liveSourceUnavailableCount、审计计数、法规/判例覆盖计数以及逐问题评分。
报告会包含每个选定的已验证判例的实时基准测试质量审计字段: 法院、法庭、裁判日期、案号/裁判编号、访问来源、文档 ID/来源 ID、来源 URL(如有)、 全文可用性、法律理由检测结果、适用性状态/理由、医疗法相关性分数、匹配的术语以及裁判来源链是否存在。报告不会输出裁判全文。
实时模式下回退到模拟模式属于严重回归。AYM 会保持禁用/仅模拟模式,且无法在不提示的情况下提供实时已验证判例。sourceUnavailable、实时搜索结果为空以及临时上游故障会作为质量指标和警告保留,除非它们导致不安全判例或架构/审计违规。
评分
每个问题会获得以下分数:
legislationMatchScore:0 到 2 分priorityScore:0 到 2 分precedentSafetyScore:0 到 2 分sourceAvailabilityScore:0 到 2 分auditScore:0 到 2 分forbiddenFieldsScore:0 或 2 分totalScore、maxScore、scorePercent和qualityBand
qualityBand:good、acceptable、needs_tuning 或 unsafe。实时来源不可用可能会降低质量,但只有安全违规或审计错误才会使条目变为 unsafe。
已验证判例的评分有意设置得较为严格。选定的已验证判例必须为 precedent_usable,具有已验证全文、已检测到的法律理由,并保留裁判来源链。仅元数据、仅程序性、没有理由、没有全文或通过模拟模式访问的记录,在实时模式下无法获得已验证判例积分。医疗法相关性较弱会限制判例安全积分,并作为调优警告报告,而不会被高总分掩盖。
基准测试会在此审计层之上进行判例相关性调优。它会按问题和来源报告相关性较弱的情况、示例裁判 ID、匹配的主题术语、缺失的预期主题术语、whyWeak 说明以及建议的后续查询术语。它还会区分 goodCleanCount 和 goodWithWarningsCount,并报告医疗法相关性分数的平均值/中位数。
相关性较弱表示裁判通过了严格的判例安全门槛,但裁判文本仅匹配了宽泛的医疗词汇,或者与问题的主题配置文件重合度不高。主题配置文件包括:知情同意、医疗过失/并发症、急救、拒绝治疗、隐私/记录、精神科隐私、暴力/威胁、转诊、私立医院费用纠纷、公职纪律、重症监护以及妊娠急症。实时来源不可用会作为指标/警告保留;unsafe 则仅用于安全违规,例如回退到模拟模式、缺少全文/理由/来源链,或不可用判例混入已验证输出。
性能基准测试命令
npm run benchmark:doctor-questions:performance
# veya limitle:
npm run benchmark:doctor-questions:performance -- --limit 5
基准测试会将全部 15 个法律问题运行两次。冷(cold)运行会访问实时网络,并填充本地文件缓存(.cache/precedents-perf/)。热(warm)运行会立即从缓存重放相同的查询。报告显示:
- 冷运行与热运行的总耗时及提升百分比
- 每个来源的冷/热平均耗时(毫秒)、p95、缓存命中数、网络请求数
- 缓存效果:命中率百分比、缓存提供次数、平均缓存年龄
- 重试/退避摘要:重试总数、退避耗时、速率限制事件、超时数
- 最慢的 10 次查询尝试(冷运行和热运行合并)
- 性能警告(不会阻止操作;硬性失败仍由测试/构建/审计处理)
p50/p95/p99 的解读
| 值 | 含义 |
|---|---|
| p50 | 查询耗时中位数——一半查询会在该时间内或更短时间内完成 |
| p95 | 第 95 百分位数——尾部延迟;大多数查询耗时更短 |
| p99 | 第 99 百分位数——异常延迟;偶尔出现的慢查询 |
冷运行 p95 > 60s 表示某个来源较慢(通常是 Yargıtay/Bedesten PDF 获取)。 热运行 p95 > 10s 表示缓存对最慢的查询未能有效发挥作用(可能是 TTL 过期,或适配器内全文获取时缓存未命中)。
缓存集成
在常规实时基准测试和 smoke CLI 运行中,缓存默认处于禁用状态。性能基准测试会注入一个共享的 PrecedentCache(TTL 为 2s,目录为
.cache/precedents-perf/)。缓存会按(source、query、pageSize)组合键存储整个 searchAndNormalize 结果。热运行重放完整无缺——缓存查询不会发起任何网络调用。
.cache/ 位于 gitignore 中。缓存条目不会提交。
版本历史请参阅 CHANGELOG.md。
许可证
本项目根据 GNU Affero 通用公共许可证第 3 版(AGPL-3.0-only)授权;完整文本见 LICENSE 文件。如果您修改本软件并通过网络向他人提供服务,则必须以相同许可证向这些用户提供您修改后的源代码。如何报告安全漏洞,请参阅 SECURITY.md。
版权所有 © 2026 Alpaslan Fatih Sözer
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。