把 ERP 變成 AI 的執行單元:iDempiere OData × MCP Server 整合策略

重點摘要(TL;DR)

  • iDempiere(開源 ERP)的 REST/OData API 包裝成 MCP server,任何支援 MCP 的 AI 工具(Claude / ChatGPT / Cursor / Claude Code / VS Code)都能直接呼叫 ERP。
  • Microsoft 已經做了 Dynamics 365 ERP MCP server(2026/4 文件更新),三類工具設計:Data tools(OData CRUD)、Form tools(模擬使用者操作)、Action tools(直接呼叫 business class)。這個設計可以直接借鏡到 iDempiere
  • iDempiere REST 已經提供 api/v1/auth(JWT)、api/v1/models(OData CRUD)、api/v1/windowsapi/v1/processes 四類 endpoint — 剛好對應 Microsoft 的三類工具
  • 整合到腦子系統:LLM Gateway + MCP Server 雙軌設計,Gateway 管 LLM 流量,MCP 管 ERP tool calls,各自有 audit log,iDempiere 內建的 AD_Role 直接當權限層,不用自寫 ABAC。
  • 本文是腦子系統四部曲的第五篇延伸(ERP 整合層)。前四篇:Why / How / Scale / Tools

一、為什麼 iDempiere OData 是腦子系統缺的拼圖

前四篇文章把 AI 治理系統蓋好了:LLM Gateway、雙引擎、Harness、Chat-native Agent。但有個關鍵問題沒解決 — AI 怎麼安全地讀寫公司的真實業務資料?

大部分公司現況:業務資料躺在 ERP 裡,AI 透過 prompt 拿不到;或者員工自己貼資料給 AI(踩到 A 級資料禁令)。第一篇的核心哲學「AI 時代不做 UI,做給 AI 安全取資料的入口」需要一個具體載體。

iDempiere(開源 ERP)的 REST/OData API 剛好就是這個載體 — 它本來就是「給機器讀的標準介面」,而且整套權限、Audit、租戶隔離都已經 30 年累積在 iDempiere 的 AD(Application Dictionary)裡。不用重新造輪子,直接接到 AI

二、事實核對:iDempiere REST API 真實狀態(2026/5)

本文涉及的 iDempiere 技術細節都來自官方來源,以下是 2026/5 撰文時的驗證結果:

事實 驗證來源
REST plugin 由 BX Service GmbH 維護,GPLv2,used in production iDempiere Wiki
支援 iDempiere release 12 及 master,plugin 已運作於 v9/v10 GitHub Repo
官方文件站 idempiere-rest-docs
Swagger UI 互動式 API 探索 hengsin/idempiere-rest-swagger-ui

2.1 四個主要 API 端點

  • POST/PUT api/v1/auth/tokens — JWT 認證(token 1 小時有效)
  • api/v1/models/{tableName} — PO(Persistent Object)CRUD,支援 OData filter
  • api/v1/windows/{windowSlug}/tabs/{tabSlug} — Window/Tab 互動(對應 ERP UI 的視窗結構)
  • api/v1/processes/{processSlug} — Process 呼叫(DocAction、報表、自動化流程)

以及附加端點:檔案存取、Reference 資料、Cache 管理、Workflow、Scheduler 資訊。[來源]

三、業界典範:Microsoft Dynamics 365 ERP MCP Server

Microsoft 在 2026/4/27 發表了 Dynamics 365 Finance & Operations 的 MCP server 完整文件 — Microsoft Learn這是目前業界最完整的 ERP × AI 整合範例,值得借鏡。

3.1 Microsoft 的三類工具設計

類別 用途 代表工具(Microsoft)
Data tools OData CRUD operations data_find_entities、data_create_entities、data_update_entities、data_delete_entities
Form tools 模擬使用者在 UI 上的操作(點按鈕、填表、開分頁) form_click_control、form_set_control_values、form_save_form
Action tools 直接呼叫 ERP 內部 business logic class api_find_actions、api_invoke_action

