oCoreoCore Docs

MCP Integration

Connect AI assistants like Claude and Cursor to manage Odoo instances through oCore using the Model Context Protocol.

oCore implements a Model Context Protocol (MCP) server that lets AI assistants interact with your Odoo instances directly. MCP is an open standard that provides a structured way for AI tools to discover and call functions exposed by external systems. Through oCore's MCP server, assistants like Claude Desktop, Cursor, and other MCP-compatible clients can search records, inspect schemas, run SQL queries, manage modules, and more -- all scoped to the instances your API key has access to.

How It Works

When an AI assistant connects to oCore's MCP server, it authenticates with an API key and receives a list of tools namespaced by instance. For example, if your API key has access to an instance with slug prod-v17, the assistant sees tools like prod_v17_search_read, prod_v17_execute_sql, and prod_v17_list_models. The assistant can then call these tools as part of a conversation to read data, inspect schemas, or perform operations on that Odoo instance.

Each MCP session is isolated: the tools available depend on the API key's permissions, instance scoping, and your organization's security settings.

Setting Up MCP Access

There are two ways to connect an AI assistant to oCore:

  1. OAuth flow (recommended): The AI client connects directly using the MCP server URL. oCore handles authentication through an OAuth consent screen in your browser -- no API key copying required.
  2. Manual API key: Create an API key in the dashboard and paste it into the client's configuration file.

Instance and Category Filtering

You can filter which instances appear in a session by appending ?instances=slug1,slug2 to the SSE URL. You can also filter tool categories with ?categories=orm,sql,metadata.

Connecting Claude Desktop

Claude Desktop supports OAuth-based MCP connections. Add this to your claude_desktop_config.json (typically at ~/.config/claude/claude_desktop_config.json on Linux or ~/Library/Application Support/Claude/claude_desktop_config.json on macOS):

{
  "mcpServers": {
    "ocore": {
      "type": "sse",
      "url": "https://your-ocore-domain.com/api/mcp/sse"
    }
  }
}

When Claude Desktop connects, it will discover oCore's OAuth endpoints automatically, open your browser for login and consent, and receive tokens without any manual key management.

