Who am I (yekar.odoo.whoami) | Read | The Odoo identity this connection acts as - uid, name, login, company and server version. EVERY action this integration takes runs as this user, so their access rights and record rules are the ceiling for everything: a record they cannot see does not exist as far as these tools are concerned, and a count they cannot see is smaller than the truth. Call this first to verify a connection. |
List models (yekar.odoo.list-models) | Read | The models installed in this database - the index for every other tool here, since a model name is what they all take. Search by technical name or label. total is Odoo's own count over the whole filter, so a page never has to be mistaken for the census. Common starting points: res.partner, res.users, res.company, crm.lead, sale.order, sale.order.line, purchase.order, account.move. |
Describe model (yekar.odoo.describe-model) | Read | A model's fields - technical name, label, type, required/readonly, the related model for relational fields, and the accepted values for selection fields. Read this before searching or writing: field names are technical (partner_id, not "Customer"), and a selection field rejects any value outside its list. Mature models carry hundreds of fields, so at most 200 are returned and total says how many exist - narrow with q rather than assuming the list is complete. |
Search records (yekar.odoo.search-records) | Read | Read records from any Odoo model with a search domain - the workhorse of this integration. total is Odoo's own count over the same domain as the rows, so a page is never mistaken for the whole set, and hasMore says whether to raise the offset. Two Odoo conventions come back untranslated and matter when reading the values: an empty field is false (not null), and a many2one is [id, "Display Name"] while an x2many is a list of ids. ARCHIVED records are excluded unless you ask for them - a count that ignores them is smaller than the database. |
Count records (yekar.odoo.count-records) | Read | How many records match a domain, counted by Odoo in SQL - no rows fetched, no page size involved. Use this whenever the answer is a number: counting a page of Search records would saturate at the page size and report a cap as a fact. The count is what the CONNECTED USER can see (record rules apply) and excludes archived records unless you ask for them. |
Get records (yekar.odoo.get-record) | Read | Read specific records by id. Ids that no longer exist - or that the connected user's record rules hide - are returned in missingIds rather than silently dropped, so a short result is never mistaken for a complete one. Values use Odoo's own encoding: an empty field is false, a many2one is [id, "Display Name"], an x2many a list of ids. Long text values are capped and named in truncatedFields. |
Create record (yekar.odoo.create-record) | Write | Create one record on any model. Odoo runs the model's own onchange-free create logic, so required fields, selection values and record rules all apply - a rejection comes back as an invalid-input error naming the field. The new id is returned even if reading the record back afterwards fails, because the create itself already committed. |
Update records (yekar.odoo.update-record) | Write | Write field values to one or more records. Only the fields you name change. The same values go to every id, so this is a bulk edit when several are passed. To ARCHIVE rather than delete - Odoo's usual answer for a record that must stop appearing but cannot be destroyed - write {"active": false}. Note that Odoo's write returns nothing but success, so the result echoes what was requested; read the records back if you need the stored values. |
Delete records (yekar.odoo.delete-record) | Write | Delete records PERMANENTLY. There is no undo and no recycle bin: Odoo drops the rows. Prefer archiving instead - Update records with {"active": false} hides a record everywhere while keeping its history, and it is what Odoo itself does for customers, products and employees that are no longer in use. Many records cannot be deleted at all: anything a posted invoice, a confirmed order or an accounting entry references is protected by the database, and that refusal comes back as a conflict rather than a silent no-op. Deletion is all-or-nothing - if one id fails, none are removed. |
Post message (yekar.odoo.post-message) | Write | Post to a record's chatter - the message log on leads, orders, invoices, partners and tasks. The audience is an explicit argument, not a default: notifyFollowers: false writes an internal log note that only people with access to the record can see, while notifyFollowers: true posts a message that notifies the record's followers, which on a customer-facing record means EMAIL LEAVES THE SYSTEM. Choose deliberately, and never repeat an internal note to a customer. |
Call model method (yekar.odoo.call-method) | Write | The escape hatch: call any public method on any model. This is how Odoo work that is not plain CRUD gets done - confirming a sale order, posting an invoice, running read_group for aggregates, resolving a name to an id with name_search. It is UNRESTRICTED: whatever the method does, it does, and the connected user's rights are the only limit - so it is treated as a write regardless of the method named. Prefer the specific tools (Search records, Update records, Post message) when they fit; use this when they do not. Results over 60000 characters are withheld and flagged rather than truncated silently. |