3.2 三個關鍵設計原則(直接可借鏡)

  1. 動態 context:MCP server 每次 tool call 都根據 agent 安全角色和環境配置「動態」回傳 context — 「the security role of the authenticated user for the agent determines which objects are returned in the view model」(原文)
  2. 角色限制 = scope 限制:Agent 只看到自己角色能存取的 menu / entities / API,既是安全也是 prompt 效率(context 不會塞太多無關資訊)
  3. Allowed MCP Clients:Microsoft 預設只允許 Copilot Studio 和 VS Code 兩個 client ID 存取 MCP,其他 agent platform 必須在 Microsoft Entra ID 註冊後加入白名單 — 不是「誰來都能接」

四、把這個設計搬到 iDempiere

關鍵 insight:iDempiere REST 的四個 endpoint,剛好對應 Microsoft 的三類工具設計,直接 mapping:

Microsoft 三分類 iDempiere REST 對應 endpoint 說明
Data tools api/v1/models/{table} PO CRUD + OData filter,直接套
Form tools api/v1/windows/{slug}/tabs/{slug} Window/Tab 結構,可模擬「打開視窗、切分頁、設欄位」
Action tools api/v1/processes/{slug} Process 呼叫(DocAction、報表、自動化)

結論:你不用設計 MCP server 的工具分類,直接複製 Microsoft 的三分類,把 iDempiere REST 端點包裝進去即可。

五、MCP 是什麼,為什麼是關鍵

Model Context Protocol 是 Anthropic 2024/11 發布的開源協議,定義 AI 應用怎麼跟外部資料來源、工具、工作流溝通。官方比喻:「USB-C port for AI applications」。[來源]

5.1 為什麼是 ERP × AI 的關鍵

  • 標準協議,一次寫多處用:同一個 MCP server 可以同時被 Claude Desktop / Claude Code / Cursor / VS Code / ChatGPT 接([來源])
  • 不是 prompt engineering 的小聰明,是基礎建設層
  • 已成 industry standard:Anthropic / OpenAI / Microsoft 都採納

5.2 寫 MCP server 的工具(2026/5 驗證)

  • Python SDK:modelcontextprotocol/python-sdk v1.x stable(v2 pre-alpha 開發中)
  • 安裝:uv add "mcp[cli]"pip install "mcp[cli]"
  • Transport:stdio、SSE、Streamable HTTP 三種
  • 認證:OAuth 2.1 resource server 標準

六、實作範例:iDempiere MCP server v0

下面是用 FastMCP + httpx 實作的最小可行版本,展示三類工具的骨架。注意:這是教學範例,production 版需要加上錯誤處理、重試、token refresh、審計 log 等。

# idempiere_mcp_server.py
from mcp.server.fastmcp import FastMCP
import httpx
from typing import Optional

mcp = FastMCP("iDempiere-MCP")
IDEMPIERE_BASE = "https://idempiere.example.com/api/v1"

# ───────── Auth ─────────
@mcp.tool()
async def authenticate(
    username: str,
    password: str,
    client_id: int,
    role_id: int,
    organization_id: int = 0,
    warehouse_id: int = 0,
    language: str = "en_US"
) -> dict:
    """One-shot authentication with all parameters.
    Returns session token valid for 1 hour."""
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{IDEMPIERE_BASE}/auth/tokens",
            json={
                "userName": username,
                "password": password,
                "parameters": {
                    "clientId": client_id,
                    "roleId": role_id,
                    "organizationId": organization_id,
                    "warehouseId": warehouse_id,
                    "language": language,
                }
            }
        )
        resp.raise_for_status()
    return resp.json()

# ───────── Data Tools (OData CRUD) ─────────
@mcp.tool()
async def query_records(
    token: str,
    table_name: str,
    filter_expr: Optional[str] = None,
    top: int = 50
) -> dict:
    """Query iDempiere PO records via OData.

    Filter examples (note iDempiere uses 'neq' not 'ne'):
      - "IsCustomer eq true and contains(Name, 'Acme')"
      - "Created gt 2026-04-01T00:00:00Z"
    """
    params = {"$top": top}
    if filter_expr:
        params["$filter"] = filter_expr
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            f"{IDEMPIERE_BASE}/models/{table_name}",
            params=params,
            headers={"Authorization": f"Bearer {token}"}
        )
        resp.raise_for_status()
    return resp.json()

