mcpField
E
efatura-kontrol

efatura-kontrol

本地服务
github.com/BerkantACUN金融数据25 周前更新

关于 efatura-kontrol

efatura-kontrol 使用税务管理局公布的模式和规则,离线验证土耳其 UBL-TR 电子单据,并检查算术结果与签名结构。它面向开发者和会计集成场景,提供命令行、Python API 和 MCP 服务,且以土耳其语解释发现的问题。

主要功能

  1. 01验证 UBL-TR XSD 与 Schematron
  2. 02检查税额、预扣税和总额计算
  3. 03检查签名结构
  4. 04提供土耳其语说明和修复建议
  5. 05命令行、Python API 与批量验证

适用场景

  1. 01提交至 GİB 前检查电子发票
  2. 02批量验证 XML 单据
  3. 03向开发者解释验证发现的问题

MCP 相关

MCP 服务提供只读工具,用于验证单据、查看摘要、解释问题、查询代码列表及生成示例发票。支持本地 stdio 和远程 Streamable HTTP;远程请求需直接提供 XML 内容。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"berkantacun-efatura-kontrol": {
"command": "uvx",
"args": [
"efatura-kontrol"
]
}
}
}
启动命令uvx efatura-kontrol

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypiefatura-kontrol0.1.0

工具

5

收录的工具列表 · 更新于 2 周前

参数类型必填说明
turany否
xmlany否
dosyaany否

详细介绍

efatura-kontrol

在将 e-Fatura、e-Arşiv Fatura、e-İrsaliye 和信封文件发送给 GİB 之前,使用 GİB 自己的规则进行检查:OASIS UBL 2.1 XSD、GİB 的 e-Fatura 套件 Schematron(498 条规则、41 个代码列表)、行/税/代扣税/合计金额算术以及签名结构。每条发现都附带行号、GİB 的原始消息、土耳其语说明和修正建议。命令行、Python 库和 MCP 服务;不会有任何数据传出本机。

使用税务管理局自己的 XSD 和 Schematron 规则,并结合算术与签名结构检查,在离线状态下验证土耳其 UBL-TR 电子发票(e-Fatura、e-Arşiv、e-İrsaliye、信封);以土耳其语说明每条发现并提供修正方法。CLI、Python API 和 MCP 服务(本地 stdio 或远程 HTTP)。英文文档 ↓

mcp-name: io.github.BerkantACUN/efatura-kontrol

$ efatura-kontrol dogrula fatura.xml
fatura.xml: GEÇERSİZ — 1 hata, 1 uyarı, 1 bilgi (fatura / TEMELFATURA / SATIS, 6.2 ms)
  HATA  sch-GeneralUnitCodeCheck-1 [satır 138]: Geçersiz unitCode niteliği : 'ADET'. Geçerli değerler için kod listesine bakınız.
        → Adet için C62, kilogram KGM, gram GRM, metre MTR, litre LTR, saat HUR, gün DAY, ay MON, kutu BX, paket PA, çift PR yazın.
  UYARI hesap-dip-odenecek [satır 134]: Ödenecek tutar vergiler dahil tutar − tevkifat + yuvarlama ile uyuşmuyor: yazılan 18.88, hesaplanan 17.88
        → Tevkifatlı faturada tevkifatı düşün; yuvarlama varsa PayableRoundingAmount yazın.
  BILGI imza-yok [satır 3]: Belge elektronik imza taşımıyor; GİB'e gönderilecek belgede XAdES imzası bulunmalıdır, taslak için normaldir

为什么

GİB 的 Schematron 使用 XPath 2.0 编写,分为三个文件,使用 133 条抽象规则和片段包含;普通工具(lxml、大多数 Python Schematron 库)无法运行。因此,集成商只能在将文件发送给 GİB 或私有集成商后才发现错误。efatura-kontrol 将 GİB 的 Schematron 扁平化,并一次性编译为 XSLT 3.0(SchXslt2),再通过 Saxon 运行:每份文档需 2–20 ms,返回与 GİB 完全相同的消息,并附上行号和修正建议。

