efatura-kontrol について
efatura-kontrolは、歳入庁が公開するスキーマとルールに基づき、トルコのUBL-TR電子文書をオフラインで検証し、計算と署名構造も確認します。開発者や会計システム連携向けにCLI、Python API、MCPサーバーを提供し、検出内容をトルコ語で説明します。
主な機能
- 01UBL-TRのXSDとSchematron検証
- 02税額、源泉徴収、合計の計算確認
- 03署名構造の確認
- 04トルコ語の説明と修正案
- 05CLI、Python API、バッチ検証
活用シーン
- 01GİBへの提出前に電子請求書を確認
- 02XML文書をまとめて検証
- 03検証結果を開発者に説明
MCP 対応
MCPサーバーは、文書検証、概要確認、検出内容の説明、コードリスト検索、サンプル請求書生成の読み取り専用ツールを公開します。ローカルstdioとリモートStreamable HTTPに対応し、リモート要求ではXML本文を直接送信します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
5掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| tur | any | いいえ | |
| xml | any | いいえ | |
| dosya | any | いいえ |
詳細
efatura-kontrol
GİBに送信する前に、e-Fatura、e-Arşiv Fatura、e-İrsaliye、エンベロープファイルをGİB独自のルールで検証します。OASIS UBL 2.1 XSD、GİBのe-Faturaパッケージのスケマトロン(498ルール、41コードリスト)、明細/税/源泉徴収/総額の算術、署名構造をチェックします。各指摘には行番号、GİBの原文メッセージ、日本語での説明、修正案が含まれます。コマンドライン、Pythonライブラリ、MCPサーバーを備え、データがネットワークに送信されることはありません。
トルコのUBL-TR e-請求書(e-Fatura、e-Arşiv、e-İrsaliye、エンベロープ)を、歳入庁独自のXSDおよびスケマトロンルールに加え、算術と署名構造のチェックを用いてオフラインで検証します。すべての指摘について、トルコ語で修正方法を説明します。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のスケマトロンはXPath 2.0で記述され、3つのファイルに分かれており、133個の抽象ルールとフラグメントインクルードを使用しています。そのため、一般的なツール(lxmlや大半のPythonスケマトロンライブラリ)では動作しません。このため、インテグレーターはGİBまたは民間インテグレーターに送信して初めてエラーを知ることになります。efatura-kontrolはGİBのスケマトロンをフラット化し、XSLT 3.0に一度コンパイルして(SchXslt2)、Saxonで実行します。文書あたり2~20ミリ秒で、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)です。初回実行時はスケマトロンのコンパイルに約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のコードリスト(スケマトロンが実際に適用する値) |
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] | 当事者、明細、VAT率から、有効で未署名の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などのエージェントは、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"
}
明細金額、税率ごとの VAT 小計、および合計金額が計算され、文書は XSD、シェマトロン、算術チェックをエラーなく通過します(指摘は imza-yok 情報のみです)。対象範囲は意図的に限定されています:SATIS タイプ、TRY、VAT 税率 > 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 スキーマ | エラー |
| シェマトロン | GİB e-Fatura パッケージ(29)、UBL-TR_Main/Common/Codelist、シェマトロン更新日 2026-07-01;121 個のルール、499 個のアサーション、41 個のコードリスト(単位、通貨、国、税、源泉徴収のコード+税率、免税、支払方法、シナリオ、請求書タイプ…) | エラー |
| 算術 | 明細金額 = 数量 × 価格 − 割引 + 加算;税額 = 課税標準額 × 税率;税額合計;源泉徴収 = VAT × 税率;合計金額(商品/サービス、割引、加算、税抜、税込、支払額);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, …"}
シェマトロンの指摘コードは、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(シェマトロン) | 有効 |
| 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 の古いサンプルで、シェマトロンが拒否 |
つまり、このツールは GİB の公式パッケージに含まれる古いサンプルでさえ検出します。ornekler/ の下には修正済みの、完全に有効な文書が 4 件あります。
最新の状態を維持する
araclar/paket_indir.py は GİB パッケージをダウンロードし(sha256 で検証)、efatura-kontrol derle kaynak はシェマトロンをフラット化してコンパイルし、コードリストと XSD を ekler/ の下に書き込みます。CI は実行ごとに、最新の GİB パッケージで生成した出力がリポジトリ内のものと同一であることを検証します。GİB パッケージが変更されるとチェックが失敗し、新しいリリースが作成されます。使用したパッケージのバージョンは efatura_kontrol.PAKET と各レポートの paket フィールドに記録されます。
制限事項
- 署名は暗号学的に検証されません(証明書、ダイジェスト、タイムスタンプ)。構造のみがチェックされます。
- GİB の本番環境でのチェック(納税者が登録されているか、ラベルが有効か、事業コードと VAT 税率が一致するか、番号が重複していないか)はこのツールにはありません。これらは GİB のシステムでのみ確認できます。
- e-Arşiv レポート(
eArsivRaporu)と e-Defter は対象外です(後続リリースで対応予定)。 - 「有効」とは、GİB が公開している XSD とシェマトロンを通過することを意味します。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 スキーマトロン(フラット化して 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 のホイール)です。初回実行時にスキーマトロンが約 0.5 秒でコンパイルされ、その後は文書をミリ秒単位で処理できます。
コマンドライン
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(安定した識別子。例:スキーマトロンルールの 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 | リッスンアドレス(Azure Container Apps は IPv6 に対応していないため、IPv4 を使用) |
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 とスキーマトロンに文書が合格することを意味します。サーバー側で追加の検証が行われないことを保証するものではありません。
参考資料
パッケージ、バージョン、スキーマトロンに対する平坦化の介入、およびGİBパッケージに含まれる不整合については、KAYNAKLAR.mdをご覧ください。変更点:CHANGELOG.md。
MITライセンスです。GİBとは関係ありません。「GİB」「e-Fatura」「UBL-TR」は関係機関の名称です。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。