Featured

Deploy OpenClaw in 60 seconds — 20% off logoDeploy OpenClaw in 60 seconds — 20% off

Launch OpenClaw on Hostinger in about 60 seconds and keep your agent live 24/7. Our referral link gives you 20% off, no coupon code needed.

Launch on Hostinger
Run your Hermes agent on Hostinger, fully managed logoRun your Hermes agent on Hostinger, fully managed

Launch Hermes on Hostinger in one click, fully managed, no VPS knowledge needed. Use code ZACAARON10 for 10% off.

Launch on Hostinger
Crawl and scrape any site into clean data, 10% off logoCrawl and scrape any site into clean data, 10% off

Firecrawl crawls and scrapes any site into clean markdown for your agent. Get 1,000 free credits, and new users get 10% off their first purchase.

Try Firecrawl free
6,000+ web scrapers for your AI agent, start free logo6,000+ web scrapers for your AI agent, start free

Apify gives your agent live web data: 6,000+ prebuilt scrapers and actors, MCP-ready. Sign up free with $5 in usage credits.

Try Apify free
One API to scrape, enrich, and extract the internet. logoOne API to scrape, enrich, and extract the internet.

Context.dev gives your agents a single API to scrape, enrich, and extract live web data — no proxies, no parsers, no maintenance.

Start building free
SetupClaw: done-for-you OpenClaw for founders & exec teams logoSetupClaw: done-for-you OpenClaw for founders & exec teams

White-glove OpenClaw for founders and exec teams (4–50+ employees): we install, harden, integrate your tools, and maintain it — secured from day one.

Get it set up for you
SEO data APIs for your agent, $1 free credit logoSEO data APIs for your agent, $1 free credit

DataForSEO gives your agent live access to SERP results, keyword data, backlinks, and on-page SEO data through one API. New accounts get a $1 credit, good for up to 20,000 keyword or backlink lookups.

Try DataForSEO free
Reach 48,000+ AI builders

A flat monthly placement in front of developers actively installing AI tools. No lock-in, cancel anytime.

Advertise here

Works with

Claude CodeClaude DesktopCursorVS CodeClineCodex CLIOpenClaw+ any MCP client

Install to Claude Code

This server doesn't publish a one-line install command. Follow the setup in the source repository.

Summary