安装

uvx efatura-kontrol --help          # kurulumsuz
pip install efatura-kontrol         # ya da kalıcı

Python ≥ 3.10;依赖项为 lxml 和 SaxonC-HE(saxonche,约 40 MB wheel;支持 Windows、macOS、Linux)。首次运行时,编译 Schematron 约需 0.5 秒;之后只需几毫秒。

命令

命令功能
dogrula belge.xml [belge2.xml…] [--tur fatura|earsiv|irsaliye|irsaliye-yaniti|uygulama-yaniti|zarf] [--json] [--sessiz]完整检查;如有错误,退出代码为 1
ozet belge.xml场景、类型、编号、参与方(VKN/TCKN)、行、税额、合计金额、是否已签名
kod / kod UnitCodeList --ara KGMGİB 代码列表(Schematron 实际应用的值)
acikla sch-GeneralUnitCodeCheck-1说明发现代码并提供修正方法
toplu klasor/ [--isci 8] [--json]并行检查文件夹中的所有 XML;200 份文档(22 MB)约需 2 秒
ornek-fatura [girdi.json|-] [-o fatura.xml] [--senaryo TEMELFATURA|TICARIFATURA|EARSIVFATURA]根据参与方、行和增值税率生成有效的、未签名的 UBL-TR 示例发票(未提供输入时使用内置示例);生成的文件会通过自身验证
mcp [--http] [--host H] [--port P]MCP 服务(stdio;使用 --http 时为 streamable HTTP)

根据根元素和 cbc:ProfileID 确定文档类型;检测到 EARSIVFATURA 时应用 e-Arşiv 规则(type=earchive)。可以使用 --tur 强制指定。

MCP 服务

适用于 Claude Desktop / Claude Code / Cursor:

{
  "mcpServers": {
    "efatura-kontrol": { "command": "uvx", "args": ["efatura-kontrol", "mcp"] }
  }
}

工具(全部只读,不会写入任何文件):belge_dogrula(dosya|xml, tur)、belge_ozeti(dosya|xml)、bulgu_acikla(kod)、kod_listesi(liste, ara)、kod_listeleri()、ornek_fatura(satici, alici, satirlar, senaryo, no, tarih)。已列入官方 MCP 注册表:io.github.BerkantACUN/efatura-kontrol。

Cline 等 Agent 可以通过 llms-install.md 自行完成安装。

远程服务(Docker)

efatura-kontrol mcp --http 会通过 streamable HTTP 在 http://<host>:8080/mcp 启动服务(无状态;可在负载均衡器后运行多个副本)。每个 v* 版本都会发布预构建镜像:

docker run --rm -p 8080:8080 -e EFATURA_API_KEY=gizli ghcr.io/berkantacun/efatura-kontrol
环境变量默认值含义
EFATURA_HOST0.0.0.0监听地址(由于 Azure Container Apps 不支持 IPv6,因此使用 IPv4)
EFATURA_PORT8080端口
EFATURA_API_KEY—如有设置,每个请求都必须在 X-API-Key 请求头中提供相同的值,否则返回 401

客户端配置:

{
  "mcpServers": {
    "efatura-kontrol": {
      "type": "http",
      "url": "https://sunucu.example.com/mcp",
      "headers": { "X-API-Key": "gizli" }
    }
  }
}

远程模式下禁用 dosya 参数(服务不会读取自己的磁盘,而是返回 uzak-dosya-kapali 错误);请通过 xml 参数发送文档。请求正文限制为 64 MB。密钥只是简单的共享密钥;将服务暴露到互联网时,请将其部署在负责 TLS 终止的反向代理(例如 Container Apps ingress)后面。

生成示例发票

