mcpField
E
ERP Report Engine

ERP Report Engine

ローカル
gulmezeren2-byte.github.ioデータ・分析213 週間前に更新

ERP Report Engine について

ERP Report Engineは、ERPデータベースからのレポート作成やAIエージェントへのデータ提供を行うチーム向けの読み取り専用SQLレイヤーです。セマンティックプロファイルでスキーマを標準エンティティに対応付け、多層のクエリ防御と監査記録でアクセスを制限します。

主な機能

  1. 01KPI、推移、データ検査を含むHTMLレポート生成
  2. 02注文、明細、在庫を標準エンティティに対応付け
  3. 034層の読み取り専用SQL防御
  4. 04クエリ、パラメーター、行数、実行時間の記録
  5. 05MSSQL、PostgreSQL、SQLiteに対応

活用シーン

  1. 01ERPの定期的な業務レポート作成
  2. 02読み取り専用制御下でのAIエージェントによるERP照会
  3. 03重複や負数などのデータ品質問題の検出

MCP 対応

MCPサーバーは標準エンティティを通じてAIエージェントにERPデータを公開し、レポートエンジンと同じ読み取り専用ガードを適用します。

設定

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

mcp.json · 共通設定
{
"mcpServers": {
"gulmezeren2-byte-erp-report-engine": {
"command": "uvx",
"args": [
"erp-report-engine"
]
}
}
}
起動コマンドuvx erp-report-engine

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

パッケージ
pypierp-report-engine0.7.0

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

erp-report-engine

月曜日の会議で使う数値は、すでに ERP のデータベースにあります。それなのに、まだレポートを書いているのは誰でしょう?

ERP の背後にある SQL データベース向けの、読み取り専用で自己検証するデータレイヤーです。週次レポートに加え、AI エージェント向けの保護された MCP サーバーも提供します。すべてのクエリが読み取り専用であることを実証済みです。文章で約束するのではなく、28 種類の攻撃に照らして検証しています。

CI Python License: MIT

🇹🇷 トルコ語版:README.tr.md

スケジュールされた run を 1 回実行するだけで、監査済みの SELECT 文 9 件を実行し、自己完結型の HTML レポートを作成します。8 週間のベースラインとの比較を含む 4 つの KPI、要因を明示した所見、データ品質ゲート、ソースと照合済みの行数を掲載します。BI ライセンスも、ERP サーバーへのエージェントのインストールも不要です。また、書き込みは一切ありません。文章で約束するのではなく、4 層(字句、構文木、副作用のある関数のガード、読み取り専用セッション)で強制します。

同梱のデモデータベースからエンジンが生成した週次レポート

同梱のデモデータベースに対して 1 つのコマンドを実行して生成した、まさにこのレポートには、意図的に埋め込まれた 3 つのデータ品質問題も含まれており、すべてゲートで検出されました。

同じ保護されたエンジンは、AI エージェントにも対応します。 erp-report-engine mcp は、同じ読み取り専用ガードの背後で、標準化されたエンティティ(LG_001_01_ORFICHE ではなく orders)を通じて ERP をエージェントに公開します。これは、MCP エコシステムで繰り返し問題になっているレイヤーです。参照実装である PostgreSQL MCP サーバーの読み取り専用モードは、COMMIT; DROP SCHEMA public CASCADE; で回避され、アーカイブされました。Supabase の MCP は、教科書どおりの「致命的な三要素」となりました。ここでは、ガードは文の形だけでなく、文が呼び出す関数も検査します。そして、その形容詞を鵜呑みにする必要はありません。

▶ 28 種類の攻撃による信頼性ベンチマークを実行 · ブラウザーで自分でガードを破ってみる(Pyodide 経由で本物の guard.py を実行。データはどこにも送信されません)。

ブラウザーのプレイグラウンドで実行する読み取り専用ガード:サーバーファイルの読み取りと有名な COMMIT; DROP による Postgres の回避は拒否され、実際の分析は許可されます — Pyodide 経由で本物の guard.py を実行

テストで実行するものとまったく同じ guard.py をブラウザーで実行します。ファイルの読み取りと読み取り専用トランザクションの回避は拒否され、実際の集計は許可されます。自分の攻撃を貼り付けてみる →

60秒デモ(ERP不要)

