feat(deck): surface remapped labels in move-card response

Round-3 review polish on PR #885:

- deck_move_card_to_board now captures the moved DeckCard and returns its
  post-move label titles in CardOperationResponse.labels, so LLM clients can
  confirm the cross-board label remap (the tool's headline behaviour) without
  a follow-up deck_get_card. The field is optional and defaults to None for
  the other card operations that share this response model.
- Tighten test_move_card_to_board_restores_done_state to assert the returned
  card reflects the restored done state.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Chris Coutinho
2026-06-10 23:53:01 +02:00
co-authored by Claude Opus 4.8
parent 7a39767482
commit 69b32f345c
3 changed files with 15 additions and 2 deletions
+8
View File
@@ -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
+4 -1
View File
@@ -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
+3 -1
View File
@@ -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):