odoo-bookkeeping-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ODOO_DB | Yes | The name of the Odoo database. | |
| ODOO_URL | Yes | The URL of the Odoo instance. | |
| ODOO_API_KEY | Yes | The API key for the Odoo user. | |
| ODOO_USERNAME | Yes | The Odoo username (typically an email address). | |
| ODOO_MCP_ALLOW_POST | No | Gates posting invoices/journal entries and registering payments. | true |
| ODOO_MCP_ALLOW_UNLINK | No | Gates the odoo_unlink tool (permanent record deletion). | false |
| ODOO_MCP_ALLOW_RECONCILE | No | Gates the reconcile_lines tool. | true |
Capabilities
Features and capabilities supported by this server
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| odoo_search_readA | Search and read records of ANY Odoo model in one call. model: technical model name, e.g. "account.move", "res.partner", "project.budget.line". domain: Odoo domain, e.g. [["state", "=", "draft"]]. Empty/omitted matches all records (subject to record rules). fields: field names to return; omit for all fields. limit: max records to return (default 80, use 0 for no limit -- careful on large models). order: e.g. "date desc, id desc". |
| odoo_fields_getA | List every field on an Odoo model: type, label, required, readonly, relation target, selection options. Use this before create/write on an unfamiliar model instead of guessing field names. |
| odoo_createA | Create ONE record on any model. Returns the new record's id. Example: odoo_create("res.partner", {"name": "Acme LLC"}). For accounting documents prefer the dedicated accounting.* tools (they set up lines/taxes/journals correctly) -- use this for anything they don't cover. |
| odoo_writeC | Update one or more existing records with the given field values. |
| odoo_unlinkA | Permanently delete one or more records. THIS CANNOT BE UNDONE. Disabled by default (ODOO_MCP_ALLOW_UNLINK=false) because Odoo has no "undo" for a deleted record -- unlike posted accounting entries, which can always be reversed with a credit note / reversal entry. Set ODOO_MCP_ALLOW_UNLINK=true in the server's environment to allow this tool to actually delete anything. |
| odoo_call_methodA | Call ANY method on an Odoo model -- the universal escape hatch. Use this for workflow actions the dedicated tools don't wrap yet, e.g. odoo_call_method("account.move", "button_draft", [123]) or odoo_call_method("project.budget", "action_approve", [7]). ids may be empty for @api.model methods that don't act on records. |
| create_invoiceA | Create a DRAFT customer invoice or vendor bill. move_type: "out_invoice" (customer invoice), "out_refund" (credit note), "in_invoice" (vendor bill), "in_refund" (vendor credit note). lines: list of dicts, each with at least "name" (description), "quantity", "price_unit". Optional per line: "product_id", "account_id", "tax_ids" (list of tax ids), "analytic_distribution" (e.g. {"": 100.0}). Always created in draft -- call post_invoice() to post it once you're satisfied. |
| update_invoiceA | Update a draft invoice/bill's header fields and/or replace its lines entirely. Odoo will reject this once the move is posted -- use a reversal/credit note for posted documents instead. lines, if given, REPLACES all existing lines (same line-dict shape
as create_invoice's |
| post_invoiceA | Post (confirm) a draft invoice/vendor bill. Irreversible in the sense that a posted move must be reversed/credited, not edited, to correct it afterwards. |
| search_invoicesC | Search customer invoices / vendor bills / credit notes. Example domain: [["move_type", "=", "in_invoice"], ["state", "=", "draft"]]. |
| get_invoiceA | Full detail of one invoice/bill including its lines. |
| create_journal_entryA | Create a DRAFT manual journal entry (move_type='entry'). lines: list of dicts, each with "account_id" and either "debit" or "credit" (or both, defaulting to 0) plus optional "name" (label), "partner_id", "analytic_distribution". Must balance (total debit == total credit) -- Odoo enforces this on post. |
| update_journal_entryA | Update a draft journal entry's header and/or replace its lines
entirely (same line-dict shape as create_journal_entry's |
| post_journal_entryA | Post a draft journal entry. Same irreversibility caveat as post_invoice -- correct a posted entry with a reversal, not a write. |
| reverse_journal_entryA | Create and post a reversal of an already-posted move -- the correct way to undo a posted entry (never edit or delete a posted move directly). |
| search_journal_entriesB | Search journal entries/invoices/bills of any move_type. Example domain: [["move_type", "=", "entry"], ["date", ">=", "2026-01-01"]]. |
| register_paymentA | Register a payment against a posted invoice/bill via Odoo's standard account.payment.register wizard model (keeps reconciliation correct -- never write account.payment directly). |
| reconcile_linesA | Reconcile a set of account.move.line ids against each other (e.g. a payment line against an invoice line). All lines must share the same partner and a reconcilable account. |
| search_unreconciled_linesA | Find open (unreconciled) receivable/payable move lines, e.g. to match a payment to its invoice. |
| profit_and_lossA | Profit & Loss (income statement) for a date range: income and expense accounts, from posted journal items only. |
| balance_sheetA | Balance Sheet (assets / liabilities / equity) as of a date, from posted journal items only, computed as cumulative balances from the earliest entry up to as_of_date. |
| trial_balanceB | Trial balance: opening + period debit/credit + closing balance per account, for a period. |
| general_ledgerA | All posted journal items on one account for a period, in date order, with a running balance. |
| aged_receivableB | Aged receivable: open customer invoice balances, bucketed by days overdue as of a date. |
| aged_payableA | Aged payable: open vendor bill balances, bucketed by days overdue as of a date. |
| list_budgetsA | List project budgets, optionally filtered by project and/or state (e.g. "draft", "submitted", "approved", "active"). |
| get_budgetA | Full detail of one budget, including every BOQ line with its planned/actual/ETC/EAC figures -- read directly from Odoo, never recomputed here. |
| create_budget_lineA | Add a new BOQ line to a budget. Either give planned_qty + planned_unit_cost, or set is_lump_sum=True with planned_total_cost. |
| update_budget_lineA | Update any field(s) on a BOQ line: planned_qty, planned_unit_cost, planned_total_cost, etc_mode ("auto"/"manual"), manual_etc, name, section_id, cost_category_id, task_id, work_package_id, etc. Never write "auto_etc", "effective_etc" or "forecast_cost_at_completion" directly -- they are always computed by Odoo from planned/actual/manual_etc; Odoo will simply ignore or reject an attempt to write them. To move the forecast, set etc_mode="manual" and manual_etc= instead. |
| submit_budgetB | Move a draft budget to Submitted (action_submit). |
| approve_budgetC | Approve a submitted budget (action_approve). |
| activate_budgetA | Activate an approved budget so it can receive real transactions (action_activate). |
| budget_vs_actualA | Budget-vs-actual summary for one budget: per line and totals for planned cost, actual cost, effective ETC, forecast EAC and available budget -- all read straight from Odoo's own computed fields, never recalculated here. |
| search_budget_linesA | Search BOQ lines across any budget/project. Example domain: [["category_type", "=", "labor"], ["budget_state", "=", "active"]]. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/Andrewraof/Bookkeeping-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server