inspect_model_relationships
Examine relationships and required field metadata of any Odoo model to understand data structure and dependencies.
Instructions
Inspect model relationships and required field metadata
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| model | Yes | ||
| fields_metadata | No | ||
| include_readonly | No | ||
| include_computed | No | ||
| use_live_metadata | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- src/odoo_mcp/server.py:873-917 (handler)MCP tool handler for inspect_model_relationships. Accepts model, optional fields_metadata, include_readonly, include_computed, and use_live_metadata. When use_live_metadata=True (default), fetches fields_get from the Odoo server via the lifespan context's OdooClient. Delegates to inspect_model_relationships_report() for the actual report building.
@mcp.tool( description="Inspect model relationships and required field metadata", annotations=READ_ONLY_TOOL, structured_output=True, ) def inspect_model_relationships( ctx: Context, model: str, fields_metadata: Optional[Dict[str, Any]] = None, include_readonly: bool = True, include_computed: bool = True, use_live_metadata: bool = True, ) -> Dict[str, Any]: """ Summarize relationship fields using provided metadata or bounded fields_get. """ try: validate_model_name(model) metadata_source = "input" if fields_metadata is not None else "none" metadata_error = None if fields_metadata is None and use_live_metadata: metadata_source = "server" try: odoo = ctx.request_context.lifespan_context.odoo fields_metadata = odoo.get_model_fields(model) if "error" in fields_metadata: metadata_error = str(fields_metadata["error"]) fields_metadata = None except Exception as exc: metadata_error = str(exc) fields_metadata = None return inspect_model_relationships_report( model=model, fields_metadata=fields_metadata, metadata_source=metadata_source, metadata_error=metadata_error, include_readonly=include_readonly, include_computed=include_computed, ) except Exception as e: return { "success": False, "tool": "inspect_model_relationships", "error": str(e), } - src/odoo_mcp/diagnostics.py:359-466 (schema)Pure function that builds the inspect_model_relationships report from field metadata. Iterates over fields_metadata, categorizing relational fields (many2one, one2many, many2many), collecting required fields, and generating create/write hints. Respects include_readonly and include_computed filters. Called by the MCP tool handler in server.py.
def inspect_model_relationships_report( *, model: str, fields_metadata: dict[str, Any] | None, metadata_source: str, metadata_error: str | None = None, include_readonly: bool = True, include_computed: bool = True, ) -> dict[str, Any]: """Summarize relationship and write/create hints from fields_get metadata.""" if not fields_metadata: return { "success": False, "tool": "inspect_model_relationships", "model": model, "error": metadata_error or "No field metadata available.", "summary": {"field_count": 0, "relationship_count": 0, "required_count": 0}, "relationships": {"many2one": [], "one2many": [], "many2many": []}, "required_fields": [], "create_hints": [], "write_hints": [], "metadata_used": { "fields_get": False, "source": metadata_source, "error": metadata_error, }, } relationships: dict[str, list[dict[str, Any]]] = { "many2one": [], "one2many": [], "many2many": [], } required_fields: list[dict[str, Any]] = [] create_hints: list[dict[str, str]] = [] write_hints: list[dict[str, str]] = [] for field_name, raw_meta in sorted(fields_metadata.items()): if not isinstance(raw_meta, dict): continue meta = raw_meta field_type = str(meta.get("type", "")) readonly = bool(meta.get("readonly", False)) required = bool(meta.get("required", False)) computed = bool(meta.get("compute") or meta.get("computed")) relation = meta.get("relation") if readonly and not include_readonly: continue if computed and not include_computed: continue if field_type in relationships: relationships[field_type].append( { "name": field_name, "relation": relation, "required": required, "readonly": readonly, "string": meta.get("string"), } ) if required: required_fields.append( {"name": field_name, "type": field_type, "relation": relation} ) if not readonly and not computed: create_hints.append( { "field": field_name, "hint": "Required on create unless Odoo provides a default.", } ) if readonly: write_hints.append( {"field": field_name, "hint": "Readonly in fields_get; do not write."} ) elif field_type == "many2one": write_hints.append( {"field": field_name, "hint": "Write the related record ID."} ) elif field_type in {"one2many", "many2many"}: write_hints.append( { "field": field_name, "hint": "Use Odoo relational command lists for create/write.", } ) relationship_count = sum(len(items) for items in relationships.values()) return { "success": True, "tool": "inspect_model_relationships", "model": model, "summary": { "field_count": len(fields_metadata), "relationship_count": relationship_count, "required_count": len(required_fields), }, "relationships": relationships, "required_fields": required_fields, "create_hints": create_hints, "write_hints": write_hints, "metadata_used": { "fields_get": True, "source": metadata_source, "error": metadata_error, }, } - src/odoo_mcp/server.py:873-877 (registration)MCP tool registration decorator. Registers 'inspect_model_relationships' as a read-only MCP tool with description 'Inspect model relationships and required field metadata'.
@mcp.tool( description="Inspect model relationships and required field metadata", annotations=READ_ONLY_TOOL, structured_output=True, ) - src/odoo_mcp/diagnostics.py:668-668 (helper)The _diagnostic_next_actions helper appends a suggestion to call inspect_model_relationships when metadata is not available.
actions: list[str] = [] - src/odoo_mcp/odoo_client.py:472-472 (helper)OdooClient method that calls fields_get on the Odoo model to retrieve field definitions. Used by the inspect_model_relationships MCP tool to fetch live metadata from the server.
def get_model_fields(self, model_name: str) -> dict[str, Any]: