关于 efatura-kontrol
efatura-kontrol 使用税务管理局公布的模式和规则,离线验证土耳其 UBL-TR 电子单据,并检查算术结果与签名结构。它面向开发者和会计集成场景,提供命令行、Python API 和 MCP 服务,且以土耳其语解释发现的问题。
主要功能
- 01验证 UBL-TR XSD 与 Schematron
- 02检查税额、预扣税和总额计算
- 03检查签名结构
- 04提供土耳其语说明和修复建议
- 05命令行、Python API 与批量验证
适用场景
- 01提交至 GİB 前检查电子发票
- 02批量验证 XML 单据
- 03向开发者解释验证发现的问题
MCP 相关
MCP 服务提供只读工具,用于验证单据、查看摘要、解释问题、查询代码列表及生成示例发票。支持本地 stdio 和远程 Streamable HTTP;远程请求需直接提供 XML 内容。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
5收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| tur | any | 否 | |
| xml | any | 否 | |
| dosya | any | 否 |
详细介绍
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 KGM | Gİ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_HOST | 0.0.0.0 | 监听地址(由于 Azure Container Apps 不支持 IPv6,因此使用 IPv4) |
EFATURA_PORT | 8080 | 端口 |
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 | 错误 |
| XSD | OASIS UBL 2.1 运行时架构(UBL-TR 1.2.1 包)+ GİB 信封/HRXML 架构 | 错误 |
| Schematron | Gİ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 货币未提供汇率 |
| IadeFaturasiOrnegi | TICARIFATURA 中不能使用 IADE;缺少退货引用 |
| IHRACAT | 缺少签名结构(示例被截断且未签名) |
| HKS-Ornek1/2 | XSD: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_HOST | 0.0.0.0 | 监听地址(IPv4,因为 Azure Container Apps 不支持 IPv6) |
EFATURA_PORT | 8080 | 端口 |
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”是相关机构的名称。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。