efatura-kontrol ornek-fatura girdi.json -o fatura.xml
{
  "satici": {"vkn_tckn": "1288331521", "unvan": "AAA Anonim Şirketi", "vergi_dairesi": "Büyük Mükellefler", "ilce": "Beşiktaş", "sehir": "İstanbul"},
  "alici": {"vkn_tckn": "11111111110", "ad": "Ali", "soyad": "Yılmaz", "ilce": "Çankaya", "sehir": "Ankara"},
  "satirlar": [
    {"ad": "Danışmanlık", "miktar": "3", "birim": "HUR", "birim_fiyat": "500", "kdv_orani": "20"},
    {"ad": "Kitap", "miktar": "2", "birim_fiyat": "45.50", "kdv_orani": "10"}
  ],
  "senaryo": "TEMELFATURA"
}

系统会计算行金额、各税率的增值税小计和合计金额;文档可无错误地通过 XSD、Schematron 和算术检查(唯一发现是 imza-yok 信息)。范围有意保持狭窄:类型为 SATIS、货币为 TRY、增值税税率 > 0;不包含折扣、预提、免税和外币。文档未签名;仅供测试和学习使用。要发送给 GİB 的文档应由集成商或财务印章签名。

Python

from efatura_kontrol.kontrol import kontrol_et, ozet

rapor = kontrol_et("fatura.xml")  # ya da bytes, tur="earsiv"
rapor.gecerli, rapor.sayim("hata"), rapor.sozluk()
for b in rapor.bulgular:
    print(b.seviye, b.kod, b.satir, b.mesaj, b.duzeltme)

检查内容

层来源级别
XML 格式良好性、大小(≤ 50 MB)、根元素lxml错误
XSDOASIS UBL 2.1 运行时架构(UBL-TR 1.2.1 包)+ GİB 信封/HRXML 架构错误
SchematronGİB e-Fatura 包(29)、UBL-TR_Main/Common/Codelist、Schematron 更新日期 2026-07-01;121 条规则、499 条断言、41 个代码列表(单位、货币、国家、税、预提代码+税率、免税、付款方式、场景、发票类型……)错误
算术行金额 = 数量 × 价格 − 折扣 + 加价;税额 = 计税基础 × 税率;税额合计;预提 = 增值税 × 税率;合计金额(商品/服务、折扣、加价、不含税、含税、应付);currencyID 一致性警告
签名是否存在 ds:Signature,是否包含 SignedInfo/SignatureValue/X509Certificate/SigningTime/SigningCertificate,Reference URI 是否可解析错误/信息

“警告”指 GİB 可能不会拒绝、但接收方会拒绝的问题;“信息”是签名状态之类的备注。由于 HKS(农产品市场)发票的合计金额规则不同,因此会跳过算术合计检查。

发现项格式

{"kod": "sch-GeneralUnitCodeCheck-1", "seviye": "hata", "kaynak": "sematron",
 "mesaj": "Geçersiz unitCode niteliği : 'ADET'. …", "gib_mesaj": "…",
 "kural": "not(//cbc:UBLVersionID = '2.1') or contains($UnitCodeList, …)",
 "konum": "/Q{…}Invoice[1]/Q{…}InvoiceLine[1]/Q{…}InvoicedQuantity[1]/@unitCode",
 "satir": 138, "aciklama": "…", "duzeltme": "Adet için C62, …"}

Schematron 发现项代码由 GİB 的抽象规则名称派生(sch-<KuralAdı>-<sıra>);如果 GİB 更改规则顺序,代码也会变化,但消息保持不变。

GİB 自带示例的检查结果

UBL-TR 1.2.1 包中的示例(未作任何更改):