twtrubiks/odoo19-mcp-server MCP server](https://glama.ai/mcp/servers/twtrubiks/odoo19-mcp-server/badges/score.svg)](https://glama.ai/mcp/servers/twtrubiks/odoo19-mcp-server) 🐍 ☁️ 🏠 🍎 🪟 🐧 - MCP Server for Odoo 19 ERP using JSON-RPC API, built with FastMCP.

README.md

Odoo 19 MCP Server (JSON-2 API)

![odoo19-mcp-server MCP server](https://glama.ai/mcp/servers/twtrubiks/odoo19-mcp-server)

![License: Apache-2.0](LICENSE) ![Python](https://www.python.org/) ![GitHub stars](https://github.com/twtrubiks/odoo19-mcp-server/stargazers) ![GitHub last commit](https://github.com/twtrubiks/odoo19-mcp-server/commits/main) ![Awesome MCP Servers](https://github.com/punkpeye/awesome-mcp-servers)

支援的 MCP Client

![Claude Code](#claude-code) ![Gemini CLI](#gemini-cli) ![Antigravity CLI](#antigravity-cli) ![OpenClaw](#openclaw) ![Codex CLI](#codex-cli)

Odoo 19 MCP Server,使用 JSON-2 API 連線。

✨ 支援多 user:設定 MCP_MULTIUSER=true 後,每個 client 以自己的 Odoo API key 認證,權限、操作歸屬、審計紀錄都對應真實 user,不再全部掛在同一個服務帳號上,詳見多 user 模式

本專案基於 Odoo 19 JSON-2 API 完整使用指南 開發。

!執行畫面

技術棧

  • Python: 3.13
  • FastMCP: >=3.0.0,<4.0.0
  • odoo-client-lib: 2.0.1 (JSON-2 API)

架構

flowchart TB
    subgraph Client["MCP Client"]
        CC[Claude Code]
        GC[Gemini CLI]
        MI[MCP Inspector]
    end

    subgraph Server["MCP Server (FastMCP)"]
        R[Resources<br/>odoo://models<br/>odoo://user<br/>odoo://company]
        T[Tools<br/>search_records<br/>create_record<br/>update_record]
        DI[Dependency Injection<br/>get_caller_client]
    end

    subgraph RPC["OdooJsonRpcClient"]
        OL[odoolib<br/>json2/json2s protocol]
    end

    subgraph Odoo["Odoo Server"]
        EP["/jsonrpc endpoint"]
    end

    Client -->|MCP Protocol<br/>stdio/http/sse| Server
    R --> DI
    T --> DI
    DI --> RPC
    RPC -->|HTTP/HTTPS| Odoo

MCP 核心概念

Resources vs Tools

| 特性 | Resources | Tools | |------|-----------|-------| | 用途 | 提供上下文資訊 | 執行操作/動作 | | 觸發 | 客戶端控制(如 Claude Code) | LLM 自動決定呼叫 | | 參數 | 無(或 URI 參數) | 有(需 LLM 生成) | | 類比 | 員工手冊(背景知識) | 工具箱(按需使用) | | HTTP 類比 | GET(讀取) | POST/PUT/DELETE(操作) |

Resources - 動態上下文,LLM 一開始就知道的背景資訊:

odoo://user     → "我是誰"
odoo://company  → "我在哪間公司"
odoo://models   → "有哪些模型可用"

Tools - 需要時才呼叫的操作:

search_records(model="res.partner", domain=[...])  → 搜尋
create_record(model="sale.order", values={...})    → 建立

為什麼不用 Default Prompt?

| 方式 | Default Prompt | Resource | |------|----------------|----------| | 資料來源 | 寫死在程式碼 | 即時從 Odoo 查詢 | | 更新時機 | 部署時 | 每次連線時 | | 換用戶登入 | 資訊錯誤 | 自動正確 |

# ❌ Default Prompt(寫死)
SYSTEM_PROMPT = "當前用戶: Admin"  # 換人登入就錯了

# ✅ Resource(動態)
@mcp.resource("odoo://user")
def get_current_user():
    return client.read("res.users", [uid])  # 即時查詢

結論:Resource 是「動態的上下文」,不是靜態文字。

參考:MCP Resources | MCP Tools

環境變數

| 變數 | 說明 | 預設值 | |------|------|--------| | ODOO_URL | Odoo 伺服器 URL | http://localhost:8069 | | ODOO_DATABASE | 資料庫名稱 | - | | ODOO_API_KEY | API Key 認證 | - | | READONLY_MODE | 唯讀模式(禁止寫入操作) | false | | MCP_ALLOW_SENSITIVE_MODELS | 設 true 停用模型黑名單(預設擋 credential 模型 ir.config_parameterres.users.apikeys 的讀寫) | false | | MCP_AUTH_TOKEN | HTTP/SSE 模式的 Bearer Token 認證(未設定=無認證;stdio 不適用),見安全機制 | -(停用) | | MCP_MULTIUSER | 多 user 模式:每個 client 拿自己的 Odoo API key 當 Bearer token,見安全機制 | false | | UPLOAD_TOKEN_SECRET | upload token 的 HMAC secret;僅多 worker 部署需要設定(單一程序自動衍生) | - |

建立 .env 檔案:

cp .env.example .env

安裝

pip install -r requirements.txt

啟動方式

開發模式(MCP Inspector)

fastmcp dev inspector odoo_mcp_server.py

傳輸模式(Transport)

本專案支援三種 MCP 傳輸模式:

| 模式 | 說明 | 適用情境 | |------|------|----------| | stdio | 標準輸入輸出(預設) | Claude Desktop、Cursor IDE、本機開發 | | http | HTTP 協定 | 遠端服務、n8n、Web 應用整合 | | sse | Server-Sent Events(已棄用) | 向下相容舊版 Client |

stdio vs HTTP/SSE:算力位置

兩種模式的關鍵差異在於「誰來啟動 MCP Server」以及「算力在哪裡執行」:

stdio 模式(本機算力)

┌─────────────────────────────────────┐
│            你的電腦 💻               │
│                                     │
│  Claude Desktop ──> MCP Server      │
│                     (使用本機算力)   │
└─────────────────────────────────────┘
  • Client(如 Claude Desktop)啟動 MCP Server 作為子進程
  • MCP Server 使用你電腦的 CPU/RAM
  • Server 隨 Client 啟動/關閉

HTTP/SSE 模式(遠端算力)

┌──────────────┐         ┌──────────────────┐
│   你的電腦    │         │     雲端 ☁️       │
│              │         │                  │
│Claude Desktop│ ──網路──>│   MCP Server     │
│  (輕量)      │         │  (使用雲端算力)   │
└──────────────┘         └──────────────────┘
  • MCP Server 獨立運行在雲端/遠端主機
  • 多個 Client 可同時連線同一個 Server
  • 適合團隊共用、n8n 整合、正式環境

啟動不同模式

# stdio 模式(預設)
python odoo_mcp_server.py

# HTTP 模式
python odoo_mcp_server.py --transport http --host 0.0.0.0 --port 8000

# SSE 模式(已棄用,建議使用 HTTP)
python odoo_mcp_server.py --transport sse --host 0.0.0.0 --port 8000

雲端部署(HTTP 模式)

⚠️ 安全提醒:HTTP 模式預設沒有認證——任何連得到該 port 的人都直接繼承 ODOO_API_KEY 的完整權限。除非 server 只在受信任的內網使用, 否則請務必設定 MCP_AUTH_TOKEN(或改用多 user 模式 MCP_MULTIUSER)並搭配 TLS,詳見安全機制

專案提供 docker-compose.example.yml 範本,複製後修改即可使用:

cp .env.example .env                                  # 填入 ODOO_URL / ODOO_DATABASE / ODOO_API_KEY
cp docker-compose.example.yml docker-compose.yml      # 依需求調整
docker compose up -d

範本內容

volumes:
  shared-uploads:

services:
  odoo-mcp:
    build: .
    command: ["python", "odoo_mcp_server.py", "--transport", "http", "--host", "0.0.0.0", "--port", "8000"]
    # 對外暴露 port 8000(host 端 client 可直接連 http://localhost:8000/mcp)。
    # ⚠️ "8000:8000" 會綁定 0.0.0.0:同網段的所有機器都連得到
    # (主機若有公網 IP,就是整個網際網路),且 Docker 發佈的 port 會繞過 ufw 防火牆規則。
    # 建議設定 MCP_AUTH_TOKEN(見 environment);只給本機 client 用可改 "127.0.0.1:8000:8000"。
    # 若只需 Docker 內網存取(例如 client 也在同一個 compose 裡),可整段移除 ports。
    ports:
      - "8000:8000"
    environment:
      - ODOO_URL=${ODOO_URL}
      - ODOO_DATABASE=${ODOO_DATABASE}
      - ODOO_API_KEY=${ODOO_API_KEY}
      - READONLY_MODE=${READONLY_MODE:-false}
      # HTTP 模式的 Bearer Token 認證(未設定=無認證,見 README「安全機制」)
      - MCP_AUTH_TOKEN=${MCP_AUTH_TOKEN:-}
      # 多 user 模式:每個 client 拿自己的 Odoo API key 當 Bearer token,
      # 權限/審計歸屬真實 user(見「多 user 模式」)
      # - MCP_MULTIUSER=true
      # HTTP 模式的 Host 標頭防護(DNS rebinding protection,來自底層 MCP SDK):
      # 用非 localhost 的 IP/網域連進來時,預設會被擋下並回 "Invalid host header"。
      # ⚠️ 快速測試可先全開(勿用於正式環境):
      - FASTMCP_HTTP_ALLOWED_HOSTS=["*"]
    volumes:
      - shared-uploads:/shared   # 圖片傳遞通道;對應 Dockerfile 預建的 /shared/uploads
    restart: unless-stopped

圖片 / 附件傳遞add_attachmentfile_path 模式會從 /shared/uploads/ 讀檔上傳到 Odoo,避免大量 base64 佔用 LLM output token。client 與 server 跨機器(不共用此 volume)時,改走 prepare_upload/upload 把檔案送進 UPLOAD_DIR,詳見安全機制

連不上、回 Invalid host header 這是底層 MCP SDK 的 DNS rebinding 防護——用非 localhost 的 IP/網域連進來時,Host 標頭不在允許清單內就會被擋。用 FASTMCP_HTTP_ALLOWED_HOSTS 放行: ``bash # 快速測試(⚠️ 對任何 Host 開放,勿用於正式環境) FASTMCP_HTTP_ALLOWED_HOSTS=[""] # ✅ 正規做法:只列出 client 實際連線的 host(含 port) FASTMCP_HTTP_ALLOWED_HOSTS=["your-server-ip:8000"] # 純 IP 部署 FASTMCP_HTTP_ALLOWED_HOSTS=["mcp.example.com"] # 反向代理/網域(建議搭配 TLS) ` 官方明確警告:使用萬用字元 會讓 server 對任何來源開放,正式環境請務必列出明確 host。必要時另有 FASTMCP_HTTP_ALLOWED_ORIGINS`(瀏覽器型 client 的 Origin 白名單)。

# server 有設 MCP_AUTH_TOKEN 時,需帶 Authorization header
claude mcp add --transport http odoo-mcp https://your-cloud-server.com:8000/mcp --header "Authorization: Bearer your_random_token_here"

# 多 user 模式(MCP_MULTIUSER=true):Bearer 改填「自己的 Odoo API key」
claude mcp add --transport http odoo-mcp https://your-cloud-server.com:8000/mcp --header "Authorization: Bearer <你的 Odoo API key>"

# server 未啟用認證(僅限受信任內網)
claude mcp add --transport http odoo-mcp https://your-cloud-server.com:8000/mcp

<details> <summary><b>手動設定 JSON(加到 ~/.claude.json)</b></summary>

{
  "mcpServers": {
    "odoo-mcp": {
      "type": "http",
      "url": "https://your-cloud-server.com:8000/mcp",
      "headers": {
        "Authorization": "Bearer your_random_token_here"
      }
    }
  }
}

⚠️ 純 HTTP 下 Bearer token 是明文傳輸,僅適合受信任內網/臨時測試;對外請改用 https://(TLS)。

server 未啟用 MCP_AUTH_TOKEN、也未開多 user 模式時,headers 整段可省略。 多 user 模式(MCP_MULTIUSER=true)下 headers 必填,Bearer 改填自己的 Odoo API key,見多 user 模式

</details>

MCP Resources

| URI | 說明 | |-----|------| | odoo://models | 列出所有模型 | | odoo://model/{model_name} | 取得模型欄位定義 | | odoo://record/{model_name}/{record_id} | 取得單筆記錄 | | odoo://user | 當前登入用戶資訊 | | odoo://company | 當前用戶所屬公司資訊 |

MCP Tools

| Tool | 說明 | 唯讀 | |------|------|------| | list_models | 列出/搜尋可用模型 | Yes | | get_fields | 取得模型欄位定義 | Yes | | search_records | 搜尋記錄 | Yes | | count_records | 計數記錄 | Yes | | read_records | 讀取指定 ID 記錄 | Yes | | create_record | 建立記錄 | No | | update_record | 更新記錄 | No | | delete_record | 刪除記錄(需二次確認) | No | | execute_method | 執行任意模型方法(萬用入口,unlink 與黑名單模型已封鎖,見安全機制) | No | | add_attachment | 上傳附件到 Odoo(file_path / base64_data 兩種模式,見安全機制) | No | | prepare_upload | 取得 /upload 端點用法與短效 upload_token(跨機器傳檔,見安全機制) | No |

Docker 建置

部分 client 的 Docker 設定(Claude Code / Gemini 的 Docker 版本)需要先建置本機映像檔:

docker build -t odoo-mcp-server .

MCP Client 設定

本專案支援以下 MCP Client,各自的完整設定步驟見對應章節:

| Client | 加入方式 | 設定檔 | |--------|----------|--------| | Claude Code | claude mcp add | ~/.claude.json | | Gemini CLI | gemini mcp add | ~/.gemini/settings.json | | Antigravity CLI | 手動編輯 | ~/.gemini/config/mcp_config.json | | OpenClaw | openclaw mcp set | OpenClaw config | | Codex CLI | codex mcp add + 手動編輯 | ~/.codex/config.toml |

Claude Code

設定檔位於 ~/.claude.json

本機執行

claude mcp add odoo-mcp-server -- python odoo_mcp_server.py

<details> <summary><b>手動設定 JSON</b></summary>

{
  "mcpServers": {
    "odoo-mcp-server": {
      "command": "/bin/python",
      "args": [
        "odoo_mcp_server.py"
      ]
    }
  }
}

</details>

Docker(host.docker.internal)

適用於 Odoo 執行在本機的情況:

claude mcp add odoo-mcp-server -- docker run -i --rm --add-host=host.docker.internal:host-gateway -e ODOO_URL=http://host.docker.internal:8069 -e ODOO_DATABASE=odoo19 -e ODOO_API_KEY=your_api_key_here odoo-mcp-server

<details> <summary><b>手動設定 JSON</b></summary>

{
  "mcpServers": {
    "odoo-mcp-server": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "--add-host=host.docker.internal:host-gateway",
        "-e",
        "ODOO_URL=http://host.docker.internal:8069",
        "-e",
        "ODOO_DATABASE=odoo19",
        "-e",
        "ODOO_API_KEY=your_api_key_here",
        "odoo-mcp-server"
      ]
    }
  }
}

</details>

Docker(host network)

使用主機網路模式:

claude mcp add odoo-mcp-server -- docker run -i --rm --network host -e ODOO_URL=http://localhost:8069 -e ODOO_DATABASE=odoo19 -e ODOO_API_KEY=your_api_key_here odoo-mcp-server

<details> <summary><b>手動設定 JSON</b></summary>

{
  "mcpServers": {
    "odoo-mcp-server": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "--network",
        "host",
        "-e",
        "ODOO_URL=http://localhost:8069",
        "-e",
        "ODOO_DATABASE=odoo19",
        "-e",
        "ODOO_API_KEY=your_api_key_here",
        "odoo-mcp-server"
      ]
    }
  }
}

</details>

Docker(遠端 Odoo)

claude mcp add odoo-mcp-server -- docker run -i --rm -e ODOO_URL=https://example.com/ -e ODOO_DATABASE=odoo19 -e ODOO_API_KEY=your_api_key_here odoo-mcp-server

<details> <summary><b>手動設定 JSON</b></summary>

{
  "mcpServers": {
    "odoo-mcp-server": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "-e",
        "ODOO_URL=https://example.com/",
        "-e",
        "ODOO_DATABASE=odoo19",
        "-e",
        "ODOO_API_KEY=your_api_key_here",
        "odoo-mcp-server"
      ]
    }
  }
}