{
  "mcpServers": {
    "ocore": {
      "type": "sse",
      "url": "https://your-ocore-domain.com/api/mcp/sse",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Create an API key in Settings > API Keys and paste it into the config.

After saving the config, restart Claude Desktop. The MCP tools will appear in the tool picker.

Connecting ChatGPT

ChatGPT uses the same OAuth-based MCP connection flow. When you add oCore as an MCP server in ChatGPT:

Enter the oCore MCP server URL: https://your-ocore-domain.com/api/mcp/sse

ChatGPT discovers the OAuth authorization server via the .well-known endpoints.

Your browser opens to the oCore login page (if not already signed in), then the consent screen.

After approving, ChatGPT receives OAuth tokens and the MCP tools become available in your conversation.

When an AI client initiates an OAuth connection, you will see a consent screen in your browser. This is what happens:

Login: If you are not already signed into oCore, you will be redirected to the login page first.

Consent screen: The consent page shows the requesting client's name and logo, the permissions (scopes) it is requesting, and your available organizations.

Select an organization: Pick which organization the AI client should have access to.

Configure permissions: Choose a permission preset or customize categories, instance scoping, tool allowlists, and read-only mode.

API key handling: Choose to auto-create a new MCP API key or link an existing one from the picker.

Approve or deny: Click approve to grant access. oCore creates the API key (if auto-creating) and issues OAuth tokens to the client.

Existing Key Picker

If you already have active MCP API keys in the selected organization, the consent form shows them in a picker. Linking an existing key avoids creating a duplicate and lets you reuse your existing permission configuration.

Managing OAuth Authorizations

Navigate to Settings > OAuth Authorizations to view and manage your active OAuth connections:

  • See which AI clients are connected and when they last authenticated
  • View the organization and API key linked to each authorization
  • Revoke individual authorizations (this soft-deletes the OAuth tokens and cleans up auto-created API keys)
  • Revoke all authorizations for a specific client

Using with Cursor

Add the following to your project's .cursor/mcp.json file:

{
  "mcpServers": {
    "ocore": {
      "type": "sse",
      "url": "https://your-ocore-domain.com/api/mcp/sse",
      "headers": {
        "Authorization": "Bearer YOUR_API_KEY"
      }
    }
  }
}

Cursor will discover the MCP server and make the tools available in chat and the agent panel.

Device Flow for CLI Tools

If you are using a CLI tool or working in an environment without browser redirects (SSH sessions, containers), the device authorization flow lets you authenticate:

The CLI tool displays a user code (e.g., BCKF-HMLT) and a verification URL.

Open the URL in any browser on any device. You can also scan the QR code displayed in the terminal.

Log into oCore, confirm the user code, select an organization, and approve.

The CLI tool automatically receives tokens and connects to the MCP server.

Device codes expire after 15 minutes. If the code expires before you approve, the CLI tool will need to request a new one.

An administrator can share an MCP invite link that lets you connect to their organization without going through the full OAuth consent flow. When you receive an invite link:

Open the link in your browser (it looks like https://ocore.example.com/oauth/invite/<token>).

Log into oCore if you are not already signed in.

Review the permissions the invite grants and accept.

oCore creates an MCP API key for you in the admin's organization with the invite's scoped permissions.

If you are not already a member of the organization, oCore automatically adds you as a Viewer. The invite's permissions cannot exceed the admin's own permissions -- scope escalation is prevented.

Using with Other MCP Clients

oCore supports two MCP transports:

  • SSE (Server-Sent Events) at /api/mcp/sse -- for browser-based and long-lived connections
  • Streamable HTTP at /api/mcp/stream -- for stateful HTTP-based clients

Any MCP-compatible client can connect by pointing to one of these endpoints. Clients that support OAuth will discover the authorization server automatically. For clients without OAuth support, include a valid API key in the Authorization: Bearer header.


Available Tools

oCore exposes 101 tools across 14 categories. Each instance-scoped tool is prefixed with the instance slug (e.g., myinstance_search_read). Platform tools use the ocore_ prefix.

Tool Categories Overview

CategoryToolsDescription
orm12Core CRUD and batch operations on Odoo models
search5Advanced search, aggregation, count, and fuzzy matching
metadata10Model schemas, field definitions, views, translations, and instance info
sql3Direct PostgreSQL queries and table inspection
shell3Python code execution in the Odoo environment
files9Read, write, and search files in Odoo addon directories
modules10Install, upgrade, uninstall, and inspect Odoo modules
system18User management, cron jobs, system parameters, logs, and backups
context14Knowledge notes, saved filters, bookmarks, and context loading
monitoring10PostHog analytics: users, errors, performance, sessions
export2CSV import and export
attachments4List, upload, download, and delete file attachments
reports1Generate QWeb reports as PDF or HTML
platform2List instances and servers (not instance-scoped)

Common Parameters

Most tools accept these optional parameters:

ParameterDescription
timeout_secondsTimeout in seconds (default: 15, max: 120)
max_response_sizeMax response size in KB (default: 50)
contextOdoo context dict (lang, tz, company_id)
confirmRequired for destructive operations. Set to true to proceed.
dry_runIf true, returns what would be affected without executing

ORM Operations

Core CRUD operations on Odoo models. Category: orm.

ToolDescriptionType
search_readSearch and read records with domain filters, pagination, field selection, and smart field defaults. Supports format: "text" for human-readable output.Read
readRead specific records by their IDs. Returns full field values for the requested records.Read
countCount records matching a domain filter without fetching data.Read
createCreate a new record. Returns the full created record with smart-selected fields.Write
writeUpdate existing records by ID. Returns the full updated records.Write
unlinkDelete records by ID. Requires confirm: true.Destructive
copyDuplicate a record with optional field overrides. Returns the full new record.Write
execute_methodCall any public model method not covered by other tools. Blocked methods (sudo, with_user, shell, etc.) and blocked models (ir.config_parameter) are rejected. Read-only methods like name_search, default_get, and onchange bypass the write check.Write

Smart Field Selection

search_read, read, create, and write automatically select the most useful fields when none are specified, omitting large binary/HTML fields and internal technical fields. You can always pass an explicit fields array to override.

Search and Aggregation

Advanced search tools for complex queries. Category: search.

ToolDescriptionType
advanced_searchSearch with a mandatory domain filter. Like search_read but domain is required. Includes total count and pagination hints.Read
aggregationGroup and aggregate data using Odoo's read_group. Supports presets (count_by_state, count_by_date) and output formats (json, table, csv).Read
distinct_field_valuesGet distinct values for one or more fields. Useful for understanding data distribution.Read
fuzzy_searchFuzzy text search with similarity scoring using Python's difflib. Supports multi-field matching via search_fields.Read

Batch Operations

Bulk operations on multiple records. Category: orm (uses ORM permission category). Max batch size: 500.

ToolDescriptionType
batch_createCreate multiple records in one call. Each record is independent -- partial failures do not roll back successful creates.Write
batch_updateUpdate multiple records with different values each. Each update is independent.Write
batch_deleteDelete multiple records by ID. Requires confirm: true.Destructive
batch_copyDuplicate multiple records with optional shared default overrides.Write
batch_executeExecute a method on multiple records independently.Write

Schema and Metadata

Inspect Odoo model definitions and instance configuration. Category: metadata.

ToolDescriptionType
list_modelsList all non-transient Odoo models with name, label, state, and source module. Results are cached for 5 minutes. Filterable by state and search.Read
get_field_metadataGet field definitions for a model. Default summary mode shows 12 attributes per field. Set detail: true for full metadata. Set grouped: true (default) to organize by simple/relational/technical categories.Read
get_model_constraintsGet SQL and Python constraints defined on a model.Read
get_model_relationsGet all relational fields (Many2one, One2many, Many2many) with their target models, inverse names, and relation tables.Read
get_model_methodsList all methods on a model including API decorator type. Set include_private: false to hide private methods.Read
get_model_viewsGet view definitions (XML arch + metadata) for form, tree, search, and kanban views. Optionally filter by view_type.Read
get_instance_infoGet oCore instance details: server, environment, project, Odoo version, edition, write status, ports, and timestamps.Read
get_addon_manifestRead a module's manifest metadata from ir.module.module: name, summary, description, author, license, category, state, and installed version.Read

SQL Queries

Direct PostgreSQL access. Category: sql.

ToolDescriptionType
execute_sqlRun a SQL query against the instance database. SELECT queries auto-add LIMIT 1000 if no LIMIT is specified. DML (INSERT/UPDATE/DELETE) requires confirm: true and shows an EXPLAIN preview first. DDL is blocked. Dangerous functions (pg_read_file, dblink, lo_import) are blocked. Output formats: json, table, csv. Supports explain: true for query plans.Write
execute_sql_scriptRun a multi-statement SQL script with transaction control (BEGIN/COMMIT/SAVEPOINT). Requires confirm: true for DML. DDL is blocked.Destructive
list_tablesList database tables with row counts, sizes, and Odoo model mapping. Set raw_pg: true for raw PostgreSQL table info without model resolution.Read

SQL Safety

DDL statements (CREATE TABLE, ALTER TABLE, DROP TABLE) are always blocked. Dangerous PostgreSQL functions for filesystem and external access are rejected. A statement_timeout is set automatically based on the timeout_seconds parameter.

Shell and Code Execution

Execute Python code in the Odoo environment. Category: shell. All shell tools require mcp_write_enabled.

ToolDescriptionType
execute_shellExecute Python code in the Odoo shell with access to env, self, and all Odoo imports. Output is wrapped as {stdout, stderr, exit_code}.Write
execute_shell_multiExecute multiple Python commands in a single session. Variables and imports persist across commands within the same call.Write
python_replStateless Python REPL. Each call starts fresh -- include all imports and setup each time.Write

File Operations

Read and modify files in Odoo addon directories. All paths are relative to the instance's custom addons root and sandboxed to prevent directory traversal. Category: files.

ToolDescriptionType
file_browseList files and directories in an addon directory. Omit path to list all custom addons.Read
file_readRead file content. Supports line ranges (start_line, end_line) for large files and encoding: "base64" for binary files. Default max size: 100KB.Read
file_writeEdit an existing file. Three modes: full_content (replace entire file), patch (unified diff), or insert_at_line (insert at a specific line).Write
file_createCreate a new file or directory. Set is_directory: true for directories. Supports nested directory creation.Write
file_deleteDelete a file. Requires confirm: true.Destructive
file_infoGet file metadata: size, permissions, modification time, and git status (modified, staged, untracked, clean).Read
file_treeRecursive directory listing. Default depth: 3 levels (max: 3).Read
file_moveMove or rename a file within the addon directory.Write
search_in_codeSearch for text or regex patterns in addon source code. Scope to a specific addon or search all custom addons. Returns file paths, line numbers, and matching content with context.Read

Module Management

Install, upgrade, and inspect Odoo modules. Category: modules. Install/upgrade/uninstall operations enforce a minimum 90-second timeout.

ToolDescriptionType
list_modulesList all available modules with state, version, category, and author. Filterable by state, category, and search.Read
install_moduleInstall an Odoo module.Write
upgrade_moduleUpgrade one or more modules to their on-disk version.Write
uninstall_moduleUninstall a module. Requires confirm: true.Destructive
module_driftDetect version drift between installed modules in the database and their on-disk manifest versions.Read
module_dependenciesGet the dependency graph for a module. Shows both direct and reverse dependencies.Read
module_categoriesList all module categories with module counts.Read
check_uninstall_depsCheck what depends on a module before uninstalling. Shows dependent modules, models, and views that would break.Read
module_historyView module install/upgrade history for the instance.Read
scaffold_moduleCreate a complete Odoo module skeleton with manifest, models, views, security, and directory structure.Write

User and System Administration

Manage Odoo users, system parameters, cron jobs, and server operations. Category: system.

ToolDescriptionType
list_usersList Odoo users with search and active filter. Returns id, login, name, active, last_login, share, and company_id.Read
user_groupsView security group memberships for a user. Returns group id, full name, and category.Read
set_user_activeActivate or deactivate a user. System users (IDs 1-3) are protected.Write
set_user_passwordReset a user's password (superuser reset, no current password needed). Min 8 characters. System users protected.Write
set_user_groupsReplace all security group assignments for a user. Use user_groups first to see current groups.Write
impersonate_userCreate a one-time login URL to impersonate an Odoo user with full audit trail. System users protected.Write
user_access_rightsView effective access rights for a user on a model. Shows can_read, can_write, can_create, can_unlink and granting groups. Set detail: true for raw ACL and ir.rule data.Read
get_system_parameterRead Odoo system parameters (ir.config_parameter). Without a key, returns all parameters. Sensitive values (passwords, secrets, tokens) are automatically masked.Read
set_system_parameterSet or create an Odoo system parameter.Write
list_scheduled_actionsList all scheduled actions (ir.cron) including disabled ones. Shows interval, next/last call times, and priority.Read
toggle_scheduled_actionEnable or disable a scheduled action.Write
run_scheduled_actionTrigger a scheduled action immediately. Enforces a 60-second cooldown between identical triggers. Requires confirm: true.Write
clear_system_cacheClear Odoo caches (asset bundles, .pyc files, session files). Requires confirm: true.Destructive
server_infoGet Odoo server version, installed module count, database name, and configuration.Read
odoo_logsTail Odoo container logs. Default 100 lines (max 1000). Supports grep-style filtering with filter parameter.Read

Database Backup and Restore

Create, list, and restore database backups. Category: system.

ToolDescriptionType
backup_databaseCreate a pg_dump backup. Pre-checks database size against a configurable limit (default 2GB). Formats: custom (binary, default) or plain (SQL text).Write
list_backupsList available backup files with timestamps and sizes. Filterable by max_age_days.Read
restore_databaseRestore a database from a backup file. Automatically creates a pre-restore snapshot before proceeding. Stops and restarts the Odoo container. Requires confirm: true.Destructive

Restore Safety

Database restore is a destructive operation. A pre-restore backup is always created automatically. If the pre-restore backup fails, the restore is aborted. The Odoo container is always restarted after restore, even if the restore fails mid-way.

Knowledge and Context

Persistent knowledge storage and reusable filters for AI sessions. Category: context.

Notes

ToolDescriptionType
add_noteAdd a knowledge note about an instance, model, record, field, or module. Notes are shared across all API keys in the organization. Max 100 notes per scope.Write
list_notesList notes filtered by target type, tags, or search text.Read
update_noteUpdate an existing note. Only provided fields are modified.Write
delete_noteSoft-delete a note. Requires confirm: true.Destructive
set_model_summarySet or update the summary note for a specific model. Upserts a note tagged ["summary"].Write
set_instance_summarySet or update the summary note for the instance. Upserts a note tagged ["summary"].Write

Saved Filters

ToolDescriptionType
save_filterSave a reusable search filter for a model. Stores domain, fields, order, and limit.Write
list_filtersList saved filters for the instance, sorted by most-used first.Read
run_filterExecute a saved filter by name or ID and return matching records.Read
delete_filterSoft-delete a saved filter. Requires confirm: true.Destructive

Bookmarks and Context

ToolDescriptionType
bookmark_callBookmark an MCP tool call for future reference. Stores an inline snapshot of the tool name, parameters, and result summary. If no audit_log_id is provided, bookmarks the most recent call in the session.Write
list_bookmarksList bookmarked tool calls. Filterable by instance, tags, or search text. Returns up to 50 bookmarks, most recent first.Read
delete_bookmarkSoft-delete a bookmark. Requires confirm: true.Destructive
get_contextLoad aggregated knowledge context: instance summary, model summaries, notes, saved filters, and recent bookmarks. Useful at session start to give the AI assistant full context.Read

Analytics and Monitoring

PostHog-powered analytics for Odoo instances. Category: monitoring. Requires PostHog to be configured. All tools accept a period parameter (1d, 7d, 14d, 30d, 90d).

ToolDescriptionType
posthog_dashboardFull analytics dashboard: DAU, WAU, MAU, sessions, error rate, top modules, and web vitals.Read
posthog_active_usersActive user counts (DAU/WAU/MAU) and top users list.Read
posthog_online_usersCurrently online users (real-time, last 5 minutes).Read
posthog_module_usageModule usage analytics: which modules are most used and adoption rates.Read
posthog_web_vitalsCore Web Vitals (LCP, INP, CLS) and performance metrics.Read
posthog_errorsError summary: top error types, counts, and trends.Read
posthog_slow_rpcsSlowest RPC calls: endpoint, average duration, and call count.Read
posthog_sessionsSession statistics: count, average duration, bounce rate, and trends.Read
posthog_feature_flagsList PostHog feature flags: key, active status, and rollout percentage.Read
posthog_surveysList PostHog surveys: name, type, status, and response count.Read

CSV Import and Export

Bulk data import/export via CSV. Category: orm (uses ORM permission category).

ToolDescriptionType
import_csvImport records from CSV content. Validates headers against model fields, supports field_mapping to remap column names, and creates records in batches of 100. Max 1000 rows. Includes CSV formula injection protection. Note: batches commit independently with no rollback between batches.Write
export_csvExport records as CSV. Uses smart field defaults (stored fields only) when no fields are specified. Max 5000 rows (default 500). Column headers use field labels.Read

Translations

Read and update Odoo translations. Handles both Odoo 17 (ir.translation model) and Odoo 18+ (field translation API) automatically. Category: metadata.

ToolDescriptionType
list_translationsList translations for a model, optionally filtered by field and language.Read
update_translationUpdate a translation value. For Odoo 18+, the source parameter (old value to replace) is required.Write

Attachments

Manage Odoo file attachments (ir.attachment). Category: attachments. Max file size: 10 MB.

ToolDescriptionType
list_attachmentsList attachments for a specific model record. Filterable by MIME type.Read
upload_attachmentUpload a base64-encoded file attachment to a model record. Requires mcp_write_enabled.Write
download_attachmentDownload attachment content by ID as base64. Runs as admin and bypasses ir.attachment record rules.Read

Reports

Generate Odoo QWeb reports. Category: reports.

ToolDescriptionType
generate_reportGenerate a QWeb report as PDF or HTML. Pre-checks wkhtmltopdf status for PDF format. Max records: 10 for PDF, 50 for HTML. Output size limit: 10 MB (base64). Minimum timeout: 60 seconds.Read

Platform Tools

These tools are not instance-scoped and use the ocore_ prefix instead of an instance slug. Category: platform.

ToolDescription
ocore_list_instancesList all instances accessible to the current API key. Returns id, name, slug, Odoo version, status, environment type, and mcp_write_enabled.
ocore_list_serversList all servers in the organization. Returns id, name, host, and status.

Knowledge Layer

The Knowledge Layer is a persistent storage system that lets AI assistants accumulate and reuse knowledge about your Odoo instances across sessions. It consists of three data types -- notes, saved filters, and bookmarks -- all scoped to your organization and optionally to specific instances.

Notes

Notes store human or AI-authored knowledge about your Odoo environment. Each note is attached to a specific target:

Target TypeDescriptionExample
instanceAbout the instance as a whole"This is our EU production instance running custom e-commerce flows"
modelAbout a specific Odoo model"sale.order: Custom fields x_approved_by and x_delivery_notes track approval workflow"
recordAbout a specific record"res.partner#42: Key customer, do not modify without sales team approval"
fieldAbout a specific field"sale.order.x_delivery_notes: Free-text field used by warehouse team"
moduleAbout a custom module"custom_invoicing: Handles VAT split for cross-border EU sales"

Notes properties:

  • Title -- Up to 200 characters
  • Body -- Up to 2,000 characters of content
  • Tags -- Optional array of tags for filtering (e.g., ["summary", "workflow"])
  • Shared -- Notes are shared across all API keys in the organization
  • Limit -- Up to 100 notes per scope to prevent unbounded growth
  • Soft delete -- Deleted notes are soft-deleted and excluded from queries

Summary Notes

Notes tagged with "summary" have special significance. The set_model_summary and set_instance_summary tools upsert a single summary note per target, making it easy to maintain one authoritative description. Summary notes are used by auto-context (see below) to inject knowledge into tool descriptions at session start.

Saved Filters

Saved filters store reusable Odoo domain searches that can be executed by name:

FieldDescription
NameUnique name per instance (e.g., "large_orders", "overdue_invoices")
ModelThe Odoo model to search (e.g., sale.order)
DomainOdoo domain filter expression as JSON (e.g., [["amount_total", ">", 10000]])
FieldsOptional list of fields to return
Order BySort order (e.g., amount_total desc)
Result LimitMaximum results to return (default 80)
Is DefaultAt most one filter per model per instance can be the default
Use CountAutomatically incremented each time the filter is executed, enabling "most-used first" sorting

Saved filters let an AI assistant quickly recall complex queries without re-specifying the domain each time. Use list_filters to see available filters (sorted by most-used first) and run_filter to execute one.

Bookmarks

Bookmarks save references to important MCP tool calls for future reference:

FieldDescription
LabelHuman-readable description (up to 200 characters)
NoteOptional extended notes (up to 1,000 characters)
TagsOptional tags for filtering
Tool NameThe MCP tool that was called
Tool ParamsSnapshot of the tool's input parameters
Result SummaryTruncated result (up to 500 characters)
Audit Log IDOptional link to the MCP audit log entry

Bookmarks store an inline snapshot of the tool call so they remain useful even if audit log entries are later purged. If no audit_log_id is provided when bookmarking, the system bookmarks the most recent call in the current session.

Auto-Context

When an API key has mcp_auto_context enabled, oCore automatically injects Knowledge Layer data into tool descriptions at session start. This gives the AI assistant immediate context without requiring an explicit get_context call.

At session registration time, oCore runs a parallel query (with a 5-second deadline) for each instance:

  1. Instance summary -- Loads the note tagged "summary" with target_type=instance
  2. Model summaries -- Loads up to 20 notes tagged "summary" with target_type=model, showing the model name and a 150-character excerpt
  3. Saved filter count -- Counts available saved filters and mentions them if any exist

The results are prepended to each instance's tool descriptions as an [Auto-context] prefix. For example:

[Auto-context] Instance context: EU production instance with custom VAT workflow.
Model summaries: sale.order: Custom approval fields x_approved_by, x_delivery_notes;
account.move: Modified to support split VAT for EU cross-border. 3 saved filters
available -- call get_context for details.

Enabling Auto-Context

Auto-context is controlled per API key. Enable it in the API key settings or during OAuth consent. The feature adds a small overhead at session start (5-second max) but provides immediate context for every conversation.

Loading Full Context

The get_context tool loads the complete Knowledge Layer for an instance in a single call:

  • Instance summary note
  • All model summary notes
  • All notes (non-summary, up to limit)
  • All saved filters with name, model, and description
  • Recent bookmarks (up to 50)

This is useful at the beginning of a session when auto-context is not enabled, or when the assistant needs the full detail beyond what auto-context provides.

Security

oCore's MCP server enforces multiple layers of security on every tool call:

Authentication

Every MCP session requires a valid API key. Keys are periodically revalidated against the database (every 30 seconds) to detect revocation, expiration, or user deactivation mid-session.

Instance Scoping

API keys can be scoped to specific instances. A key scoped to prod-v17 will only see tools for that instance -- no other instances are visible or callable.

RBAC Categories

API keys can be restricted to specific tool categories (e.g., orm, sql, metadata). If a key only has orm and metadata permissions, shell and SQL tools are blocked. An empty permission list grants full access.

Read-Only Mode

Keys can be marked as read-only, which blocks all write and destructive operations while still allowing search, read, and metadata inspection tools.

Production Guard

Each instance has a mcp_write_enabled flag. When disabled (the default for production instances), all write operations are blocked regardless of the API key's permissions. This prevents accidental data modification in production.

Destructive Operation Confirmation

High-risk tools require a confirm: true parameter. Without it, the tool returns a warning message describing what would happen instead of executing. The following tools are marked destructive:

  • unlink, batch_delete -- record deletion
  • execute_sql_script -- multi-statement SQL
  • file_delete -- file deletion
  • uninstall_module -- module removal
  • clear_system_cache -- cache clearing
  • restore_database -- database restore
  • delete_note, delete_filter, delete_bookmark -- knowledge deletion

IP Allowlist

API keys can include an IP allowlist. Connections from IPs not on the list are rejected.

Kill Switch

Organization administrators can disable MCP access entirely via the organization settings toggle. This immediately blocks all MCP tool calls for every key in the organization.

Rate Limiting

Per-key rate limiting prevents abuse:

TransportDefault Limit
SSE100 calls/minute
Stdio30 calls/minute

Tool Allow/Deny Lists

API keys support per-tool filtering with allow or deny lists, giving fine-grained control over which specific tools a key can invoke.

Model Allowlist

API keys can restrict which Odoo models are accessible. When a model allowlist is set, list_models only returns models in the allowlist, and ORM operations on other models are rejected.

Input Validation

All tool inputs are validated before execution:

  • Model names, field names, and method names are checked against a strict identifier pattern ([a-zA-Z_][a-zA-Z0-9_.]*).
  • SQL queries are stripped of comments and strings, then scanned for DDL, dangerous functions, and blocked statements.
  • File paths are sandboxed to the instance's addon directory with traversal prevention.
  • User IDs 1-3 (admin, public, __system__) cannot be modified by user management tools.

Audit Logging

Every MCP tool call is recorded in a dedicated mcp_audit_log table with:

  • Tool name and category
  • Input parameters (sensitive values like passwords are automatically redacted)
  • Result summary (truncated to 500 characters)
  • Whether the call succeeded or errored
  • Latency in milliseconds
  • Session ID, API key ID, user ID, and IP address

High-level session events (session started, session ended) are also logged to the main audit log.

Sensitive Data Redaction

Parameters containing keys like password, secret, token, or credential are automatically replaced with [REDACTED] before being written to the audit log.

Prompt Templates

oCore includes built-in MCP prompt templates that AI assistants can use for guided analysis:

PromptDescription
analyze_errorAnalyze an Odoo traceback and suggest fixes
explain_modelExplain an Odoo model's purpose, fields, and relationships
debug_performanceDiagnose Odoo performance issues based on symptoms

Example Usage Patterns

Exploring an instance

1. ocore_list_instances          -- discover available instances
2. myinstance_get_instance_info  -- get version, environment, status
3. myinstance_server_info        -- Odoo server details
4. myinstance_list_models search="sale"  -- find sale-related models
5. myinstance_get_field_metadata model="sale.order"  -- understand the schema

Searching and reading data

1. myinstance_search_read model="res.partner" domain=[["is_company","=",true]] fields=["name","email"] limit=10
2. myinstance_aggregation model="sale.order" fields=["amount_total:sum"] groupby=["state"] format="table"
3. myinstance_count model="sale.order" domain=[["state","=","sale"]]
4. myinstance_fuzzy_search model="res.partner" query="Acme Corp" min_score=0.6

Modifying data safely

1. myinstance_create model="res.partner" values={"name":"New Partner","email":"new@example.com"}
2. myinstance_write model="res.partner" ids=[42] values={"phone":"+1234567890"}
3. myinstance_unlink model="res.partner" ids=[99] confirm=true

Working with modules

1. myinstance_list_modules state="installed"
2. myinstance_module_dependencies addon="sale"
3. myinstance_check_uninstall_deps module="sale_stock"
4. myinstance_install_module module="sale_management"

Debugging with SQL and logs

1. myinstance_execute_sql query="SELECT id, name FROM res_partner WHERE active = false LIMIT 10"
2. myinstance_odoo_logs lines=200 filter="ERROR"
3. myinstance_execute_sql query="SELECT state, count(*) FROM sale_order GROUP BY state"

Using knowledge context

1. myinstance_get_context           -- load all saved knowledge at session start
2. myinstance_set_model_summary model="sale.order" summary="Main sales model. Custom fields: x_approved_by, x_delivery_notes."
3. myinstance_save_filter name="large_orders" model="sale.order" domain=[["amount_total",">",10000]] fields=["name","partner_id","amount_total"]
4. myinstance_run_filter name="large_orders"

Troubleshooting

Tools not appearing in the AI assistant

  • Verify the API key is valid and not expired or revoked
  • Check that the organization has MCP enabled (kill switch is off)
  • Confirm at least one instance is in running status
  • Check your AI client's MCP configuration for syntax errors

Tool calls returning "unauthorized"

  • The API key may have been revoked or expired since the session started
  • The owning user account may have been deactivated
  • The organization may have toggled MCP off via the kill switch

Tool calls returning "permission denied"

  • The API key's MCP permissions do not include the tool's category
  • Check the key's category list and add the required category (e.g., sql, shell)
  • Keys with no explicit permissions have full access to all categories

Write operations blocked

  • The instance has mcp_write_enabled set to false (production guard)
  • The API key is in read-only mode
  • For destructive operations, include confirm: true in the tool arguments

Rate limit exceeded

  • Reduce the frequency of tool calls
  • Contact your administrator to adjust rate limits if the default is too low for your use case

Shell/SQL tools timing out

  • Increase the timeout_seconds parameter (max 120 seconds)
  • For module operations, the minimum timeout is automatically raised to 90 seconds
  • For report generation, the minimum timeout is automatically raised to 60 seconds
  • Long-running SQL queries have a statement_timeout set automatically
Was this page helpful?