mcpField
A
ANAF e-Factura

ANAF e-Factura

ローカル
foreverworks.github.io金融データ1今日更新

ANAF e-Factura について

ANAF e-Factura は、ルーマニア企業向けに電子請求書と e-Transport 申告を読み取り、検証、提出する MCP サーバーです。請求書の作成・解析、ANAF 署名の確認、VAT 登録情報の検索にも対応し、提出操作はクライアントの確認を要します。

主な機能

  1. 01送受信した請求書の一覧表示
  2. 02請求書のダウンロードと ANAF 署名の検証
  3. 03請求書の作成・解析・検証
  4. 04請求書と輸送申告の ANAF への提出
  5. 05企業の VAT 登録情報の検索

活用シーン

  1. 01最近の仕入先請求書と明細の確認
  2. 02提出前の CIUS-RO 請求書の検証
  3. 03請求書の ANAF 署名の有効性確認
  4. 04企業の VAT 状況と適用条件の確認

MCP 対応

MCP サーバーとして、請求書、申告、署名検証、企業検索のツールをクライアントに提供します。請求書と e-Transport の提出ツールは確認が必要な操作として扱われます。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"com-foreverworks-anaf-efactura": {
"command": "npx",
"args": [
"-y",
"@foreverworks/mcp-anaf-efactura"
],
"env": {
"ANAF_CONFIG": "<ANAF_CONFIG>"
}
}
}
}
起動コマンドnpx -y @foreverworks/mcp-anaf-efactura
設定が必要な環境変数
ANAF_CONFIGPath of app.json: the OAuth app you registered with ANAF (its client id and secret, the callback URL) and the company's CIF, as the README shows. lookup_company, validate_invoice and parse_invoice work without it.

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
npm@foreverworks/mcp-anaf-efactura0.1.0

ツール

20

掲載時のツール一覧 · 3 日前に更新

パラメーター型必須説明
redirect_uristringいいえapp.json に登録されているリダイレクト URI のいずれかです。空の場合は最初の URI が使われます。

詳細

ANAF e-Factura アイコン ANAF e-Factura MCP サーバー

AI アシスタントから、ルーマニアの e-Factura を通じて会社が送受信した請求書を読み取り、請求書に付された ANAF の電子署名を確認し、請求書や e-Transport の申告書をANAFに提出できます。また、請求書の検証、レンダリング、作成を行い、ANAF の VAT 登録簿で会社を検索できます。3 つのmoneyツール(upload_invoice、upload_invoice_b2c、etransport_file)は、取り消せない書類を提出します。クライアントは呼び出しのたびに確認を求め、別途指定がない限り、いずれも ANAF のテスト環境に提出されます。

必要なもの: ANAF に登録した OAuth アプリケーション(クライアント ID、シークレット、コールバック URL)、会社の CIF、および会社の SPV 権限を持つ有資格デジタル証明書の所有者です。この所有者は、ブラウザーで一度サインインする必要があります。その後、サーバーが認証許可を自動更新します。また、--healthチェックでは、その所有者による再認証が必要になる 2 週間前に警告が表示されます。請求書の検証、レンダリング、作成、読み取り、電子署名の確認、会社の検索には、アカウントは必要ありません。

できること

  • 「過去 2 週間に、仕入先から送られてきた請求書はどれですか?」
  • 「受信した最新の請求書をダウンロードし、ANAF の電子署名を確認して、明細を一覧表示してください。」
  • 「RO87654329 は VAT 納税者ですか? また、入金時に VAT を適用しますか?」
  • 「Client SRL に、1 時間あたり 500 RON、VAT 21% でコンサルティング 10 時間分を請求し、ANAF で検証して、テスト環境に提出してください。」
  • 「ANAF の認証の有効期限はあと何日ですか?」

インストール

VS Code にインストール Cursor にインストール Claude Desktop 用にダウンロード

Claude Code の場合:

claude mcp add anaf-efactura -e ANAF_CONFIG="<path to ANAF app.json>" -- npx -y @foreverworks/mcp-anaf-efactura

Claude Desktop(Settings、Developer、Edit Config)や、その他の多くのクライアントでは、同じコマンドを JSON として読み込みます。

{
  "mcpServers": {
    "anaf-efactura": {
      "command": "npx",
      "args": ["-y", "@foreverworks/mcp-anaf-efactura"],
      "env": {
        "ANAF_CONFIG": "<path to ANAF app.json>"
      }
    }
  }
}

