MCP Server for Odoo について
MCP Server for Odoo は、AI アシスタントが標準化されたリソースとツールを通じて Odoo ERP システムを操作できるようにする MCP サーバーです。自然言語で Odoo のデータを検索・編集したいユーザー向けです。YOLO モードでは任意の Odoo インスタンスに素早く接続でき、標準モードでは Odoo MCP モジュールによるアクセス制御を利用できます。
主な機能
- 01ツールによる Odoo レコードの検索・作成・更新・削除
- 02レコードの件数取得とモデルのフィールド構造の確認
- 03生データを取得せずに行うサーバー側の集計
- 04公開されたビジネスメソッドの呼び出し(オプトイン)
- 05URI 指定によるバイナリと添付ファイルのリソース取得
- 06API キーまたはユーザー名とパスワードによる認証
活用シーン
- 01顧客・製品・請求書データの自然言語による検索
- 02AI アシスタントからの Odoo レコードの集計と件数確認
- 03非本番環境での Odoo データ操作の迅速な検証
MCP 対応
本プロジェクトは MCP サーバーであり、Claude Desktop、Claude Code、Cursor などの MCP クライアントに Odoo のリソースとツールを公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
Odoo 用 MCP サーバー
Claude のような AI アシスタントが Odoo ERP システムとやり取りできるようにする MCP サーバーです。自然言語を使って、業務データへのアクセス、レコードの検索、新規レコードの作成、既存データの更新、Odoo インスタンスの管理ができます。
あらゆる Odoo インスタンスで動作します! 標準的な Odoo インストール環境で手早くテストやデモを行うには、YOLO モードを使用してください。エンタープライズ向けのセキュリティ、アクセス制御、本番環境での利用には、Odoo MCP モジュールをインストールしてください。
機能
- 🔍 あらゆる Odoo レコードを検索・取得(顧客、製品、請求書など)
- ✨ 新しいレコードを作成(フィールドの検証と権限チェック付き)
- ✏️ 既存データを更新(スマートなフィールド処理付き)
- 🗑️ モデルレベルの権限に従ってレコードを削除
- 🔢 特定の条件に一致するレコードをカウント
- 📋 モデルのフィールドを調べてデータ構造を把握
- 📊 サーバー側で集計 — 生の行データを取得せずにグループ化、合計、カウントを実行
- ⚡ ワークフローアクション — オプトイン形式のエスケープハッチを使って、公開されている業務メソッドを呼び出し(請求書の転記、SO の確認など)
- 📎 バイナリと添付ファイルのリソース — リソース URI を使って画像、ドキュメント、
ir.attachmentファイルを取得 - 👤 パーソナライズされたセッションコンテキスト — 接続ユーザー、タイムゾーン、会社の範囲をセッション指示に注入
- 🔐 API キーまたはユーザー名/パスワード認証によるセキュアなアクセス
- 🎯 大規模なデータセットに対応するスマートなページネーション
- 🧠 スマートなフィールド選択 — モデルごとに最も関連性の高いフィールドを自動選択
- 💬 階層化されたテキスト形式によるLLM 向けに最適化された出力
- 🌍 多言語サポート — 希望する言語で応答を取得
- 🚀 あらゆる Odoo インスタンスで手軽にアクセスできるYOLO モード(モジュール不要)
インストール
前提条件
- Python 3.10 以降
- Odoo インスタンスへのアクセス:
- 標準モード(本番環境):バージョン 16.0 以降で、Odoo MCP モジュールがインストール済み
- YOLO モード(テスト/デモ):XML-RPC が有効な任意の Odoo バージョン(モジュール不要)
まず UV をインストール
MCP サーバーは Odoo サーバーではなく、Claude Desktop がインストールされているローカルコンピューターで実行されます。ローカルマシンに UV をインストールする必要があります。
macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
インストール後、UV が PATH に設定されていることを確認するため、ターミナルを再起動してください。
MCP 設定からインストール(推奨)
次の設定を MCP 設定に追加します。
{
"mcpServers": {
"odoo": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here"
}
}
}
}
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json に追加します。
{
"mcpServers": {
"odoo": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here",
"ODOO_DB": "your-database-name"
}
}
}
}
Claude Code
プロジェクトのルートにある .mcp.json に追加します。
{
"mcpServers": {
"odoo": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here",
"ODOO_DB": "your-database-name"
}
}
}
}
または、CLI を使用します。
claude mcp add odoo \
--env ODOO_URL=https://your-odoo-instance.com \
--env ODOO_API_KEY=your-api-key-here \
--env ODOO_DB=your-database-name \
-- uvx mcp-server-odoo
Cursor
~/.cursor/mcp.json に追加します。
{
"mcpServers": {
"odoo": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here",
"ODOO_DB": "your-database-name"
}
}
}
}
VS Code(GitHub Copilot を使用)
ワークスペースの .vscode/mcp.json に追加します。
{
"servers": {
"odoo": {
"type": "stdio",
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here",
"ODOO_DB": "your-database-name"
}
}
}
}
注: VS Code では、ルートキーに
"mcpServers"ではなく"servers"を使用します。
Windsurf
~/.codeium/windsurf/mcp_config.json に追加します。
{
"mcpServers": {
"odoo": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here",
"ODOO_DB": "your-database-name"
}
}
}
}
Zed
~/.config/zed/settings.json に追加します。
{
"context_servers": {
"odoo": {
"command": {
"path": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here",
"ODOO_DB": "your-database-name"
}
}
}
}
}
別のインストール方法
Docker を使用する
Docker で実行します。Python のインストールは不要です。
{
"mcpServers": {
"odoo": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "ODOO_URL=http://host.docker.internal:8069",
"-e", "ODOO_API_KEY=your-api-key-here",
"ivnvxd/mcp-server-odoo"
]
}
}
}
注: ホストマシン上で実行されている Odoo に接続するには、
localhostの代わりにhost.docker.internalを使用してください。
HTTP トランスポートの場合:
docker run --rm -p 8000:8000 \
-e ODOO_URL=http://host.docker.internal:8069 \
-e ODOO_API_KEY=your-api-key-here \
ivnvxd/mcp-server-odoo --transport streamable-http --host 0.0.0.0
⚠️ セキュリティ: HTTP トランスポートには認証機能が組み込まれていません。ポートにアクセスできる人は誰でも、サーバーの認証情報を使って Odoo にアクセスできます。ポートを公開するのは信頼できるネットワーク内に限るか、認証機能を備えたリバースプロキシの背後に配置してください。トランスポートのオプションを参照してください。
イメージは GHCR からも利用できます:ghcr.io/ivnvxd/mcp-server-odoo
pip を使用する
# Install globally
pip install mcp-server-odoo
# Or use pipx for isolated environment
pipx install mcp-server-odoo
次に、MCP 設定のコマンドとして mcp-server-odoo を指定します。
ソースからインストールする
git clone https://github.com/ivnvxd/mcp-server-odoo.git
cd mcp-server-odoo
pip install -e .
次に、MCP 設定でパッケージへのフルパスを指定します。
設定
環境変数
サーバーには、次の環境変数が必要です。
| 変数 | 必須 | 説明 | 例 |
|---|---|---|---|
ODOO_URL | はい | Odoo インスタンスの URL | https://mycompany.odoo.com |
ODOO_API_KEY | はい* | 認証用 API キー | 0ef5b399e9ee9c11b053dfb6eeba8de473c29fcd |
ODOO_USER | はい* | ユーザー名(API キーを使用しない場合) | admin |
ODOO_PASSWORD | はい* | パスワード(API キーを使用しない場合) | admin |
ODOO_DB | いいえ | データベース名(未設定の場合は自動検出されます) | mycompany |
ODOO_LOCALE | いいえ | Odoo のレスポンスに使用する言語/ロケール | es_ES、fr_FR、de_DE |
ODOO_ALLOWED_COMPANIES | いいえ | すべての操作の対象を限定する会社 ID(複数会社の設定では、カンマ区切りで指定) | 1、1,3 |
ODOO_YOLO | いいえ | YOLO モード — MCP のセキュリティを回避します(⚠️ 開発時のみ) | off、read、true |
ODOO_MCP_ENABLE_METHOD_CALLS | いいえ | call_model_method ツールを有効にします — ODOO_YOLO=true が必要です(⚠️ 危険です。詳細は call_model_method を参照) | false、true |
ODOO_RPC_TRANSPORT | いいえ | YOLO モードで使用する RPC プロトコル:auto(Odoo 19 以降で API キーを使用する場合は JSON-2、それ以外は XML-RPC)、xmlrpc、または Odoo の JSON-2 API 用の json2(Odoo 19 以降、API キーのみ) | auto、json2 |
*ODOO_API_KEY、または ODOO_USER と ODOO_PASSWORD の両方が必要です。XML-RPC を使用する YOLO モードでは、API キーを使用する場合でも ODOO_USER が必要です。JSON-2 では、Odoo が API キーからユーザーを特定するため、API キーだけで十分です。
注:
- サーバーでデータベース一覧の表示が制限されている場合は、
ODOO_DBを指定する必要があります - セキュリティを高めるため、API キー認証を推奨します
- サーバーは、作業ディレクトリにある
.envファイルからも環境変数を読み込みます - 標準モードでは、サーバーは各モデルの MCP 権限を 5 分間保持します。Odoo で権限を削除すると、MCP モジュールが呼び出しごとに権限を確認するため、次の呼び出しは直ちに拒否されます。権限を付与した場合、反映まで最大 5 分かかることがあります。サーバーを再起動すると、すぐに反映できます。
複数会社のスコープ設定(ODOO_ALLOWED_COMPANIES):
複数会社のデータベースでは、認証済みユーザーの既定の会社がサーバーによって作成されるすべてのレコードに適用され、レコードの表示範囲はユーザーがアクセスを許可されているすべての会社に及びます。ODOO_ALLOWED_COMPANIES を設定すると、すべての RPC 呼び出しのコンテキストに allowed_company_ids が挿入されるため、レコードルール、env.company、および作成時の既定値が、指定した会社に限定されます。単一の Odoo ユーザーを共有し、会社ごとに MCP サーバーのエントリーを設定する方法が有効です。
{
"mcpServers": {
"odoo-company-a": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": { "ODOO_URL": "...", "ODOO_API_KEY": "...", "ODOO_ALLOWED_COMPANIES": "1" }
},
"odoo-company-b": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": { "ODOO_URL": "...", "ODOO_API_KEY": "...", "ODOO_ALLOWED_COMPANIES": "3" }
}
}
}
起動時に、サーバーは各 ID がユーザーの会社に含まれていることを確認し、含まれていない場合は起動しません。ユーザーが自身の res.users レコードを読み取れない場合(res.users が有効になっていない標準モード)は、警告を表示して確認をスキップし、代わりに Odoo が各呼び出しで他社へのアクセスを拒否します。先頭の ID がアクティブな会社です。Odoo はその会社を作成時の既定値に使用し、get_current_context とセッションの指示にも表示します。呼び出しでは、指定した会社の一部にスコープを狭めることはできますが、広げることはできません。
これはコンテキストレベルのスコープ設定であり、セキュリティ境界ではないことに注意してください。認証情報を使用すると、Odoo ユーザーがアクセスを許可されているすべての会社に引き続きアクセスできます。厳密に分離するには、Odoo 自体でユーザーがアクセスできる会社を制限してください。
高度な設定
| 変数 | デフォルト | 説明 |
|---|---|---|
ODOO_MCP_DEFAULT_LIMIT | 25 | 検索ごとに返されるレコード数のデフォルト値 |
ODOO_MCP_MAX_LIMIT | 100 | リクエストごとに許可されるレコード数の上限 |
ODOO_MCP_MAX_SMART_FIELDS | 15 | スマートフィールド選択で返されるフィールド数の上限 |
ODOO_MCP_LOG_LEVEL | INFO | ログレベル(DEBUG、INFO、WARNING、ERROR、CRITICAL) |
ODOO_MCP_LOG_JSON | false | 構造化 JSON ログ出力を有効にします |
ODOO_MCP_LOG_FILE | — | ローテーションするログファイルのパス(10 MB、5 バックアップ) |
ODOO_MCP_LOG_FORMAT | — | カスタム Python ロギング形式文字列(デフォルト:%(asctime)s - %(name)s - %(levelname)s - %(message)s) |
ODOO_MCP_SLOW_OPERATION_THRESHOLD_MS | 1000 | これを超えると操作が低速としてログに記録されるしきい値(ミリ秒) |
ODOO_MCP_TRANSPORT | stdio | トランスポートの種類(stdio、streamable-http) |
ODOO_MCP_HOST | localhost | HTTP トランスポートでバインドするホスト |
ODOO_MCP_PORT | 8000 | HTTP トランスポートでバインドするポート |
ODOO_MCP_ALLOWED_HOSTS | — | HTTP トランスポートで受け入れる Host ヘッダー(DNS リバインディング対策)。外部ホストを転送するリバースプロキシの背後で streamable-http を実行する場合に設定します。例:odoo.example.com,localhost。IPv6 リテラルは角括弧付きまたは括弧なしで指定できます([::1]:8000、::1)。未設定の場合、保護はループバックへのバインド時にのみ自動的に有効になります — それ以外のホスト(例:0.0.0.0)にバインドすると、Host/Origin の検証は一切行われません。 |
ODOO_MCP_SESSION_IDLE_TIMEOUT | — | streamable-http セッションが閉じられ、サーバー側の状態が解放されるまでの非アクティブ時間(秒)。例:600。未設定の場合、セッションは期限切れになりません。 |
ODOO_MCP_MAX_BINARY_SIZE | 52428800 | 1 回のバイナリ/添付ファイルの resources/read で返される最大バイト数。ペイロードの取得前にチェックされます(レコードフィールドの場合、Odoo 19 以前では bin_size の確認、Odoo 20 では元になる添付ファイルのサイズまたは field.size のカウント。添付ファイルの場合は保存された file_size)。そのため、サイズ超過の読み取りは、メモリに読み込んでワイヤー向けに base64 へ再エンコードするのではなく、明確なエラーで拒否されます。Odoo 20 では、非保存のバイナリフィールド(avatar_128 など)、またはユーザーが読み取れない添付ファイルを持つ保存済みフィールドは、取得後にのみチェックされます。 |
トランスポートのオプション
サーバーは、さまざまなユースケースに対応する複数のトランスポートプロトコルをサポートしています。
1. stdio(デフォルト)
標準入出力トランスポート — Claude Desktop のようなデスクトップ AI アプリケーションで使用されます。
# Default transport - no additional configuration needed
uvx mcp-server-odoo
2. streamable-http
REST API 形式のアクセスとリモート接続に対応する標準 HTTP トランスポートです。
⚠️ セキュリティ:このトランスポートにはクライアント認証機能が組み込まれていません。ポートに接続できるクライアントはすべて、サーバーが保持する Odoo 認証情報を使って、すべてのツールとリソースを利用できます — YOLO フルアクセスモードでは書き込みも含まれます。ネットワークが信頼できる場合を除き、デフォルトの
localhostバインドを維持し、リモートアクセスには認証機能を備えたリバースプロキシ(例:基本認証または OAuth を設定した nginx)を前段に配置してください。ループバック以外のホストにバインドすると、サーバーは警告をログに記録します。
# Run with HTTP transport (localhost only — safe default)
uvx mcp-server-odoo --transport streamable-http --port 8000
# Binding 0.0.0.0 exposes the server to the network — see the security note above
uvx mcp-server-odoo --transport streamable-http --host 0.0.0.0 --port 8000
# Or use environment variables
export ODOO_MCP_TRANSPORT=streamable-http
export ODOO_MCP_HOST=0.0.0.0
export ODOO_MCP_PORT=8000
uvx mcp-server-odoo
HTTP エンドポイントは http://localhost:8000/mcp/ で利用できます。
注:SSE(Server-Sent Events)トランスポートは、MCP プロトコルバージョン 2025-03-26 で非推奨になりました。HTTP ベースの通信には、代わりに streamable-http トランスポートを使用してください。
注:HTTP トランスポートは、4 MiB を超えるリクエストボディを HTTP 413 で拒否します。開いているセッションは最大 10,000 件で、それを超える新規セッションには HTTP 503 を返します。
ODOO_MCP_SESSION_IDLE_TIMEOUTが未設定の場合、セッションは期限切れにならないため、長時間稼働する公開サーバーでは設定してください。
リモートアクセス用に streamable-http トランスポートを実行する
{
"mcpServers": {
"odoo-remote": {
"command": "uvx",
"args": ["mcp-server-odoo", "--transport", "streamable-http", "--port", "8080"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_API_KEY": "your-api-key-here",
"ODOO_DB": "your-database-name"
}
}
}
}
-
MCP モジュールをインストールする:
- mcp_server モジュールをダウンロードします
- Odoo インスタンスにインストールします
- Settings > MCP Server に移動します
-
MCP からアクセスするモデルを有効にする:
- Settings > MCP Server > Enabled Models に移動します
- アクセスするモデル(例:res.partner、product.product)を追加します
- モデルごとに権限(読み取り、書き込み、作成、削除)を設定します
-
API キーを生成する:
- Settings > Users & Companies > Users に移動します
- ユーザーを選択します
- 「API Keys」タブで、新しいキーを作成します
- Odoo 20 では、キーに RPC スコープ(
rpc)を付与します。Odoo 20 では、そのスコープがないキーは RPC ルートで受け付けられません。 - MCP の設定用にキーをコピーします
-
ユーザーに MCP アクセスを許可する:
- ユーザーのアクセス権で、そのユーザーを MCP User グループに追加します
- 最近のモジュールバージョンでは、このグループに属さないユーザーの API キーとパスワードログインは拒否されます。その場合、サーバーは起動時にモジュールから報告された理由を表示します。
YOLO モード(開発/テスト専用)⚠️
YOLO モードを使用すると、MCP モジュールなしで MCP サーバーを任意の標準 Odoo インスタンスに直接接続できます。このモードはすべての MCP セキュリティ制御を迂回するため、開発、テスト、デモ専用です。
🚨 警告:本番環境では YOLO モードを絶対に使用しないでください!
YOLO モードのレベル
-
読み取り専用モード(
ODOO_YOLO=read):- すべての読み取り操作(検索、読み取り、件数の取得)を許可します
- すべての書き込み操作(作成、更新、削除)をブロックします
- デモやテストに安全です
- レスポンスに「READ-ONLY」の表示が含まれます
-
フルアクセスモード(
ODOO_YOLO=true):- 制限なしですべての操作を許可します
- すべてのモデルに対する完全な CRUD アクセスが可能です
- 非常に危険です。隔離された環境でのみ使用してください
- レスポンスに「FULL ACCESS」の警告が含まれます
YOLO モードの設定
読み取り専用 YOLO モード(デモ向けのより安全な設定)
{
"mcpServers": {
"odoo-demo": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "http://localhost:8069",
"ODOO_USER": "admin",
"ODOO_PASSWORD": "admin",
"ODOO_DB": "demo",
"ODOO_YOLO": "read"
}
}
}
}
フルアクセス YOLO モード(⚠️ 最大限の注意を払って使用してください)
{
"mcpServers": {
"odoo-test": {
"command": "uvx",
"args": ["mcp-server-odoo"],
"env": {
"ODOO_URL": "http://localhost:8069",
"ODOO_USER": "admin",
"ODOO_PASSWORD": "admin",
"ODOO_DB": "test",
"ODOO_YOLO": "true"
}
}
}
}
YOLO モードを使用する場面
✅ 適切な用途:
- テストデータを使ったローカル開発
- 機密性のないデータを使った簡単なデモ
- MCP モジュールをインストールする前の MCP クライアントのテスト
- 隔離された環境でのプロトタイピング
❌ 使用してはいけない用途:
- 本番環境
- 実際の顧客データがあるインスタンス
- 共有開発サーバー
- 機密情報を含む環境
YOLO モードのセキュリティに関する注意事項
- Odoo の標準 XML-RPC エンドポイントに直接接続します。API キーを使用する場合、Odoo 19 以降では JSON-2(
/json/2)にも接続します(ODOO_RPC_TRANSPORTを参照) - すべての MCP アクセス制御とモデル制限を迂回します
- レート制限は適用されません
- すべての操作が記録されますが、制限はされません
- モデル一覧には、有効化されたモデルだけでなく 200 以上のモデルが表示されます
- フル YOLO モード(
true)では、作成、更新、削除の各ツールは、スケジュール済みアクション(ir.cron)やサーバーアクション(ir.actions.server)を含むすべてのモデルに対して実行できます。call_model_methodはこれらを直接実行することを拒否しますが、変更されたアクションは次回のスケジュール実行時またはトリガー時に実行されます。これは Odoo の UI で管理者が持つ権限と同等です。
使用例
設定が完了したら、Claude に次のように依頼できます。
検索と取得:
- 「スペインの顧客をすべて表示して」
- 「在庫が 10 個未満の商品を探して」
- 「今日の 1000 ドルを超える販売注文を一覧表示して」
- 「先月の未払い請求書を検索して」
- 「有効な従業員が何人いるか数えて」
- 「Microsoft の連絡先情報を表示して」
作成と管理:
- 「Acme Corporation の新しい顧客連絡先を作成して」
- 「価格 99.99 ドルの『Premium Widget』という新商品を追加して」
- 「明日の午後 2 時にカレンダーイベントを作成して」
- 「顧客 John Doe の電話番号を +1-555-0123 に更新して」
- 「注文 SO/2024/001 のステータスを確認済みに変更して」
- 「先ほど作成したテスト用連絡先を削除して」
利用可能なツール
search_records
フィルターを使用して、任意の Odoo モデルのレコードを検索します。
{
"model": "res.partner",
"domain": [["is_company", "=", true], ["country_id.code", "=", "ES"]],
"fields": ["name", "email", "phone"],
"limit": 10
}
フィールド選択オプション:
fieldsを省略するか、nullに設定すると、一般的なフィールドが自動的に選択されます- フィールドのリストを指定すると、そのフィールドのみが返されます
- 空のリスト
[]はnullと同様に扱われます(スマートなデフォルトが適用されます) ["__all__"]を使用すると、すべてのフィールドが返されます(慎重に使用してください)。認証情報に類するフィールドは返されず、レスポンスのnoteに一覧表示されます。必要な場合は、名前を明示してリクエストしてください
get_record
ID を指定して、特定のレコードを取得します。
{
"model": "res.partner",
"record_id": 42,
"fields": ["name", "email", "street", "city"]
}
フィールド選択オプション:
fieldsを省略するか、nullに設定すると、一般的なフィールドがメタデータとともに自動的に選択されます- フィールドのリストを指定すると、そのフィールドのみが返されます
- 空のリスト
[]はnullと同様に扱われます(スマートなデフォルトが適用されます) ["__all__"]を使用すると、すべてのフィールドが返されます。認証情報に類するフィールドは返されず、レスポンスのメタデータに記載されます。必要な場合は、名前を明示してリクエストしてください
レスポンスには related_summaries も含まれます。これは、最大 5 個の ID を持つ one2many/many2many コレクションの表示名で、追加の検索を行わなくても小規模な関連データを確認できます。
get_fields
モデルのフィールド(型、ラベル、必須/読み取り専用、関連先、選択肢)を説明します。レコードの読み取りや書き込みを行う前に、モデルのスキーマを確認するために使用します。attributes を省略すると、厳選されたデフォルトセット(type、string、required、readonly、relation、selection)が使用されます。明示的なリストを指定すると、厳選されたセットが置き換えられます。デフォルトも必要な場合は、リストに含めてください(例:["type", "string", "help", "store"])。field_names を省略すると、関連性の高い値フィールドの上位 60 個に加えて、すべての one2many、many2many、ファイル、HTML フィールドが返され、選択肢の一覧は 20 個までに制限されます。その場合、レスポンスには省略されたフィールド数を示す omitted と note が含まれます。すべてのフィールドを取得するには ["__all__"] を渡すか、必要なフィールド名を指定してください。この 2 つの形式では、選択肢の一覧は制限されません。どちらのパラメーターも、空のリスト [] は省略した場合と同様に扱われます。
{
"model": "res.partner",
"field_names": ["name", "email", "parent_id"]
}
get_current_context
現在のセッションコンテキストを返します。接続中のユーザー、そのタイムゾーン、アクティブな会社、およびアクセスが許可されているその他の会社と、UTC の日時の取り扱いに関するガイダンスが含まれます。リクエストがどのユーザーまたは会社として実行されるか、あるいは日時の解釈方法が不明な場合に便利です。仕様に準拠したクライアントは、initialize レスポンスの指示を通じてもこのコンテキストを受け取ります。
{}
list_models
MCP アクセスが有効なすべてのモデルを一覧表示します。
{}
list_resource_templates
利用可能なリソース URI テンプレートとそのパターンを一覧表示します。
{}
create_record
Odoo に新しいレコードを作成します。
{
"model": "res.partner",
"values": {
"name": "New Customer",
"email": "[email protected]",
"is_company": true
}
}
create_records
1 回の呼び出しで、同じモデルの複数のレコードを作成します。呼び出しごとに最大 100 件のレコードを指定できます。これは 1 つのトランザクションとして実行され、すべてのレコードが作成されるか、どれも作成されないかのいずれかです。
{
"model": "res.partner",
"records": [
{"name": "Customer A", "email": "[email protected]"},
{"name": "Customer B", "email": "[email protected]"}
]
}
update_record
既存のレコードを更新します。
{
"model": "res.partner",
"record_id": 42,
"values": {
"phone": "+1234567890",
"website": "https://example.com"
}
}
update_records
1 回の呼び出しで、同じモデルの複数のレコードを更新します。異なるレコードは最大 100 件まで指定できます。ID が 1 つでも存在しない場合、書き込みは一切行われません。アーカイブ済みのレコードも更新できます。たとえば、"active": true を指定してアーカイブを解除できます。次の 2 つの形式のいずれかを使用します。
Odoo のすべてのバージョンで、すべてのレコードに同じ値を設定する場合:
{
"model": "res.partner",
"record_ids": [42, 43, 44],
"values": {
"category_id": [[4, 7]]
}
}
Odoo 19 以降で、1 つのトランザクション内でレコードごとに異なる値を設定する場合:
{
"model": "res.partner",
"updates": [
{"id": 42, "values": {"phone": "+1 555 0100"}},
{"id": 43, "values": {"phone": "+1 555 0101"}}
]
}
2 つ目の形式では、Odoo の web_save_multi を使用します。標準モードでは、Odoo MCP モジュールでこのメソッドを許可する必要があります。
delete_record
Odoo からレコードを削除します。
{
"model": "res.partner",
"record_id": 42
}
read_attachment
ファイルを読み取ります。添付ファイル、または画像などのバイナリフィールドを指定できます。uri(ツールの結果から取得した odoo://attachment/{id} または odoo://{model}/record/{id}/{field} URI)か attachment_id のいずれか一方だけを指定してください。結果はファイルの種類によって異なります。
- テキストファイル:最大 100,000 文字のテキスト
- PDF ファイルおよび Office ファイル:Odoo が抽出したテキスト(Odoo が PDF のテキストを抽出するのは
attachment_indexationモジュールがある場合のみです) - 256 KB 以下の PNG、JPEG、GIF、WebP 画像:画像そのもの
- その他のファイル:Odoo にログインしている人向けのダウンロードリンク
{
"uri": "odoo://res.partner/record/42/image_1920"
}
ほとんどのチャットクライアントは MCP リソースを自ら読み取らないため、モデルがファイルを参照するにはこのツールを使います。
list_record_attachments
レコードに添付されたファイルを新しい順に一覧表示します。各ファイルの名前、MIME タイプ、サイズ、日付、odoo://attachment/{id} URI が含まれます。image_1920 などのバイナリフィールドに保存されているファイルは一覧に表示されません。これらは get_record が URI として返すためです。
{
"model": "res.partner",
"record_id": 42
}
upload_attachment
ファイルをレコードに添付します。data にはプレーンな Base64 形式のファイルを指定します。デコード後のサイズは約 2.9 MB までです。mimetype が指定されていない場合、Odoo が MIME タイプを判別します。結果には、新しい添付ファイルの ID と odoo://attachment/{id} URI が含まれます。ファイルをチャターに表示するには、ID を attachment_ids として post_message に渡してください。
{
"model": "res.partner",
"record_id": 42,
"name": "contract.pdf",
"data": "JVBERi0xLjQK...",
"mimetype": "application/pdf"
}
標準モードでは、ユーザーにレコードのモデルへの書き込み権限と、ir.attachment の作成権限が必要です。
post_message
レコードのチャター(mail.thread)にメッセージを投稿します。subtype="note"(デフォルト)は内部ログ、subtype="comment" はフォロワーへの通知です。HTML マークアップを使う場合は body_is_html=true を設定してください。任意の subject でメッセージの件名を設定できます。任意の partner_ids と attachment_ids では、既存の取引先と添付ファイルを参照できます。
{
"model": "res.partner",
"record_id": 42,
"body": "Called customer, will follow up Tuesday"
}
{
"model": "sale.order",
"record_id": 17,
"body": "<p>Shipping confirmed for Monday</p>",
"subtype": "comment",
"body_is_html": true
}
aggregate_records
サーバー側で集計します。「レコードの一覧」ではなく「合計/件数/グループ分け」を求める質問では、未加工の行を取得する代わりに処理を PostgreSQL に委ねるこのツールを使ってください。Odoo 19 以降では formatted_read_group(新しい専用メソッド)を呼び出し、それより古いバージョンでは read_group を呼び出してレスポンスを正規化します。呼び出し元には、すべての対応バージョンで一貫した形式のレスポンスが返されます。aggregates を省略すると ["__count"] がデフォルトで指定され、各グループに必ず件数が含まれます。要求したページを超えるグループがある場合、レスポンスには has_more: true と、次のオフセットを指定する next_hint が設定されます。
{
"model": "sale.order",
"groupby": ["date_order:month"],
"aggregates": ["amount_total:sum"],
"domain": [["state", "in", ["sale", "done"]]]
}
{
"model": "res.partner",
"groupby": ["country_id"]
}
call_model_method
汎用 XML-RPC execute_kw のエスケープハッチです。CRUD では対応できないワークフローアクション(請求書の転記、販売オーダーの確定、ピッキングの検証など)で、公開されている業務メソッドを呼び出します。ODOO_YOLO=true(フル YOLO)と ODOO_MCP_ENABLE_METHOD_CALLS=true の両方が設定されている場合にのみ利用でき、それ以外ではツールは登録されません。メソッド名として受け付けるのは、公開されている ASCII の Python 識別子のみです。ドット、ハイフン、空白、非 ASCII 文字、_ で始まる名前は拒否されます。
フル YOLO モードでも、安全のため一部の呼び出しはブロックされます。
ir.actions.*/ir.cronモデル — メソッドが昇格された権限で実行されます(サーバーアクション、スケジュール済みジョブ)- 任意のモデルに対する
run/method_direct_trigger— プロキシ経由で同様に権限が昇格するリスクがあります - ORM の CRUD/データアクセスプリミティブ(
create、write、unlink、read、search*、copy、sudoなど)— 専用ツールを使用してください web_*メソッド — Web クライアントのデータアクセス機能群
リストの結果は 100 件に切り詰められます。
JSON-2 経由(Odoo 19 以降で API キーを使用した YOLO モード、または ODOO_RPC_TRANSPORT=json2)では、Odoo は名前付き引数のみを受け付けます。この場合、arguments に含められるのはレコード ID のみで、最初の項目として指定します。それ以外の引数はすべて、パラメーター名を使って keyword_arguments に渡してください。例:{"partner_ids": [3]}。
警告
このツールでは、破壊的なワークフローメソッド(例:
button_draft、action_cancel、toggle_active、カスタムメソッド)も呼び出せます。影響範囲を許容できる、信頼できる環境でのみ有効にしてください。認証済みユーザーには、引き続き Odoo のレコードルールと ACL が適用されます。
{
"model": "account.move",
"method": "action_post",
"arguments": [[42]]
}
{
"model": "sale.order",
"method": "action_confirm",
"arguments": [[7]],
"keyword_arguments": {"context": {"lang": "en_US"}}
}
スマートフィールド選択
fields パラメーターを省略するか null に設定すると、サーバーはスコアリングアルゴリズムを使って、各モデルで最も関連性の高いフィールドを自動選択します。
id、name、display_name、activeなどの必須フィールドは常に含まれます- (state、amount、email、phone、partner などの)業務関連フィールドが優先されます
- (メッセージスレッド、アクティビティ追跡、Web サイトのメタデータなどの)技術フィールドは除外されます
- コストの高いフィールド(binary、HTML、大きなテキスト)はスキップされ、計算される非保存フィールドの優先度は下げられます
- 認証情報に類するフィールド(
*passwordで終わる名前、smtp_passのような*_pass、passwd、*secret、*_token、*apikey、またはapi_key/secret_keyのような複合的な*_key)は、スマートなデフォルト選択から除外され、["__all__"]の読み取りでは説明付きの注記を添えて除外されます。フィールド名を明示的に指定して要求した場合は、引き続き返されます
デフォルトでは、リクエストあたり最大 15 フィールドです。レスポンスには、返されたフィールドと利用可能なフィールドの総数を示すメタデータが含まれます。ODOO_MCP_MAX_SMART_FIELDS で上限を調整するか、fields: ["__all__"] ですべてのフィールドを取得できます。
Odoo が接続ユーザーによるフィールドへのアクセスを拒否する場合(たとえば、会計権限のないユーザーが連絡先の会計合計を取得しようとする場合)、スマートなデフォルト選択または ["__all__"] による読み取りでは、そのフィールドは除外されます。レスポンスでは、skipped_fields と注記にそのフィールドが記載されます。フィールドのリストを明示した読み取りでは、アクセスエラーが発生します。
呼び出しごとのコンテキスト
search_records、get_record、aggregate_records、create_record、create_records、update_record、update_records では、省略可能な context オブジェクトを指定できます。次の4つのキーを受け付けます。
| キー | 効果 |
|---|---|
allowed_company_ids | 呼び出しの対象となる会社です。最初の会社が有効な会社となるため、standard_price など会社に依存するフィールドは、その会社の値を読み書きします。 |
lang | ラベルと翻訳済みの値に使用する言語です。Odoo にインストールされていない言語は拒否されます。Odoo 16 と 17 では、サーバーがこの設定をチェックします。標準モードでは、これには res.partner または res.lang を MCP で有効にする必要があります。有効にしない場合は en_US のみ受け付けられます。 |
tz | 呼び出しのタイムゾーンです。 |
active_test | false にすると、検索にアーカイブ済みレコードも含まれます。 |
このツールは、その他のキーを拒否し、そのキー名を示します。各会社はユーザーの所属会社のいずれかであり、ODOO_ALLOWED_COMPANIES が設定されている場合は、その中の会社である必要があります。コンテキストは、検索、件数の取得、読み取り、存在確認、書き込み後の再読み取りに適用されます。
{
"model": "product.product",
"record_id": 42,
"values": {"standard_price": 12.5},
"context": {"allowed_company_ids": [5]}
}
リソース
サーバーは、リソース URI を通じて Odoo データに直接アクセスする機能も提供します。
| URI パターン | 説明 |
|---|---|
odoo://{model}/record/{id} | ID を指定して特定のレコードを取得します |
odoo://{model}/search | デフォルト設定(先頭から ODOO_MCP_DEFAULT_LIMIT 件。デフォルトは25件)でレコードを検索します |
odoo://{model}/count | モデル内のすべてのレコード数を取得します |
odoo://{model}/fields | モデルのフィールド定義とメタデータを取得します |
odoo://{model}/record/{id}/{field} | レコードのバイナリ/画像フィールドを、適切な mimeType で取得します |
odoo://attachment/{id} | ID を指定して ir.attachment を取得します(URL タイプの添付ファイルはテキストとして URL を返します) |
例:
odoo://res.partner/record/1— ID 1 の取引先を取得しますodoo://product.product/search— 先頭の製品を一覧表示します(ODOO_MCP_DEFAULT_LIMIT。デフォルトは25件)odoo://res.partner/count— すべての取引先数を取得しますodoo://product.product/fields— 製品のすべてのフィールドを表示しますodoo://res.partner/record/1/image_128— 取引先1のアバター画像を取得しますodoo://attachment/42— 添付ファイル42をダウンロードします
get_record/search_records の結果で値が設定されたバイナリフィールドは、インラインの base64 ではなく、これらのリソース URI として返されます。実際のバイトデータを取得するには URI を読み取ってください。バイトデータは resources/read、または read_attachment ツールから取得できます。read_attachment ツールは、リソースを読み取らないクライアント向けに、テキストファイル(最大1 MB)と PNG、JPEG、GIF、WebP 画像(最大256 KB)をインラインで返します。
レコードおよび検索リソースの読み取りでは、ツールの一括読み取りと同様に、認証情報に該当するフィールドが除外されます。このようなフィールドを読み取るには、ツールの fields パラメーターでフィールド名を明示的に指定してください。
バイナリと添付ファイルは、ODOO_MCP_MAX_BINARY_SIZE(デフォルトは50 MB)まで全体を読み取って返します。サイズはペイロードを取得する前に確認されるため、上限を超えるフィールドや添付ファイルは、同等に大きな応答にバッファーされるのではなく、明確なエラーとともに拒否されます。Odoo 20 では、非保存のバイナリフィールド、または保存済みでもユーザーが添付ファイルを読み取れないフィールドは、取得後にのみ確認されます。
注: リソース URI は、
?domain=...のようなクエリパラメーターに対応していません。フィルタリング、ページネーション、フィールド選択には、代わりにsearch_recordsツールを使用してください。
仕組み
AI Assistant (Claude, Copilot, etc.)
↓ MCP Protocol (stdio or HTTP)
mcp-server-odoo
↓ XML-RPC, or JSON-2 on Odoo 19+ in YOLO mode
Odoo Instance
このサーバーは、MCP ツールの呼び出しを Odoo の XML-RPC リクエストに変換します。YOLO モードで API キーを使用する場合、Odoo 19 以降では JSON-2 リクエストに変換します。認証、アクセス制御、フィールド選択、データの整形、エラー処理を行い、LLM が扱いやすい階層型テキスト形式で Odoo データを提供します。
セキュリティ
- 本番環境では必ず HTTPS を使用してください
- API キーを安全に保管し、定期的にローテーションしてください
- モデルへのアクセスは慎重に設定し、必要なモデルのみを有効にしてください
- MCP モジュールは、Odoo に組み込まれたアクセス権とレコードルールを尊重します
- 各 API キーは、それぞれの権限を持つ特定のユーザーに紐付けられます
標準モードでのモデル許可リストの適用方法
標準モードでは、サーバーは各呼び出しの前に MCP モジュールのモデル許可リストを確認します。また、呼び出しが別のモデルを経由してアクセスするモデルも確認します。
values内のネストされた x2many コマンド。作成コマンド([0, 0, {...}])には関連モデルへの作成アクセス権、更新([1, id, {...}])には書き込みアクセス権、削除([2, id])には削除アクセス権が必要です。- one2many フィールドでのリンク(
[4, id])には関連モデルへの書き込みアクセス権が必要です。削除([3, id]、[5]、または[6, 0, ids])には書き込みアクセス権と削除アクセス権が必要です。これは、逆フィールドのカスケードによって Odoo が関連レコードを削除するためです。関連モデルで削除が許可されていない場合は、代わりに関連レコードのリンクフィールドを更新してください。 - 添付ファイル、メッセージ、メール、フォロワー、アクティビティ、トラッキング値、通知。読み取りでは、読み取りが許可されたモデルの行のみが返されます。行の作成、変更、移動、削除には、ネストされたコマンド(
message_ids: [[1, id, {...}]]など)を介する場合も含め、その行が属するモデルへの書き込みアクセス権が必要です。 - アクティビティを作成するには、サーバーが
res_model_idのモデルを特定するためにir.modelを読み取ります。そのため、MCP でir.modelの読み取りが許可されている必要があります。 - リレーションを介した読み取り。
user_ids.groups_id.nameのようなドット区切りパスの条件、anyまたはnot anyの条件、x2many フィールドの名前に対する条件、リレーションを介したorderには、経由する各関連モデルへの読み取りアクセス権が必要です。x2many フィールドでグループ化する場合も、その関連モデルへの読み取りアクセス権が必要です。many2one の名前による条件(country_id ilike Germany)は引き続き許可されますが、その中のドット区切りパス(country_id.code = DE)には関連モデルへの読み取りアクセス権が必要です。
これらのチェックは、書き込み可能な関連フィールドと _inherits の親モデルには適用されません。たとえば、ユーザーの email を書き込むと、パートナーにも書き込まれます。同様に、会社の名前、メールアドレス、電話番号、住所はそのパートナーレコードのフィールドです。res.partner で書き込みが許可されていれば、res.company が読み取り専用でも変更できます。many2one の値は、その値を保持するレコードの一部として扱われます。読み取りやグループ化ではその名前が返され、無効化されているモデルのレコードにも設定できます。many2many リンク([4, id]、[3, id]、[6, 0, ids])にも同じことが当てはまります。Odoo 独自のアクセス権とレコードルールは、すべての呼び出しに適用されます。
トラブルシューティング
接続の問題
接続エラーが発生する場合:
- Odoo の URL が正しく、アクセス可能であることを確認してください
- MCP モジュールがインストールされていることを確認してください:
https://your-odoo.com/mcp/healthにアクセスします - ファイアウォールで Odoo への接続が許可されていることを確認してください
認証エラー
認証に失敗する場合:
- Odoo で API キーが有効であることを確認してください
- ユーザーに適切な権限があることを確認してください
- API キーを再生成してみてください
- ユーザー名/パスワード認証の場合は、2FA が有効になっていないことを確認してください
- Odoo 20 では、API キーに
rpcスコープがあることを確認してください - 標準モードでは、ユーザーが MCP User グループに所属していることを確認してください
モデルへのアクセスエラー
特定のモデルにアクセスできない場合:
- Odoo で Settings > MCP Server > Enabled Models に移動します
- モデルがリストにあり、適切な権限が設定されていることを確認してください
- Odoo のセキュリティ設定で、ユーザーがそのモデルにアクセスできることを確認してください
「spawn uvx ENOENT」エラー
このエラーは、UV がインストールされていないか、PATH に含まれていないことを意味します。
解決策 1:UV をインストールする(上記のインストールセクションを参照)
解決策 2:macOS の PATH の問題 macOS 版 Claude Desktop はシェルの PATH を引き継ぎません。次の手順を試してください:
- Claude Desktop を完全に終了します(Cmd+Q)
- ターミナルを開きます
- ターミナルから Claude を起動します:
open -a "Claude"
解決策 3:フルパスを使用する UV の場所を確認し、フルパスを使用します:
which uvx
# Example output: /Users/yourname/.local/bin/uvx
次に、設定を更新します:
{
"command": "/Users/yourname/.local/bin/uvx",
"args": ["mcp-server-odoo"]
}
データベース設定の問題
データベースの一覧表示時に「Access Denied」と表示される場合:
- これは正常です。一部の Odoo インスタンスでは、セキュリティ上の理由からデータベースの一覧表示が制限されています
- 設定で
ODOO_DBを指定してください - サーバーは検証を行わず、指定されたデータベースを使用します
設定例:
{
"env": {
"ODOO_URL": "https://your-odoo.com",
"ODOO_API_KEY": "your-key",
"ODOO_DB": "your-database-name"
}
}
注:サーバーでデータベースの一覧表示が制限されている場合、ODOO_DB は必須です。
「SSL: CERTIFICATE_VERIFY_FAILED」エラー
このエラーは、Python が SSL 証明書を検証できない場合に発生し、macOS や企業ネットワークでよく見られます。
解決策:環境設定に SSL 証明書のパスを追加します:
{
"env": {
"ODOO_URL": "https://your-odoo.com",
"ODOO_API_KEY": "your-key",
"SSL_CERT_FILE": "/etc/ssl/cert.pem"
}
}
これにより、HTTPS 接続で使用するシステムの SSL 証明書バンドルの場所を Python に知らせます。パス /etc/ssl/cert.pem は、ほとんどのシステムで標準の場所です。
デバッグモード
詳細情報を得るには、デバッグログを有効にしてください:
{
"env": {
"ODOO_URL": "https://your-odoo.com",
"ODOO_API_KEY": "your-key",
"ODOO_MCP_LOG_LEVEL": "DEBUG"
}
}
開発
ソースから実行する
# Clone the repository
git clone https://github.com/ivnvxd/mcp-server-odoo.git
cd mcp-server-odoo
# Install in development mode
pip install -e ".[dev]"
# Run tests
pytest --cov
# Run the server
python -m mcp_server_odoo
# Check version
python -m mcp_server_odoo --version
MCP Inspector でテストする
# Using uvx
npx @modelcontextprotocol/inspector uvx mcp-server-odoo
# Using local installation
npx @modelcontextprotocol/inspector python -m mcp_server_odoo
テスト
テストの実行
# Unit tests (no Odoo needed)
uv run pytest -m "not yolo and not mcp" --cov
# YOLO integration tests (vanilla Odoo, no MCP module)
uv run pytest -m "yolo" -v
# MCP integration tests (Odoo + MCP module installed)
uv run pytest -m "mcp" -v
# All tests
uv run pytest --cov
# Run specific test categories
uv run pytest tests/test_tools.py -v
uv run pytest tests/test_server_foundation.py -v
ライセンス
このプロジェクトは Mozilla Public License 2.0(MPL-2.0)の下でライセンスされています。詳細については、LICENSE ファイルを参照してください。
貢献
貢献を心より歓迎します!詳細については、CONTRIBUTING ガイドを参照してください。
サポート
このプロジェクトをご利用いただきありがとうございます!役に立ったと感じ、私の活動を支援したいと思われたら、コーヒーをおごっていただけると幸いです。ご支援に心より感謝いたします!
気に入っていただけたら、プロジェクトにスターを付けるのもお忘れなく! :star:
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。