@mcp.tool()
async def create_record(token: str, table_name: str, data: dict) -> dict:
    """Create a PO record. Caller must include all mandatory fields.
    Tip: query AD_Column WHERE IsMandatory='Y' to discover them first."""
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{IDEMPIERE_BASE}/models/{table_name}",
            json=data,
            headers={"Authorization": f"Bearer {token}"}
        )
        resp.raise_for_status()
    return resp.json()

# ───────── Action Tools (Process call) ─────────
@mcp.tool()
async def run_process(
    token: str,
    process_slug: str,
    parameters: dict
) -> dict:
    """Execute an iDempiere Process (e.g. DocAction, scheduled job, report).

    Parameters must be FLAT top-level keys, NOT a 'parameters' array:
      Correct:  {"StatementYear": 2026, "StatementPeriod": "2"}
      Wrong:    {"parameters": [{"parameterName": ..., "value": ...}]}
    """
    async with httpx.AsyncClient() as client:
        resp = await client.post(
            f"{IDEMPIERE_BASE}/processes/{process_slug}",
            json=parameters,
            headers={"Authorization": f"Bearer {token}"}
        )
        resp.raise_for_status()
    return resp.json()

if __name__ == "__main__":
    mcp.run(transport="streamable-http")

這支 script 跑起來後,任何支援 MCP 的 client(Claude Desktop / Claude Code / Cursor / VS Code)都可以連到 http://localhost:8000 並使用上述工具。

6.1 範例對話(架構驗證)

員工(在 chat 工具中):
  「幫我查最近 10 筆訂單金額大於 100 萬的客戶」

AI agent(透過 MCP 自動執行):
  1. authenticate(...) → 拿到 session token
  2. query_records(
       token=...,
       table_name="C_Order",
       filter_expr="GrandTotal gt 1000000",
       top=10
     )
  3. 解析結果,回給員工

員工看到:
  「最近 10 筆大於 100 萬的訂單列表如下:...」

注意:第 1 步的 authenticate 只執行一次,session token 1 小時有效,後續 query 都用同一個 token。

七、整合進腦子系統:雙軌架構

員工 chat app (LINE / Mattermost / Telegram / Slack)
    ↓
