Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gemini-extension.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "brass-monkey",
"version": "1.3.2",
"description": "Secure, intelligent bridge between AI agents and Odoo instances.",
"version": "1.3.3",
"description": "A high-fidelity Gemini CLI extension and MCP bridge for Odoo ERP/CRM.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"author": "Matthew Martella",
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "brass-monkey",
"version": "1.3.2",
"version": "1.3.3",
"type": "module",
"main": "dist/index.js",
"scripts": {
Expand All @@ -13,14 +13,18 @@
"keywords": [
"odoo",
"gemini",
"gemini-cli",
"cli",
"extension",
"mcp",
"ai-agent",
"xml-rpc",
"erp",
"crm"
],
"author": "",
"author": "Actinon",
"license": "MIT",
"description": "Secure, intelligent bridge between AI agents and Odoo instances.",
"description": "A high-fidelity Gemini CLI extension and MCP bridge for Odoo ERP/CRM.",
"dependencies": {
"@modelcontextprotocol/sdk": "^1.29.0",
"keytar": "^7.9.0",
Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-crm/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-crm
description: High-level functional expertise in Odoo's CRM engine, covering Lead qualification, Opportunity management, and Activity tracking.
description: MANDATORY for Leads and Opportunities (crm.lead). Expertise in Odoo's CRM pipeline, stages, and activity tracking.
---
# Skill: Odoo CRM & Pipeline Management

Expand Down
8 changes: 7 additions & 1 deletion skills/odoo-data-ops/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ Every CRUD tool supports an `instance_alias` parameter.
- **Field Categorization:** By default, `search_read` only returns "Base" fields to save context. If you need more, use `include_extended: true` (for extra modules) or `include_computed: true` (for calculated fields).
- **Aggregations:** Use `aggregate_records` for BI-style queries (grouping, counting, summing). This is much more context-efficient than reading thousands of records to perform local math.

### 5. Agent-Driven Undo Workflow
### 5. Schema Strictness & Error Recovery
Odoo v18+ is strict about field lists in `search_read`.
- **The Trigger:** If you receive a `ValueError` or `KeyError` stating a field does not exist.
- **The Mandate:** You must STOP and call `inspect_model` to verify the current live schema. Do NOT guess field names.
- **Action:** After finding the correct field, retry the operation with the updated field list.

### 6. Agent-Driven Undo Workflow
If you make a mistake or are asked to "undo" a change:
1. **Locate:** Use `search_read` on the `mail.message` model for the target record to find the "Before Snapshot" you previously posted.
2. **Analyze:** Verify the current record state. Do not attempt a rollback if it violates Odoo's business logic (e.g., trying to revert an invoice that has since been paid).
Expand Down
3 changes: 2 additions & 1 deletion skills/odoo-dev/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-dev
description: High-level technical expertise in Odoo's customization engine, covering Server Actions, Automated Rules, and Odoo Studio modifications.
description: MANDATORY for customizations. High-level technical expertise in Odoo's customization engine, covering Server Actions, Automated Rules, and Odoo Studio modifications.
---
# Skill: Odoo Development & Customization

Expand All @@ -21,6 +21,7 @@ Before troubleshooting or proposing changes, the agent must identify existing lo
### 2. Server Actions (`ir.actions.server`)
- **Purpose:** Execute Python code, update records, or trigger multi-step workflows via the UI.
- **Mandate:** When writing Python code in a Server Action, ensure all variables (`env`, `model`, `record`, `records`, `time`) are used correctly. Avoid long-running loops or operations that could cause database locks.
- **HTML Communication:** If using `message_post` within a Server Action to send HTML, remember to pass `body_is_html=True` to prevent escaping.

### 3. Automated Rules (`base.automation`)
- **Purpose:** Automatically trigger Server Actions based on specific events.
Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-finance/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-finance
description: High-level business expertise in Odoo's unified accounting engine, covering Invoicing, Billing, Banking, Consolidation, and Analytics.
description: MANDATORY for Customer Invoices (out_invoice), Vendor Bills (in_invoice), and Payments (account.payment). High-level expertise in Odoo's unified ledger and banking.
---
# Skill: Odoo Finance & Accounting

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-get-started/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-get-started
description: Orientation skill to establish context immediately upon connecting to an Odoo instance.
description: MANDATORY FIRST STEP. Orientation skill to establish the Odoo World Map context (Version, Apps, Company, Permissions) BEFORE executing any other tools.
---
# Skill: Odoo Orientation (The Mandatory Start)

Expand Down
6 changes: 3 additions & 3 deletions skills/odoo-helpdesk/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-helpdesk
description: High-level functional expertise in Odoo's Customer Support engine, covering Ticket management, SLA compliance, and multi-channel integration.
description: MANDATORY for Tickets (helpdesk.ticket) and SLAs (helpdesk.sla). Expertise in Odoo's support engine and customer service.
---
# Skill: Odoo Helpdesk & Customer Support

Expand All @@ -24,8 +24,8 @@ Helpdesk is the bridge between a customer problem and a technical solution:
- **Sales/Invoicing:** Reference the original `sale.order_id` to verify warranty status or bill for support time via `sale_line_id`.

### 4. Communication Protocol
- **Public Reply:** Use `message_post` with `message_type: 'comment'` for messages sent directly to the customer via email/portal.
- **Internal Note:** Use `message_post` with `subtype_xmlid: 'mail.mt_note'` for internal technical updates.
- **Public Reply:** Use `message_post` with `message_type: 'comment'` and `body_is_html: true` (if sending HTML) for messages sent directly to the customer.
- **Internal Note:** Use `message_post` with `subtype_xmlid: 'mail.mt_note'` and `body_is_html: true` (if sending HTML) for internal technical updates.
- **Mandate:** Clearly distinguish between the two. Never leak internal technical jargon to the customer.

## Available Resources
Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-hr/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-hr
description: Functional expertise in Odoo's HR module, covering Employee management, Departmental structures, and Employment contracts.
description: MANDATORY for Employees (hr.employee) and Departments (hr.department). Expertise in Odoo's human resources and org structure.
---
# Skill: Odoo Human Resources (HR)

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-introspector/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-introspector
description: Expertise to examine, understand, and interpret Odoo's internal ORM structures and metadata.
description: MANDATORY for technical discovery. Expertise in Odoo's internal ORM structures, field types, and metadata interpretation.
---
# Skill: Odoo Introspector

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-inventory/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-inventory
description: Expertise required to manage Odoo's inventory operations, covering transfers, stock moves, and physical warehouse structure.
description: MANDATORY for Transfers (stock.picking), Stock Moves (stock.move), and Locations (stock.location). Expertise in Odoo's logistics and warehouse structure.
---
# Skill: Odoo Inventory & Logistics

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-mrp/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-mrp
description: High-level functional expertise in Odoo's Manufacturing and Product Lifecycle Management engines, covering production planning, execution, and engineering changes.
description: MANDATORY for Manufacturing Orders (mrp.production), BoMs (mrp.bom), and Work Orders (mrp.workorder). Expertise in Odoo's production engine.
---
# Skill: Odoo MRP (Manufacturing) & PLM

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-products/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-products
description: Expertise required to manage Odoo's product catalog, covering both general templates and specific product variants.
description: MANDATORY for Product Templates (product.template) and Variants (product.product). Expertise in Odoo's catalog and attribute management.
---
# Skill: Odoo Product Management

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-projects/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-projects
description: High-level functional expertise in Odoo's Project Management engine, covering Tasks, Milestones, and integration with Sales and Accounting.
description: MANDATORY for Projects (project.project) and Tasks (project.task). Expertise in Odoo's project management and milestone tracking.
---
# Skill: Odoo Projects, Milestones & Timesheets

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-purchasing/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-purchasing
description: High-level functional expertise in Odoo's Purchasing engine, covering RFQs, Purchase Orders, and Vendor Price management.
description: MANDATORY for RFQs and Purchase Orders (purchase.order). Expertise in Odoo's procurement engine and vendor pricing.
---
# Skill: Odoo Purchasing & Procurement

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-relations/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-relations
description: Expertise required to manage the res.partner ecosystem, the foundational directory for all people and organizations in Odoo.
description: MANDATORY for Contacts, Customers, and Vendors (res.partner). Expertise in Odoo's central directory and relationship hierarchies.
---
# Skill: Odoo Relations (Partners & Contacts)

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-sales/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-sales
description: Functional expertise in Odoo's Sales engine, covering the entire lifecycle from Quotation to Order Fulfillment.
description: MANDATORY for Sales Orders (sale.order), Quotations, and Order Fulfillment. Functional expertise in Odoo's Sales engine and lifecycle states.
---
# Skill: Odoo Sales & Order Fulfillment

Expand Down
2 changes: 1 addition & 1 deletion skills/odoo-ux/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
name: odoo-ux
description: Expertise to navigate Odoo's user interface architecture and interpret frontend metadata.
description: MANDATORY for UI navigation. Expertise in Odoo's interface architecture (Menus, Actions, Views) and frontend metadata.
---
# Skill: Odoo UX & Navigation

Expand Down
2 changes: 1 addition & 1 deletion src/mcp-server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));

