From 4b3a2f543276af1fad377205fe20332f3d71398c Mon Sep 17 00:00:00 2001 From: Colin Maudry Date: Thu, 9 Jul 2026 19:53:08 +0200 Subject: [PATCH] =?UTF-8?q?feat(mcp):=20s=C3=A9rialisation=20Polars=20->?= =?UTF-8?q?=20JSON=20pour=20les=20tools=20MCP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 5 --- src/mcp/__init__.py | 0 src/mcp/serialization.py | 21 +++++++++++++++++++++ tests/mcp/__init__.py | 0 tests/mcp/test_serialization.py | 20 ++++++++++++++++++++ 4 files changed, 41 insertions(+) create mode 100644 src/mcp/__init__.py create mode 100644 src/mcp/serialization.py create mode 100644 tests/mcp/__init__.py create mode 100644 tests/mcp/test_serialization.py diff --git a/src/mcp/__init__.py b/src/mcp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/mcp/serialization.py b/src/mcp/serialization.py new file mode 100644 index 0000000..9b81ff5 --- /dev/null +++ b/src/mcp/serialization.py @@ -0,0 +1,21 @@ +import datetime +from typing import Any + +import polars as pl + + +def to_json_records(df: pl.DataFrame) -> list[dict[str, Any]]: + """Convertit un DataFrame Polars en liste de dicts JSON-sérialisables. + + Les dates/datetimes deviennent des chaînes ISO 8601 ; les valeurs nulles + restent None. Utilisé par tous les tools MCP pour produire une sortie propre. + """ + return [ + {key: _jsonify(value) for key, value in row.items()} for row in df.to_dicts() + ] + + +def _jsonify(value: Any) -> Any: + if isinstance(value, (datetime.date, datetime.datetime)): + return value.isoformat() + return value diff --git a/tests/mcp/__init__.py b/tests/mcp/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/mcp/test_serialization.py b/tests/mcp/test_serialization.py new file mode 100644 index 0000000..ad35b88 --- /dev/null +++ b/tests/mcp/test_serialization.py @@ -0,0 +1,20 @@ +import datetime + +import polars as pl + +from src.mcp.serialization import to_json_records + + +def test_dates_become_iso_strings(): + df = pl.DataFrame({"d": [datetime.date(2025, 1, 1)], "n": [10]}) + assert to_json_records(df) == [{"d": "2025-01-01", "n": 10}] + + +def test_none_is_preserved(): + df = pl.DataFrame({"nom": [None], "x": [3]}) + assert to_json_records(df) == [{"nom": None, "x": 3}] + + +def test_strings_and_numbers_untouched(): + df = pl.DataFrame({"s": ["abc"], "f": [1.5]}) + assert to_json_records(df) == [{"s": "abc", "f": 1.5}]