</details>

Gemini CLI

gemini mcp add --scope user odoo-mcp docker -- run -i --rm --add-host=host.docker.internal:host-gateway -e ODOO_URL=http://host.docker.internal:8069 -e ODOO_DATABASE=odoo19 -e ODOO_API_KEY=your_api_key_here odoo-mcp-server

<details> <summary><b>手動設定 JSON(加到 ~/.gemini/settings.json)</b></summary>

{
  "mcpServers": {
    "odoo-mcp": {
      "command": "docker",
      "args": [
        "run",
        "-i",
        "--rm",
        "--add-host=host.docker.internal:host-gateway",
        "-e",
        "ODOO_URL=http://host.docker.internal:8069",
        "-e",
        "ODOO_DATABASE=odoo19",
        "-e",
        "ODOO_API_KEY=your_api_key_here",
        "odoo-mcp-server"
      ]
    }
  }
}

</details>

Antigravity CLI

自 2026/6/18 起個人版 Gemini CLI 停止服務,改用 Antigravity CLI。目前 沒有 mcp add 子指令,需手動編輯設定檔。

設定檔路徑為 ~/.gemini/config/mcp_config.json(Antigravity CLI / IDE / SDK 共用,等同 Gemini CLI 的 --scope user)。

JSON 格式與上方 Gemini CLI 設定相同。

