원클릭으로
odoo-mcp-legacy-reference
Legacy reference document kept for migration context. Use the odoo-mcp skill and tools for active Odoo operations.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Legacy reference document kept for migration context. Use the odoo-mcp skill and tools for active Odoo operations.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Recursive Language Models utilities for partitioning large datasets and aggregating results from sub-agents in OdooClaw.
Microsoft Edge Text-to-Speech (TTS) synthesis. Converts text to natural audio using Edge's AI voices. Uploads directly to Odoo as voice attachments with discuss.voice.metadata. Use when user wants voice/audio response, asks to "speak this", "read aloud", "voice response".
Read and control I2C and SPI peripherals on Sipeed boards (LicheeRV Nano, MaixCAM, NanoKVM).
Extract supplier invoice data from Odoo attachment (PDF/image) using an OpenAI-compatible vision model and optionally create the vendor bill automatically in Odoo.
Speech-to-Text transcription using Whisper. Transcribes voice messages from Odoo attachments to text. Supports local Faster Whisper (no API key) and OpenAI Whisper API fallback. Use when user sends a voice note or audio attachment.
Extract supplier invoice data from Odoo attachment (PDF/image) using an OpenAI-compatible vision model and optionally create the vendor bill automatically in Odoo.
| name | odoo-mcp-legacy-reference |
| description | Legacy reference document kept for migration context. Use the odoo-mcp skill and tools for active Odoo operations. |
| homepage | https://www.odoo.com/documentation/ |
| metadata | {"openclaw":{"emoji":"🏢","requires":{"env":["ODOO_URL","ODOO_DB","ODOO_USERNAME","ODOO_PASSWORD"]},"primaryEnv":"ODOO_PASSWORD"}} |
Odoo server URL precedence (highest to lowest):
temporary_url — one-time URL for a specific operationuser_url — user-defined URL for the current sessionODOO_URL — environment default URLThis allows you to:
Examples (conceptual):
// Default: uses ODOO_URL from environment
{{resolved_url}}/xmlrpc/2/common
// Override for one operation:
temporary_url = "https://staging.mycompany.odoo.com"
{{resolved_url}}/xmlrpc/2/common
// Override for session:
user_url = "https://client-xyz.odoo.com"
{{resolved_url}}/xmlrpc/2/common
Database name (db) precedence:
temporary_dbuser_dbODOO_DBUse this to:
Username precedence:
temporary_usernameuser_usernameODOO_USERNAMESecret (password or API key) precedence:
temporary_api_key or temporary_passworduser_api_key or user_passwordODOO_API_KEY (if set) or ODOO_PASSWORDImportant:
Environment variables are handled via standard OpenClaw metadata: requires.env declares required variables (ODOO_URL, ODOO_DB, ODOO_USERNAME, ODOO_PASSWORD). ODOO_API_KEY is an optional environment variable used instead of the password when present; it is not listed in metadata and should simply be set in the environment when needed.
At runtime the skill always works with:
{{resolved_url}} — final URL{{resolved_db}} — final database name{{resolved_username}} — final login{{resolved_secret}} — password or API key actually used to authenticateThese are computed using the precedence rules above.
The
temporary_*anduser_*names are runtime context variables used by the skill logic, not OpenClaw metadata fields. OpenClaw does not have anoptional.contextmetadata key; context is resolved dynamically at runtime as described below.
User examples:
odoo_demo juste pour cette opération"Behavior:
temporary_* (url, db, username, api_key/password)This is ideal for:
User examples:
clientx_prod pour cette session"Behavior:
user_* (url, db, username, api_key/password)temporary_* or by clearing user_*User examples:
Action:
user_url, user_db, user_username, user_password, user_api_keyODOO_URL, ODOO_DB, ODOO_USERNAME, ODOO_PASSWORD / ODOO_API_KEY)User examples:
Response should show (never full secrets):
Current Odoo Context:
- URL: https://client-xyz.odoo.com (user_url)
- DB: clientxyz_prod (user_db)
- Username: api_integration (user_username)
- Secret: using API key (user_api_key)
- Fallback URL: https://default.odoo.com (ODOO_URL)
- Fallback DB: default_db (ODOO_DB)
Odoo exposes part of its server framework over XML-RPC (not REST). The External API is documented here: https://www.odoo.com/documentation/18.0/fr/developer/reference/external_api.html
Two main endpoints:
{{resolved_url}}/xmlrpc/2/common — authentication and meta calls{{resolved_url}}/xmlrpc/2/object — model methods via execute_kwCall version() on the common endpoint to verify URL and connectivity:
common = xmlrpc.client.ServerProxy(f"{resolved_url}/xmlrpc/2/common")
version_info = common.version()
Example result:
{
"server_version": "18.0",
"server_version_info": [18, 0, 0, "final", 0],
"server_serie": "18.0",
"protocol_version": 1
}
Use authenticate(db, username, password_or_api_key, {}) on the common endpoint:
uid = common.authenticate(resolved_db, resolved_username, resolved_secret, {})
uid is an integer user ID and will be used in all subsequent calls.
If authentication fails, uid is False / 0 — the skill should:
ODOO_URL, ODOO_DB, username, and secretBuild an XML-RPC client for the object endpoint:
models = xmlrpc.client.ServerProxy(f"{resolved_url}/xmlrpc/2/object")
Then use execute_kw with the following signature:
models.execute_kw(
resolved_db,
uid,
resolved_secret,
"model.name", # e.g. "res.partner"
"method_name", # e.g. "search_read"
[positional_args],
{keyword_args}
)
All ORM operations in this skill are expressed in terms of execute_kw.
Domains are lists of conditions:
domain = [["field_name", "operator", value], ...]
Examples:
[['is_company', '=', True]][['country_id', '=', france_id]][['probability', '>', 50]]Common operators:
"=", "!=", ">", ">=", "<", "<=""like", "ilike" (case-insensitive)"in", "not in""child_of" (hierarchical relations)YYYY-MM-DD or ISO 8601 format.int) when writing; reads often return [id, display_name].Each subsection below shows typical user queries and the corresponding
execute_kw usage. They are applicable to any model (not only res.partner).
User queries:
Action (generic):
ids = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "search",
[domain],
{"offset": 0, "limit": 80}
)
Notes:
domain is a list (can be empty [] to match all records).offset and limit for pagination.User queries:
Action:
count = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "search_count",
[domain]
)
User queries:
Action:
records = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "read",
[ids],
{"fields": ["name", "country_id", "comment"]}
)
If fields is omitted, Odoo returns all readable fields (often a lot).
Shortcut for search() + read() in a single call.
User queries:
Action:
records = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "search_read",
[domain],
{
"fields": ["name", "country_id", "comment"],
"limit": 5,
"offset": 0,
# Optional: "order": "name asc"
}
)
User queries:
Action:
new_id = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "create",
[{
"name": "New Partner"
# other fields...
}]
)
Returns the newly created record ID.
User queries:
Action:
success = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "write",
[ids, {"field": "new value", "other_field": 123}]
)
Notes:
ids is a list of record IDs.ids receive the same values.User queries:
Action:
success = models.execute_kw(
resolved_db, uid, resolved_secret,
"model.name", "unlink",
[ids]
)
Useful for quick lookup on models with a display name (e.g. partners, products).
User queries:
Action:
results = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "name_search",
["Agrolait"],
{"limit": 10}
)
Result is a list of [id, display_name].
res.partner is the core model for contacts, companies, and many business relations in Odoo.
User queries:
Action:
companies = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "search_read",
[[["is_company", "=", True]]],
{"fields": ["name", "country_id", "comment"], "limit": 80}
)
User queries:
Action:
[partner] = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "read",
[[7]],
{"fields": ["name", "country_id", "comment"]}
)
User queries:
Minimal body:
partner_id = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "create",
[{
"name": "New Partner",
"is_company": True
}]
)
Additional fields examples:
street, zip, city, country_idemail, phone, mobilecompany_type ("person" or "company")User queries:
Action:
models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "write",
[[7], {
"street": "New street 1",
"phone": "+33 1 23 45 67 89"
}]
)
User queries:
Action:
models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "unlink",
[[999]]
)
User queries:
Action:
fields = models.execute_kw(
resolved_db, uid, resolved_secret,
"res.partner", "fields_get",
[],
{"attributes": ["string", "help", "type"]}
)
The result is a mapping from field name to metadata:
{
"name": {"type": "char", "string": "Name", "help": ""},
"country_id": {"type": "many2one", "string": "Country", "help": ""},
"is_company": {"type": "boolean", "string": "Is a Company", "help": ""}
}
User queries:
Action:
models_list = models.execute_kw(
resolved_db, uid, resolved_secret,
"ir.model", "search_read",
[[]],
{"fields": ["model", "name", "state"], "limit": 200}
)
state indicates whether a model is defined in code ("base") or created dynamically ("manual").
User queries:
Action (simplified):
partner_model_ids = models.execute_kw(
resolved_db, uid, resolved_secret,
"ir.model", "search",
[[["model", "=", "res.partner"]]]
)
fields_meta = models.execute_kw(
resolved_db, uid, resolved_secret,
"ir.model.fields", "search_read",
[[["model_id", "in", partner_model_ids]]],
{"fields": ["name", "field_description", "ttype", "required", "readonly"], "limit": 500}
)
authenticate returns False or later calls fail.xmlrpc/2/common or xmlrpc/2/object.The skill should:
limit / offset on search and search_read to handle large datasets.limit to a reasonable value (e.g. 80).fields list for read / search_read when possible.=, in) for large datasets.{{resolved_url}}, {{resolved_db}}, {{resolved_username}}, {{resolved_secret}}version() on {{resolved_url}}/xmlrpc/2/commonuidexecute_kw on res.partner with search_read and domain [['is_company', '=', True]]common.authenticatecreate a new res.partner with {"name": "New Partner", "is_company": True}read that ID with fields ["name", "is_company", "country_id"]temporary_url and/or temporary_db to point to another Odoo environment.This skill can:
search, search_count, read, search_read, create, write, unlink) on any Odoo model via execute_kw.res.partner (contacts / companies).fields_get, ir.model, and ir.model.fields.