Odoo Pulse
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ODOO_DB | Yes | The Odoo database name | |
| ODOO_URL | Yes | The URL of your Odoo instance (e.g., https://acme.odoo.com) | |
| ODOO_API_KEY | Yes | Your Odoo API key (generated in Settings → Users → Account Security) | |
| ODOO_USERNAME | Yes | Your Odoo user email | |
| ODOO_READ_ONLY | No | Set to false to enable write operations (requires additional configuration) | true |
| ODOO_TOOL_GROUPS | No | Comma-separated list of tool groups to enable (e.g., 'sale,stock,account'). Leave empty for default set. |
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_version | Check connectivity and return the Odoo server version info. |
| list_modelsA | List Odoo models (technical name + label). Optionally filter by a case-insensitive substring matched against the model name or label, e.g. 'sale', 'res.partner', 'invoice'. |
| get_model_fields | Inspect the schema of an Odoo model. Returns each field's label, type,
help text, requiredness and relation. Pass |
| search_read | Query records from an Odoo model. Args: model: Technical model name, e.g. 'sale.order', 'res.partner'. domain: Odoo search domain as a list of triplets, e.g. [["state", "=", "sale"], ["amount_total", ">", 1000]]. Use 'and'/'|' operators as Odoo expects. Defaults to all records. fields: Field names to return. Omit to let Odoo decide (can be large). limit: Max records (capped by ODOO_MAX_RECORDS). offset: Pagination offset. order: Sort spec, e.g. 'date_order desc'. |
| search_countC | Count records in a model matching an Odoo domain filter. |
| read_recordsB | Fetch specific records by their ids. Pass |
| aggregate_recordsA | Group and aggregate records server-side (one call instead of pulling rows). Args: model: Technical model name, e.g. 'sale.order'. group_by: One or more fields to group on. A field may carry a granularity, e.g. 'date_order:month'. measures: 'field:agg' specs. Bare 'field' means sum. Allowed aggregators: sum, avg, min, max, count, count_distinct. Omit to count records. domain: Odoo search domain (list of triplets). Defaults to all records. limit: Max groups (capped by ODOO_MAX_RECORDS). offset: Pagination offset over groups. order: Sort spec, e.g. 'amount_total desc'. |
| read_attachmentA | Read an ir.attachment: metadata always, base64 content when small enough. Binary attachments under ODOO_MAX_ATTACHMENT_BYTES are returned with their
base64 Args: attachment_id: The ir.attachment id. include_data: When False, return metadata only (no base64 fetch). |
| create_recordA | Create one record. Returns a preview unless confirm=True. Args: model: Odoo model name (must be in ODOO_WRITABLE_MODELS). values: Field -> value mapping for the new record. confirm: Set True to actually create; otherwise a dry-run preview. |
| update_recordsA | Update one or more records. Returns a preview unless confirm=True. Args: model: Odoo model name (must be in ODOO_WRITABLE_MODELS). ids: Record ids to update. values: Field -> value mapping to write. confirm: Set True to actually write; otherwise a dry-run preview. |
| delete_recordsA | Delete one or more records. Returns a preview unless confirm=True. Deletes also require ODOO_ALLOW_DELETE=true on the server. Args: model: Odoo model name (must be in ODOO_WRITABLE_MODELS). ids: Record ids to delete. confirm: Set True to actually delete; otherwise a dry-run preview. |
| create_lead | Create a CRM lead/opportunity (crm.lead). Preview unless confirm=True. Use extra_values to set fields this helper doesn't model, including custom mandatory fields (e.g. {"presales_id": 5}). |
| create_contactB | Create a contact (res.partner). Preview unless confirm=True. Use extra_values to set fields this helper doesn't model (e.g. {"vat": ...}). |
| create_taskA | Create a project task (project.task). Preview unless confirm=True. Use list_projects to find the project_id first. Use extra_values to set fields this helper doesn't model (e.g. {"tag_ids": [(6, 0, [1])]}). |
| confirm_sale_orderC | Confirm a quotation into a sales order (sale.order action_confirm). |
| team_workloadA | Report who is over- or under-loaded, in one call. Composes the open project.task records in scope into a per-assignee load (open count plus overdue / due-soon / high-priority / no-deadline tallies), flags overloaded members and unassigned work, and returns a rule-based verdict. Done tasks carry no current load and are excluded. Args: project: Optional project-name filter (ilike). exclude_stages: Stage names dropped from scope. Default ["Cancelled"]. done_stages: Stage names treated as completed. Default ["Done", "Delivered"]. lookahead_days: Days ahead that count as "due soon" (default 7). overload_threshold: Open-task count above which a member is flagged "overloaded" (default 8). Sign-off point with the workflow owner. timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). subtasks_only: Count only subtasks (parent_id != False), the team's unit of work. Default True. |
| project_status_reportA | Report which projects are in trouble, across a portfolio, in one call. Composes project.project records (filtered by manager / customer / name) with their project.milestone rows into a per-project derived health verdict (off_track / at_risk / on_track) driven by overdue-or-unreached milestones and the project end date. Surfaces the PM's declared status alongside, flags projects declared healthier than the data (divergence), and ranks by risk. Args: manager: Optional project-manager filter (user_id.name ilike). customer: Optional customer filter (partner_id.name ilike). project: Optional project-name filter (name ilike) to narrow the set. include_on_hold: Keep projects whose declared status is on_hold (default True). include_done: Keep projects whose declared status is done (default False). lookahead_days: Days ahead that count as "due soon" for at_risk (default 7). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). |
| standup_digestA | Generate a daily standup digest for a project. Fetches all active subtasks (parent_id != False, stage not in exclude_stages, exactly 1 assigned user) and categorises them by deadline into OVERDUE / TODAY / UPCOMING / NO DEADLINE sections. Returns a plain-text digest ready to paste or send as an email body. Args: project: Project name (ilike match, e.g. "The Body Shop"). exclude_stages: Stage names to treat as closed. Defaults to ["Done", "Cancelled", "Delivered"]. lookahead_days: Days ahead to include in UPCOMING (default 7). timezone_offset: UTC offset in hours for "today" (default 7 = Asia/Ho_Chi_Minh). |
| pipeline_review | Report the health of the CRM pipeline, in one call. Composes open crm.lead opportunities into totals (count, expected and probability-weighted revenue), stalled deals (no stage change in stalled_days), close-date buckets, per-stage / per-salesperson breakdowns, the recent win rate, and a rule-based verdict. Args: salesperson: Optional filter on user_id.name (ilike). team: Optional filter on team_id.name (ilike). stalled_days: Days without a stage change before a deal counts as stalled (default 14). lookahead_days: Days ahead that count as "closing soon" (default 30). win_rate_days: Look-back window for the won/lost ratio (default 90). top_n: Max stalled deals listed in the breakdown (default 5). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). company: Optional company name (ilike) or id; scopes every count and total to that company. stalled_pct_at_risk: Stalled share (%) at which the verdict drops to at_risk (default 25). stalled_pct_off_track: Stalled share (%) at which the verdict drops to off_track (default 50). |
| sales_snapshot | Report how sales are going versus the previous period, in one call. Composes confirmed sale.order records over the last two periods into revenue/order deltas, top customers, top products (server-side aggregate over order lines), a stale-quotation count, and a growing / steady / declining verdict. Args: period_days: Length of the comparison window in days (default 7). stale_quote_days: Age in days after which a draft/sent quotation counts as stale (default 7). top_n: Rows in the top-customers / top-products lists (default 5). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). growth_threshold_pct: Delta (%) beyond which the verdict is growing / declining (default 10). company: Optional company name (ilike) or id to scope the report. trend_weeks: Weeks of history bucketed into the weekly_revenue trend series; 0 disables the extra query (default 8). |
| receivables_health | Report AR/AP aging and who owes what, in one call. Composes open posted invoices and vendor bills into standard aging buckets (not_due / 1-30 / 31-60 / 61-90 / 90+), the share of receivables overdue, the top overdue customers, and a verdict. Args: top_n: Rows in the top-overdue-customers list (default 5). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). company: Optional company name (ilike) or id to scope the report. overdue_pct_at_risk: Overdue AR share (%) that drops the verdict to at_risk (default 25). overdue_pct_off_track: Overdue AR share (%) that drops the verdict to off_track (default 50). |
| inventory_riskA | Report stock at risk — shortages and dead stock — in one call. Shortages are storable products with negative forecasted quantity (demand exceeds supply). Dead stock is on-hand product with no done stock move in dead_stock_days, valued at standard_price. The dead-stock check is a bounded heuristic: when the recently-moved product list hits the 200-group cap, a risk flags that the list may over-count. Args: dead_stock_days: No-movement window for dead stock (default 90). top_n: Rows listed per breakdown section (default 10). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). company: Optional company id or name; scopes stock quantities via allowed_company_ids context and dead-stock moves via company_id. |
| absence_overview | Report who is off and where coverage is thin, in one call. Composes approved hr.leave records overlapping the next Args: days: Look-ahead window in days (default 14). coverage_threshold: Department share off in the window that counts as a coverage risk (default 0.3). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). |
| business_pulseA | One-call company briefing: sales, leads, receivables, tasks, absences. The morning-standup view of the whole company: yesterday's confirmed revenue and new leads, overdue customer invoices, tasks past deadline, and who is off today. Sections are independent — if an app is not installed, its section reports available=false and the rest still renders. Args: timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). company: Optional company name (ilike) or id; scopes every section. |
| procurement_watchA | Report purchasing health — late receipts and stale RFQs — in one call. Composes confirmed purchase orders into open value, receipts past their planned date, per-vendor open spend, plus a count of quotation requests (draft/sent) older than rfq_stale_days, and a rule-based verdict. Args: late_grace_days: Days past date_planned before a receipt counts as late (default 0). rfq_stale_days: Age in days after which a draft/sent RFQ counts as stale (default 7). top_n: Rows in the late-receipts / top-vendors lists (default 5). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). company: Optional company name (ilike) or id to scope the report. |
| production_health | Report manufacturing health — late starts and stuck orders — in one call. Composes open mrp.production orders (confirmed / progress / to_close) into a by-state backlog, orders that should have started but haven't (confirmed with date_start in the past), orders running longer than stuck_days, and a rule-based verdict. Args: stuck_days: Days an order may run (progress/to_close) before it counts as stuck (default 14). top_n: Rows in the behind-start / stuck lists (default 5). timezone_offset: UTC offset for "today" (default 7 = Asia/Ho_Chi_Minh). company: Optional company name (ilike) or id to scope the report. |
| project_budgetA | Report planned vs actual budget per project, line by line. Reads the Budgets app (budget.line on Odoo 18+, else crossovered.budget.lines) and matches lines to active projects by a line-level project_id m2o when the instance has one, else through the project's analytic account. Amounts are absolute company-currency sums; server-computed practical/theoretical amounts are used as-is. Also compares each project's total analytic cost against the practical amounts booked on its budget lines, flagging spend the budget does not capture. When the filter matches exactly one project the report gains a per-line breakdown. No date filters: budget lines carry their own period. Args: project: Optional project-name filter (name ilike). Exactly one match switches on the per-line breakdown. manager: Optional project-manager filter (user_id.name ilike). customer: Optional customer filter (partner_id.name ilike). top_n: Rows in the per-line breakdown (default 10). burn_pct_at_risk: Burn %% >= this -> at_risk (default 80). burn_pct_off_track: Burn %% >= this -> off_track (default 100). timezone_offset: UTC offset for "today" (default 7). |
| project_profitability | Report delivery hours, money and budget burn per project in one call. Composes active project.project records (filtered by name / manager / customer) with timesheet hours (account.analytic.line grouped by project), analytic cost/revenue (grouped by analytic account) and the Budgets app when installed, into a per-project burn verdict (off_track / at_risk / on_track). When the filter matches exactly one project the report gains per-employee and per-task breakdowns. Args: project: Optional project-name filter (name ilike). Exactly one match switches on the drill-down breakdowns. manager: Optional project-manager filter (user_id.name ilike). customer: Optional customer filter (partner_id.name ilike). date_from: Optional YYYY-MM-DD lower bound on logged hours and analytic amounts. Allocated hours and budgets stay lifetime totals, so ANY date filter disables the burn verdicts (verdict "n/a", burn percentages null). date_to: Optional YYYY-MM-DD upper bound (same caveat). top_n: Rows in the drill-down breakdowns (default 5). burn_pct_at_risk: Worst burn %% >= this -> at_risk (default 80). burn_pct_off_track: Worst burn %% >= this -> off_track (default 100). timezone_offset: UTC offset for "today" (default 7). |
| project_subtask_hours | Total sub-task hours for one project, filtered server-side, in ONE call. Sums delivery/allocated/effective hours over the project's sub-tasks (project.task with parent_id set). Use this instead of paginating project.task through search_read — especially for the "exactly one assignee" condition, which Odoo domains cannot express. Args: project_id: project.project id (int, not name). only_closed_stages: Count only tasks whose stage name is in closed_stage_names (default False). Cancelled tasks DO count toward delivery hours (business decision 2026-07-15). closed_stage_names: Stage names treated as closed (default ["Done", "Cancelled", "Delivered"]). single_assignee_only: Count only tasks with exactly 1 user in user_ids (default False). group_by_month: Also bucket by local-time month of date_end; tasks without date_end are excluded from the buckets and summarised under "no_date_end" (default False). periods: Optional list of {"date_from": "YYYY-MM-DD", "date_to": "YYYY-MM-DD"} ranges applied to date_end, OR-combined (matching per-budget-period filtering, not a union). Empty/omitted = no date filter. timezone_offset: UTC offset for dates (default 7). |
| project_dashboardA | Everything the project-detail page needs, in one call. Replaces ~12 separate calls (status, profitability, milestones,
weekly hours, budgets, budget lines, cost breakdowns, delivery by
month). Use Sections fail soft: a broken section lands in "errors" while the rest return. Args: project_id: project.project id. only_closed_stages / closed_stage_names / single_assignee_only: sub-task filters, as in project_subtask_hours; they shape the "hours" and "delivery_monthly" sections. budget_ids: crossovered.budget / budget.analytic ids to select. OMIT (null) for ALL budgets of the project; pass [] for NO selection (budget_detail then shows all-time cost only). These two states are different on purpose — do not send [] to mean "all". include: Subset of ["core", "hours", "budgets", "budget_detail", "delivery_monthly"]; omitted = all. "core" covers project, milestones, finance and weekly_logged. lookahead_days: "due soon" window for derived health (default 7). timezone_offset: UTC offset for dates (default 7). |
| portfolio_healthA | Portfolio overview: one row per project, joined by id server-side. Replaces the project_status_report + project_profitability pair the overview tab used to call and join BY NAME in JS (which broke on duplicate project names). Returns raw signals only — the client computes its own health score from user-configured thresholds. Args: manager: Optional project-manager filter (user_id.name ilike). customer: Optional customer filter (partner_id.name ilike). include_on_hold: Keep on_hold projects (default True). include_done: Keep done projects (default False). lookahead_days: "due soon" window for derived health (default 7). timezone_offset: UTC offset for dates (default 7). |
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
- 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/minhhq-a1/odoo-pulse'
If you have feedback or need assistance with the MCP directory API, please join our Discord server