odoo19-mcp-server
This server provides an MCP (Model Context Protocol) interface to interact with Odoo 19 ERP systems via its JSON-2 API, enabling AI assistants to query and manipulate Odoo data.
Model Discovery & Schema Inspection
list_models: Browse all available Odoo models with optional name filteringget_fields: Inspect field metadata (types, labels, required/readonly flags, relations, etc.) for any model
Data Querying
search_records: Query records using Odoo domain syntax with filtering, sorting, pagination, and Odoo 19+anyoperator supportcount_records: Count records matching a domain without fetching dataread_records: Fetch specific records by ID (includes direct browser URL links)
Data Manipulation
create_record: Create single or multiple records in any modelupdate_record: Update one or more records by IDdelete_record: Delete records via a mandatory two-step confirmation flowexecute_method: Call arbitrary methods on any model (e.g., confirm orders, trigger workflows)
Resources (Dynamic Context)
odoo://user/odoo://company: Current user and company infoodoo://models: All available modelsodoo://model/{model_name}: Field definitions for a modelodoo://record/{model_name}/{record_id}: A single record
Safety & Security
READONLY_MODE=truehides all write tools from the LLM entirely (includingexecute_methodfor write operations)Delete operations require explicit user confirmation
Sensitive fields (binary/image/HTML) are automatically filtered
API key authentication for Odoo access
Deployment & Integration
Supports
stdio(local),http, andssetransport modesDocker/Docker Compose support for cloud deployment
Compatible with Claude Code, Gemini CLI, and MCP Inspector
/healthendpoint for monitoring in HTTP/SSE modes
Enables interaction with Odoo 19 instances via the JSON-2 API, allowing users to search, create, read, update, and delete records across various models, as well as access system metadata, model definitions, and user/company information.
Odoo 19 MCP Server (JSON-2 API)
支援的 MCP Client
Odoo 19 MCP Server,使用 JSON-2 API 連線。
本專案基於 Odoo 19 JSON-2 API 完整使用指南 開發。

技術棧
Python: 3.13
FastMCP: >=3.0.0,<4.0.0
odoo-client-lib: 2.0.1 (JSON-2 API)
Related MCP server: odoo-mcp
架構
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_shared_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| OdooMCP 核心概念
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 |
|
| 資料庫名稱 | - |
| API Key 認證 | - |
| 唯讀模式(禁止寫入操作) |
|
| HTTP/SSE 模式的 Bearer Token 認證(未設定=無認證;stdio 不適用),見安全機制 | -(停用) |
建立 .env 檔案:
cp .env.example .env安裝
pip install -r requirements.txt啟動方式
開發模式(MCP Inspector)
fastmcp dev inspector odoo_mcp_server.py傳輸模式(Transport)
本專案支援三種 MCP 傳輸模式:
模式 | 說明 | 適用情境 |
| 標準輸入輸出(預設) | Claude Desktop、Cursor IDE、本機開發 |
| HTTP 協定 | 遠端服務、n8n、Web 應用整合 |
| 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並搭配 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:-}
# 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_attachment的file_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放行:# 快速測試(⚠️ 對任何 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"
# server 未啟用認證(僅限受信任內網)
claude mcp add --transport http odoo-mcp https://your-cloud-server.com:8000/mcp{
"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 時,headers 整段可省略。
MCP Resources
URI | 說明 |
| 列出所有模型 |
| 取得模型欄位定義 |
| 取得單筆記錄 |
| 當前登入用戶資訊 |
| 當前用戶所屬公司資訊 |
MCP Tools
Tool | 說明 | 唯讀 |
| 列出/搜尋可用模型 | Yes |
| 取得模型欄位定義 | Yes |
| 搜尋記錄 | Yes |
| 計數記錄 | Yes |
| 讀取指定 ID 記錄 | Yes |
| 建立記錄 | No |
| 更新記錄 | No |
| 刪除記錄(需二次確認) | No |
| 執行任意模型方法(萬用入口, | No |
| 上傳附件到 Odoo( | No |
| 取得 | No |
Docker 建置
部分 client 的 Docker 設定(Claude Code / Gemini 的 Docker 版本)需要先建置本機映像檔:
docker build -t odoo-mcp-server .MCP Client 設定
本專案支援以下 MCP Client,各自的完整設定步驟見對應章節:
Client | 加入方式 | 設定檔 |
|
| |
|
| |
手動編輯 |
| |
| OpenClaw config | |
|
|
Claude Code
設定檔位於 ~/.claude.json:
本機執行
claude mcp add odoo-mcp-server -- python odoo_mcp_server.py{
"mcpServers": {
"odoo-mcp-server": {
"command": "/bin/python",
"args": [
"odoo_mcp_server.py"
]
}
}
}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{
"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"
]
}
}
}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{
"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"
]
}
}
}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{
"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"
]
}
}
}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{
"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"
]
}
}
}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"}'OpenClaw 會自動正規化設定,把 type:"http" 轉成 transport:"streamable-http" 後存入:
{
"mcp": {
"servers": {
"odoo-mcp": {
"url": "http://your-server-ip:8000/mcp",
"transport": "streamable-http"
}
}
}
}步驟 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 placeholdercodex 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直接填Authorizationheader。
安全機制
部署定位與 HTTP 認證(MCP_AUTH_TOKEN)
設定 MCP_AUTH_TOKEN 環境變數即可啟用 Bearer Token 認證(opt-in):
# 產生隨機 token
openssl rand -hex 32啟用後
/mcp端點要求Authorization: Bearer <token>,未帶或錯誤一律回 401未設定時行為與過去版本相同(無認證),但 HTTP/SSE 模式啟動時會在 stderr 印出警告
附件檔案讀取範圍(UPLOAD_DIR)
add_attachment 的 file_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內,否則回ToolErrorresolve()會一併解掉 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 衍生短效 token(MCP_AUTH_TOKEN為根秘密簽出、預設 10 分鐘、只對/upload有效、無狀態驗證)——master token 不進 LLM context,就算對話 transcript 外流,外洩的也只是效期內的上傳權限磁碟檔名由 server 端
uuid產生,client 給的檔名絕不進入路徑,無法逃出UPLOAD_DIR單檔大小上限
UPLOAD_MAX_BYTES(預設 25 MiB),超過回 413不自動清理
UPLOAD_DIR,請搭配定期清理或使用 ephemeral volume
唯讀模式
設定 READONLY_MODE=true 啟用唯讀模式,適用於生產環境查詢:
寫入工具(
create_record、update_record、delete_record、execute_method、add_attachment)在註冊時即被停用——LLM 看不到這些工具,直接呼叫也會被拒絕停用發生在模組層級,任何啟動方式(
python odoo_mcp_server.py、fastmcp run、fastmcp dev)都同樣生效
刪除二次確認
delete_record 內建 confirm 機制,LLM 必須先以 confirm=False 呼叫取得確認提示,經使用者同意後才能以 confirm=True 執行刪除。
execute_method 已攔下 unlink,無法用它繞過此確認流程。
注意:confirm 參數由 LLM 自行填入,屬於「引導 LLM」層級的防護, 並非強制性的安全邊界(LLM 理論上可直接傳
confirm=True)。
execute_method 的安全邊界
execute_method 是萬用入口(escape hatch),用來呼叫沒有專用工具的模型方法,請理解其風險:
ORM 原語
unlink已被攔下,會導向delete_record的二次確認流程但
action_confirm、action_post、button_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
Maintenance
Appeared in Searches
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/twtrubiks/odoo19-mcp-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server