Odoo MCP

io.github.ebmurha由 GitHub 帳號 ebmurha 發布v0.3.0更新於 Oct 25, 2026

Workflow-native MCP server for safe Odoo Enterprise back-office operations

概覽

AI 產生的概覽

本機 MCP 伺服器,讓助理以受控、依公司限定的方式存取 Odoo Enterprise 的會計與薪資資料,寫入預設僅預覽。

可以做什麼
讀取會計報表:試算表、損益表、資產負債表、應收應付帳齡、現金簿、匯率歷史、未結發票與帳單、日記帳分錄,以及未匹配的銀行對帳單行,並產生 Markdown 產物與稽核紀錄。預覽或建立草稿會計紀錄:客戶發票、供應商帳單、貸項通知單、平衡的日記帳分錄,以及透過 Odoo 標準精靈登記付款,需明確執行並提供冪等鍵。檢視薪資證據:期間、批次、薪資單、薪資規則、員工薪資脈絡、出勤彙總、期間比較、異常偵測與核准包。預覽或套用受控的草稿薪資輸入
適用情境
當助理需要讀取或準備 Odoo Enterprise 後台工作時適用:財務報表、應收應付審查、銀行對帳建議、草稿發票與日記帳分錄,或薪資證據的審查與比較。適合使用 Odoo.sh 或自架 Odoo 18、19 的營運者,希望取得受控且有稽核的存取,而非通用模型增刪改查。
執行需求
本機 Python 3.11 以上執行環境,搭配 uv 或 pipx(PyPI 套件 odoo-erp-mcp,指令為 odoo-mcp),使用 stdio 傳輸。需要受支援的 Odoo.sh 或自架 Odoo Enterprise 18 或 19 部署。必要環境變數:ODOO_MCP_ODOO_URL、ODOO_MCP_ODOO_DATABASE、ODOO_MCP_ODOO_USERNAME、ODOO_MCP_ODOO_API_KEY、ODOO_MCP_ALLOWED_COMPANY_IDS、ODOO_MCP_DEFAULT_COMPANY_ID。需要專用的 Odoo 技術使用者與權限對應設定檔。遠端設定另需 bearer JWT 相關設定與簽章
安裝前請注意
它持有 Odoo API 金鑰(ODOO_MCP_ODOO_API_KEY),在明確啟用執行後可建立草稿發票、帳單、貸項通知單、日記帳分錄並登記付款;應使用權限最小的專用非生產技術使用者。付款登記可能產生伺服器標示為未知的外部影響。人工確認由 MCP 用戶端負責,伺服器不會最終完成對帳或薪資。本機狀態、稽核鏈與加密金鑰保存在磁碟上;

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Odoo MCP,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。

其他 MCP 客戶端

參照 儲存庫 中的啟動說明。

README

Odoo MCP

odoo-mcp is a workflow-native MCP server for Odoo Enterprise. It exposes read-only capability discovery, trial-balance reporting, aged receivables and payables reporting, cashbook visibility, unmatched bank-line detection, and proposal-only bank reconciliation. It also exposes bounded, read-only Payroll evidence for exact periods, batches, payslips, employees, salary rules, and payroll work entries, plus deterministic Payroll comparison and anomaly review.

The initial accounting release also supports bounded invoice, supplier-bill, credit-note, payment-registration, and manual-journal workflows. Mutating tools are preview-only by default and require explicit execution plus idempotency.

The internal Odoo adapter provides bounded, typed, company-scoped primitives for the accounting and Payroll workflows. It enforces fixed model/action allowlists, strips denied fields, normalizes dates, decimals, relations, and cursor pages, and translates Odoo authentication, permission, and transport failures into safe errors. It does not expose generic CRUD or an Odoo configuration surface.

Supported connection targets are Odoo.sh and self-hosted Odoo Enterprise:

  • Odoo 18 through external JSON-RPC
  • Odoo 19 through JSON-2

Other Odoo versions, Odoo Online, Community edition, and custom forks are not supported. This package is not an Odoo module and does not expose generic model CRUD.

Installation

The product and commands are named odoo-mcp; the PyPI distribution is odoo-erp-mcp because the odoo-mcp distribution name is owned by another project.