設定後進入 Antigravity CLI 以 /mcp 指令重新載入,並確認連線狀態。

OpenClaw

OpenClaw 透過 CLI 管理 MCP server,設定會寫入 mcp.servers.<name>

/mcp 指令為 owner-only 且預設關閉,需以 commands.mcp: true 開啟才能在 chat session 中使用。

步驟 1:註冊 MCP server

# 請將 your-server-ip 換成你的 MCP server 位址
openclaw mcp set odoo-mcp '{"type":"http","url":"http://your-server-ip:8000/mcp"}'

<details> <summary><b>手動設定 JSON(寫入 OpenClaw 設定的 mcp.servers)</b></summary>

OpenClaw 會自動正規化設定,把 type:"http" 轉成 transport:"streamable-http" 後存入:

{
  "mcp": {
    "servers": {
      "odoo-mcp": {
        "url": "http://your-server-ip:8000/mcp",
        "transport": "streamable-http"
      }
    }
  }
}

</details>

步驟 2:開啟 /mcp 指令

openclaw config set commands.mcp true

步驟 3:重啟 Gateway 套用設定

openclaw gateway restart

若想等進行中的工作排空再重啟,可改用 openclaw gateway restart --safe

驗證

# server 是否註冊成功
openclaw mcp list
openclaw mcp show odoo-mcp

