diff --git a/nextcloud_mcp_server/models/deck.py b/nextcloud_mcp_server/models/deck.py index 1d9890a1..98eb1a6b 100644 --- a/nextcloud_mcp_server/models/deck.py +++ b/nextcloud_mcp_server/models/deck.py @@ -337,6 +337,14 @@ class CardOperationResponse(StatusResponse): card_id: int = Field(description="ID of the affected card") stack_id: int = Field(description="ID of the stack containing the card") board_id: int = Field(description="ID of the board containing the card") + labels: list[str] | None = Field( + default=None, + description=( + "Label titles on the card after the operation, when relevant — " + "e.g. after a cross-board move that remaps board-scoped labels to " + "the destination board" + ), + ) # Label Response Models diff --git a/nextcloud_mcp_server/server/deck.py b/nextcloud_mcp_server/server/deck.py index 9fa8069b..4a8a7632 100644 --- a/nextcloud_mcp_server/server/deck.py +++ b/nextcloud_mcp_server/server/deck.py @@ -1291,7 +1291,7 @@ def configure_deck_tools(mcp: FastMCP): order: Position within the destination stack (default 0 = top) """ client = await get_client(ctx) - await client.deck.move_card_to_board( + moved = await client.deck.move_card_to_board( source_board_id, source_stack_id, card_id, @@ -1299,12 +1299,15 @@ def configure_deck_tools(mcp: FastMCP): target_stack_id, order, ) + # Surface the post-move labels so callers can confirm the remap without + # a follow-up get_card (label remapping is this tool's whole point). return CardOperationResponse( success=True, message="Card moved to board successfully", card_id=card_id, stack_id=target_stack_id, board_id=target_board_id, + labels=[label.title for label in (moved.labels or [])], ) # Label Tools diff --git a/tests/client/deck/test_deck_move_card_api.py b/tests/client/deck/test_deck_move_card_api.py index 172047ec..32c2cb73 100644 --- a/tests/client/deck/test_deck_move_card_api.py +++ b/tests/client/deck/test_deck_move_card_api.py @@ -122,7 +122,7 @@ async def test_move_card_to_board_restores_done_state(mocker): ) client = DeckClient(mocker.AsyncMock(spec=httpx.AsyncClient), "testuser") - await client.move_card_to_board( + result = await client.move_card_to_board( source_board_id=1, source_stack_id=10, card_id=8, @@ -134,6 +134,8 @@ async def test_move_card_to_board_restores_done_state(mocker): done_call = mock_make_request.call_args_list[3] assert done_call.args[0] == "PUT" assert done_call.args[1] == "/apps/deck/cards/8/done" + # The returned card reflects the re-fetched (restored) done state + assert result.done is not None async def test_move_card_to_board_rejects_stack_not_on_target_board(mocker):