bash
pipx install odoo-erp-mcpodoo-mcp --help

The package also exposes odoo-erp-mcp as a compatibility launcher for MCP Registry clients. It starts the same server as odoo-mcp.

Local Development

Requires Python 3.11 or newer and uv.

powershell
Copy-Item .env.example .env.local# Replace the placeholders in .env.local, then:uv sync --locked --all-extrasuv run odoo-mcp --profile local --config config/config.example.yaml

Local Development uses stdio. Process-environment settings take precedence over .env.local. Never commit .env.local.

Remote profiles

Dedicated Remote and Shared Hosted use the same server, registry, workflow, and Odoo adapter as Local Development, exposed through Streamable HTTP:

powershell
uv run odoo-mcp --profile dedicated --host 127.0.0.1 --port 8000uv run odoo-mcp --profile shared --host 127.0.0.1 --port 8000

Dedicated Remote reads its single Odoo connection from the process environment; it never loads .env.local. Every /mcp request must carry a deployment-issued HS256 bearer JWT. The server validates its signature, fixed issuer, fixed audience, expiry, issued-at time, subject, and client ID before MCP routing; permissions and company grants remain server-owned. Configure ODOO_MCP_AUTH_ISSUER, ODOO_MCP_AUTH_AUDIENCE, and a secret-store supplied ODOO_MCP_AUTH_SIGNING_KEY of at least 32 characters.

Shared Hosted is a runnable open-enrollment application in the same image. It serves OAuth discovery, dynamic client registration, authorization, token, revocation, browser enrollment, protected-resource metadata, and MCP routes. The application verifies each Odoo connection, lets the user select from the companies that Odoo returned, stores the credential encrypted, and binds every token to exactly one active connector. Configure it from .env.shared.example; its versioned 256-bit encryption keys must come from an operator-controlled secret store. Missing configuration, invalid ciphertext, inactive grants, unsafe Odoo destinations, and unauthorized connector bindings fail closed. Shared Hosted supports either one writable process with a durable local SQLite volume or qualified PostgreSQL with pooled runtime and direct migration connections. TLS, public ingress, monitoring, and production deployment remain operator responsibilities.

Reproducible Dedicated Remote Docker and systemd templates, Shared Hosted integration requirements, and network hardening guidance are in docs/deployment.md. Do not expose the example HTTP listener directly to the public internet.

Durable state

odoo_mcp.storage.Storage provides ordered SQLite and PostgreSQL migrations and tenant-scoped repositories for audit records, proposals, artifacts, idempotency reservations, capability snapshots, and encrypted Shared Hosted connections. Audit rows are append-only and SHA-256 hash-chained per tenant. Idempotency reservations bind the tenant, company, tool, key, and request payload for 24-hour replay, while in-progress and unknown outcomes remain blocked for explicit recovery. Final outcomes must retain a replayable response and match the reserving company. Audit failure text is derived from registered error codes; free-form upstream error text is not persisted.

SQLite backups use a consistent snapshot. Restore writes to a new destination and is accepted only after database integrity, migrations, tenant audit chains, idempotency state, capability data, and encrypted connections verify. Encryption keys must be backed up and restored separately. PostgreSQL uses database-level migration serialization and preserves the same repository, OAuth, audit, idempotency, encryption, and lifecycle contracts.

The server stores local durable state at .odoo-mcp/state.sqlite3 by default. Use --storage <path> to select a different SQLite file. Successful accounting reports atomically persist their Markdown artifact and a compact audit outcome; failed and denied report calls persist a secret-safe failure audit when an isolation identity has been resolved.

Write safety

odoo_mcp.policy.WriteSafetyCoordinator is the required boundary for write-capable workflows. It enforces registry risk metadata, resolved identity, permission, company, and capability gates before workflow preparation. Calls default to preview-only behavior. Execution requires explicit dry_run: false and a non-empty idempotency key, then reserves that key and appends the attempt audit before fresh-state validation and the Odoo mutation.

