import os import xmlrpc.client from mcp.server.fastmcp import FastMCP from typing import Dict, Any, List, Optional # Odoo Credentials defaults to Hazard environment URL = os.getenv("ODOO_URL", "http://localhost:16001") DB = os.getenv("ODOO_DB", "hazard_new") USER = os.getenv("ODOO_USER", "admin") PASSWORD = os.getenv("ODOO_PASSWORD", "admin") # FastMCP Initialization mcp = FastMCP("odoo-mcp-hazard") def _get_uid(): common = xmlrpc.client.ServerProxy(f'{URL}/xmlrpc/2/common') return common.authenticate(DB, USER, PASSWORD, {}) def _get_models(): return xmlrpc.client.ServerProxy(f'{URL}/xmlrpc/2/object') @mcp.tool() def odoo_search_read(model: str, domain: List[Any], fields: Optional[List[str]] = None, limit: Optional[int] = None) -> List[Dict[str, Any]]: """ Search and read records from Odoo. Args: model: Odoo model name (e.g., 'sale.order', 'product.product') domain: Search domain list of tuples (e.g., [['name', '=', '123']]) fields: Optional list of field names to return limit: Optional maximum number of records to return """ uid = _get_uid() if not uid: raise Exception("Authentication failed with Odoo") models = _get_models() kwargs = {} if fields: kwargs['fields'] = fields if limit: kwargs['limit'] = limit return models.execute_kw(DB, uid, PASSWORD, model, 'search_read', [domain], kwargs) @mcp.tool() def odoo_create(model: str, vals: Dict[str, Any]) -> int: """ Create a new record in Odoo. Args: model: Odoo model name (e.g., 'res.partner') vals: Dictionary of field values for the new record Returns: The ID of the newly created record """ uid = _get_uid() models = _get_models() return models.execute_kw(DB, uid, PASSWORD, model, 'create', [vals]) @mcp.tool() def odoo_write(model: str, ids: List[int], vals: Dict[str, Any]) -> bool: """ Update existing records in Odoo. Args: model: Odoo model name ids: List of record IDs to update vals: Dictionary of field values to update """ uid = _get_uid() models = _get_models() return models.execute_kw(DB, uid, PASSWORD, model, 'write', [ids, vals]) @mcp.tool() def odoo_execute_method(model: str, method: str, ids: List[int], kwargs: Optional[Dict[str, Any]] = None) -> Any: """ Execute an arbitrary method on an Odoo model. Args: model: Odoo model name method: Method name to execute (e.g., 'action_confirm') ids: List of record IDs to apply the method to kwargs: Optional keyword arguments for the method """ uid = _get_uid() models = _get_models() kwargs = kwargs or {} return models.execute_kw(DB, uid, PASSWORD, model, method, [ids], kwargs) if __name__ == "__main__": mcp.run()