Chat-native Agent (QwenPaw) 或 Coding Agent (Claude Code)
    │
    ├─ LLM 流量 ───→ 公司 LLM Gateway (LiteLLM + Portkey)
    │                ├─ 分級/脫敏/路由
    │                └─ → 雲端 frontier 或本地 Ollama
    │
    └─ Tool calls ─→ iDempiere MCP Server (自製)
                      ├─ OAuth 2.1 / Allowed Clients 白名單
                      ├─ Data tools (OData CRUD)
                      ├─ Form tools (Window/Tab 互動)
                      ├─ Action tools (Process call)
                      └─ Audit log → SIEM
                      ↓
                  iDempiere REST API (api/v1/*)
                      ↓ (內建 AD_Role 過濾)
                  iDempiere PostgreSQL

關鍵設計:

  • LLM Gateway 跟 MCP Server 是兩條平行軌道:Gateway 管 prompt,MCP 管 tool calls。兩者都要 audit log,可獨立縱深防禦
  • 權限不重複設計:iDempiere 內建 AD_Role 直接當權限層,MCP server 帶 user 的 token 進去,iDempiere 自動套 role 過濾資料 — 不用自寫 ABAC 規則
  • Allowed MCP Clients 白名單:借鏡 Microsoft 設計,只允許特定 agent platform 接 MCP server,不是「誰來都能接」

八、權限層的對應(這是最大紅利)

員工從 chat app 問問題時的完整權限路徑:

1. 員工 LINE/Slack ID → Agent 認 ALLOWED_USERS 白名單
2. Agent → MCP Server,帶員工的 iDempiere session token
3. MCP Server → iDempiere REST,帶 token
4. iDempiere 自動套員工的 AD_Role 過濾資料:
   - 業務員角色 → 只看自己的 SalesRep 訂單
   - CFO 角色 → 看全公司
   - RD 角色 → 完全看不到業務資料
5. 回應只含「員工角色應該看到」的資料

iDempiere 30 年累積的 AD_Role / AD_Window_Access / AD_Column 權限設計直接拿來用。這比自己在 Gateway 寫 ABAC 簡單一個量級

九、為什麼這比 Dynamics 365 / NetSuite MCP server 適合中小規模製造業

特性 Dynamics 365 ERP MCP iDempiere + 自製 MCP
License Microsoft 訂閱 + Copilot 點數 GPLv2 開源
Hosting Cloud only(Tier 2+) self-host / air-gapped 可
Tool 計費 0.1 Copilot Credits per tool call(非 Copilot Studio 環境) 0(自架)
A 級資料 需透過 Cloud,法規場景受限 完全本地處理
客製化 透過 ICustomAPI + AI tool framework 直接改 plugin / 加 process

對製造業中小集團、要 air-gapped 的法規場景、預算有限的公司:iDempiere + 自製 MCP server 是唯一既可離線又能整合 AI 的開源路徑

十、工程藍圖:漸進式 v0 → v1 → v2

v0:Read-only Data Tools(2-4 週,1 RD)

  • 實作 authenticate + query_records(本文範例)
  • 支援 5-10 個常用 table:C_BPartner、C_Order、M_Product、M_InOut、M_Movement、AD_User、R_Request 等
  • OData filter 支援 eq / neq / contains / gt / lt
  • 串接 Claude Desktop 或 Claude Code 測試

v1:加入 Action Tools(2-4 週)

  • 實作 run_process(DocAction、報表、自動化)
  • 實作 create_record / update_record(POST/PUT)
  • 處理 mandatory field 偵測(自動查 AD_Column WHERE IsMandatory=’Y’)
  • token 自動 refresh(1 小時過期)
  • 串接公司 LLM Gateway,流量都過 audit

v2:Form Tools + 進階 Window 互動(4-8 週)

  • 包裝 api/v1/windows/{slug}/tabs/{slug}
  • 讓 AI 模擬「打開視窗、切分頁、設欄位、按按鈕」
  • 處理複雜流程(發票核銷、應收沖帳等)
  • 整合 Allowed MCP Clients 白名單機制

對中小企業:v0 可能就夠用 80%。對中大型集團:v0 → v1 → v2 漸進式投資,12-16 週完整版可上線。

十一、結語:把 AI 變成 ERP 的執行單元

前四篇腦子系統的 AI 仍然是「跟業務資料分開的工具」 — 員工問問題,AI 回答。

加上 iDempiere MCP Server,AI 變成能直接動 ERP 的執行單元:查訂單、開請款單、跑 process、生報表。員工從 chat app 一句話完成原本要打開 ERP 點 5 個選單的工作。

這才是「AI 時代不做 UI,做給 AI 安全取資料的入口」的真實落地。RD 不再被 UI 工單吃掉,而 80% 不寫 code 的員工終於能用一句中文操作 ERP。

對企業 IT 主管的具體下一步:

  1. 裝 bxservice/idempiere-rest plugin 到既有 iDempiere(若還沒)
  2. 用 Postman 測 4 個主要 endpoint(repo 內有 collection)
  3. 用本文 v0 範例寫 MCP server,跑在開發機 localhost
  4. 掛到 Claude Desktop / Claude Code 試用,驗證權限層運作
  5. 確認可用後,搬上公司內網,接入 LLM Gateway

延伸閱讀:腦子系統四部曲 + 本篇

可運作的 Reference Links(2026/5 撰文時驗證)

iDempiere 官方資源

MCP 官方資源

業界 ERP MCP server 參考

OData 標準

留言

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *