diff --git a/backend/app/api/mcp_server.py b/backend/app/api/mcp_server.py index f5f31c6..d2faac1 100644 --- a/backend/app/api/mcp_server.py +++ b/backend/app/api/mcp_server.py @@ -8,8 +8,9 @@ from sqlalchemy import select, and_ from app.core.database import AsyncSessionLocal from app.models.todos import TodoItem -from app.models.notes import NoteItem -from app.models.shopping import ShoppingList, ListItem, Product + +_VALID_STATUSES = {"pending", "done", "cancelled"} +_VALID_PRIORITIES = {"low", "medium", "high"} mcp = FastMCP("HomeHub", stateless_http=True) @@ -79,6 +80,8 @@ async def create_todo( domain: str | None = None, ) -> str: """Crée une tâche. due_date en ISO 8601 (ex: 2025-06-01T10:00:00Z). priority: low/medium/high.""" + if priority and priority not in _VALID_PRIORITIES: + return _dumps({"error": f"Priorité invalide : {priority}. Valeurs: low/medium/high"}) async with AsyncSessionLocal() as session: parsed_due = None if due_date: @@ -121,6 +124,10 @@ async def update_todo( item = await session.get(TodoItem, todo_id) if not item: return _dumps({"error": f"Tâche introuvable : {id}"}) + if status is not None and status not in _VALID_STATUSES: + return _dumps({"error": f"Statut invalide : {status}. Valeurs: pending/done/cancelled"}) + if priority is not None and priority not in _VALID_PRIORITIES: + return _dumps({"error": f"Priorité invalide : {priority}. Valeurs: low/medium/high"}) if title is not None: item.title = title if status is not None: diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index 061d1e9..a5c2d39 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -13,7 +13,7 @@ def make_test_engine(): return create_async_engine(settings.database_url, poolclass=NullPool) -@pytest.fixture(autouse=True) +@pytest.fixture async def mcp_nullpool_session(): """Remplace AsyncSessionLocal dans mcp_server par un sessionmaker NullPool pour éviter les conflits d'event loop entre tests.""" diff --git a/backend/tests/test_mcp.py b/backend/tests/test_mcp.py index f551ef6..2f73e11 100644 --- a/backend/tests/test_mcp.py +++ b/backend/tests/test_mcp.py @@ -1,8 +1,21 @@ import json import pytest +from sqlalchemy import delete from app.api.mcp_server import ( get_todos, create_todo, update_todo, postpone_todo, delete_todo, ) +from app.core.database import AsyncSessionLocal +from app.models.todos import TodoItem + +pytestmark = pytest.mark.usefixtures("mcp_nullpool_session") + + +@pytest.fixture(autouse=True) +async def cleanup_mcp_todos(): + yield + async with AsyncSessionLocal() as session: + await session.execute(delete(TodoItem).where(TodoItem.title.like("TEST_MCP_%"))) + await session.commit() async def test_get_todos_retourne_liste_json():