odoo-mcp
This server lets MCP clients interact with Odoo through generic read/write tools, governed by Odoo permissions and deployment guardrails.
odoo_search_read— search and read records from any permitted Odoo model, with domain filters, field selection, pagination, and ordering.odoo_fields_get— inspect field metadata and attributes for a model.odoo_create— create records in allowed models.odoo_write— update one or multiple existing records by ID.odoo_unlink— permanently delete records; explicitly marked destructive.Operates read-only by default; enabling mutations requires switching to read-write mode.
Optional model allow/deny lists restrict which Odoo models are reachable.
Runs over stdio or stateless Streamable HTTP with optional Bearer-token authentication.
Provides read/write integration with Odoo's JSON-2 external API, enabling tools to search-read records, inspect model fields, create, update, and delete records while respecting Odoo ACLs and record rules.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@odoo-mcpsearch res.partner records with name containing Acme"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
odoo-mcp
A generic Model Context Protocol (MCP) server for integrating MCP clients with Odoo.
Status
Active development. The server exposes generic Odoo read/write primitives with deployment guardrails, structured errors, and observability.
Related MCP server: Odoo MCP Server
Requirements
Node.js 22+
npm
Docker + Docker Compose (optional)
Local development
npm ci
npm run check
npm startFor development without building first:
npm run devThe server supports MCP over stdio (default) and stateless Streamable HTTP. Odoo tools are registered from the configured connection and policy.
Docker
cp .env.example .env
# edit .env with your Odoo URL and API key
docker compose build
docker compose run --rm odoo-mcpCompose passes all supported Odoo and guardrail settings into the container. ODOO_URL and ODOO_API_KEY are required; Compose fails fast when either is missing. Optional empty values are treated as unset. Because the transport is stdio, docker compose run --rm odoo-mcp is the intended interactive container entrypoint rather than a background daemon with a restart policy.
Project structure
src/
config/ # environment and deployment policy
observability/ # structured logging
odoo/ # JSON-2 client and read/write services
tools/ # MCP tool registration and schemas
index.ts # process entrypoint / stdio transport
server.ts # MCP server factory
test/ # unit testsDevelopment approach
Changes are developed PR by PR. Every pull request documents its scope, tests, and Definition of Done. Odoo-specific business logic does not belong in this bootstrap layer.
License
MIT
Odoo connection
The client layer targets Odoo's JSON-2 external API (/json/2/<model>/<method>), introduced for Odoo 19. Authentication uses an Odoo API key as a bearer token. X-Odoo-Database is sent only when ODOO_DATABASE is configured.
Copy .env.example and provide the connection values for your Odoo instance. Credentials are read from the environment and are never stored in source code.
Read-only MCP tools
The first MCP surface is intentionally read-only and generic:
odoo_search_read— searches and reads records from any model available to the configured Odoo user.odoo_fields_get— inspects model field metadata.
Both tools are annotated as read-only and rely on Odoo itself for ACLs and record rules. The MCP server does not bypass or duplicate Odoo authorization.
Write MCP tools
Generic write operations are exposed separately from reads:
odoo_create— creates a record.odoo_write— updates one or more records.odoo_unlink— permanently deletes one or more records and is explicitly marked destructive.
Inputs are validated before reaching Odoo: record id lists must be non-empty and bounded, and create/update values cannot be empty. Odoo ACLs and record rules remain authoritative for every mutation.
Guardrails
odoo-mcp adds deployment-level guardrails without replacing Odoo authorization. Odoo ACLs and record rules are still the final authority for every request.
The server starts in read-only mode by default. Set ODOO_MCP_MODE=read-write to expose effective mutation capability. Optional exact-name model allow/deny lists can further reduce the models reachable through this MCP instance; deny rules take precedence over allow rules.
ODOO_MCP_MODE=read-only
ODOO_MCP_ALLOW_MODELS=res.partner,sale.order
ODOO_MCP_DENY_MODELS=res.users,ir.config_parameterThese controls are intentionally coarse deployment constraints, not a duplicate RBAC system. Use Odoo users, groups, ACLs, and record rules for business authorization.
Observability and errors
Odoo requests emit structured JSON logs to stderr with a request id, model, method, outcome, HTTP status when available, and duration. Request parameters, API keys, authorization headers, and response bodies are intentionally excluded from logs.
Transport failures are classified as http, timeout, or network errors. Timeouts and network failures do not invent an HTTP status code when no HTTP response was received. The generated request id is also forwarded to Odoo as X-Request-ID for correlation where upstream infrastructure preserves it.
Container releases
Published GitHub Releases produce a versioned OCI image in GitHub Container Registry. For release v0.1.0, consumers can pin ghcr.io/<owner>/odoo-mcp:0.1.0; the workflow also publishes the corresponding minor tag and latest. Pin a version (or digest) for deployments where reproducibility matters.
The publish workflow authenticates with the repository-scoped GITHUB_TOKEN; no registry password or personal access token is stored in the repository. Publishing is release-driven, so ordinary pushes to main never publish a container image.
Continuous integration
Every pull request and push to main runs the same lint, test, TypeScript build, Compose validation, and Docker image build used during local development. CI uses placeholder connection values only for configuration/build validation and does not connect to an Odoo instance.
Streamable HTTP
For a long-running network endpoint, select the HTTP transport explicitly:
MCP_TRANSPORT=http
MCP_HTTP_HOST=0.0.0.0
MCP_HTTP_PORT=3000
MCP_HTTP_ALLOWED_HOSTS=mcp.example.com,localhostThe MCP endpoint is POST /mcp. HTTP mode is stateless: each request receives a fresh MCP server/transport pair and no MCP session state is stored by odoo-mcp. GET /mcp and DELETE /mcp return 405.
The server uses the MCP SDK's Express helper so host validation can be applied. When binding beyond localhost, configure MCP_HTTP_ALLOWED_HOSTS for the hostnames that are expected to reach the service.
HTTP authentication has two modes: MCP_AUTH_MODE=oauth (default) and MCP_AUTH_MODE=none. OAuth mode makes odoo-mcp an OAuth Resource Server: an external OIDC provider such as Keycloak issues JWT access tokens, while odoo-mcp validates signature, issuer, resource audience, expiration, and required scopes using mcp-auth. Configure MCP_AUTH_ISSUER, MCP_AUTH_RESOURCE (the public MCP URL, also the required JWT aud), and optional MCP_AUTH_REQUIRED_SCOPES. none is an explicit opt-out intended only for trusted/private networks.
OAuth discovery metadata is published according to RFC 9728 and points MCP clients to the external Authorization Server. odoo-mcp does not implement login, authorization-code, token, refresh-token, or client-registration endpoints itself.
The Docker Compose file publishes MCP_HTTP_PORT; with MCP_TRANSPORT=http it can run as a normal long-running container using docker compose up -d.
MCP protocol compatibility
odoo-mcp uses the MCP TypeScript SDK v2 packages. The HTTP entrypoint is built with createMcpHandler(), which serves the current 2026-07-28 stateless protocol and retains the SDK's stateless compatibility path for 2025-era clients. stdio uses the v2 serveStdio() entrypoint.
The transport layer depends on the official split packages (@modelcontextprotocol/server and @modelcontextprotocol/node) rather than the legacy monolithic v1 SDK package.
Live Odoo integration test
The unit suite does not require an Odoo server. A separate opt-in integration suite can validate the real Odoo 19 JSON-2 contract:
ODOO_TEST_URL=https://odoo.example.com \
ODOO_TEST_API_KEY=replace-with-a-short-lived-api-key \
ODOO_TEST_DATABASE=your-database \
npm run test:integrationThe live test uses only generic res.partner operations: it inspects fields, creates a uniquely named temporary record, verifies search_read, updates it, verifies the update, deletes it, and verifies cleanup. Cleanup also runs from afterAll if an assertion fails after record creation. Use a dedicated test database or short-lived API key whenever possible.
For a completely disposable real-Odoo run, Docker can provision Odoo 19 and PostgreSQL automatically:
npm run test:integration:dockerThe disposable integration suite also connects with the official MCP v2 client over Streamable HTTP, authenticates with Bearer auth, discovers the generic tools, and exercises a create/read/write/delete round trip through MCP into Odoo.
That command initializes a fresh database, seeds a fixed credential that exists only inside the disposable test database, runs the same JSON-2 integration suite, and removes the containers and volumes afterward. It never needs credentials from a real Odoo deployment.
Available Tools
5 toolsodoo_createA
Create a record in an Odoo model using the configured Odoo user permissions.
| Name | Required | Description | Default |
|---|---|---|---|
| model | Yes | Technical Odoo model name, for example res.partner | |
| values | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds the useful context that creation happens 'using the configured Odoo user permissions,' which signals an authorization dependency. However, it does not disclose other behavioral traits such as immediate persistence, possible side effects, or return behavior. Annotations already indicate non-read-only and non-idempotent, so the description contributes only modestly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single clear, front-loaded sentence with no filler. Every word contributes either to the core action or to the permission context.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description should explain the return value or result of the create operation, but it does not. It also omits error cases, required fields, and the relationship to the update/write operation. A mutation tool with minimal annotations needs more operational context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is only 50% since only 'model' has a description; 'values' has none. The description does not compensate by explaining that 'values' should be a mapping of Odoo field names to field values for the new record, leaving the agent to infer the key parameter's meaning.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Create a record in an Odoo model.' This clearly communicates the tool's core operation and distinguishes it from sibling tools like odoo_write (update), odoo_search_read, and odoo_unlink.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The verb 'create' implies the tool is for adding new records rather than updating, reading, or deleting them, but the description gives no explicit when-to-use guidance, prerequisites, or alternatives. Usage is inferred rather than stated.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
odoo_fields_getARead-onlyIdempotent
Inspect field metadata for an Odoo model using fields_get.
| Name | Required | Description | Default |
|---|---|---|---|
| model | Yes | Technical Odoo model name, for example res.partner | |
| attributes | No | Field metadata attributes to return |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description reinforces the read-only nature with 'Inspect' but adds no further behavioral details such as auth requirements, return shape, or edge cases. With annotations present, this is adequate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence: verb, resource, and method. It has no filler or redundant elaboration.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
This is a simple introspection tool with two well-described parameters and strong annotations. The description plus schema provide everything needed for correct invocation: the model name is required, attributes are optional, and the operation is read-only and non-destructive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%: both 'model' and 'attributes' have meaningful descriptions. The tool description does not add parameter-level detail, but the schema already carries that burden, so the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Inspect' and a clear resource 'field metadata for an Odoo model', and it names the underlying method fields_get. This clearly distinguishes it from sibling tools that operate on records (odoo_search_read, odoo_create, odoo_write, odoo_unlink).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes the tool's context clear: it is for inspecting metadata, not for reading or modifying records. It does not explicitly list alternatives or exclusion conditions, but the purpose is sufficiently clear that an agent can route to it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
odoo_search_readARead-onlyIdempotent
Search and read records from any Odoo model using the permissions of the configured Odoo API user.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | ||
| model | Yes | Technical Odoo model name, for example res.partner | |
| order | No | ||
| domain | No | Odoo search domain | |
| fields | No | ||
| offset | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already convey readOnly, idempotent, and non-destructive behavior. The description adds useful context about results being scoped by the configured API user's permissions, but it does not disclose pagination behavior, return shape, or error/access boundary behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with no filler. Every clause carries meaning: search, read, any Odoo model, and permission scoping.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with six parameters, no output schema, and low schema coverage, this description is too sparse. It omits crucial operational details such as domain format, field list behavior, pagination through limit/offset, ordering, and what the returned records look like.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With only 33% schema description coverage, the description needed to compensate for limit, order, fields, and offset semantics, but it does not mention any of them. It only reinforces the model parameter and the general search/read purpose, leaving most parameters under-explained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Search and read') and a clear resource ('records from any Odoo model'). It naturally differentiates from sibling tools: create/write/unlink are mutations, and fields_get targets field metadata rather than records.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The read-only phrasing provides clear context for when to use this tool instead of the mutation siblings. However, it does not explicitly contrast with odoo_fields_get or state exclusion conditions, so it stops short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
odoo_unlinkADestructive
Permanently delete one or more Odoo records using the configured Odoo user permissions.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| model | Yes | Technical Odoo model name, for example res.partner |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool as destructive, and the description adds that deletion is permanent and governed by configured Odoo user permissions. This gives the agent a clear warning about irreversibility and permission dependency beyond the bare destructiveHint flag.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence with no filler. The key action and irreversibility are front-loaded, and every word contributes to the tool's meaning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple destructive delete operation, the description covers the essential context: what is deleted, that it is permanent, and that permissions apply. It does not detail edge cases like deletion failures due to relational constraints, but the annotation and schema provide enough for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema documents 'model' with a clear example, but 'ids' has no description. The description's phrase 'one or more Odoo records' partially clarifies that ids correspond to record identifiers, but it does not fully compensate for the missing parameter-level documentation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Permanently delete') and the resource ('one or more Odoo records'), making the tool's purpose unambiguous. It naturally distinguishes itself from siblings like odoo_create, odoo_write, and odoo_search_read by focusing on deletion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage context is implied by the word 'delete' rather than explicitly stated; an agent can infer to use this when removal of records is intended versus creation or update. However, there are no explicit when-to-use or alternative-routing instructions, so the guidance remains indirect.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
odoo_writeBIdempotent
Update one or more Odoo records using the configured Odoo user permissions.
| Name | Required | Description | Default |
|---|---|---|---|
| ids | Yes | ||
| model | Yes | Technical Odoo model name, for example res.partner | |
| values | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already establish that this is a non-read-only, non-destructive, idempotent operation. The description adds a small but useful behavioral note about running under the configured Odoo user permissions, but it does not disclose partial-failure behavior or outcomes when permissions are insufficient.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no filler. The update action and permission context are the most important information and appear first.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write operation with an under-described values object, no output schema, and no return-value hints, the description is too thin. It omits important invocation context such as how ids map to records, what values accepts, and what result or failure behavior the agent should expect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Only the model parameter is documented in the schema, with schema description coverage at 33%. The tool description does not explain that values should be an Odoo field-value map or that ids must identify existing records, so it fails to compensate for the gaps around ids and values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('Update') with a clear resource ('one or more Odoo records') and adds the scope of operating under configured permissions. It is clear but does not explicitly distinguish this from sibling tools like odoo_create or odoo_unlink, though the update semantics are inferable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus the sibling alternatives odoo_create, odoo_unlink, or odoo_search_read. The description only implies existing-record updates from the word 'Update' and does not state exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
- Changed
odoo_create6 fields changed- added
Input schema / $defsAdded value: +{ + "__schema0": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "items": { + "$ref": "#/$defs/__schema0" + }, + "type": "array" + }, + { + "additionalProperties": { + "$ref": "#/$defs/__schema0" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + ] + } +} - changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / values / additionalProperties / $refAdded value: +"#/$defs/__schema0" - removed
Input schema / properties / values / additionalProperties / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - }, - { - "items": { - "$ref": "#/properties/values/additionalProperties" - }, - "type": "array" - }, - { - "additionalProperties": { - "$ref": "#/properties/values/additionalProperties" - }, - "type": "object" - } -] - added
Input schema / properties / values / propertyNamesAdded value: +{ + "type": "string" +}
- Changed
odoo_fields_get2 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false
- Changed
odoo_search_read6 fields changed- added
Input schema / $defsAdded value: +{ + "__schema0": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "items": { + "$ref": "#/$defs/__schema0" + }, + "type": "array" + }, + { + "additionalProperties": { + "$ref": "#/$defs/__schema0" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + ] + } +} - changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / domain / items / $refAdded value: +"#/$defs/__schema0" - removed
Input schema / properties / domain / items / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - }, - { - "items": { - "$ref": "#/properties/domain/items" - }, - "type": "array" - }, - { - "additionalProperties": { - "$ref": "#/properties/domain/items" - }, - "type": "object" - } -] - added
Input schema / properties / offset / maximumAdded value: +9007199254740991
- Changed
odoo_unlink3 fields changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / ids / items / maximumAdded value: +9007199254740991
- Changed
odoo_write7 fields changed- added
Input schema / $defsAdded value: +{ + "__schema0": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "items": { + "$ref": "#/$defs/__schema0" + }, + "type": "array" + }, + { + "additionalProperties": { + "$ref": "#/$defs/__schema0" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + ] + } +} - changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema" - removed
Input schema / additionalPropertiesRemoved value: -false - added
Input schema / properties / ids / items / maximumAdded value: +9007199254740991 - added
Input schema / properties / values / additionalProperties / $refAdded value: +"#/$defs/__schema0" - removed
Input schema / properties / values / additionalProperties / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "number" - }, - { - "type": "boolean" - }, - { - "type": "null" - }, - { - "items": { - "$ref": "#/properties/values/additionalProperties" - }, - "type": "array" - }, - { - "additionalProperties": { - "$ref": "#/properties/values/additionalProperties" - }, - "type": "object" - } -] - added
Input schema / properties / values / propertyNamesAdded value: +{ + "type": "string" +}
5 tool updates
v0.1.0- First observed
odoo_create - First observed
odoo_fields_get - First observed
odoo_search_read - First observed
odoo_unlink - First observed
odoo_write
TDQS
Scored across 5 tools
Each tool maps to a distinct operation: metadata inspection, create, search/read, update, and delete. There is no meaningful overlap between them.
All tools share the 'odoo_' prefix, which is good. The second part is mostly a verb, though 'fields_get' and 'search_read' are compound forms while 'create', 'write', and 'unlink' are simple verbs, creating a minor inconsistency.
Five tools is a tight, well-scoped set for a generic Odoo CRUD server. Each tool covers a fundamental operation without unnecessary bloat.
The tool set covers the full core lifecycle: read schema, create, read/search, update, and delete. For a generic Odoo model API server, these are the essential operations and no major gaps are apparent.
Maintenance
Related MCP Connectors
Read-only MCP server exposing a user ORANO library to their own AI agent.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
Your whole business as one MCP server: analytics, CRM, SEO, ads, revenue. Scoped per data class.
Build multi-tenant apps over MCP. Schemas, CRUD, deploys — access control enforced server-side.
Related MCP Servers
- AlicenseAqualityDmaintenanceEnables AI assistants to interact with Odoo data using natural language to search, read, create, and update records. It acts as a secure bridge between MCP clients and Odoo instances version 17.0 through 19.0.11Apache 2.0
- AlicenseNot gradedqualityDmaintenanceProvides read-only access to Odoo databases via OdooRPC, allowing AI assistants to query and analyze Odoo data through the MCP protocol.1MIT
- AlicenseNot gradedqualityDmaintenanceA read-only MCP server that enables AI assistants to query Odoo instances via XML-RPC, supporting search, read, count, and field inspection without requiring custom modules.37 PyPI1Mozilla Public 2.0
- AlicenseNot gradedqualityDmaintenanceEnables interaction with Odoo 18 (JSON-RPC API) via MCP, supporting model exploration, CRUD operations, and secure API key authentication.Apache 2.0