Successful, rejected, conflicting, replayed, known-failed, and unknown outcomes remain distinct and replay-safe across restart. An uncertain mutation is never automatically retried; if outcome persistence fails after a possible mutation, the in-progress reservation continues to block duplicate execution. Odoo permission denials that prove no mutation occurred remain structured known failures. Audit and response text suppress raw exception details.

Human confirmation belongs to the MCP client host. The server does not issue approval tokens, provide an approval UI, or automatically turn a preview into execution. Reconciliation calls default to preview. An explicit dry_run: false call with an idempotency key stores a server-owned proposal and Markdown artifact, but never finalizes reconciliation or changes a bank statement line in Odoo.

Configuration

Local and Dedicated Odoo settings are documented in .env.example; Shared Hosted operator settings are documented in .env.shared.example. Do not configure an Odoo version: the adapter detects it and fails explicitly for unsupported or malformed responses. config/config.example.yaml is the safe MCP permission-map example and enables the current read tools. A tool is authorized only when it is listed under its registry-defined permission; unknown or mismatched entries prevent startup.

Use a dedicated non-production Odoo technical user with only the required company and module access. Company IDs are an additional MCP authorization boundary and never expand the technical user's Odoo permissions.

Accounting workflows

  • get_currency_rate_history returns the selected company's Odoo rate history for one exact currency, preserving company-over-shared precedence and both rate directions without performing conversions.
  • get_trial_balance returns posted opening balances, inclusive-period debit and credit movement, closing balances, totals, and a Markdown artifact.
  • get_profit_and_loss classifies posted lines by Odoo's income and expense account types for an inclusive period. Income uses credit-minus-debit, expenses use debit-minus-credit, and net profit is income minus expenses.
  • get_balance_sheet classifies posted lines by Odoo's asset, liability, and equity account types through an inclusive date. It reports unclosed earnings separately within total equity and verifies the accounting equation at company-currency precision.
  • get_aged_receivables and get_aged_payables reconstruct posted residuals as of a date, including later partial reconciliations, and group them into not-yet-due, 1–30, 31–60, 61–90, and 90+ day buckets.
  • get_cashbook returns posted move lines from cash and bank journals with opening balance, period debit and credit, and closing balance.
  • flag_unmatched_statement_lines identifies unreconciled statement lines without one unique eligible match at or above the requested threshold.
  • reconcile_bank_statement_lines scores exact one-to-one candidates by amount, partner, normalized reference, and date proximity. Ties and candidate reuse remain explicit unmatched results. The tool can persist a proposal locally; it does not perform Odoo reconciliation.
  • list_open_invoices and list_open_bills reconstruct record- and company-currency residuals as of a date, including later partial reconciliations.
  • create_customer_invoice and create_supplier_bill provide non-mutating, input-only previews by default. Explicit execution creates one unposted draft and reads back Odoo's effective accounting results.
  • create_credit_note creates one linked full draft reversal. Before posting, validate_invoice reports locally determinable balance, currency, account, total, and tax blockers while explicitly deferring Odoo-only posting checks.
  • register_payment delegates route discovery and execution to Odoo's standard payment-registration wizard. Preview may create bounded ephemeral wizard records but never executes a payment or alters accounting records. Non-manual or unidentified methods report their possible external effect as unknown. Execution requires an idempotency key and a freshly revalidated wizard route.
  • list_journal_entries returns filtered draft and posted manual entries with bounded line details and opaque continuation cursors. create_journal_entry creates only a balanced draft, while the separate post_journal_entry tool revalidates and posts one existing draft after explicit execution.

Report results are deterministically ordered and cursor-paginated with a default limit of 100 and maximum of 500. Empty data is a successful empty report; upstream denial, timeout, malformed data, or partial retrieval is a structured failure rather than an empty result. Paginated Markdown artifacts label the row range, continuation state, and whole-report totals explicitly.

Profit-and-loss and balance-sheet analytic filters apply Odoo's percentage distribution to exact analytic account IDs. These reports do not infer custom chart-of-accounts groups, fiscal-year closing rules, consolidation, eliminations, or localization-specific report layouts. Unsupported account classifications fail explicitly instead of being guessed.