# install (pipx or uv keep it isolated; plain pip works too)
pipx install erp-report-engine          # or: uv tool install erp-report-engine
# from source instead:  pip install .

erp-report-engine init-demo             # builds demo.db + config.demo.yaml here
erp-report-engine run -c config.demo.yaml

すべてのコマンドは python -m erp_report_engine … からも実行できます。追加機能を指定してデータベースドライバーを追加してください:pipx install "erp-report-engine[mssql]"(Logo Tiger / Netsis / Mikro — SQL Server)または [postgres]。

Dockerを使いますか? docker build -t erp-report-engine . を実行してから、docker run --rm -v "$PWD:/work" erp-report-engine run -c config.demo.yaml を実行してください。SQLiteとPostgreSQLはそのまま動作します。MSSQLの場合はMicrosoftのODBCドライバーを追加してください(Dockerfileを参照)。PyPIへの公開は、GitHub Releaseを作成するだけです。publish.ymlがTrusted Publishing(OIDC、保存済みトークン不要)を使ってビルドとアップロードを行い、CIではすでにwheelをビルドし、同梱されているすべてのプロファイルが含まれていることを検証します。

reports/erp_report_<week>.htmlを開いてください。エンジンが売上の急増を検知して1つの地域に要因を特定し、納期遵守率の2ポイント低下にフラグを立て、在庫カバーが2週間未満の品目を一覧表示し、処理中に見つけた重複行やマイナス行をすべて報告する様子を確認できます。

▶ ライブサンプルレポートを見る:gulmezeren2-byte.github.io/erp-report-engine(docs/sample-report.htmlにもコミットされています)。

または、run --dashboardを実行して、プレミアム版のCommand Centerを使ってください。アニメーション付きKPIと光るSPC管理限界チャートを備えた、ダークでモダンな自己完結型ダッシュボードです(ライブ版):

Command Centerダッシュボード — SPC管理限界チャートを備えた、ダークなグラスモーフィズムのベントーグリッド

1回の実行で生成されるもの

セクションわかること
KPIカード売上、注文数、納期遵守率、在庫不足数 — それぞれ前週および8週間のベースラインと比較
検出結果「売上は前週比+6.5% — 主な要因:地域『Ege』(今週の変動の54%。Marmara(−14,697)が一部相殺)」 — 要因と逆方向に動いたセグメントを示し、対応策を提案
シグナル(SPC)「売上シグナル:148,291は管理限界を超えています(UCL 143,078 = 平均93,168 ± 2.66 × 移動範囲の平均18,763、ベースライン n=25週)」 — 週ごとのノイズとは切り分けて真の変化を検知し、計算式とサンプル数も表示
トレンド売上と納期遵守率の過去13週間分を、インラインSVGで表示(外部アセット不要)
在庫注意リストカバーしきい値を下回る品目を、深刻度の高い順に表示
データ品質ゲート重複ID、解析できない日付、マイナスの合計、注文前に出荷された行
ソース照合取得した行数と、同じクエリに対する独立したCOUNT(*)の結果を比較 — ✓またはMISMATCH
SQL監査証跡実行したすべてのステートメントと、パラメーター、行数、実行時間
実行状態メモリ「売上は3週連続で減少」 — ルックバック期間を超えたコンテキスト

仕組み

flowchart LR
    DB[("ERP database<br/>MSSQL · PostgreSQL · SQLite")]
    PROF["Semantic profile<br/>(YAML contract)"]
    GUARD["safe_read<br/>read-only guard + audit"]
    GATE["Data-quality gate<br/>+ source reconciliation"]
    KPI["KPI engine<br/>ISO weeks, 8-wk baseline"]
    INS["Insight rules<br/>driver attribution"]
    HTML["Self-contained<br/>HTML report"]
    STATE[("state.db<br/>run memory")]

    PROF --> GUARD
    DB --> GUARD --> GATE --> KPI --> INS --> HTML
    STATE --- HTML
    GATE --> PBI["Power BI Command Center<br/>(TMDL + PBIR, code-authored)"]

このツールの可搬性を支えるのがセマンティックプロファイルです。これは、各ERP固有の判読しにくいスキーマを3つの標準エンティティ、orders、order_lines、inventoryに対応付ける、バージョン管理されたYAML契約です。さらに**オプションのreceivables**エンティティ(未回収売掛金。期間別の分析に使用)もあります。元帳にアクセスできる場合はプロファイルで対応付け、アクセスできない場合は後続処理で適切にスキップします。エンジンが扱うのは常に標準列のみです。プロファイルを差し替えても、レポートはそのまま使えます。