// Read package.json for metadata
let version = "1.3.2";
let version = "1.3.3";
try {
const pkgPath = path.resolve(__dirname, "../package.json");
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
Expand Down
1 change: 1 addition & 0 deletions src/services/audit-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export class AuditService {
body: `<div><strong>🤖 AI Agent Action:</strong><br/>${body}</div>`,
message_type: 'comment',
subtype_xmlid: 'mail.mt_note',
body_is_html: true,
});
} catch (error) {
// Odoo models without 'mail.thread' inheritance will fail here.
Expand Down
34 changes: 32 additions & 2 deletions src/services/odoo-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export class OdooClient {
private objectClient: any;
private uid: number | null = null;
private versionInfo: any = null;
private companyIds: number[] = [];

constructor(private config: OdooConfig) {
const commonUrl = new URL('/xmlrpc/2/common', config.url).toString();
Expand Down Expand Up @@ -62,7 +63,18 @@ export class OdooClient {
}

this.uid = uid as number;
resolve(this.uid);

// Fetch allowed companies for cross-company visibility
this.objectClient.methodCall(
'execute_kw',
[db, this.uid, api_key, 'res.users', 'read', [[this.uid]], { fields: ['company_ids'] }],
(companyError: any, userRecords: any) => {
if (!companyError && userRecords && userRecords.length > 0) {
this.companyIds = userRecords[0].company_ids || [];
}
resolve(this.uid as number);
}
);
}
);
}
Expand Down Expand Up @@ -120,6 +132,22 @@ export class OdooClient {

const { db, api_key } = this.config;

// Safety Interceptor: Auto-detect HTML in message_post calls
if (method === 'message_post' && kwargs && typeof kwargs.body === 'string') {
const containsHtml = /<[a-z][\s\S]*>/i.test(kwargs.body);
if (containsHtml && kwargs.body_is_html === undefined) {
kwargs.body_is_html = true;
}
}

// Context Injection: Enable cross-company visibility by default
if (this.companyIds.length > 0) {
kwargs.context = kwargs.context || {};
if (kwargs.context.allowed_company_ids === undefined) {
kwargs.context.allowed_company_ids = this.companyIds;
}
}

return new Promise((resolve, reject) => {
this.objectClient.methodCall(
'execute_kw',
Expand All @@ -145,7 +173,9 @@ export class OdooClient {
/odoo\.exceptions\.UserError: (.*)/,
/odoo\.exceptions\.ValidationError: (.*)/,
/odoo\.exceptions\.AccessError: (.*)/,
/odoo\.exceptions\.MissingError: (.*)/
/odoo\.exceptions\.MissingError: (.*)/,
/ValueError: (.*)/,
/KeyError: (.*)/
];

for (const pattern of businessErrors) {
Expand Down
Loading
Loading