A Model Context Protocol server written in C99 using the BCHS stack (BSD, C, Hypermedia, SQL). Connects any MCP-capable LLM to your Odoo 15/16/17 instance over its native XML-RPC API.
One source tree produces two artifacts from a single nob.c build driver — a native FreeBSD ELF binary and a wasm32-wasi module for Cloudflare Workers. The only platform-specific code is a single #ifdef __wasm__ in net.h.
fields_get. Returns field names, types, labels, and required flags. Use before querying an unfamiliar model.FreeBSD/BSD: pkg install kcgi libressl · wasi-sdk for WASM target · cc (clang or gcc)
# Bootstrap the build driver once cc nob.c -o nob # Build native FreeBSD binary ./nob # Run env ODOO_URL=https://dapla.net \\ ODOO_DB=your_db \\ ODOO_USER=you@dapla.net \\ ODOO_API_KEY=your_api_key \\ ./odoo-mcp-server
# Build WASM module cc -Dwasm nob.c -o nob && WASI_SDK=/opt/wasi-sdk ./nob # → odoo-mcp.wasm # Deploy via Terraform (wrangler called via local-exec) cd terraform/ terraform init && terraform apply
/* Only this file knows about the target */ #ifdef __wasm__ /* CF Worker JS shim exports http_fetch → Workers fetch() */ __attribute__((import_module("env"), import_name("http_fetch"))) extern int wasm_http_fetch(...); #define net_http_post(...) wasm_http_fetch(...) #else /* BSD sockets + libtls — implemented in net.c */ int net_http_post(...); #endif
cloudflare_worker + local-exec wrangler until provider issue #6852 (wasm_module) is fixed. Lives at WAF layer — rate limiting, Bot Management, Zero Trust all apply.pledge/capsicum sandbox, no WASM runtime needed.cloudbuild.yaml not included — use the Dockerfile pattern and GCP Secret Manager for credentials.ODOO_URL=https://dapla.net # base URL, no trailing slash ODOO_DB=your_database_name # Odoo database name ODOO_USER=you@dapla.net # login email ODOO_API_KEY=your_api_key # Settings → Technical → API Keys
{
"mcpServers": {
"odoo": {
"command": "/path/to/odoo-mcp-server",
"env": {
"ODOO_URL": "https://dapla.net",
"ODOO_DB": "your_db",
"ODOO_USER": "you@dapla.net",
"ODOO_API_KEY": "your_api_key"
}
}
}
}
All four Rego policies evaluated by OPA before any deploy. Every gate uses --fail-defined violations[_] — any finding blocks CI.
cdxgen produces sbom.cdx.json (CycloneDX 1.6) and sbom.spdx.json (SPDX 2.3) on every CI run. osv-scanner ingests the CycloneDX SBOM for CVE scanning.