Skip to content
Agentmart
Submit a tool

Odoo Assistant

Odoo virtual employee via MCP: query, create, modify records, workflows, PDFs, and activities.

Connector by singleflo · GitHub account verified by the MCP Registry

IndexedMITLocal (stdio)Remote (HTTP)★ 1
Write a review

Install

Works with Claude Code, VS Code, Codex, Cursor, Windsurf, Claude Desktop. Read the repository before you give any tool access to your data.

npx agentmarket install connector/singleflo-odoo-assistant

Asks which of your tools to add it to (Claude Code, Codex, Cursor, VS Code, Windsurf, Gemini CLI, Claude Desktop) and shows the change first. See https://agentmart.dev/cli.

Remote endpoint

  • https://odoomcp.singleflo.com/mcp Remote (HTTP)

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

Odoo virtual employee via MCP: query, create, modify records, workflows, PDFs, and activities.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this server can do and what it asks for, from its tool list, install config and code. Checked Oct 25, 2026.

Tools
11 read · 10 write · 0 delete · 1 not yet classified
Secrets
1 (API keys, tokens or passwords)
Install scripts
None found
Runs as
Python package

Tools by what they do 22

Read from the source code; the running server may list different tools.

Read 11 · Look things up without changing anything.

  • count_records
  • describe_model
  • explore_module
  • instance_overview
  • list_known_modules
  • list_message_targets
  • read_conversation
  • read_long_field
  • read_record
  • required_fields
  • search_read

Write 10 · Create, change, send or run things.

  • cancel_record
  • create_activity
  • create_record
  • download_docs
  • group_records
  • notify_user
  • run_action
  • send_channel_message
  • send_direct_message
  • write_record

Not yet classified 1 · We could not tell from the name and description.

  • generate_pdf

Secrets and settings it asks for

Secrets: values you paste in that let it act as you.

  • ODOO_API_KEY

Other settings (environment variables or headers).

  • ODOO_BASE_URL
  • ODOO_DB
  • ODOO_MCP_ALLOW
  • ODOO_MCP_ALLOW_UNLINK
  • ODOO_MCP_DENY
  • ODOO_USER

Network hosts it talks to 7

  • agent-plugins.org · found in code
  • chatgpt.com · found in code
  • claude.ai · found in code
  • github.com · found in code
  • mycompany.odoo.com · found in code
  • odoomcp.singleflo.com · found in remote endpoint, install command, code
  • singleflo.com · found in code

Files it touches

  • /usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf
  • Your home directory (~)
  • ~/.hermes/odoo/instances
  • ~/.local/share

Tools (22)

