Odoo Claude MCP
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| ODOO_DB | Yes | Database name | |
| ODOO_URL | Yes | URL of the Odoo instance | |
| ODOO_API_KEY | No | Odoo API key | |
| ODOO_PASSWORD | No | Odoo password | |
| ODOO_USERNAME | Yes | Odoo username | |
| MCP_ADMIN_TOKEN | No | Admin token for MCP gateway |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| completions | {} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| odoo_connectA | Add/update an Odoo connection. Auth via password or API key. Protocol: xmlrpc (Odoo 8+) or jsonrpc (Odoo 14+). |
| odoo_cert_infoA | Return the pinned SSL certificate details (issuer, subject, notAfter, fingerprint) for a connection. Useful to verify which self-signed cert MCP has trusted. Requires verify_ssl=False on the connection. |
| odoo_cert_refreshA | Re-fetch the peer SSL certificate for a connection and overwrite the pinned copy. Use after the server's self-signed cert was rotated. Fails if the connection has verify_ssl=True (standard CA verification does not need pinning). |
| odoo_disconnectC | Remove an Odoo connection. |
| odoo_connectionsA | List all configured Odoo connections. |
| odoo_list_modelsC | List available Odoo models (ir.model). Optionally filter by name pattern. |
| odoo_fields_getB | Get field definitions for an Odoo model. Returns field names, types, labels, and attributes. |
| odoo_searchB | Search for record IDs matching a domain filter. |
| odoo_readB | Read specific records by IDs. |
| odoo_search_readC | Search and read records in one call. Most common operation. |
| odoo_search_countC | Count records matching a domain. |
| odoo_createB | Create one or more records. Returns list of new IDs. |
| odoo_writeD | Update existing records. |
| odoo_unlinkC | Delete records by IDs. |
| odoo_executeA | Execute any model method via execute_kw. Use for workflow actions (action_confirm, action_done), custom methods, or anything not covered by CRUD tools. |
| odoo_message_postA | Post a message or internal note on any Odoo record (chatter). Body supports Markdown formatting (headers, bold, italic, tables, code blocks) — automatically converted to HTML. Use message_type='note' for internal notes (employees only) or 'comment' for public messages (visible to followers). |
| odoo_attachment_uploadA | Upload a file as an ir.attachment on an Odoo record. Returns the attachment ID which can be used with odoo_message_post (attachment_ids parameter) or linked to any record. |
| odoo_attachment_downloadA | Download an ir.attachment from Odoo by ID. Returns filename, mimetype, size, and base64-encoded content. |
| odoo_module_infoA | Get detailed information about an Odoo module: Odoo RPC state + filesystem locations (OCA, EE, custom repos). Shows where the module physically exists, its manifest, dependencies, and installation status. |
| odoo_list_translatable_fieldsA | List all translatable fields on an Odoo model. Returns per-field: translate type ('simple' for translate=True, 'html' for html_translate, 'xml' for xml_translate, 'callable' for other), field type, label, help. Use this to discover which fields on blog.post, product.template, website.page, res.partner, etc. can be translated. |
| odoo_get_field_translationsA | Read current translations for a translatable field on a record. For simple translate=True fields returns {lang: value}. For html_translate/xml_translate fields returns {lang: {term: value}}. Auto-detects the translate type via fields_get. Works on blog.post.content, blog.post.name, product.template.website_description, ir.ui.view.arch_db, any res.partner.name with translate=True, etc. |
| odoo_translate_fieldA | Write translations for a simple translate=True field (Char/Text/Selection). Use for: blog.post.name/subtitle/teaser, product.template.name, res.partner.name, account.account.tag.name — any short/plain field. Format: translations = {lang_code: value, ...}. Pass value=null/'' to remove a language's translation (falls back to source_lang). Errors if field.translate is not True (use odoo_translate_html for HTML). Auto-detects Odoo version: v16+ uses update_field_translations() native API, older falls back to ir.translation. |
| odoo_translate_htmlA | Write/read translations for translate=html_translate / translate=xml_translate fields. Use for: blog.post.content, product.template.website_description, hr.job.description, ir.ui.view.arch_db (covers website.page), website.menu.mega_menu_content, event.track.description, forum.forum.guidelines, res.partner.website_description. Three modes: (a) mode='extract' — READ-ONLY. translations arg ignored. Returns the list of translatable terms that Odoo's html_translate engine extracts from source_lang. Each term is an HTML-serialised translatable block (preserves inline tags like ). Use this to see what must be translated before writing. (b) mode='terms' — translations = {lang: {source_term: translated_term, ...}} Direct term map. Terms must match exactly those from mode='extract'. Calls update_field_translations() with JSONB payload. (c) mode='replace' — translations = {lang: full_html_string}. The tool writes each language's HTML through Odoo's native ORM with {'lang': } context. Odoo's html_translate engine aligns terms automatically — no manual term extraction required. This is what Odoo's Website editor does internally. Errors if field.translate is not callable. Requires Odoo 16+. |
| odoo_website_list_snippetsA | List available Odoo website snippet templates (ir.ui.view records with key matching 'website.s_*' or similar). Returns per-snippet: key, name, module, category (structure|content|dynamic|effect|unknown), preview. Use this to discover what snippets can be added to a page. Categories inferred from snippet key patterns and modules. |
| odoo_website_list_page_snippetsA | List snippets currently embedded in a target HTML field. Target can be a blog.post (field=content), website.page (field=arch_db via view_id), product.template (field=website_description), or any HTML field. Parses the HTML with lxml, finds all elements bearing a data-snippet attribute. Returns per-snippet: index, data_snippet, data_name, xpath, text_preview, has_background (detects url() in style), background_url. |
| odoo_website_add_snippetA | Insert a snippet into a target HTML field. Fetches the snippet template from ir.ui.view by key, extracts its root HTML element, applies optional substitutions (text/attr/src changes before insertion), and places it at the specified position relative to an anchor. Positions: 'end' (after last element), 'begin' (before first), 'after' (after anchor_xpath), 'before' (before anchor_xpath), 'replace' (replace anchor_xpath). Substitutions format: {'relative_xpath': value} for text; {'relative_xpath/@attr': value} for attribute; {'relative_xpath/@style:background-image': 'url(...)'} for CSS property; {'relative_xpath/@src': 'https://...'} for image URL. |
| odoo_website_update_snippetA | Update an existing snippet on a target HTML field. Locates the snippet via snippet_xpath (absolute in target), applies substitutions to its descendants via relative xpaths, and writes back. Common use cases: swap background image, change H1/H2 text, update CTA button text+href, change card content. Substitution syntax identical to odoo_website_add_snippet. |
| odoo_website_remove_snippetB | Remove a snippet block from a target HTML field. Locates via snippet_xpath (absolute). Writes back the reduced HTML. |
| odoo_web_loginA | Login to Odoo web interface with user/password. Creates a persistent cookie session for accessing web controllers, exports, reports, and any frontend URL. Session is reused until logout or expiry. |
| odoo_web_callB | Call any Odoo model method via web session (JSON-RPC /web/dataset/call_kw). Works like odoo_execute but uses cookie session instead of XML-RPC. |
| odoo_web_readB | Search and read records via web session (frontend web_search_read format). Supports field specification, domain, limit, offset, order. |
| odoo_web_exportC | Export records to structured data via web session (Odoo export_data). |
| odoo_web_reportC | Download PDF report via web session. Returns base64-encoded PDF. |
| odoo_web_requestC | Raw HTTP request to any Odoo controller URL via web session. Access frontend pages, custom controllers, website routes, etc. |
| odoo_web_logoutC | Destroy web session and logout. |
| public_access_export_xlsxC | Export Odoo list data as XLSX file via web session. Returns base64. |
| public_access_export_csvC | Export Odoo list data as CSV via web session. |
| public_access_report_pdfC | Download PDF report via web session. Route: /report/pdf/{report_name}/{doc_ids}. |
| public_access_report_htmlC | Render report as HTML via web session. |
| public_access_downloadB | Download attachment/binary content by ID via /web/content/{id}. Public route. |
| public_access_imageB | Download image field from record via /web/image/{model}/{id}/{field}. |
| public_access_barcodeC | Generate barcode image via /report/barcode/{type}/{value}. |
| public_access_portal_homeC | Get portal home page content via web session (/my/home). |
| public_access_portal_invoicesC | Get list of portal invoices (/my/invoices). Returns HTML page content. |
| public_access_portal_ordersC | Get list of portal sale orders (/my/orders). Returns HTML page content. |
| public_access_portal_purchasesC | Get list of portal purchase orders (/my/purchase). |
| public_access_portal_ticketsB | Get list of portal helpdesk tickets (/my/tickets). |
| public_access_report_xlsxC | Download XLSX report via OCA reporting-engine (/report/xlsx/{name}/{ids}). |
| public_access_shopC | Get website shop product listing (/shop). Returns HTML. |
| public_access_sitemapC | Download sitemap.xml from Odoo website. |
| odoo_reportC | Generate a PDF report for records. Returns base64-encoded PDF. |
| odoo_versionC | Get Odoo server version info. |
| odoo_refreshA | Send a refresh notification to the user's Odoo browser tab. Call this after creating, updating, or deleting records so the user's list/form/kanban view reloads automatically. Requires l10n_bg_claude_terminal module installed on the Odoo instance. |
| odoo_fp_listA | List fiscal positions with tax action map summary (l10n_bg_tax_admin). Shows position name, auto_apply, country, company, and action mapping count. |
| odoo_fp_detailsB | Get detailed fiscal position with all tax action map entries (l10n_bg_tax_admin). Returns position info plus full action mappings: move types, BG move types, VAT types, document types, narrations, replacement rules, etc. |
| odoo_fp_configureA | Add or update a tax action map entry for a fiscal position (l10n_bg_tax_admin). Provide action_id to update existing entry, or position_id to create new. Use odoo_fp_types for available selection values. |
| odoo_fp_remove_actionC | Remove a tax action map entry from a fiscal position (l10n_bg_tax_admin). |
| odoo_fp_typesA | Get available selection values for fiscal position configuration (l10n_bg_tax_admin). Returns move_types, bg_move_types, doc_types, and type_vat. Use as reference when calling odoo_fp_configure. Set live=true to fetch current values from Odoo instead of cached. |
| odoo_stock_product_flip_to_storableA | Flip a product from consumable (is_storable=false) to storable (is_storable=true) when the product ALREADY has stock.move records. Bypasses Odoo's ORM constraint 'You can not change the inventory tracking of a product that was already used' via raw SQL in an ir.actions.server. Then inserts a stock.quant DIRECTLY (not through an inventory adjustment wizard) so no duplicate SVL is created — existing SVLs stay intact. Use when a GRN/bill was recorded for a product that was mistakenly set as consu. ALWAYS use dry_run=true first to preview impact. Returns full pre/post snapshot. |
| odoo_translate_context_awareA | Translate Odoo records using Claude with rich domain context for natural, fluent results (not literal). AUTO-DETECTS field kind and handles both: (1) simple char/text fields (e.g. ir.ui.menu.name, account.account.name) → batch translate via update_field_translations; (2) HTML/XML fields (e.g. ir.ui.view.arch_db, website.page, product.template.website_description) → extracts canonical terms via get_field_translations, translates each term preserving inline HTML tags (, , ...), writes back in terms mode. Context to LLM: Odoo model, parent chain for menus, existing translations, user-supplied domain hint, field kind (simple/html/xml). Requires Odoo 16+. Requires ANTHROPIC_API_KEY env var (per-tenant override: ANTHROPIC_API_KEY_). Recommended models: 'claude-haiku-4-5' (menu labels, fast), 'claude-sonnet-4-6' (balanced, website pages), 'claude-opus-4-7' (complex legal/accounting terminology). ALWAYS use dry_run=true first to review proposals. |
| odoo_stock_mo_delete_draftA | Safely DELETE a draft or cancelled mrp.production with cascade (raw stock.moves, finished stock.moves, procurement.group if orphaned). Bypasses Odoo's ORM 'cannot be deleted' constraint by forcing state='cancel' via raw SQL, then using DELETE statements inside an ir.actions.server. Refuses if MO has any SVL, stock.move with quantity > 0, or an already-done state. ALWAYS use dry_run=true first. |
| odoo_record_backupA | Read full field snapshot of one or more records (any model) and return as a JSON structure. Use BEFORE destructive operations to capture state for possible rollback. Returns a dict with metadata (date, connection alias, model, ids, field count) plus the records themselves. Does NOT write to disk — caller decides what to do with the JSON. |
| odoo_stock_close_unaccounted_valueA | Create an Inventory Valuation journal entry (Dr stock valuation / Cr GRNI/stock-input) for a stocked movement that was valued but not accounted (account_move_id=false), then bind the new account.move back to the record. Version-aware: works on stock.valuation.layer (Odoo 14-18) OR stock.move (Odoo 19+). GRNI account auto-detection order: (a) v14-18 → category.property_stock_account_input_categ_id; (b) v19 with l10n_bg_stock_account → category.l10n_bg_stock_input_account_id; (c) v19 vanilla → category.account_stock_variation_id (fallback). User can override via grni_account_id parameter. Refuses if record is already accounted or category is not real_time. ALWAYS use dry_run=true first. |
| odoo_stock_initial_importA | Import opening stock balances (initial inventory) via direct SQL INSERT, bypassing ORM overrides (e.g. custom modules that null out stock.move.name). Version-aware: v14-v18 creates stock.move + stock.move.line + stock.valuation.layer + stock.quant; v19 creates stock.move (with value/price_unit/remaining_qty/remaining_value/is_valued=true/is_in=true fields — SVL does not exist) + stock.move.line + stock.quant. All datetimes anchored at 23:59:59 in the caller's timezone, converted to UTC before INSERT. Writes a JSON snapshot to /backups// before execution. ALWAYS use dry_run=true first to preview the plan and catch category/location/product errors. For real_time valuation, follow up with odoo_stock_initial_opening_journal to book the account entry (SQL INSERT does NOT create account.move). |
| odoo_stock_initial_deleteA | Delete wrong opening stock balances — cascade-removes stock.move (is_inventory=TRUE) records, their stock.move.line, and (v14-v18) stock.valuation.layer; then zeros out stock.quant on affected (product, location, lot). Bypasses Odoo's ORM guard 'You can not delete product moves if the picking is done' via raw SQL in an ir.actions.server + env.cr.commit(). Version-aware: v14-v18 DELETEs SVL→SML→SM; v19 DELETEs SML→SM (SVL doesn't exist). PRE-FLIGHT: refuses if any affected SVL/stock.move has account_move_id set (orphan journal entries would remain). Caller must reverse those first. ALWAYS writes a full JSON backup to /backups// BEFORE any delete. ALWAYS use dry_run=true first to see the impact scope. |
| odoo_stock_initial_opening_journalA | Book the opening-balance journal entry for a previous SQL-inserted initial stock (complements odoo_stock_initial_import — SVL/stock.move written via raw SQL do NOT auto-create account.move even for real_time valuation). Creates ONE account.move (MISC journal, state=posted) with: DR lines grouped by category.property_stock_valuation_account_id (e.g. 302 Materials, 303 Products); CR contra account (default: code '122000' Retained earnings from prior years). Version-aware: v14-v18 reads stock.valuation.layer for the date; v19 reads stock.move (is_inventory=true, is_valued=true) for the same date — totals the 'value' column. DUPLICATE GUARD: before create, scans account.move.line for the same accounts on the same date — if any posted lines found, refuses and returns them (Alpinter lesson: comprehensive opening entries often already include the stock lines). ALWAYS use dry_run=true first. |
| google_authA | Authenticate with Google OAuth2 for Gmail and Calendar access. Requires credentials.json from Google Cloud Console (Desktop app type). First call opens browser for consent. Token is saved for reuse. |
| google_auth_statusB | Check Google authentication status. |
| google_gmail_searchA | Search Gmail messages. Uses Gmail search syntax (e.g. 'from:user@example.com', 'subject:invoice', 'after:2026/01/01', 'is:unread'). |
| google_gmail_readA | Read a specific Gmail message by ID. Returns full body, headers, and labels. |
| google_gmail_sendB | Send an email or reply to an existing message. |
| google_gmail_labelsA | List all Gmail labels (folders). |
| google_calendar_listA | List all available Google calendars. |
| google_calendar_eventsB | List upcoming calendar events. Supports time range and text search. |
| google_calendar_create_eventC | Create a new calendar event. |
| google_calendar_update_eventB | Update an existing calendar event. Only provided fields are changed. |
| google_calendar_delete_eventC | Delete a calendar event. |
| telegram_configureA | Set Telegram API credentials (api_id and api_hash from my.telegram.org). |
| telegram_authA | Authenticate with Telegram. Two-step process: 1) Call with phone → code is sent to Telegram. 2) Call with phone + code → authenticated. If 2FA enabled, provide password too. |
| telegram_auth_statusA | Check Telegram authentication status. |
| telegram_get_dialogsC | List recent Telegram chats (users, groups, channels). |
| telegram_search_contactsC | Search Telegram contacts by name or username. |
| telegram_get_messagesA | Read messages from a Telegram chat. Chat can be @username, phone, or numeric ID. |
| telegram_send_messageB | Send a Telegram message. Chat can be @username, phone, or numeric ID. |
| telegram_send_fileA | Send a file/document to a Telegram chat. The file must live under the MCP download root (MCP_DOWNLOAD_ROOT, default /data/downloads) — pass a relative path or an absolute path inside it. Chat can be @username, phone, or numeric ID. |
| telegram_download_mediaA | Download media/document from a Telegram message into the MCP download root (MCP_DOWNLOAD_ROOT, default /data/downloads). Returns the saved path. |
| telegram_sub_addA | Subscribe a principal's Telegram listener to a chat (admin allow-list). No subscriptions for a principal = listen to ALL (back-compat). Once a principal has any subscription, only those chats are pushed to its telegram: channel. Use 'principal' to assign for another user. |
| telegram_agent_enrollA | Enroll a Telegram chat for agentic handling with a scenario. mode: auto (self-converse) | advisory (suggest, human sends) | notify. scenario (optional dict): persona, default_toolset, data_scope {models,fields,pricelist}, forbid[], company_id, quote_send (approve|auto), skills[] ({name,toolset,triggers[]}). Confidentiality is enforced by data_scope. Enrolments are per-principal — you never see or change another principal's. |
| telegram_agent_unenrollC | Stop agentic handling for a chat. |
| telegram_agent_listA | List enrolled chats with their mode/persona/skills. |
| telegram_agent_get_scenarioA | Get the full scenario for an enrolled chat. |
| telegram_agent_set_scenarioB | Replace the scenario for an enrolled chat. |
| telegram_agent_routeA | Classify the conversation direction for an enrolled chat and return the active TOOLSET to switch to (based on the scenario's skills), plus the data_scope/forbid guardrails and a memory_search_hint. Call this on each incoming message before acting. |
| telegram_agent_product_lookupA | Search products for an enrolled chat, returning ONLY the scenario's allowlisted fields (confidential fields withheld by design). Uses the scenario's company + pricelist. |
| telegram_agent_create_quoteC | Create a DRAFT sale.order in the scenario's company. Returns a shareable summary. Honors quote_send (approve → confirm before sending; auto → may send). |
| telegram_sub_listB | List a principal's Telegram chat subscriptions. allow_all=true means no filter (listens to all). |
| telegram_sub_removeC | Remove a chat from a principal's Telegram subscription allow-list. |
| open_connection_managerA | Open the Connection Manager GUI (desktop app). Launches GTK4 version on Linux, Qt6 on Windows/macOS. Use this when the user wants to visually manage connections, configure Portainer/GitHub, manage SSH keys, or see active sessions. |
| ssh_executeA | Execute a command on a remote server via SSH. Uses SSH config from connections.json (connection's ssh section). Provide either a connection alias (to use saved SSH config) or explicit host/user. |
| git_remoteB | Run git commands on a remote server via SSH. Shortcut for common git operations (pull, status, log, branch, diff) on remote repositories. Provide the connection alias and repo path. |
| github_apiA | Call GitHub REST API directly. Uses the GitHub token from local_profile.json. For operations not covered by the GitHub MCP server, or when it's not running. |
| identifyA | Identify yourself to load your personal settings and connections. Call this at the start of a session. Returns your saved connections. |
| who_am_iA | Show current user identity and active connection. |
| session_listA | List MCP session-store rows. Regular callers see their own sessions; admin principals (MCP_ADMIN_PRINCIPALS) see all. |
| session_revokeA | Revoke one MCP session (admin, or your own): marks the row revoked and tears down its live resources (connection, web, telegram client when unreferenced). |
| user_connection_addB | Add/update a personal Odoo connection (saved per-user). Supports Odoo, SSH, and Portainer settings. |
| user_connection_listB | List your personal connections. |
| user_connection_activateA | Activate one of your personal connections as the working connection. |
| user_connection_deleteA | Delete a personal connection. |
| memory_listA | List memory files. Shows personal files (for current user) and shared files. Use scope='personal', 'shared', or 'all' (default). |
| memory_readA | Read a memory file by filename. Searches personal first, then shared. |
| memory_writeA | Write/update a memory file. Saves to personal storage by default. Content should be markdown with YAML frontmatter (name, description, type). |
| memory_deleteC | Delete a memory file from personal or shared storage. |
| memory_shareA | Share personal memory file(s) — copies to shared storage so colleagues can pull. Use filename='*' to share ALL personal files. |
| memory_pullA | Pull shared memory file(s) into your personal storage. Use filename='*' to pull ALL shared files at once. If a file already exists locally, it gets overwritten with the shared version. |
| proxy_callA | Forward a tool call to an internal MCP sub-service. Available services: 'portainer' (Docker/K8s management, 38 tools), 'github' (repos/issues/PRs, 20 tools), 'teams' (MS Teams messaging, 6 tools). Use proxy_discover first to see available tools on each service. |
| proxy_discoverA | List available tools on an internal MCP sub-service. Call this first to see what tools are available on portainer/github/teams. |
| proxy_refreshA | Re-discover tools from all internal MCP sub-services. Use after starting a new sub-service or if tools are missing. |
| ai_tokenize_recordB | Tokenize a single Odoo record: build composite document, embed via configured provider, upsert to Qdrant. Synchronous — returns final state. |
| ai_tokenize_collectionA | Tokenize ALL records of a model via the registry entry. Heavy operation — for large models prefer the nightly cron. Returns count of processed records. |
| ai_search_similarA | Semantic search across tokenized Odoo records. Embeds the query with the configured provider, searches the per-DB Qdrant collection. Filterable by model, view_type, company. Returns ranked hits with score + snippet. |
| ai_list_documentsC | List ai.composite.document records (tokenized records tracked by Odoo). Useful for monitoring tokenization progress / errors. |
| ai_collection_infoB | Return info about the per-database Qdrant collection: vector size, distance metric, point count, indexed-vectors count, plus Odoo-side indexed-document count for cross-check. |
| ai_invoice_extractA | Extract structured invoice data from an Odoo attachment via Anthropic Vision. Auto-routes to haiku/sonnet/opus based on pages+size. Writes extract_prefill_data back to account.move (if write_back). Logs usage to the billing ledger with token counts + cost in millicents. |
| ai_usage_log_queryA | Query the AI usage billing ledger. Filter by tenant, state, source, date range. Returns detailed rows for audit + monthly reconciliation. |
| ai_usage_log_statsA | Dashboard KPIs for the billing ledger: totals, per-model breakdown, 30-day timeseries, recent errors, derived metrics (cache hit rate, avg cost per billed doc, monthly €). |
| ai_usage_log_exportA | Export billing ledger rows as CSV for a tenant + date range. Used for month-end invoice generation and audit trails. |
| ai_invoice_stack_inspectA | Cross-layer snapshot for a single account.move: Odoo state + attachments + extraction history + skill status + decided next_step with blockers and hints. Read-only. |
| ai_invoice_scan_pendingA | List vendor-bill drafts that have an attachment and no successful extraction yet. Oldest first (FIFO). Feeds batch processing. Set requested_only=true to return only moves explicitly queued by the l10n_bg_ai_invoice_glue attachment auto-trigger (ai_pipeline_requested=True) — recommended for cron drivers. |
| ai_invoice_pipeline_summaryB | Dashboard aggregation: counts of vendor bill moves by next_step across the last 60 days. Use for header KPI cards. |
| ai_usage_budget_statusB | Current month's vision spend vs configured cap. Reads res.company.ai_monthly_budget_eur (requires l10n_bg_ai_invoice_glue) and sums billed ai_usage_log rows. Returns spent, limit, remaining, % used. |
| ai_invoice_pipeline_runB | Execute the full registered step pipeline for one move+attachment. Steps: probe_move → guard_already_extracted → extract_vision → log_usage → write_back_move → invoke_posting_skill + any loaded plugins. Returns step-by-step audit trail. |
| ai_invoice_pipeline_stepsA | List currently registered pipeline steps with sequence, description, and plugin vs built-in provenance. Useful for debugging which steps will run against a move. |
| ai_invoice_plugins_reloadA | Reload plugin steps from the plugins directory (default /data/plugins/ai_invoice). Called after uploading a new plugin without restarting the server. |
| ai_pipeline_runA | Execute an Odoo-defined pipeline (ai.pipeline.step records for the given pipeline name, ordered by sequence). Respects skill_id + trigger_domain + on_error. MCP-native steps (model starts with 'mcp') are dispatched to the local registry; other steps are invoked via RPC on the configured Odoo model.method. Writes back last_run_state/message per step. |
| ai_pipeline_steps_listA | List ai.pipeline.step records in Odoo for a given pipeline name. Shows sequence, model.method, skill_id, on_error, last run state — mirrors the Odoo Settings view. |
| ai_pipeline_step_executeA | Execute a single ai.pipeline.step by name via Odoo RPC. Looks up the step in Odoo by name, builds a ctx from the supplied parameters, calls env[step.model].step.method(ctx), and returns the updated ctx (with composite_fields populated by the step). Use ai_pipeline_steps_list to discover available step names. |
| mcp_terminal_get_configA | Generate a password-protected ZIP archive with the Claude Terminal configuration keys (MCP, Qdrant, Embeddings) for the requesting tenant. Anthropic API key is NOT included by default (set include_anthropic=true to embed it). Returns base64-encoded ZIP + a temporary password (shown ONCE — copy it now). Use the password in the Odoo Setup Wizard (Settings → Technical → Настройка с ZIP конфигурация) to apply the config across res.company + res.users records in 5 guided steps. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 138 tools
Many tools have clear distinct purposes, but there are several overlapping pairs like odoo_search vs odoo_search_read vs odoo_search_count, odoo_report vs odoo_web_report vs public_access_report_pdf, and odoo_execute vs odoo_web_call. The separation between web-session and XML-RPC tools is subtle and could cause misselection. Some AI and stock tools are also highly specialized, but their descriptions help.
Most tools follow a consistent snake_case prefix_domain_action pattern (e.g., odoo_read, telegram_send_message, google_calendar_list). Some outliers like identify, who_am_i, and open_connection_manager break the pattern but are still readable. Overall the naming is predictable and grouped by domain.
138 tools is far beyond any reasonable scope for a single MCP server. Even for a multi-domain personal assistant, this is excessive and will overwhelm an agent's tool selection. The server would benefit from splitting into separate MCP servers per domain (Odoo, Telegram, Google, AI, etc.).
The tool surface covers a wide range of operations across Odoo (CRUD, web, reports, translations, website snippets, fiscal positions, stock), Telegram, Google (Gmail, Calendar), AI pipelines, and memory. Some minor gaps exist (e.g., no Gmail draft/delete, no Odoo user management), but core workflows are well covered. The sheer number suggests high coverage, though it could be more focused.