示例结果
IDIS_Fatura、SARJ、SARJANLIK、OTV、OZELMATRAH、YTB_*(12 个文件)、HKS-Ornek1(Schematron)有效
TemelFaturaOrnegi发票编号格式(ABC2009123456789 模式)、10 位 TCKN
TEVKIFAT、ISTISNA-2、HASTANE缺少 unitCode(包中示例遵循 2022 年之前的规则)
ISTISNA-1/2非 TRY 货币未提供汇率
IadeFaturasiOrnegiTICARIFATURA 中不能使用 IADE;缺少退货引用
IHRACAT缺少签名结构(示例被截断且未签名)
HKS-Ornek1/2XSD:ext:ExtensionContent 为空
e-FaturaPaketi/xml/*UBL 2.0 / TR1.0 旧示例,Schematron 会拒绝

也就是说,该工具甚至能检测出 GİB 自带包中过时的示例;ornekler/ 下有四份已修正且完全有效的文档。

保持更新

araclar/paket_indir.py 会下载 GİB 包(使用 sha256 校验),efatura-kontrol derle kaynak 会展平并编译 Schematron,并将代码列表和 XSD 写入 ekler/。每次 CI 运行时,都会验证使用最新 GİB 包生成的输出与仓库中的内容相同;GİB 包发生变化时,构建会失败并需要发布新版本。所用包的版本记录在 efatura_kontrol.PAKET 中,以及每份报告的 paket 字段中。

限制

  • 不会进行签名的加密验证(证书、摘要、时间戳);仅检查其结构。
  • 此工具不包含 GİB 的实时检查(纳税人是否已注册、标签是否有效、经营代码与增值税税率是否匹配、编号是否重复);这些信息只能通过 GİB 系统获知。
  • 不在支持范围内:e-Arşiv 报告(eArsivRaporu)和 e-Defter(后续版本再支持)。
  • “有效”表示通过 GİB 发布的 XSD 和 Schematron 检查;不保证通过 GİB 系统端的其他检查。

English

efatura-kontrol 会在土耳其电子单据(UBL-TR 格式的 e-Fatura、e-Arşiv 发票、e-İrsaliye 发货通知、收据/应用响应和信封)发送给税务局(GİB)之前进行检查。它会离线运行 GİB 自己的规则:UBL-TR 软件包附带的 OASIS UBL 2.1 XSD、GİB 的 e-Fatura Schematron(已展平并编译为 XSLT 3.0,使用 Saxon 运行)、行项目/税费/预扣税/总额计算,以及 XAdES 签名的结构。不会通过网络发送任何内容。

安装
uvx efatura-kontrol --help      # no install, needs uv (https://docs.astral.sh/uv/)
pip install efatura-kontrol     # or install permanently

Python ≥ 3.10。依赖项为 lxml 和 SaxonC-HE(saxonche,适用于 Windows、macOS 和 Linux、约 40 MB 的 wheel)。首次运行时,Schematron 会在约半秒内编译完成;之后每份文档的处理只需几毫秒。

命令行
efatura-kontrol dogrula invoice.xml            # validate; exit code 1 if there is an error
efatura-kontrol dogrula *.xml --json           # machine-readable report
efatura-kontrol ozet invoice.xml               # parties, lines, taxes, totals
efatura-kontrol kod UnitCodeList --ara KGM     # values of a GİB code list
efatura-kontrol acikla sch-GeneralUnitCodeCheck-1
efatura-kontrol toplu folder/ --json           # validate a folder in parallel (JSON lines)

命令名称为土耳其语:dogrula = 验证,ozet = 摘要,kod = 代码列表,acikla = 解释,toplu = 批量处理。文档类型根据根元素和 cbc:ProfileID 自动检测;使用 --tur fatura|earsiv|irsaliye|irsaliye-yaniti|uygulama-yaniti|zarf 可强制指定类型。

查看结果

每条发现项都包含 kod(稳定标识符,例如 Schematron 规则对应的 sch-GeneralUnitCodeCheck-1、xsd-…、计算问题对应的 hesap-…、签名问题对应的 imza-…)、seviye(严重性)和行号。严重性为 hata(错误)意味着 GİB 会拒收该文档;uyari(警告)表示计算或货币不一致,GİB 可能接受,但买方可能拒收;bilgi(信息)是诸如“尚未签名”的提示。gib_mesaj 是 GİB 的原始(土耳其语)消息;aciklama 和 duzeltme 分别是土耳其语说明和建议的修复方法。JSON 键也使用土耳其语:gecerli = 有效,bulgular = 发现项,satir = 行。

MCP 服务(本地)

适用于 Claude Desktop、Claude Code、Cursor 和其他 MCP 客户端:

{
  "mcpServers": {
    "efatura-kontrol": { "command": "uvx", "args": ["efatura-kontrol", "mcp"] }
  }
}

工具(均为只读):belge_dogrula(通过文件路径 dosya 或内容 xml 验证文档)、belge_ozeti(摘要)、bulgu_acikla(解释发现项代码)、kod_listesi(代码列表中的值)、kod_listeleri(可用代码列表和 GİB 软件包版本)。已在官方 MCP 注册表中列出,名称为 io.github.BerkantACUN/efatura-kontrol。

远程服务(Docker / HTTP)

efatura-kontrol mcp --http 会通过 MCP 可流式传输的 HTTP,在 http://<host>:8080/mcp 提供相同的工具。该服务为无状态,因此可在负载均衡器后运行多个副本。每次发布 v* 版本时,都会将镜像发布到 GitHub Container Registry:

docker run --rm -p 8080:8080 -e EFATURA_API_KEY=change-me ghcr.io/berkantacun/efatura-kontrol
变量默认值含义
EFATURA_HOST0.0.0.0监听地址(IPv4,因为 Azure Container Apps 不支持 IPv6)
EFATURA_PORT8080端口
EFATURA_API_KEY—如果已设置,每个请求都必须携带 X-API-Key: <value>,否则返回 401。未设置时,服务会记录警告并对任何人开放

--host 和 --port 可覆盖这些变量。客户端配置:

{
  "mcpServers": {
    "efatura-kontrol": {
      "type": "http",
      "url": "https://your-server.example.com/mcp",
      "headers": { "X-API-Key": "change-me" }
    }
  }
}

在远程模式下,出于安全考虑,dosya(文件路径)参数已禁用(服务不会读取自己的磁盘;该工具会返回 uzak-dosya-kapali),因此请将文档内容放在 xml 参数中发送。请求正文大小上限为 64 MB。该镜像以非 root 用户运行 Python 3.12 slim。API 密钥只是简单的共享密钥:在将服务暴露到互联网之前,请将其置于 TLS 终止反向代理(例如 Container Apps 入口)之后。

Python API
from efatura_kontrol.kontrol import kontrol_et, ozet

report = kontrol_et("invoice.xml")  # or bytes; tur="earsiv" forces the type
report.gecerli, report.sayim("hata"), report.sozluk()
for f in report.bulgular:
    print(f.seviye, f.kod, f.satir, f.mesaj, f.duzeltme)
限制
  • 签名仅检查结构,不进行密码学验证(证书、摘要、时间戳)。
  • GİB 的实时检查(纳税人是否已注册、邮箱别名是否有效、编号是否重复……)无法离线执行,因此不包含在内。
  • e-Arşiv 报告(eArsivRaporu)和 e-Defter(电子账簿)不在范围内。
  • “有效”表示文档通过了 GİB 发布的 XSD 和 Schematron;这并不保证通过服务器端的其他检查。

参考资料

有关包、版本、对模式执行的扁平化处理,以及 GİB 包中存在的不一致之处,请参阅:KAYNAKLAR.md。变更记录:CHANGELOG.md。

MIT 许可证。与 GİB 无关;“GİB”、“e-Fatura”和“UBL-TR”是相关机构的名称。

评论

支持 Markdown

第一次接触 MCP?

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

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