Commit Graph
9 Commits
Author SHA1 Message Date
Chris CoutinhoandClaude Opus 4.7 271904c227 fix(deck): address review — notesPath key, scopes, modernize types
PR #781 review round 1:

- 🔴 Fix notesPath key: the Notes API returns the folder under camelCase
  ``notesPath`` (see models/notes.py:43), but `deck_attach_note` was
  looking up snake_case ``notes_path`` and silently falling back to
  ``"Notes"``. Users with a non-default notes folder would have produced
  shares pointing at non-existent files (404 on click in Deck UI).

- 🔴 Add wire-through unit test that would have caught the above:
  extract `_resolve_note_attach_path(client, note_id)` as a testable
  helper that encapsulates the camelCase-key lookup. Three new tests:
  custom notesPath honored, missing key falls back to default, null
  category handled.

- 🟡 Modernize new fields on `DeckAttachmentExtendedData` to PEP 604
  (`X | None`) per CLAUDE.md.

- 🟡 Drop unnecessary string forward reference on
  `ListAttachmentsResponse.results` — DeckAttachment is defined earlier
  in the same module.

- 🟢 Move `pytestmark = pytest.mark.unit` to module level in
  test_sharing_client.py to match the convention in test_deck_server.py.

Per user request: `deck_attach_file` is now scoped `deck.write` +
``files.read`` (was just `deck.write`) so the generic file-share
permission story is consistent — only `deck_attach_note` keeps
`notes.read` since it specifically reads from the Notes app. Docstring
updated to emphasise the tool is generic over the user's Files
(PDFs/images/etc., not just markdown).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 23:28:37 +02:00
Chris CoutinhoandClaude Opus 4.7 c0a974c498 feat(deck): add file/note attachment MCP tools
Adds four tools that expose Deck card attachments via the MCP surface:
deck_attach_file, deck_attach_note, deck_list_attachments, and
deck_delete_attachment. The attach* variants share an existing Files
entry (or Notes-app note) with the card via OCS shareType=12 — same
mechanism the Deck UI's "Share from Files" picker uses, no file copy.

This replaces the prior workaround of appending bulky activity content
as Deck card comments: per-PR/per-event narrative now lives in NC Notes
and surfaces on the tracking card as a clickable attachment that opens
the original note in place.

Implementation reuses existing client methods (SharingClient.create_share,
DeckClient.get/delete_attachment, NotesClient.get_settings/get_note);
no new client code. _SHARE_TYPE_DECK is centralised with a CI-guard test
to prevent silent drift, and SharingClient.create_share's wire format is
pinned to what the Deck Vue source sends.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 23:17:20 +02:00
Chris CoutinhoandClaude Opus 4.7 2129bd6fac fix(deck): address review feedback on card comment tools
- Wrap raw DeckComment returns in CardCommentResponse(BaseResponse) for
  create/update so the success/timestamp envelope matches other deck tools
  (#737 review issue 2).
- Rename ListCardCommentsResponse.total → count and clarify in the
  description that it's the page size, not a server-side total — the Deck
  list endpoint does not expose one (#737 review issue 3).
- Validate the documented 1000-character limit on create/update with an
  inline length check + ValueError, matching the pattern in
  api/management.py (#737 review issue 4).
- Use modern int | None union syntax for the new parent_id parameter
  (#737 review issue 1); rest of the file is left in the existing
  Optional[...] style.

Also add an MCP-level test that the >1000 char message is rejected, and
update the existing comment tests to unwrap the new comment field.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 16:57:46 +02:00
Chris CoutinhoandClaude Opus 4.7 454f6912bc feat(deck): add card comment tools
Expose four new MCP tools backed by existing DeckClient comment methods:

- deck_get_card_comments — list with limit/offset pagination
- deck_create_card_comment — top-level or threaded (via parent_id)
- deck_update_card_comment — author-only on the server
- deck_delete_card_comment — author-only, destructive, idempotent

Adds ListCardCommentsResponse and CardCommentOperationResponse models, and
extends the client unit tests to cover replies, deletion, pagination, and
the request shape for updates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:39:24 +02:00
Chris CoutinhoandClaude Opus 4.6 18e5baf2a5 fix: address PR #574 fourth review round
- Use lowercase generics (list[...]) in new deck response models
- Add clarifying comment on AddressBook.uri slug semantics
- Fall back calendar_display_name to calendar_name when absent

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-21 09:36:14 +01:00
Chris CoutinhoandClaude Opus 4.6 8887aa241a fix: wrap raw list returns in response models to produce single TextContent block
MCP tools returning raw lists caused FastMCP's _convert_to_content() to create
one TextContent block per element. Most MCP clients only read content[0], so
they saw a single result instead of the full list.

Wrapped 9 tool functions in proper response objects:
- deck: deck_get_boards, deck_get_stacks, deck_get_cards, deck_get_labels
- calendar: nc_calendar_list_events, nc_calendar_get_upcoming_events
- contacts: nc_contacts_list_addressbooks, nc_contacts_list_contacts
- tables: nc_tables_list_tables

Closes #568

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 09:22:16 +01:00
Chris Coutinho 13e4915e38 test: Remove unused pytest fixtures 2025-10-14 01:23:39 +02:00
Chris Coutinho d2d413afcd feat(deck): Add support for stack, cards, labels 2025-09-11 00:35:02 +02:00
Chris Coutinho 167053578d feat(deck): Initialize Deck app client/server 2025-09-11 00:10:25 +02:00