Read from the source code; the running server may differ. Descriptions are the server’s own words; hidden characters are shown as [U+…].

  • cancel_recordCancel a record

    Cancel a record through `action_cancel`, following the wizard it returns. `action_cancel` sits in the default ODOO_MCP_DENY list, so this tool is refused until the operator removes that entry from the variable.

  • count_recordsCount records

    Count the records matching a domain (Odoo `search_count`). A count is only as honest as its domain: * `account.move` / `account.move.line` without a `move_type` filter is refused — it would count invoices, bills, credit notes and journal entries together and match no figure the user has ever seen. * A count answers "how many", never "how much". For an amount, read `amount_total_signed` (company currency) and never `amount_total`. * On a multi-company instance the count differs per company: pass `company_ids` or you are reporting one company as the whole business. One value per call …

  • create_activitySchedule an activity

    Schedule an activity: the only notification that carries a deadline. A chatter note is passive. An activity appears in the assignee's To-Do list and turns overdue when the date passes. Args: model: the Odoo model, e.g. "crm.lead". record_id: id of the record the activity hangs off. summary: the one-line title the assignee will read. user_id: res.users id of the assignee. days: deadline offset from today, in days. activity_type: substring of an activity type name, e.g. "call". Activity types differ per instance; the first available type is used when thi…

  • create_recordCreate a record

    Create a record, reusing an existing match when `unique_on` is given. `unique_on` is a list of FIELD NAMES taken from `values` (e.g. `["name", "email"]`): they are searched first and the existing id comes back instead of a duplicate. Odoo has no idempotency key, so a create that is retried is simply a second record — this is the only protection there is, and a cold-start run without it produced four identical customers. Multi-company: put `company_id` in `values`. The context decides what is visible, not which company owns the new record. When the gate refuses, tell the user which entry of …

  • describe_modelDescribe a model

    List a model's fields as the live instance defines them (Odoo `fields_get`). Answers "what can I filter, group or write on this model" in one call — the alternative, reading `ir.model.fields` through `search_read`, takes one call per batch of names and returns rows you then have to join. Required fields are starred. For what a `create` demands — including the default Odoo would apply and how existing records actually use it — use `required_fields`, which reads deeper on exactly that question. Args: model: Odoo model, e.g. "crm.lead".

  • download_docsDownload a record's documents

    Save every document of a record to disk — chatter files included. Returns {"saved": [paths], "skipped": [[name, why]]}. `skipped` is not noise: a database restored without its filestore keeps the attachment rows and loses the bytes, and an empty result would read exactly like "this record has no attachments". On the hosted server the result is a download link valid for 15 minutes; `dest_dir` is ignored there. Args: model: the Odoo model, e.g. "account.move". record_id: id of the record whose documents to fetch. dest_dir: directory to write the files into. Defaults to this …

  • explore_moduleExplore a module

    Discover a module's structure by interrogating the live instance. Args: module_name: Module to explore, e.g. "helpdesk". Must be a module slug, since it names the reference file on "generate"; ignored on "list". action: "generate" (the default) writes the reference document, replacing the generated part of an earlier one (its NOTES section is kept); "list" ranks what is worth exploring and writes nothing. models: Comma-separated models for a module the script does not know, e.g. "superchat.message,superchat.template". Defaults to the…

  • generate_pdfGenerate a record's PDF

    Render the PDF of a record and return where it was saved. An already rendered PDF is reused. Otherwise the model's own print/send wizard produces it, and that wizard can also SEND the document — which is why this is gated on `action_send_and_print` rather than as a plain read. `action_send_and_print` is allowed by default; add it to ODOO_MCP_DENY to refuse PDFs that could trigger the send wizard. On the hosted server the result is a download link valid for 15 minutes; `dest_dir` is ignored there. Args: model: the Odoo model, e.g. "account.move". record_id: id of the record to print.…

  • group_recordsGroup records

    Group records and count (or aggregate) per bucket (Odoo `read_group`). The tool for "how many per state / stage / month": one call returns every existing bucket with its count. Issuing one `count_records` per value is the pattern this tool exists to prevent — N round trips where one answers, and on a live instance half of them come back zero. Args: model: Odoo model, e.g. "crm.lead". domain: Odoo domain, e.g. [["state", "=", "sale"]]. group_by: one or two fields, e.g. ["stage_id"] or ["create_date:month", "stage_id"]. Date granularity: day, week, month, quarter, y…

  • instance_overviewInstance overview

    Summarise the connected instance: version, companies, volumes per area, in-house modules, anomalies. The profile is built from the instance this server is CONNECTED to, and cached per instance — `census.profile_path()` keys it on the live client, not on an environment variable. That distinction is the whole point: with two instances profiled on one machine, choosing by `ODOO_DB` (which is discovered now, so often unset) once fell through to "the first file on disk" and reported a neighbour's numbers as this instance's, with no error and a perfectly plausible report. First call against a new …

  • list_known_modulesList known modules

    List the modules this server has learned: name, generation date, records.

  • list_message_targetsList message targets

    Who can be messaged and where — ASK THIS BEFORE SENDING ANYTHING. Two lists in one call, because an agent that cannot see the roster invents ids: * `users`: the internal, active users, each with `im_status` — 'online', 'away' (idle 30 minutes) or 'offline'. Presence is worth reading first: a Discuss message is delivered either way, but "offline" tells you nobody is going to answer right now. * `conversations`: the ones the sender already belongs to and has not archived, with `channel_type` — 'chat' is a 1-to-1, 'group' is a private multi-party, 'channel' is a room tha…

  • notify_userNotify users on a record

    Write a note on a record's chatter and notify the users you name, on the user's behalf. Two calls, so the user approves before anything is posted. The first, with no confirmation_token, posts NOTHING: it answers with a preview — the record, the people notified, who would be emailed and the message — and a token. Show the preview to the user and ask, and say plainly when it lists people who will receive an email. Only once they approve, call again with the same arguments and the token; that call posts. Both subtypes post a message that IS VISIBLE in the record's chatter. The difference is who…

  • read_conversationRead a conversation

    Read what was said in a Discuss conversation, newest first. This is how you answer "what did they write to me" or "what is going on in that channel". `list_message_targets` gives you the `channel_id` and says how many messages are unread. Reading does not mark anything as read: the unread counter belongs to the member record and only the user's own client clears it. Args: channel_id: the Discuss channel, from `list_message_targets`. limit: how many recent messages to return.

  • read_long_fieldRead a long text field

    Read ONE long text field in windows, so a value larger than the 5000-char result cap stays readable to the end. Every tool result is capped at 5000 characters. When a single value is bigger than that — a `description` holding a pasted transcript, an email `body` — narrowing the domain or the field list cannot help: that one value already IS the whole answer, so the tail is unreachable and the caller ends up asking for the same cut text again. Measured on a live lead: its description came back cut, and no limit or offset could ever reach the rest of it. This reads that field alone and returns…