各クライアントは、Node 22.19 以降で公開済みのパッケージを実行します。VS Code と Claude Desktop バンドルでは、サーバーを追加するときにANAF_CONFIGの入力を求められます。Cursor は代わりに環境変数(${env:ANAF_CONFIG})から読み込むため、Cursor を起動する前に設定してください。設定では、その内容について説明しています。

クローンから
git clone https://github.com/foreverworks/mcps.git && cd mcps
npm ci && npm run build
claude mcp add anaf-efactura -e ANAF_CONFIG="<path to ANAF app.json>" -- node "$PWD/servers/anaf-efactura/dist/index.js"

JSON 設定では、コマンドはnodeで、その唯一の引数はservers/anaf-efactura/dist/index.jsのフルパスです。複数のクライアントで 1 つの実行中のコピーを HTTP 経由で共有する方法については、docs/deploying.mdを参照してください。

設定

変数必須意味
ANAF_CONFIGはいサーバーが読み取りのみを行う app.json(以下)のパスです。
ANAF_STATE_DIRいいえ認可情報、開始済みの認可、申告済み書類の台帳の保存先です。デフォルトは docs/configuration.md に記載されています。
ANAF_DOWNLOADS_DIRいいえダウンロードしたアーカイブ、PDF、作成した請求書の出力先です。デフォルトは <state dir>/invoices です。

app.json には、ANAF に登録するアプリケーションを記述します(以下)。

{
  "app_name": "<the name you gave it at ANAF, shown by health>",
  "client_id": "<Client ID>",
  "client_secret": "<Client Secret>",
  "redirect_uris": ["<the Callback URL you registered>"],
  "company_cif": "<the company's CIF, with or without RO>"
}

client_id と client_secret は必須です。認可には redirect_uris が必要です。company_cif(または cif)は、呼び出し時に指定されなかった場合に対象となる会社です。1つの認可情報で複数の会社を対象にできるため、cif 引数を指定するとその値が優先されます。endpoints では、ANAF の URL を名前(authorize、token、hello、fctelProd、fctelTest、etransportProd、etransportTest)で指定して上書きでき、api_base / api_test_base では e-Factura のベース URL を指定できます。サーバーが app.json に書き込むことはありません。エラーには値ではなく、不正なフィールド名が表示されます。ANAF_CONFIG がなくてもサーバーは起動し、認可情報を必要としないツールは使用できます。

クライアント ID とシークレットの取得

