Static source inference · medium confidence · detected: Logging
Deprecated protocol patterns detected
Summary
The server defines 12 tools with varying quality. Naming follows verb_noun convention (search_read, create, write, unlink, execute_kw, fields_get, search_count, schema_version, schema_models, schema_fields, domain_validate). Input schemas are present with proper JSON Schema types for most tools. However, descriptions are inconsistent, some are 20-50 characters (minimal), parameter descriptions are sparse or missing, and output schemas are not documented. The server properly exposes Odoo CRUD operations and introspection tools, but lacks comprehensive guidance on parameter constraints, error recovery, and field mappings. Risk classification (READ_ONLY, WRITE, DESTRUCTIVE) is noted but not reflected in tool metadata (missing toolAnnotations like readOnlyHint/destructiveHint). Critical security concerns exist: execute_kw exposes arbitrary method invocation without restriction, and domain parameters accept arrays without documented constraints.
Tools (12)
domain_validateread onlyauthsource verified65/100
Validate and compile a domain expression using global authentication.
odoo.createwriteauthsource verified57/100
Create an Odoo record
odoo.execute_kwwriteauthsource verified57/100
Call an arbitrary Odoo model method via execute_kw
execute_kw exposes arbitrary method invocation without whitelist, permission checks, or audit trail. An LLM can invoke any Odoo backend method, bypassing domain-specific safeguards.
No tool annotations (readOnlyHint, destructiveHint, idempotentHint) in tool definitions. Server declares risk levels (READ_ONLY, WRITE, DESTRUCTIVE) in metadata but does not expose them via MCP tool annotations.
Output schemas are not documented for any tool. LLM cannot predict response structure, forcing trial-and-error parsing and increasing hallucination risk. Baseline: 100% of A+ tools document return types.
Recommendations
Add comprehensive output schemas for every tool. Document return types in tool descriptions, e.g., 'Returns: { id: integer, record: object, created: boolean }'. Baseline: 100% of A+ tools document return types.
Expand all tool descriptions to 100-200 characters. Follow the pattern: WHAT it does + WHEN to use it + key constraints. Example: 'Search and read Odoo records by model and domain. Use this to find records before updating or deleting. Supports pagination via limit/offset.'
Add descriptions to every parameter. Template: '[ParamName]: [Type]. [Meaning]. [Constraints]. Example: model (string), the Odoo model name (e.g., sale.order). Must exist and user must have access.'
Replace untyped 'object' schemas with concrete field schemas. For 'values' in create/write, generate the schema from fields_get or document expected keys: 'values: object with keys matching model fields (e.g., { name: string, email: string, phone: string }). Required fields depend on model configuration.'
Document domain parameter structure explicitly. Add to description: 'domain: array of [field, operator, value] tuples joined by implicit AND. Operators: =, !=, <, >, <=, >=, in, not in, like, ilike. Example: [["state", "=", "draft"], ["user_id", "!=", 1]]'
Add tool annotations to definitions: readOnlyHint for introspection/search tools; destructiveHint for unlink; idempotentHint for read operations. This exposes risk classification to clients.
Refactor execute_kw with a whitelist of allowed methods and a permission gate. Do NOT allow arbitrary method invocation. Replace with domain-specific tools: execute_workflow_transition, call_model_action, invoke_report. Or gate execute_kw behind explicit permission checks with audit logging.
Score history
Overall score trend
↑ 8 points across a rubric change (v1 → v2)
59/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-22
D
59
2026-07-28+
v2
2026-03-09
D
51
-
v1
odoo.unlinkdestructiveauthsource verified55/100
Delete Odoo records
odoo.writereversibleauthsource verified57/100
Update Odoo records
schema_fieldsread onlyauthsource verified63/100
Get fields for a specific model using global authentication.
schema_modelsread onlyauthsource verified62/100
Get accessible models using global authentication.
Parameter descriptions are sparse or missing (only 'async' in search_read has a description; most other params lack guidance). Baseline: 100% of A+ tools describe every parameter.
'domain' parameter is documented as array type but lacks schema detail explaining element structure (e.g., [field, op, value] tuples). LLM cannot construct valid domains without trial-and-error.
Tool descriptions for create/write/unlink are 20-26 characters, at or below the minimum threshold. Descriptions lack state-modification warnings, idempotency guidance, or hints on when to use each tool. Baseline: average description is 194 chars.
No error recovery guidance documented. Errors from Odoo (field validation, permission denied, record not found) are not mapped to recovery patterns (try search_*, ask user, retry). Pattern:recovery-guide missing.
'values' parameter in create/write is typed as untyped 'object' with no schema detail. LLM cannot infer valid keys, required fields, or data types for field values. Should specify expected schema or link to fields_get.
search_read and search_count accept 'domain' as array but lack enumeration or constraints on domain operators (=, !=, <, >, <=, >=, in, not in, like, ilike, etc.). LLM guesses valid operators.
Pagination support (limit, offset) documented for search_read but lack explicit constraints (min=1, max=200?). Baseline: numeric parameters should specify min/max to prevent absurd values.
No tool supports batch operations. If an agent needs to create 10 records, it must call create 10 times, wasting tokens and latency. Batch variants (create_batch, write_batch, unlink_batch) would improve efficiency.
Tool naming inconsistencies: 'schema_version' vs. 'schema_models' vs. 'schema_fields' are discovery tools but lack consistent prefix (list_*, get_*, or describe_*). 'domain_validate' is singular; 'schema_*' are nouns. Inconsistent naming increases LLM confusion.
Add confirmation flow for destructive operations. Document support for a dry_run parameter in write/unlink, or offer a separate unlink_preview tool that returns affected records before deletion.
Document error cases and recovery paths. Example for unlink: 'Errors: RecordNotFound (404, try search_read first), AccessDenied (403, user lacks delete permission), ValidationError (422, some records cannot be deleted due to dependencies). On error, call search_read to re-fetch and diagnose.'
Add pagination totals. search_read should return {records: [...], total_count: integer, has_more: boolean}. Baseline: paginated results include total count or next_cursor.
Consolidate discovery tool names. Rename to list_schema_models, get_schema_version, get_model_fields (not schema_fields). Use consistent verb_noun pattern.
Add batch tool variants: create_batch, write_batch, unlink_batch accepting arrays of payloads. Return per-item success/failure to handle partial failures gracefully.
Document idempotency guarantees. Are reads idempotent? Can create/write be retried safely? State explicitly: 'create is idempotent if duplicate detection is enabled; write with same values is idempotent; unlink is NOT idempotent (second call fails record not found).'
Add field and limit constraints to parameter descriptions. Example: 'limit: integer, 1 - 200 (default 20). Requests exceeding 200 are truncated to prevent context window exhaustion.'
Include dependency hints in descriptions. Example for search_read: 'If you only have a partial model name, call schema_models first to find exact name. If you need field types, call get_model_fields after searching.'
Document 'async' parameter behavior in search_read. Explain what a task handle is and how to poll for results. If async is not fully implemented, remove it from the schema.