# /mcp 開關狀態(應回傳 true)
openclaw config get commands.mcp

完成後請開一個新的 chat session(或硬重整 dashboard),再輸入 /mcp 確認 odoo-mcp 連線狀態。

Codex CLI

Codex 的 codex mcp add 只支援 stdio(command / args,並不支援 url(streamable HTTP)形式的遠端 server。因此要連雲端 HTTP 模式的 MCP server,需先用佔位指令建立設定,再手動編輯 ~/.codex/config.toml

codex mcp add odoo-mcp -- echo placeholder

<details> <summary><b>手動設定 TOML(修改 ~/.codex/config.toml)</b></summary>

codex mcp add 產生的佔位設定:

[mcp_servers.odoo-mcp]
command = "echo"
args = ["placeholder"]

手動改為 url(streamable HTTP):

[mcp_servers.odoo-mcp]
url = "https://your-cloud-server.com:8000/mcp"

若 server 端設定了 MCP_AUTH_TOKEN,需加上 bearer_token_env_var = "ODOO_MCP_TOKEN", 並在執行 Codex 的環境中 export ODOO_MCP_TOKEN=<與 server MCP_AUTH_TOKEN 相同的值>; 或改用自訂 http_headers 直接填 Authorization header。 多 user 模式(MCP_MULTIUSER=true)下同理,ODOO_MCP_TOKEN 改 export 自己的 Odoo API key

</details>

安全機制

部署定位與 HTTP 認證(MCP_AUTH_TOKEN

設定 MCP_AUTH_TOKEN 環境變數即可啟用 Bearer Token 認證(opt-in):

# 產生隨機 token
openssl rand -hex 32
  • 啟用後 /mcp 端點要求 Authorization: Bearer <token>,未帶或錯誤一律回 401
  • 未設定時行為與過去版本相同(無認證),但 HTTP/SSE 模式啟動時會在 stderr 印出警告

多 user 模式(MCP_MULTIUSER

預設情況下,所有操作都透過 ODOO_API_KEY 這一個 Odoo 帳號執行——多人共用時, Odoo 端的權限、chatter、審計紀錄全部歸到同一個 user。設定 MCP_MULTIUSER=true 後改為 pass-through 認證

  • 每個 user 在 Odoo「偏好設定 → 帳戶安全」產生自己的 API key,直接當

HTTP/SSE 連線的 Bearer token(json2 protocol 的 API key 即完整憑證, Odoo 會從 key 解析出擁有者)

  • Server 收到 token 後拿去問 Odoo 驗證(結果快取 5 分鐘、驗證失敗快取 30 秒

以防暴力破解),驗證成功即建立綁該 user API key 的專屬連線

  • 權限(ACL / record rules)、操作歸屬、審計全部由 Odoo 原生機制處理;

撤銷存取 = 在 Odoo 刪除該 API key(最遲 5 分鐘後生效)

  • Server 端不保存任何使用者資料,新增/移除 user 都在 Odoo 操作即可
  • MCP_AUTH_TOKEN 可並存,作為 admin fallback(走 ODOO_API_KEY 的共享連線);

stdio 模式不受影響

  • 純多 user 部署(不設 MCP_AUTH_TOKEN、不跑 stdio)可ODOO_API_KEY 都不設

——server 端零長效憑證,設定檔外洩也沒東西可偷。誤走到 fallback 路徑時會收到 明確的設定錯誤訊息(不會拿 placeholder 去打 Odoo)

  • Bearer token 就是 Odoo API key 本體,務必搭配 TLS

Client 端設定與 MCP_AUTH_TOKEN 完全相同(完整範例見雲端部署(HTTP 模式)), 只是 Bearer 換成各自的 Odoo API key

"headers": {
  "Authorization": "Bearer <你的 Odoo API key>"
}

附件檔案讀取範圍(UPLOAD_DIR

add_attachmentfile_path 模式是本 server 唯一會讀取 MCP 主機本地檔案的入口。 若不設限,被 prompt injection 的 LLM 可用 file_path="/app/.env" 把 server 機密 (含 ODOO_API_KEY 本身)讀出、上傳成 Odoo 附件外洩——這是 confused deputy, MCP_AUTH_TOKEN 擋不住(LLM 本來就是合法持 token 的 client)。

因此 file_path 被限制在 UPLOAD_DIR(預設 /shared/uploads)底下:

  • 路徑經 Path.resolve() 正規化後,必須落在 UPLOAD_DIR 內,否則回 ToolError
  • resolve() 會一併解掉 symlink,所以「白名單目錄裡放一個指向外部的 symlink」也擋得掉
  • 預設值對齊 compose 的 /shared/uploads 圖片傳遞通道,Docker 部署無需額外設定
  • 純本機 stdio 若要放行任意路徑,設 UPLOAD_DIR=/(等於解除限制,自負風險)
  • 檔案不在磁碟上(如 Discord 上傳的圖片)時,改用 base64_data 模式,不受此限制

跨機器上傳圖片(prepare_upload/upload

當 client 與 server 不在同一台機器時,shared-uploads volume 用不到,file_path 沒有共用檔案系統可讀;若改走 base64_data,整包 base64 會流經 LLM 的 token stream,又慢又貴。

/upload 提供一條 out-of-band 的檔案通道:client 用普通 HTTP POST 把位元組直接推到 server (不經 LLM),server 存進 UPLOAD_DIR 後回傳 file_path,client 再用這個路徑呼叫 add_attachment——只有短路徑字串會進 token stream。

整個工作流透過 MCP 協定自我描述,client 端零安裝、零設定:agent(如 Claude Code)呼叫 prepare_upload 工具就拿到端點用法與短效 upload_token,接著自己上傳:

# upload_token 由 prepare_upload 簽發(server 未設 MCP_AUTH_TOKEN 時免帶 header)
curl -fsS -F "file=@/local/invoice.png" \
     -H "Authorization: Bearer <upload_token>" \
     https://your-server:8000/upload
# → {"file_path": "/shared/uploads/<uuid>.png", "file_name": "invoice.png"}

接著呼叫 add_attachment(file_path="/shared/uploads/<uuid>.png", file_name="invoice.png", ...)。 不經 MCP 的手動整合(腳本、CI 等)也可以直接拿 MCP_AUTH_TOKEN 本體打同一個端點。

安全機制:

  • /upload會寫檔的端點,設了 MCP_AUTH_TOKEN 就要求 Bearer token(custom route 不受 MCP 認證保護,故自行驗證)
  • prepare_upload 簽發的是 HMAC 衍生短效 tokenMCP_AUTH_TOKEN 為根秘密簽出、預設 10 分鐘、只對 /upload 有效、無狀態驗證)——master token 不進 LLM context,就算對話 transcript 外流,外洩的也只是效期內的上傳權限
  • 磁碟檔名由 server 端 uuid 產生,client 給的檔名絕不進入路徑,無法逃出 UPLOAD_DIR
  • 單檔大小上限 UPLOAD_MAX_BYTES(預設 25 MiB),超過回 413
  • 不自動清理 UPLOAD_DIR,請搭配定期清理或使用 ephemeral volume

模型黑名單(MCP_ALLOW_SENSITIVE_MODELS

預設封鎖以下兩個機密模型的所有讀寫,防範 prompt injection——LLM 讀到藏在資料裡的惡意指令,拿著你的 API key 做出「權限上合法、但你沒要求」的操作:

  • ir.config_parameter:存第三方 API key、webhook token 等機密,一句 search 就全外洩
  • res.users.apikeys:可產生新的長效 API key——事後 rotate 原 key 也擋不住,等於留後門

正常的 agent 工作流程用不到這兩個模型,封鎖不影響日常使用;所有工具與 Resources(含 execute_method)都會檢查。

黑名單只是多一層保險,不是權限控管——權限仍由 Odoo ACL 決定,請給 MCP 低權限使用者的 API key (res.usersir.rule 等安全模型因此不在黑名單內)。 真的需要透過 MCP 管理這兩個模型時,設 MCP_ALLOW_SENSITIVE_MODELS=true 停用。

唯讀模式

設定 READONLY_MODE=true 啟用唯讀模式,適用於生產環境查詢:

  • 寫入工具(create_recordupdate_recorddelete_recordexecute_methodadd_attachment)在註冊時即被停用——LLM 看不到這些工具,直接呼叫也會被拒絕
  • 停用發生在模組層級,任何啟動方式(python odoo_mcp_server.pyfastmcp runfastmcp dev)都同樣生效

刪除二次確認與 execute_method 的安全邊界

delete_record 內建 confirm 機制:LLM 必須先以 confirm=False 呼叫取得確認提示,經使用者同意後才能以 confirm=True 執行刪除。

注意:confirm 參數由 LLM 自行填入,屬於「引導 LLM」層級的防護, 並非強制性的安全邊界(LLM 理論上可直接傳 confirm=True)。

execute_method 是萬用入口(escape hatch),用來呼叫沒有專用工具的模型方法,請理解其風險:

  • ORM 原語 unlink 已被攔下,會導向 delete_record 的二次確認流程,無法藉此繞過確認
  • 模型黑名單同樣適用:credential 模型(ir.config_parameterres.users.apikeys)全擋
  • action_confirmaction_postbutton_validate 這類會改資料的業務方法不設防——

Odoo 有上千個模型方法,server 無法枚舉哪些會寫入資料庫

  • 真正的安全邊界應該是給 MCP 使用低權限的 Odoo 使用者 API key(最小權限原則)

健康檢查

HTTP/SSE transport 模式下提供 /health 端點:

curl http://localhost:8000/health
# {"status": "healthy", "service": "odoo-mcp-server", "version": "1.0.0"}

適用於 Docker healthcheck、Kubernetes probe、load balancer 探活。stdio 模式下不影響。 此端點不受 MCP_AUTH_TOKEN 保護(不需帶 token)。

License

Apache 2.0

See related servers & alternatives →

Related MCP servers

Browse all →

Related guides

Hand-picked reading to help you choose and use AI & ML servers.