Skip to content
Open
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
42 changes: 42 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,48 @@ An MCP server implementation that integrates with Odoo ERP systems, enabling AI
* `ODOO_TIMEOUT`: Connection timeout in seconds (default: 30)
* `ODOO_VERIFY_SSL`: Whether to verify SSL certificates (default: true)
* `HTTP_PROXY`: Force the ODOO connection to use an HTTP proxy
* `ODOO_CUSTOM_INSTRUCTIONS`: Path to a text file containing custom instructions to append to all tool descriptions

### Custom Instructions

You can provide custom instructions that will be appended to all tool descriptions. This is useful for providing context-specific guidance or organizational conventions.

1. Create a text file with your instructions (e.g., `odoo_instructions.txt`):

```text
When working with this Odoo instance:
- Always use Spanish for field labels
- The fiscal year starts in July
- Contact the IT department before modifying res.users records
```

2. Set the environment variable to point to your file:

```bash
export ODOO_CUSTOM_INSTRUCTIONS="/path/to/odoo_instructions.txt"
```

3. Or add it to your Claude Desktop configuration:

```json
{
"mcpServers": {
"odoo": {
"command": "python",
"args": ["-m", "odoo_mcp"],
"env": {
"ODOO_URL": "https://your-odoo-instance.com",
"ODOO_DB": "your-database-name",
"ODOO_USERNAME": "your-username",
"ODOO_PASSWORD": "your-password-or-api-key",
"ODOO_CUSTOM_INSTRUCTIONS": "/path/to/odoo_instructions.txt"
}
}
}
}
```

The instructions will be automatically included in all tool descriptions, helping the AI assistant follow your specific guidelines.

### Usage with Claude Desktop

Expand Down
30 changes: 20 additions & 10 deletions src/odoo_mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

import json
import os
from contextlib import asynccontextmanager
from dataclasses import dataclass
from datetime import datetime, timedelta
Expand All @@ -15,6 +16,12 @@

from .odoo_client import OdooClient, get_odoo_client

# Load custom instructions from environment variable
CUSTOM_INSTRUCTIONS = ""
if "ODOO_CUSTOM_INSTRUCTIONS" in os.environ:
with open(os.environ["ODOO_CUSTOM_INSTRUCTIONS"]) as f:
CUSTOM_INSTRUCTIONS = f.read()


@dataclass
class AppContext:
Expand Down Expand Up @@ -211,16 +218,15 @@ class SearchHolidaysResponse(BaseModel):
# ----- MCP Tools -----


@mcp.tool(description="Execute a custom method on an Odoo model")
@mcp.tool()
def execute_method(
ctx: Context,
model: str,
method: str,
args: List = None,
kwargs: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
"""
Execute a custom method on an Odoo model
f"""Execute a custom method on an Odoo model

Parameters:
model: The model name (e.g., 'res.partner')
Expand All @@ -233,6 +239,8 @@ def execute_method(
- success: Boolean indicating success
- result: Result of the method (if success)
- error: Error message (if failure)

{CUSTOM_INSTRUCTIONS}
"""
odoo = ctx.request_context.lifespan_context.odoo
try:
Expand Down Expand Up @@ -348,21 +356,22 @@ def execute_method(
return {"success": False, "error": str(e)}


@mcp.tool(description="Search for employees by name")
@mcp.tool()
def search_employee(
ctx: Context,
name: str,
limit: int = 20,
) -> SearchEmployeeResponse:
"""
Search for employees by name using Odoo's name_search method.
f"""Search for employees by name using Odoo's name_search method

Parameters:
name: The name (or part of the name) to search for.
limit: The maximum number of results to return (default 20).

Returns:
SearchEmployeeResponse containing results or error information.

{CUSTOM_INSTRUCTIONS}
"""
odoo = ctx.request_context.lifespan_context.odoo
model = "hr.employee"
Expand All @@ -381,23 +390,24 @@ def search_employee(
return SearchEmployeeResponse(success=False, error=str(e))


@mcp.tool(description="Search for holidays within a date range")
@mcp.tool()
def search_holidays(
ctx: Context,
start_date: str,
end_date: str,
employee_id: Optional[int] = None,
) -> SearchHolidaysResponse:
"""
Searches for holidays within a specified date range.
f"""Search for holidays within a specified date range

Parameters:
start_date: Start date in YYYY-MM-DD format.
end_date: End date in YYYY-MM-DD format.
employee_id: Optional employee ID to filter holidays.

Returns:
SearchHolidaysResponse: Object containing the search results.
SearchHolidaysResponse: Object containing the search results.

{CUSTOM_INSTRUCTIONS}
"""
odoo = ctx.request_context.lifespan_context.odoo

Expand Down