Show 7 more tools
  • read_recordRead a record

    Read one record by id, always with named fields (writing.md pattern 12). Omitting `fields` asks for a short list of state fields — never for all of them: that read is slow at best and fails at worst. `account.move` and `account.move.line` are refused here, because the structural guard wants a `move_type` filter and this tool has nowhere to put one. Use `search_read` with `[["id", "=", <id>], ["move_type", "=", "out_invoice"]]` instead. And never add up `amount_total` across records — it is in the record's own currency. `amount_total_signed` is the company-currency twin to sum. The answer i…

  • required_fieldsRequired fields for create

    List the fields Odoo demands before it will accept a `create`, with the default it would apply and how existing records actually use it. Ask this BEFORE `create_record` on a model you have not written to in this session. The answer is read from the live instance — `fields_get` plus `default_get` — never from a table in this file, so a model customised in-house reports its own requirements. The dangerous required field is the one that already carries a default: the create succeeds without you naming it and the record lands wherever the default points, with no error to notice. `crm.lead.type` …

  • run_actionRun a workflow action

    Run a workflow step on Odoo records — the method behind a button such as Confirm on a quotation or Post on an invoice — and report the state each record is in afterwards. Side effects: this changes records in the user's Odoo, and most steps cannot be undone from here (a posted invoice stays posted). Confirm the records and the step with the user before calling it. A step runs once: calling it again on the same records fails instead of doing nothing, so never retry — re-read the records to see whether it already ran. If the answer carries `res_model`, Odoo opened a wizard that needs more inpu…

  • search_readSearch records

    Search and read records in one call (Odoo `search_read`). Two pitfalls this tool cannot fix for you: * `account.move` and `account.move.line` mix customer invoices, vendor bills, credit notes and raw journal entries. A domain without `move_type` is refused — add `["move_type", "=", "out_invoice"]` (or `in_invoice`, `out_refund`, `in_refund`) so the answer matches what the user sees on screen. * NEVER sum `amount_total`: it is expressed in each record's own currency, and eight foreign-currency invoices once inflated a total 11,9×. Ask for `amount_total_signed` instead — any field …

  • send_channel_messagePost to a channel

    Post to an EXISTING Discuss channel, on the user's behalf — everyone in it sees this. Two calls, so the user approves before anything is posted. The first, with no confirmation_token, posts NOTHING: it answers with a preview — the channel, how many members it reaches and the message — and a token. Show the preview to the user and ask. Only once they approve, call again with the same arguments and the token; that call posts. A changed message or channel needs a new preview. The channel is never created here: `list_message_targets` shows the ones that exist, and posting to a room of the wrong …

  • send_direct_messageSend a direct message

    Send a 1-to-1 Discuss message, on the user's behalf, that appears in the recipient's chat systray. Two calls, so the user approves before anything is sent. The first, with no confirmation_token, sends NOTHING: it answers with a preview — the recipient, the route and the message — and a token. Show the preview to the user and ask. Only once they approve, call again with the same arguments and the token; that call sends. A changed message or recipient needs a new preview. This is the tool for "tell X", "message X", "warn X". It opens the private chat with that user — reusing the existing one, …

  • write_recordUpdate a record

    Write field values to one record and report what actually changed. Writing the value a record already holds succeeds and changes nothing; only the before/after comparison tells that apart from a real update, so that comparison is the answer. Setting `active` to False archives the record — the same visible outcome as deleting it — so the gate matches it as `archive`, which the default ODOO_MCP_DENY list refuses. When the gate refuses, tell the user which entry of ODOO_MCP_DENY (or ODOO_MCP_ALLOW_UNLINK) would allow it and stop; never retry with another method name.

Signals

Stars
1
Forks
3
Open issues
0
Weekly downloads
193
Last commit
Oct 22, 2026 (6 days ago)
Last release
Oct 22, 2026 (6 days ago)
Last package publish
Oct 22, 2026 (6 days ago)

From GitHub (fetched Oct 24, 2026) and the package registry.

Details

Registry name
io.github.singleflo/odoo-assistant
Version
0.3.15
Auth
Auth not stated, API key
Packages
pypi odoo-assistant
License
MIT
First seen
Oct 24, 2026
Last checked
Oct 24, 2026

More from singleflo

Cite this page

Odoo Assistant MCP server. Agent Mart. https://agentmart.dev/connectors/singleflo-odoo-assistant (last updated 2026-10-24)