セキュリティモデル

本番ERPデータベースにソフトウェアを接続するのは、信頼に関わる判断です。このエンジンはそれを重く受け止め、保証をコードで強制し、テストで確認しています。

読み取り専用は4つのレイヤーで強制されるため、1つのミスだけでエンジンがデータを書き込めるようにはなりません。

レイヤー担当する保護機能
字句ガード単一のステートメントであること、先頭がSELECT/WITHであること、コメント(--、/*、#)がないこと、書き込み/DDLキーワードがないこと、書き込みを強めるロックヒント(TABLOCKX、UPDLOCK、XLOCK)がないことを検査します。文字列リテラルを空白に置き換えてスキャンするため、SELECT 'please delete this note'は脅威ではなく読み取りと判断されます
構文木ガードsqlglotでステートメントを解析します。解析に失敗した場合はクエリを拒否します。クエリを読み取れないガードは、その安全性を保証できないためです。単一の読み取りクエリであり、そのASTにINSERT/UPDATE/DELETE/CREATE/DROP/ALTER/MERGE/EXEC/INTOのノードが含まれないことを確認します(CTE内に隠された書き込みも検出します)
関数ガード読み取り専用に見えるSELECTの多くは、読み取りではありません。 pg_read_file、lo_export(ファイルに書き込みます)、dblink(外部に接続します)、OPENROWSET、LOAD_FILE、load_extension(任意のコードを実行します)、query_to_xml(任意のSQLを実行します)、set_config(セッションの保護策を無効にします)、SLEEP/BENCHMARK(サービス拒否)をすべて拒否します。OPENROWSETはまさにsqlglotで解析できないものなので、ASTと字句の両方で拒否します
読み取り専用セッションPostgreSQLのdefault_transaction_read_only=on、SQLiteのPRAGMA query_only、MySQLのSET SESSION TRANSACTION READ ONLYとmax_execution_timeを使用し、さらにすべての環境でステートメントごとにタイムアウトを設定します

アドホックSQL、つまりエージェントが実行する経路には、さらに厳格な制約を設けています。 queryとguarded_queryは厳格モードで実行され、ガードが識別できない関数はすべてデフォルトで拒否されます。sqlglotの関数レジストリを許可リストとして使います。ここには移植可能な分析関数だけが登録されており、ファイルを読み取ったりソケットを開いたりする関数は含まれていません。付属の4つのプロファイルはすべてこの検査に合格します。認識されない関数を一切呼び出さないためです。

そして、私たちの管理外にあるレイヤーもあります。 MSSQLにはセッションレベルで読み取り専用にする方法がないため、エンジンは最小限の権限を持つ読み取り専用ログイン(MSSQLではdb_datareader、PostgreSQLではSELECTのみの権限付与。可能であれば読み取りレプリカ)で実行してください。ガードは多層防御の一部であり、ガードに抜け穴があっても機能するのは権限付与のレイヤーです。過去には実際に抜け穴がありました。この関数による回避方法は、このリポジトリの監査で見つかり、現在は方言ごとにtests/test_guard.pyで名前を指定してテストされています。

信頼性は、言葉ではなく測定結果で確かめてください。 ガードには、再現可能な信頼性ベンチマークが付属しています。4つの方言を対象に、形式として正しいSQLを使った攻撃を28件用意し、構造だけを見るガードなら通してしまう攻撃をすべて拒否することに加え、正当に許可される読み取りクエリも検証します。数値は実際にガードを実行して算出され、説明文で宣言されているだけではありません。また、CIでコミットのたびに検証されます。

「28件中28件」という数字も、同じ28件に対する、より弱いガードの結果と並べて初めて意味を持ちます。そこでベンチマークでは、実際のツールで使われている簡易的な手法、つまり先頭がSELECTかどうかの確認と、書き込みキーワードのブロックリストでもテストコーパスを実行し、その差を示します。これらの手法が拒否するのは28件中それぞれ6件と9件であり、キーワードスキャンは「delete」という単語を含む正当な読み取りクエリまでブロックします。一方、このガードは28件すべてを拒否し、正当な読み取りは一切ブロックしません。テストでは、このガードがこうした簡易的な手法すべてを確実に上回ることを検証しています。

erp-report-engine trust-benchmark
#   this guard               28/28 attacks refused · 8/8 reads allowed
#   starts-with-SELECT        6/28                  · 8/8   (waves 22 through)
#   write-keyword blocklist   9/28                  · 7/8   (leaky AND breaks a real read)

▶ 結果を見る:信頼性ベンチマーク — すべてのケース、その重大度、実際に起きることを確認できます。または**自分で試す**:実際のガードにSQLを貼り付けて、ブラウザー上で実行できます(インストール不要。データが外部に送信されることもありません。テストで実行されるものとまったく同じguard.pyを、Pyodide経由で動かします)。

ご自身のMCP サーバーやDBツールにガードだけを導入したい場合は、スタンドアロンパッケージとして切り出されています:readonly-sql-guard(pip install readonly-sql-guard)。関数は1つだけで、依存するのはreとsqlglotのみです。 同じ考え方を一段上のレイヤーで実現するのが、ossie-guard です。Apache Ossie のセマンティックモデルを検査し、方言によって結果が暗黙に食い違うメトリクス(あるデータウェアハウスでは SUM、別のデータウェアハウスでは AVG)や、純粋で再現可能な読み取りではない式を検出して、SARIF 形式で GitHub のコードスキャンに報告します。

関連資料:「文章上は読み取り専用」が読み取り専用ではない理由(有名な MCP データベース障害の2例と、その背後にある攻撃の種類)・AI エージェント向け読み取り専用データベースアクセスの比較(トランザクション、ロール、ステートメントガード、セマンティックレイヤーを比較し、それぞれの強みを率直に説明します)。

さらに、プロファイル変数は識別子として安全です(^[A-Za-z0-9_]{1,16}$ に適合するため、"001; DROP TABLE x" は接続前にエラーになります)。シークレットが設定ファイルに保存されることはありません(ローダーは、password、passwd、pwd、sslpassword、ODBC の PWD= など、どの表記であっても埋め込み認証情報を拒否します。url_env を使用してください)。実行されたすべてのステートメントはレポートの監査証跡に記録され、行数の上限(デフォルトは 500k)によって1回のクエリの規模が制限されます。

テストスイートでは、マルチステートメント、3種類の構文によるコメントの偽装、トランザクション制御の挿入(ROLLBACK/COMMIT)、SELECT INTO、ロックヒント、CTE 内に隠された DELETE など、さまざまなインジェクションをガードに対して試し、すべてがエラーになることを確認します。SECURITY.md をご覧ください。

独自の ERP を接続する

  1. 接続 URL を環境変数に設定します(ファイルには記載しないでください)。
# Windows (System Properties → Environment Variables, or:)
setx ERP_DB_URL "mssql+pyodbc://readonly_user:***@SERVER/LOGODB?driver=ODBC+Driver+17+for+SQL+Server"
  1. config.example.yaml を config.yaml にコピーします。
connection:
  url_env: ERP_DB_URL          # the engine reads the URL from this env var
profile: logo_tiger            # a bundled profile name, or a path to your own YAML
profile_vars:
  firm_no: "001"               # identifier-safe values only, validated
  period_no: "01"
report:
  company_alias: "Company"     # display name — use an alias if you prefer
  lookback_weeks: 13
  low_cover_weeks: 2.0
limits:
  row_cap: 500000
  query_timeout_s: 60
  1. ドライランを実行します。validate は接続し、プロファイルの契約を確認して件数を照合します。それ以外には何も行いません。
python -m erp_report_engine validate -c config.yaml
python -m erp_report_engine run -c config.yaml
同梱プロファイル

プロファイルはパッケージ内に同梱され、名前(generic、logo_tiger)で参照できます。設定ファイルと同じ場所に profiles/ フォルダーを用意する必要はありません。

  • generic — 標準スキーマです。独自プロファイルを作成する際のテンプレートとしても使えます。
  • logo_tiger — MSSQL 上の Logo Tiger/GO:LG_{firm}_{period}_ORFICHE の受注ヘッダーを、CLCARD の顧客、ORFLINE の明細、STINVTOT の在庫合計と結合し、TRCODE = 2 で販売を絞り込みます。また、PAYTRANS から売掛金の任意の年齢分析を取得します(分割払いの TOTAL − PAID、MODULENR = 4)。Logo のスキーマはリリースによって異なるため、プロファイルには、信頼して使用する前にご使用のバージョンで確認すべきフィールドの注記が記載されています。
  • netsis — MSSQL 上の Logo Netsis 3(会社ごとにデータベースを分ける構成):TBLSIPAMAS/TBLSIPATRA の受注(FTIRSIP = '6')、TBLCASABIT の顧客、TBLSTOKPH の在庫合計、および TBLCAHAR からの売掛金の任意の年齢分析を扱います(未決済項目と残高繰越方式の注意点をインラインで明記しており、率直に弱点も示しています)。実際の本番環境の統合に基づいてフィールドを対応付けており、弱点(受注ステータス、納品日、売掛金の締め方法)は、インストール環境で確認できるようインラインで明記されています。
  • mikro — MSSQL 上の Mikro ERP(Mikro Yazılım、Fly/Jump/V16–V17):SIPARISLER(sip_ プレフィックス、明細レベル)の受注、CARI_HESAPLAR の顧客、STOK_HAREKETLERI の手持ち在庫(入出庫を sth_tip で判定)、および CARI_HESAP_HAREKETLERI からの売掛金の任意の年齢分析(支払期日は cha_vade)を扱います。弱点についても率直に示しています。sip_tip による販売の絞り込み、合計金額に VAT が含まれるかどうか、受注に出荷日がないこと、未決済項目フラグのない純粋な残高繰越方式の売掛金台帳は、バージョンごとに確認できるようインラインで明記されています。

Logo Tiger、Netsis、Mikro を合わせると、トルコの中小企業向け ERP 市場の大半をカバーできます(いずれも MSSQL)。別の ERP(SAP B1、Odoo、カスタムシステムなど)のプロファイルを作成するには、標準列を出力する3つの SELECT ステートメントを記述します。profile: で指定する単独の YAML ファイルにするか、erp_report_engine/profiles/ にファイルを追加してパッケージに同梱できます。これが契約のすべてです。validate を実行すれば、正しく設定できたかすぐにわかります。

自律的に実行する

エンジンは冪等な単一コマンドなので、どのスケジューラーでも動作します。

# Windows Task Scheduler — every Monday 07:00
schtasks /create /tn "erp-weekly-report" /sc weekly /d MON /st 07:00 ^
  /tr "cmd /c cd /d C:\erp-report-engine && python -m erp_report_engine run -c config.yaml"
# cron — every Monday 07:00
0 7 * * 1  cd /opt/erp-report-engine && python -m erp_report_engine run -c config.yaml

実行のたびに state.db に追記されます。これにより、ERP の履歴を再クエリせずに、レポートで「週次の減少が3週連続」と示せます。実行をまたいで情報が保持されます。

終了コードを使えば、実行が失敗した理由に応じてスケジューラーで処理を分岐できます。0 は成功、2 は設定エラー、3 はデータベース/接続エラー、4 は契約エラー(プロファイルのスキーマが誤っている、またはソースの件数が一致しない)、5 は --strict 指定時のデータ品質エラー、1 はそれ以外の予期しないエラーです。機械可読な結果は標準出力に出力されます(… run -c config.yaml | jq)。ログは標準エラーに出力され、必要に応じて --log-file run.jsonl で JSON Lines ファイルにも記録できます。CI では validate --strict を実行し、数値が一致しない場合にパイプラインを失敗させます。

嘘をつけない、任意の AI サマリー。 run --narrate を指定すると、LLM によるエグゼクティブサマリーが追加されます。ただし、設計上、内容は必ず誠実です。モデルに渡されるのは監査済みの集計値(KPI、検出結果、滞留期間/集中度)のみで、生の行データは渡されません。また、レポートにはモデルが受け取ったペイロードがそのまま出力されるため、誰でも渡された内容を確認できます。キーが設定されていない場合、このフラグは何もせず、レポートも変わりません。Ollama/LM Studio など、ローカルでキー不要のモデルを含め、OpenAI 互換のエンドポイントならどれでも動作します。ほとんどのツールは生成後にハルシネーションをチェックしますが、この場合、モデルが漏えいや過剰な主張につながる可能性のある情報を見ることはありません。

配信機能を標準搭載。 run --send を指定すると、レポートをメール送信(SMTP)し、Slack または Teams にサマリーを投稿(Power Automate Workflows)し、成功時も失敗時も healthchecks.io のデッドマンスイッチに通知するため、無音で実行される cron も検知できます。すべてのシークレットは環境変数から取得します。失敗したチャネルはログに記録されますが、実行全体は停止しません。delivery: ブロックで設定してください(config.example.yaml を参照)。完全に手間のかからないパイプラインを構築するには、power_automate チャネルを使うと Teams に Adaptive Card を投稿し、さらに HTML レポートを SharePoint/OneDrive にアーカイブできます。インポート可能なフローと手順を追ったガイドは automation/POWER-AUTOMATE.md にあります。レポートは自動作成され、さらに自動配信されます。多くの BI ツールでは有料の機能です。

Power BI コマンドセンター

エンジンはインタラクティブな Power BI レイヤーにもデータを提供します。このリポジトリに .pbix バイナリはありません。成果物全体が、コードとして作成された PBIP プロジェクトです。TMDL のセマンティックモデル(スター型スキーマ、ドキュメント付き DAX メジャー 28 個――顧客ごとのスパークラインや品目ごとのカバーバーを DAX から直接描画する SVG マイクロチャートメジャー、売掛金年齢分析のファクトとメジャー、欠損のない週次序数に基づく Time Shift 計算グループ、フィールドパラメーターを含む)、PBIR のレポート(5 ページ/30 個のビジュアル。コンパクトな仕様からスクリプトで生成)、そしてMicrosoft の公式テーマスキーマに照らして検証された、ダークで未来的なテーマで構成されています。

# a demo export already ships in powerbi/data — just open the project:
#   powerbi/ERP Command Center.pbip   (Power BI Desktop)
# to feed it your own ERP (writes to gitignored powerbi/data.local by default):
erp-report-engine export-powerbi -c config.yaml

このプロジェクトの特徴は Trust ページです。ソースの照合、データ品質ゲート、完全な SQL 監査証跡をビジュアルとして表示し、ダッシュボードが証拠を示します。アラートのしきい値は insights.py と同じものを DAX で再定義しており、定義は1つ、表示面は2つです。プロジェクトを Desktop で開く前に、pbir-cli がフィールドのバインドを TMDL モデルに照らして検証します。詳しいガイドは powerbi/README.md をご覧ください。

エージェント経由で ERP に問い合わせる — ガード付き MCP サーバー

ERP に接続する AI エージェントは、誰も十分に解決できていない信頼性の問題を抱えています。既存の「ERP MCP」はどれも ERP 独自の権限に依存する REST ラッパーであり、データベース MCP はエージェントに生のテーブルを渡します。このエンジンは、ほかには存在しない組み合わせを提供します。Model Context Protocol サーバーを通じて、エージェントは正規エンティティ(LG_001_01_ORFICHE ではなく、orders)を、レポートと同じ読み取り専用ガードと監査証跡を通して利用します。厳格モードでは、ガードが名前を認識できないすべての関数をデフォルトで拒否し、すべてのデータ結果を信頼できない入力として扱います。

pipx install "erp-report-engine[mcp]"
erp-report-engine mcp -c config.yaml          # stdio server

6 つのツールが、すべてガード付きの経路を通じて動作します。

ツールエージェントが得られるもの
describe_model正規のセマンティックレイヤー。各エンティティの粒度と、各列の型およびその意味(例:出荷されるまで actual_ship_date は NULL なので、出荷が遅れている未出荷の注文は納期遵守率に影響しません)に加え、実行可能なクエリ例も得られます。単なる名前ではなく意味がわかるため、エージェントが正確なテキストから SQL への変換を行えます。生の ERP テーブル名は含まれません
weekly_reportKPI の詳細な報告。調査結果、データ品質ゲート、照合、SQL 監査証跡が含まれます
reconcileエンティティごとに、取得した行と独立した COUNT(*) を比較し、信頼性の判定を行います
aging売掛金のエイジング分析。延滞日数の区分別未回収残高、延滞率、延滞額が最も多い顧客(集計のみ)を示します
check_querySQL 文を実行せずに、ガードを通過するかどうかを確認します
query読み取り専用の SELECT/WITH を、上限を設けて監査しながら実行します。返される行は信頼できないデータとして扱われます

正規モデルは機械可読な仕様としても公開されています。[model.json](https://gulmezeren2-byte.github.io/erp-report-engine/model.json) または erp-report-engine schema を使えば、接続せずにエンティティ、列の型、意味、クエリ例をツールから読み取れます。CI はコードから仕様を再生成し、差異があれば失敗するため、仕様にエンジンが保持する以上の内容が記載されることはありません。

ファーストパーティの**[エージェントスキルパック](https://github.com/gulmezeren2-byte/erp-report-engine/tree/main/skills)**(`erp-safe-query`、`explain-kpi-move`、`write-erp-profile`)は、この粒度に*沿って*作業する方法をエージェントに教えます。クエリ前にドライランを行う、行をそのまま出力するのではなく集計する、監査済みの数値を引用する、ERP 内のテキストをコマンドとして扱わない、といった方法です。

ERP も設定も不要。1 行で試せます — 同梱のデモデータベースでガード付き MCP を起動します。

erp-report-engine mcp --demo        # or: docker run --rm -i erp-report-engine

次に、Claude Desktop(または任意の MCP クライアント)から接続します。

{ "mcpServers": { "erp": { "command": "erp-report-engine", "args": ["mcp", "-c", "C:\\path\\config.yaml"] } } }

Claude Code プラグインとしてインストールすることもできます — ガード付き MCP サーバー、安全なクエリのスキル、設定不要の /trust-benchmark および /erp-schema コマンドを、2 行でインストールできます。

/plugin marketplace add gulmezeren2-byte/erp-report-engine
/plugin install erp-report-engine

サーバーは uvx 経由で起動するため(手動インストール不要)、プロジェクトの erp-config.yaml を読み込みます。データベースを接続する前でも、スキルとベンチマーク/スキーマコマンドはすぐに使えます。(詳細は[.claude-plugin/](https://github.com/gulmezeren2-byte/erp-report-engine/tree/main/.claude-plugin) を参照してください。)

エージェントは書き込みできません。ガードは、認識する関数だけを呼び出す単一の読み取りクエリ以外を拒否し、セッションは読み取り専用です。また、2025 年に発生した MCP のデータ流出インシデントを踏まえ、返される値にはすべて、行はデータであり指示ではないことを示す注記が付いています。確認できる限り、これは SQL レベルのガードを備えた初の ERP MCP サーバーであり、Logo Tiger 向けとしても初です。トルコのデータやドメイン向け MCP サーバーを厳選してまとめた[awesome-turkish-mcp](https://github.com/gulmezeren2-byte/awesome-turkish-mcp) に掲載されています。

これは行わないこと

宣伝より誠実さを大切にしています。本番環境に適用する前に、限界を把握しておいてください。

  • ここでの納期遵守は、OTIF-liteです。 注文単位で shipped ≤ promised を評価します。真のOTIFには明細行単位の受領データが必要ですが、ほとんどのERP注文テーブルには含まれていません。そのため、レポートでは「納期どおりの出荷」と表記し、フッターにその理由を記載しています。
  • 納期遵守の評価対象は出荷済みの注文のみです。この方向性には危険があります。 遅延していて、まだ出荷されていない注文には actual_ship_date がないため、分子にも分母にも含まれず、指標を一切下げません。行き着くところ、フルフィルメントが崩壊するほど、納期遵守率は上昇します。最悪の注文がサンプルから除外されるためです。注文テーブルにあるデータだけではエンジンでこれを解決できないため、割合では見えない数を集計し、カードと独立した所見に「今週出荷予定だったものの、まだ出荷されていない注文はN件です」と表示します。この2つをあわせて読むか、割合を読まないでください。
  • サンプル数が少ない場合、納期遵守率の変動は断定しません。 2件中1件から2件中2件への変化は「+50ポイント」ですが、それを平然と報告すれば、レポートへの信頼を失います。評価対象の配送が5件未満の場合、変動は表示しますが、明示的に断定を避けます。
  • 所見は手がかりであり、断定ではありません。 「要因:エーゲ地方、変動の111%」は、最初に調べるべき場所を示しています。なぜそうなったかまでは示しません。それを分析するのがアナリストの仕事です(あなたの仕事です)。
  • Logo Tigerプロファイルはフィールドマッピングであり、認定済みの連携機能ではありません。 Logoのスキーマはバージョンやローカライズによって異なります。プロファイルのフィールド注記には、確認が必要な項目を記載しています。
  • 進行中の週はグラフに表示しません。 傾向の表示は、最後に完了したISO週までです。月曜朝に「急落」と見えたものが、実際にはまだ2日分しかない週だった、ということが続けば、ダッシュボードへの信頼が失われるためです。
  • これは週次ブリーフィングであり、BIプラットフォームではありません。 ドリルダウン、リアルタイム表示、ユーザー管理には対応していません。機能は1つです。根拠とともに、月曜のレポートを自動作成します。

設計上の判断

なぜLLMではなく、ルールベースの所見なのですか? 決定論性のためです。同じデータベースの状態からは常に同じレポートが生成され、ERPのそばでエアギャップ環境でも実行できます。また、レポート内の数値は必ず監査証跡のSQL文までたどれます。再計算できないものは生成されません。

なぜ自己完結型のHTMLファイルなのですか? インフラが不要だからです。SVGグラフとCSSをインラインで埋め込み、CDNもトラッキングも使いません。Outlookのブラウザープレビューでも、スマートフォンでも、ファイル共有からでも、10年後でも表示できます。

なぜ行数を照合するのですか? 「DataFrameに494行ある」と「ソースクエリが494行を返す」は別の主張だからです。無人で動作するシステムは、自らの入力を監査しなければなりません。各エンティティを独立した COUNT(*) で再カウントし、不一致があれば、誰かがKPIを信頼する前に赤字で警告します。

テスト

pip install pytest && python -m pytest tests/ -v

テストスイートでは、読み取り専用ガード(多数のインジェクション試行)、プロファイルのコントラクト、カレンダーのコア機能(単体テストとプロパティベーステスト)、レンダリング時のエスケープ、誠実さに関する修正、CLIの終了コード、MCPツール、SPCシグナル、配送ルーティング、エンドツーエンドの完全な実行に加え、Power BI PBIPの整合性(エクスポーターのキー、途切れのない週序数、ビジュアルの重なりの検出、各ビジュアルのフィールドがすべてモデルに存在すること)を網羅しています。CIではさらに ruff を実行し、Python 3.10~3.13でPBIRジェネレーターのドリフトがあれば失敗します。

ロードマップ

リリース済み:ガード機能付きMCPサーバーとファーストパーティのエージェントスキルパック、オプションのLLMによる説明レイヤー(集計データのみを扱い、設計上、誠実さを保ちます)、SPC/XmR異常検知レイヤー、ネイティブな配信機能(SMTP/Slack/Teams/healthchecks)とPower Automateパイプライン、宣言型プロファイルコントラクト、実際のトルコ製ERP向けプロファイル3種類(Logo Tiger、Netsis、Mikro)—それぞれオプションで**売掛金年齢分析(cari yaşlandırma)**に対応—、売上集中度分析(上位3社のシェア+HHI)、DAX SVGマイクロチャート、スキーマ検証済みのダークPower BIテーマ。次の予定:

  • PyPIでのpip install erp-report-engineとDockerイメージ
  • ERPプロファイルの追加(SAP Business One、Odoo、汎用ODBCテンプレート)
  • 残高繰越型の元帳(Netsis / Mikro)向けの正確なFIFO未決済項目年齢分析。これにより、未決済項目の照合が設定されていなくても、売掛金の年齢分析を正確に行えます

測定の誠実さシリーズの一部

業務の実態を正直に伝えるツール、Eren Gülmezによる:

  • otif-analytics — 「報告値98%」から「OTIF 59%」へ至る5段階の指標ラダー
  • forecast-accuracy-lab — WMAPEとMAPEの比較、そしてゼロの除外が予測を実態以上によく見せる理由
  • opsaudit — 取り除けない誠実性ブロックを備えた運用指標CLI
  • auto-report-pipeline — このエンジンのCSVを入力とする小さな姉妹プロジェクト
  • forecast-autoresearch — 封印されたホールドアウトデータに対して予測を改善するエージェント

ライセンス

MIT © Eren Gülmez

コメント

MCP は初めてですか?

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

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