Payroll evidence workflows

  • list_payroll_periods lists exact date pairs observed on company-scoped payslips, with bounded status, batch, and currency evidence.
  • get_payroll_batch returns one exact batch, compact payslips, complete employee and state counts, and currency-partitioned observed rule/category totals.
  • list_payslips lists compact payslip facts for an exact batch, exact period, or both. get_payslip returns one exact payslip with all bounded calculated lines, worked days, and one-off inputs.
  • get_employee_payroll_context returns only the employee and contract/version evidence applicable to an exact period.
  • list_salary_rules reports rule metadata observed on eligible payslip lines; it is not a Payroll configuration catalogue.
  • get_attendance_summary summarizes Payroll work entries by employee, type, code, and state. It does not read raw attendance or claim proof of physical attendance.
  • compare_payroll_periods compares exact employee sets, contract facts, work-entry hours, and currency-partitioned observed line, rule, and category totals across two non-overlapping periods.
  • analyze_employee_payroll_change separates directly observed changes from correlations and unresolved causes for one exact employee.
  • detect_payroll_anomalies applies fixed public percentage thresholds and an optional request-time modified-z-score check. It does not learn or retain a customer baseline; its source-linked Markdown summary is returned inline and is not stored as an artifact. The percentage thresholds are 5% (strict), 10% (standard), and 20% (relaxed). Statistical checks require six comparable history values and an absolute modified z-score of at least 3.5; fewer values or a zero median absolute deviation is reported as unavailable.
  • explain_payslip organizes Odoo-returned line arithmetic, categories, worked-day evidence, and contract context without evaluating salary-rule code or reproducing gross-to-net calculation.
  • prepare_payroll_approval_pack returns one request-time JSON and inline Markdown review pack with source-linked totals, optional prior-period variance, anomalies, exceptions, limitations, recommended human review actions, and a sign-off checklist. It neither approves payroll nor creates a durable pack or workflow record.

These evidence tools require payroll_read and the accessible Odoo Payroll capability. They are read-only, use request-bound pagination, return Odoo source IDs, and store only non-sensitive invocation metadata in the audit chain. Payroll responses are not persisted as artifacts, proposals, idempotency records, or workflow state. Monetary comparisons never combine or convert currencies; recognized BASIC, GROSS, and NET totals require those exact Odoo rule codes, and employer cost remains explicitly unavailable.

Controlled draft Payroll writes

  • set_draft_payroll_input previews or explicitly creates or updates one eligible one-off input on one editable payslip.
  • remove_draft_payroll_input previews or explicitly removes one exact, eligible one-off input.
  • recalculate_draft_payslip separately invokes Odoo's standard payslip calculation and returns fresh payslip evidence.

These tools require payroll_draft_write and the accessible Odoo Payroll capability. Every call defaults to a mutation-free preview. Execution requires dry_run: false and a non-empty idempotency key, rechecks the complete current input state, and serializes writes per payslip. Input changes never trigger recalculation automatically. Recalculation remains limited to an editable payslip and cannot confirm, post, close, pay, or otherwise finalize Payroll. Only operational IDs and statuses are retained for audit and replay; input descriptions, amounts, employee details, and calculated Payroll values are not stored by these write workflows.

Verification

One command runs formatting checks, static analysis, tests, package builds, and artifact inspection in temporary directories:

powershell
uv run python scripts/verify.py

Automated tests use synthetic Odoo responses. They do not establish live Odoo version compatibility, real permissions, installed modules, or deployment networking.

Storage backup, restore, integrity verification, monitoring, upgrade, rollback, and incident procedures are documented in docs/operations.md. See SECURITY.md for the security boundary and vulnerability reporting, and SUPPORT.md for supported configurations and support requests.

docs/demo.md provides a bounded accounting demonstration that keeps every write-capable call in preview mode unless the operator separately authorizes execution in a non-production Odoo environment.

來源:README.md,提交 4718656

工具

0
SourceWeft 尚未在沙箱中啟動過該軟體包,因此其工具未知。

版本歷史

2
  1. v0.3.0最新Sep 27, 2026
  2. v0.1.0Sep 25, 2026

評分

已滿足適用檢查項的 50%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通25 分

    請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。

  • 已宣告認證方式10 分

    請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。

  • 已列出工具15 分

    請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。

  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分