Skip to content

Commit 69d35e6

Browse files
committed
feat: optimize create and update record operations
1 parent a8318f6 commit 69d35e6

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.2.2] - 2025-08-04
9+
10+
### Changed
11+
- **Minimal Response Fields**: Reduced `create_record` and `update_record` tool responses to return only essential fields (id, name, display_name) to minimize LLM context usage
12+
813
## [0.2.1] - 2025-06-28
914

1015
### Changed

mcp_server_odoo/tools.py

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -771,14 +771,21 @@ async def _handle_create_record_tool(
771771
# Create the record
772772
record_id = self.connection.create(model, values)
773773

774-
# Read the created record to return full details
775-
records = self.connection.read(model, [record_id])
774+
# Return only essential fields to minimize context usage
775+
# Users can use get_record if they need more fields
776+
essential_fields = ["id", "name", "display_name"]
777+
778+
# Read only the essential fields
779+
records = self.connection.read(model, [record_id], essential_fields)
776780
if not records:
777781
raise ToolError(f"Failed to read created record: {model} with ID {record_id}")
778782

783+
# Process dates in the minimal record
784+
record = self._process_record_dates(records[0], model)
785+
779786
return {
780787
"success": True,
781-
"record": records[0],
788+
"record": record,
782789
"message": f"Successfully created {model} record with ID {record_id}",
783790
}
784791

@@ -814,22 +821,29 @@ async def _handle_update_record_tool(
814821
if not values:
815822
raise ValidationError("No values provided for record update")
816823

817-
# Check if record exists
818-
existing = self.connection.read(model, [record_id])
824+
# Check if record exists (only fetch ID to verify existence)
825+
existing = self.connection.read(model, [record_id], ["id"])
819826
if not existing:
820827
raise NotFoundError(f"Record not found: {model} with ID {record_id}")
821828

822829
# Update the record
823830
success = self.connection.write(model, [record_id], values)
824831

825-
# Read the updated record to return full details
826-
records = self.connection.read(model, [record_id])
832+
# Return only essential fields to minimize context usage
833+
# Users can use get_record if they need more fields
834+
essential_fields = ["id", "name", "display_name"]
835+
836+
# Read only the essential fields
837+
records = self.connection.read(model, [record_id], essential_fields)
827838
if not records:
828839
raise ToolError(f"Failed to read updated record: {model} with ID {record_id}")
829840

841+
# Process dates in the minimal record
842+
record = self._process_record_dates(records[0], model)
843+
830844
return {
831845
"success": success,
832-
"record": records[0],
846+
"record": record,
833847
"message": f"Successfully updated {model} record with ID {record_id}",
834848
}
835849

tests/test_write_tools.py

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Tests for write operation tools."""
22

3-
from unittest.mock import Mock
3+
from unittest.mock import Mock, call
44

55
import pytest
66

@@ -53,20 +53,26 @@ async def test_create_record_success(self, tool_handler, mock_connection):
5353
model = "res.partner"
5454
values = {"name": "Test Partner", "email": "[email protected]"}
5555
created_id = 123
56-
created_record = {"id": created_id, "name": "Test Partner", "email": "[email protected]"}
56+
essential_record = {
57+
"id": created_id,
58+
"name": "Test Partner",
59+
"display_name": "Test Partner",
60+
}
5761

5862
mock_connection.create.return_value = created_id
59-
mock_connection.read.return_value = [created_record]
63+
mock_connection.read.return_value = [essential_record]
6064

6165
# Execute
6266
result = await tool_handler._handle_create_record_tool(model, values)
6367

6468
# Verify
6569
assert result["success"] is True
66-
assert result["record"] == created_record
70+
assert result["record"] == essential_record
6771
assert "Successfully created" in result["message"]
6872
mock_connection.create.assert_called_once_with(model, values)
69-
mock_connection.read.assert_called_once_with(model, [created_id])
73+
mock_connection.read.assert_called_once_with(
74+
model, [created_id], ["id", "name", "display_name"]
75+
)
7076

7177
@pytest.mark.asyncio
7278
async def test_create_record_no_values(self, tool_handler):
@@ -91,8 +97,10 @@ async def test_update_record_success(self, tool_handler, mock_connection):
9197
model = "res.partner"
9298
record_id = 123
9399
values = {"email": "[email protected]"}
94-
existing_record = {"id": record_id, "name": "Test Partner", "email": "[email protected]"}
95-
updated_record = {"id": record_id, "name": "Test Partner", "email": "[email protected]"}
100+
# First read call (existence check) returns just ID
101+
existing_record = {"id": record_id}
102+
# Second read call returns essential fields
103+
updated_record = {"id": record_id, "name": "Test Partner", "display_name": "Test Partner"}
96104

97105
mock_connection.read.side_effect = [[existing_record], [updated_record]]
98106
mock_connection.write.return_value = True
@@ -105,6 +113,12 @@ async def test_update_record_success(self, tool_handler, mock_connection):
105113
assert result["record"] == updated_record
106114
assert "Successfully updated" in result["message"]
107115
mock_connection.write.assert_called_once_with(model, [record_id], values)
116+
# Verify both read calls with correct parameters
117+
expected_calls = [
118+
call(model, [record_id], ["id"]), # Existence check
119+
call(model, [record_id], ["id", "name", "display_name"]), # Essential fields
120+
]
121+
mock_connection.read.assert_has_calls(expected_calls)
108122

109123
@pytest.mark.asyncio
110124
async def test_update_record_not_found(self, tool_handler, mock_connection):

0 commit comments

Comments
 (0)