ANAF では、これを OAuth プロファイルでのアプリケーション登録と呼びます。手順を説明したマニュアル(ルーマニア語)では、各画面が示されています。

  1. サインインする担当者が、資格証明書と会社における次のいずれかの権限(法定代表者、指定代表者、委任を受けた担当者:reprezentant legal、reprezentant desemnat、împuternicit)を使って SPV に登録されていることを確認します。
  2. anaf.ro/InregOauth(Servicii Online、Înregistrare utilizatori、Dezvoltatori aplicații、「Înregistrare pentru API-uri」)で開発者アカウントを作成します。新規作成するか、お持ちのポータルアカウントを使い、ANAF から送信される「Cod de verificare」でメールアドレスを確認します。
  3. サインイン(「Autentificare utilizator」)し、「Editare profil Oauth」を開いてから「Gestionare aplicații」を開きます。
  4. アプリケーションに名前を付け、サービス(E-Factura ツールには E-Factura、e-Transport ツールには E-Transport)を選択し、管理している Callback URL(例:https://example.com/anaf/callback)を入力します。そこに応答するものを用意する必要はありません。「Generare Client ID」を押します。
  5. リスト内のアプリケーションをクリックし、Client ID、Client Secret、Callback URL を app.json にコピーします。

認可情報で可能な操作は、アプリケーションのサービスと証明書保持者の SPV 権限の両方で許可された範囲に限られます。health では、そのロール(EFACTURA、ETRANSPORT)を確認できます。

ファイルの入出力

書類は、モデルがテキストを再入力したものではなく、バイト単位でそのまま渡す必要があります。ANAF のシールは正確なバイト列を対象とするためです。サーバーのファイルルート(MCP_FILE_ROOTS。stdio の場合はクライアントのフォルダーまたは作業ディレクトリ)からパスで指定するか、スクリプトから { "content_base64": "...", "sha256": "..." } として渡します。リンク、ルート外のファイル、チェックサムの不一致、UTF-8 ではない書類は、送信前に拒否されます。出力先フォルダー内のパスも対象になるため、build_invoice が作成したファイルはそのまま validate_invoice と upload_invoice に渡せます。

ファイルは出力先フォルダーにモード 0640 で、全体を書き込むか、まったく書き込まないかのいずれかで保存されます。他のバイト列を含むファイルを上書きすることはありません(その場合は 5001-2.zip のような次の番号の名前が使われます)。save_dir は出力先フォルダー内のフォルダーである必要があります。状態ディレクトリには tokens.json、authorization.json、uploads.json が 0600 で保存されます。状態ディレクトリと出力先フォルダーは、app.json のディレクトリ内に置けません。すべてのサーバーに共通する変数は docs/configuration.md に記載されています。

初回実行

ANAF で読み取りや登録を行うツールには権限付与が必要で、付与できるのは証明書の保有者だけです。アシスタントに、ANAF でサーバーを認可するよう依頼してください。

  1. begin_authorization は、アプリケーション用の ANAF サインインページ(authorizeUrl)を返します。このページは 30 分間有効です。redirect_uri では複数あるコールバック URL のいずれかを指定します。リンクを独自に表示するクライアント(標準入出力経由の MCP URL elicitation、または Claude Code のようにプロトコル 2026-07-28 の HTTP 経由のクライアント)では、ページが表示されます。証明書をお持ちでない場合は、認可を拒否して URL を証明書の保有者に渡してください。
  2. **証明書の保有者が、**証明書がインストールされているブラウザーでページを開き、証明書を選択してサインインします。
  3. **ブラウザーがコールバック URL に移動すると、**アドレスに ?code=...&state=... が表示されます。ページが読み込めない場合もありますが、重要なのはアドレスです。
  4. **そのアドレス全体を、すぐに complete_authorization の redirect_url に渡してください。**ANAF のコードは発行から 60 秒で無効になります。サーバーは state を検証し、コードを交換して tokens.json に書き込み、有効期限の日付だけを返します。トークンが会話に渡ることはありません。
  5. **health を確認します。**権限付与のロールと、各トークンの残り日数が表示されます。
権限付与を維持する

ANAF の手順書(28 ページ、33 ページ)によると、アクセストークンの有効期間は 90 日(または記載されている exp の値)、リフレッシュトークンの有効期間は 365 日です。アクセストークンの期限切れまで 3 日を切ってから呼び出すと、先に更新されます(force を指定して refresh_token を呼び出すと、すぐに更新されます)。更新するたびに、さらに 365 日間有効なリフレッシュトークンが発行されます。リフレッシュトークンの有効期限が切れた場合、または ANAF に拒否された場合(invalid_grant)、権限付与を再開できるのは証明書の保有者だけです。上記の手順を繰り返してください。使用頻度の低いサーバーでは、タイマーを使って毎日更新してください。クローンから servers/anaf-efactura で実行します。

node dist/index.js --health            # greet ANAF with the stored token; the days left
node dist/index.js --refresh           # refresh when the access token has under 14 days left
node dist/index.js --refresh --force   # refresh now

いずれも ANAF: OK|WARN|FAIL ... の形式で 1 行だけ出力し、トークンは出力しません。終了コードは、OK が 0、FAIL が 1(権限付与の無効化や設定の破損など、人による対応が必要)、WARN が 2(ANAF の不調、またはリフレッシュトークンの有効期限まで 14 日以内)です。

ツール

read は ANAF に何も変更を加えません(一部のファイルは送信ボックスに保存します)。write は保存済みの grant を変更します。money は ANAF に書類を提出し、クライアントは呼び出しごとに確認を求めます。

ツールアクセス内容
healthread保存済みトークンを使って ANAF に挨拶します。アプリケーション、デフォルトの CIF、grant のロール、各トークンの残り日数を確認します。ANAF が挨拶の最初の行にベアラートークンを含めて返すため、その行だけが返されます。
token_statusreadANAF を呼び出さずに、保存済み grant の有効期限とロールを確認します。
refresh_tokenwrite現在のアクセストークンの有効期限が切れるまで3日以内の場合、または force を指定した場合に、新しいアクセストークンを取得します。
begin_authorization / complete_authorizationwrite新しい grant を取得します。証明書の保有者向け ANAF ページを開き、その後、ブラウザーが移動したアドレスを渡します。
list_invoicesread過去 zile 日間の e-Factura メッセージを最大60件取得します。送信、受信、エラー、購入者メッセージが含まれ、download_invoice が使用する ID も含まれます。
list_invoices_windowread最大60日間の日付範囲から、ページごとに同じ内容を取得します。filtru(E はエラー、T は送信、P は受信、R は回答待ち)で絞り込みます。
download_invoicereadZIP を開けること、すべてのエントリがチェックサムと一致すること、ANAF のシールが有効であることを確認した後、署名済み ZIP を1つ送信ボックスに保存します。ANAF では、メッセージごとに1日10回までダウンロードできます。
upload_invoicemoney請求書の XML(UBL、CII、CN、RASP)を企業に提出します。test が false でない限り、テスト環境を使用します。
upload_invoice_b2cmoneyANAF の /uploadb2c を通じて個人に請求書を提出します。それ以外は upload_invoice と同じです。
upload_statusreadアップロードの処理状況を確認します。成功(ダウンロード ID を含む)、処理中、または ANAF の理由を伴う失敗のいずれかです。
etransport_listread過去 zile 日間の e-Transport 申告を最大60件取得します。UIT、申告者、取引先、運送業者、車両、拒否された申告に対する ANAF の理由が含まれます。
etransport_filemoney申告の XML(schema v2)を提出します。新しい輸送、修正、削除、確認、または車両の変更に対応します。test が false でない限り、テスト環境を使用します。
etransport_statusread申告の処理状況を確認します。成功(UIT は現在から有効)、処理中、または失敗のいずれかです。
build_invoicereadフィールドから CIUS-RO 請求書(UBL)を作成して送信ボックスに書き込み、合計額を正確に計算し、下書きを最初に検証します。提出は行いません。
parse_invoicereadUBL 請求書またはクレジットノート(ファイル、または送信ボックス内のアーカイブ)を JSON として解析します。すべての値は書類の本文から取得します。何も呼び出しません。
validate_invoicereadUBL 請求書またはクレジットノートを、提出せずに ANAF 独自の検証で確認します(スキーマ、EN 16931、CIUS-RO のルール)。
invoice_pdfreadUBL 書類の ANAF PDF、または message_id で指定した提出済み請求書の PDF を送信ボックスに保存します。
verify_signatureread請求書が ANAF のシールのもとで ANAF に保存されたファイルかどうかを確認します。ピン留めされた CA に対してローカルで検証し、それだけでは判定できない場合に限り ANAF に問い合わせます。
lookup_companyread指定日の ANAF VAT 登録簿から最大100件の CIF を検索します。事業者情報、登録事務所、VAT 納税者かどうかとその期間、現金主義 VAT、分割 VAT、非アクティブ状態、RO e-Factura 登録簿を確認できます。

最後の6つは、message_id を指定した invoice_pdf と verify_signature を除き、grant は不要です。e-Transport ツールには ETRANSPORT ロールが必要です。ANAF を呼び出すツールは cif(デフォルトでは app.json の値)と test を受け取ります。リスト取得とダウンロードは test が true の場合を除き本番環境を読み取ります。一方、提出を行う3つのツールとステータスを取得する2つのツールは test が false の場合を除きテスト環境を使用するため、ステータスは提出先の環境で確認されます。

金銭

upload_invoice、upload_invoice_b2c、etransport_file は、ANAF に法的または税務上の書類を提出します。書類は取引先に届き、取り消すことはできません(請求書を取り消すにはクレジットノートが必要です)。これらは tools/list で money としてマークされ、クライアントは呼び出しごとに承認を求めます(Claude Code はすべての権限モードでそうします)。誰が確認する場合でも、次の3つのルールが適用されます。

  • 特に指定がない限り、テスト環境を使います。 test が false でない限り、各書類は ANAF のテスト環境に送信され、提出しても法的効力はありません。
  • refile が true でない限り、本番環境では同じバイト列を二度提出しません。 本番環境への提出に使う正確なバイト列の SHA-256 は、送信前に台帳(uploads.json)に記録されます。ANAF に拒否された提出や、送信されなかった提出は対象外です。
  • 失われた応答は再送しません。 接続切断、5xx、または仕様に記載のない応答があった場合、提出が完了している可能性があるため、outcome_unknown として失敗します(トラブルシューティング)。

ファイルは確認を求める前に一度だけ読み込まれるため、確認する内容と提出される内容は同じバイト列に基づきます。MCP_CONFIRM=elicit の場合、サーバー自身が XML から読み取った内容を1行で尋ねます。行末にはファイルの SHA-256 が付加されます。

anaf-efactura: FILE with ANAF e-Factura PRODUCTION (legal filing, cannot be withdrawn): invoice EX-0042 of 2026-09-28, buyer Client SRL (87654329), payable 1234.50 RON, seller Exemplu SRL (RO92345672); UBL, file sha256 3f1c0a9e27b4
anaf-efactura: File e-Transport declaration for a new UIT, Cluj-Napoca (county 12) to Iasi (county 22), vehicle CJ12ABC + trailer CJ34DEF, 1800.50 RON, environment prod; declarant 92345672, file sha256 5d0e7b2a91c4

テスト環境へのアップロードでは、行頭が TEST upload to ANAF's test environment (no legal effect) になります。個人宛ての請求書には B2C invoice と表示され、再提出の場合は AGAIN (refile) が追加されます。金額は書類に記載された10進数文字列です。e-Transport の金額は、商品の valoareLeiFaraTva の正確な合計です。サーバーが読み取れない書類には UNREADABLE XML と表示されます。「いいえ」と答えてください。

確認を求められる前に、支払い用として請求書に記載されているすべての IBAN(BT-84、BT-91)、販売者の CIF、e-Transport の申告者の CIF または CNP、すべての UIT のチェックデジットが有効である必要があります(ANAF のルール BR-019 による UIT のチェックデジットは、文字の誤りは検出できますが、2文字の入れ替わりは検出できません)。新しい UIT は、etransport_status が ok を返した場合にのみ有効とみなされます。

トラブルシューティング

config:「tokens at ... are missing or unparseable」。 まだ認可が保存されていないか、ファイルが破損しています。初回実行の手順で認可してください。

config が ANAF_CONFIG、app.json のフィールド、company_cif、または「... is inside app.json's directory」を示す場合。 変数またはフィールドを修正するか、cif を渡すか、ANAF_STATE_DIR/ANAF_DOWNLOADS_DIR を app.json の場所から移動してください。

auth が invalid_grant、refresh_expired、invalid_client、または unauthorized_client を返す場合。 認可が無効になっています。再度認可してください。それ以外の auth コードは、現在 ANAF 側で問題が発生していることを示します。後でもう一度お試しください。

input:「そのアドレスの state は begin_authorization が発行したものではありません」、または「30 分以上前に開始されています」。 そのアドレスは古いタブのものか、ウィンドウが閉じられています。begin_authorization を再度呼び出し、新しいアドレスをすぐに渡してください(60 秒以上前のコードは auth エラーになります)。

api がステータス 401 または 403 を返す場合。 ANAF がこの CIF またはロールに対するトークンを拒否しました(ロールは token_status で確認できます)。e-Transport ツールには ETRANSPORT が必要です。ANAF でアプリケーションにサービスを追加してから、再度認可してください。

api が reason: "outcome_unknown" を返す場合、または input:「このファイルそのものは ... すでに ANAF の本番環境に送信されています」。 申告が ANAF に届いている可能性があるか、これと同じバイト列がすでに送信されています。まず確認してください(upload_status に test: false を指定するか、list_invoices、etransport_status、または etransport_list を使用)。同じバイト列を意図的に再申告する場合に限り、refile: true を渡してください。

input:「請求書は送信されませんでした」、「申告は送信されませんでした」、または「請求書は作成されませんでした」。 チェックディジットまたはルールの検証に失敗しています。メッセージにそれぞれの内容が示されます。書類または build_invoice のフィールドを修正してください。

validate_invoice が ERRIdentif「nu a fost identificat cui cumparator」だけを検出する場合。 買い手は外国企業です。ANAF のバリデーターにはその旨を指定できないため、この検出結果は想定どおりです。このような買い手に対して build_invoice が設定する extern: true を指定してアップロードしてください。

checksum_mismatch。 到着したバイト列が、sha256 に記載されたファイルと一致しません。たとえば、モデルが base64 を再入力した場合に発生します。何も送信されていません。ファイルパスを指定して送信するか、スクリプトでエンコードしてください。

api のステータスが 0 の場合:ANAF に接続できなかったか、呼び出しに必要なフィールドが応答にありませんでした。後でもう一度お試しください。「... answered in a shape ANAF does not document」:ANAF の応答形式が変更され、サーバーは推測による処理を拒否しています。報告してください。

仕組み

返される内容。 ANAF のワイヤ形式はサーバー内部にとどまります。一覧表示されるメッセージには kind(sent、received、error、buyerMessage、unknown)と、ANAF の文章から抽出したアップロード ID および両方の CIF を含む details があります。createdAtLocal にタイムゾーンがないのは意図的です。ANAF はブカレスト時間でタイムスタンプを付けますが、そのことを明示しないためです。日付の範囲は UTC なので、どこでも同じように読み取れます。ANAF が HTTP 200 と eroare キーを伴って拒否した場合(「この期間にメッセージはありません」も含む)、notice が設定されます。この応答を空の一覧として扱うのは、最も重大な誤りになり得るためです。実際の応答に含まれる、証明書保有者の CNP である cui は返されません。

ANAF の封印。 download_invoice は、すべてのエントリーの CRC が一致し、ANAF の封印(semnatura_<id>.xml)が有効な場合に限り、アーカイブを保持します。この封印は、添付された XML-DSig 署名です。そのダイジェストは請求書ファイルの未加工バイト列の SHA-256 です(そのため、インデントを変更したコピーは封印されたファイルではありません)。この署名は、「Trans Sped Electronic Seal QCA G3」により Ministerul Finanțelor に発行された証明書によるものです。verify_signature はこれをローカルで検証します。証明書はピン留めされた CA(src/infra/sealTrust.ts)から発行され、請求書の日付より前に有効期限が切れていない必要があります。RSA 署名を検証した後、ダイジェストを照合します。そのため、証明書を差し替えると CA のチェックに失敗し、請求書を変更してダイジェストを書き換えると署名に失敗します。署名が検証できない場合はすべて、ANAF の公開エンドポイント /api/validate/signature に送信され、誰が応答したかは checkedBy に示されます。npx tsx scripts/check-seals.ts <folder> を実行すると、オフラインで検証できます。 請求書の作成。 build_invoice は、ツールキットの invoiceTotals.ts を使い、ANAFが確認するEN 16931のルールに従って合計します(各明細を小数点以下2桁に丸め、税率区分ごとに明細の合計額に対してVATを一度だけ計算し、ちょうど中間の値はゼロから遠い方に丸めます)。これはoblioサーバーと同じ方式です。書き込む前に、ANAFが拒否するすべての問題を列挙します。

  • チェックディジット:ルーマニアのVAT IDまたはCUIのCIF、個人のCNP、IBAN。
  • 住所:ルーマニアの住所には県が必要です(CJ または RO-CJ)。ブカレストでは市区が市名となり(Sector 3 は SECTOR3 と記載します)、住所に含めます。
  • VAT:Sには税率が必要で、その他の区分には税率を指定できません。Eには理由が必要です(AE、G、OはVATEXコードが既定値です)。リバースチャージには買い手のIDが必要です。OにはVAT IDを指定できず、他の区分と併用できません。
  • 金額:支払額がある場合は支払期日または支払条件が必要です。銀行振込にはIBANが必要です。また、別の通貨での請求書には vat_exchange_rate が必要です(bnrサーバーから取得するRONの単位あたり為替レート)。CIUS-ROではVATもRONで記載するためです。
  • CIUS-ROの文字数と件数の制限、および少なくとも1桁を含む番号。

テストでは、scripts/record-validation.ts --send を使って7つの架空の請求書(test/fixtures/validation)から記録した、各ファイルの正確なバイト列に対するANAF独自の判定を確認します。

請求書の読み取り。 parse_invoice はANAFのダウンロード枠を消費せず、400.0000 は 400.0000 のままです。これは忠実な表示であり、判定は validate_invoice の役割です。

検証、PDF、VAT登録簿。 validate_invoice と invoice_pdf はANAFの公開ホスト webservicesp.anaf.ro を呼び出します。このホストではトークンは不要です(同じ操作を api.anaf.ro で行う場合は、トークンがないと401を返します)。そのため、許可の有効期限が切れた後も利用できます。5 MBを超えるものは呼び出し前に拒否されます。提出済み請求書のPDFは再検証せずに作成するため、今日のルールで古いルールのもとに提出された書類が拒否されることはありません。それ以外は、validate が false でない限り、先に検証します。lookup_company は各CIFの制御数字を確認してから、ANAFの要件どおり、1秒に1リクエストの頻度でPlatitorTvaRest v9に問い合わせます。ANAFが送信しなかったステータスは、false ではなく存在しない値として扱います。

ローテーション。 リフレッシュすると古いリフレッシュトークンは無効になるため、新しいトークンのペアはアクセストークンを使用する前に tokens.json に書き込まれます。ロックは、同じ状態ディレクトリを共有するすべてのプロセスで共通です。--refresh ではバックアップを保持しません。ローテーション前のコピーには無効になったリフレッシュトークンが含まれるためです。

ANAFのエンドポイントは src/infra/anafApi.ts にあります。npm run gen:types は、ANAFのSwagger UIページにあるOpenAPIドキュメントから型を再生成します(-- --offline を指定すると openapi/ のスナップショットから生成します。mfinante.gov.roはルーマニア国外からの接続をリセットするため、ANAF_SPEC_MIRROR=http://web.archive.org/web/2025id_/ を指定するとアーカイブされたコピーを読み込みます)。ANAFが誤って文書化しているもの、または文書化していないものは src/domain/schema.ts で手作業でモデル化し、すべての応答を境界で解析するため、仕様とのずれがあれば明確にエラーになります。

スモークテスト。 npx tsx scripts/smoke.ts は、お使いの設定でビルド済みサーバーを読み取り専用で実行します(許可が不要なツールには --public-only を指定します)。--allow-writes を指定すると、force なしの refresh_token と begin_authorization が追加されます。書類の提出は行わず、直近のメッセージで利用できる日次ダウンロード枠を2件消費します。

制限事項

  • build_invoice が作成するのは請求書であり、クレジットノートではありません(ストルノは数量を負数にした請求書です)。書類レベルの値引きや手数料、添付ファイル、EU域内の商品供給(VAT区分K。配送先の国が必要です)には対応していません。
  • e-Transportは、作成済みの申告書を提出します。 項目から申告書を作成する機能も、/info(あなたを輸送手配者として他者が申告した内容)を読み取る機能もありません。
  • 読み取り、検証、PDF生成で受け付けるのはUBLのみです(ANAFのバリデーターと同じです)。upload_invoice はCIIも提出できます。
  • 封印の失効(Trans SpedのCRLとOCSP)はローカルで確認しません。
  • 台帳は1つの状態ディレクトリに保存されます。状態ディレクトリが別々のデプロイメント間では、互いの本番提出データを参照できません。
  • SPVのメールボックスと税務申告には対応していません。

ANAF e-Factura 向けのその他のサーバー

2026-10-15 に検索しました。ANAF は何も公開していません。唯一の公開 GitHub リポジトリは、SPV 向けの 2019 年の Java サンプルクライアントで、MCP Registry にも e-Factura 向けのものは登録されていません。コミュニティ製のサーバーが 3 つ、ANAF に直接接続します。

  • anafpy は PyPI で公開されており、最も幅広い機能を備えています。Python 製の stdio サーバーで、e-Factura、e-Transport の申告、適格証明書を使った SPV メールボックスへのアクセス、税務申告、公的登録簿向けに 48 個のツール(mcp エクストラ)を提供します。すべての申告は、文書のバイト列に紐付けられた準備・確認ステップを経て行われます。
  • @florinszilagyi/anaf-mcp は npm で公開されており(stdio)、一覧表示、ダウンロード、検証、アップロードに対応し、B2C も含みます。XML はテキスト引数として渡し、独自の確認ステップはありません。
  • anaf-efactura-mcp は npm で公開されており(stdio または HTTP)、請求書を作成してアップロードします。デフォルトではテスト環境を使用します。

ほかに見つかったものは、ホスト型サービスを介してアップロードとポーリングのみを行うもの、別の請求アカウントを介して e-Factura に接続するもの、ファイルをオフラインで検証するものだけでした。

これらのいずれも、固定した CA に対するローカルなシール検証、ファイルまたはチェックサム付きバイト列のみでの文書受け渡し、XML から読み取った明細に基づくテスト優先の申告、チェックディジット、同じバイト列の二重申告や無条件の再送信の禁止、クライアントへのトークン非保存をすべて組み合わせてはいません。anafpy のように SPV メールボックスにアクセスしたり、税務申告を行ったりする機能もありません。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。