Add document notes tools (create/list/delete) - #125
Conversation
Adds MCP tools for Paperless document notes, backed by the
/api/documents/{id}/notes/ endpoint: create_document_note,
list_document_notes, and delete_document_note. Notes are the natural
place for an audit trail or progress notes on a document.
Closes baruchiro#124
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014EoK17h8dBErKg9cwNFoLn
🦋 Changeset detectedLatest commit: 67acb95 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughThis PR adds document notes support to the paperless-mcp server. Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (4)
src/api/PaperlessAPI.ts (1)
224-241: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd JSDoc comments to the new API methods.
As per coding guidelines, API methods in
PaperlessAPI.tsshould include JSDoc comments. The three new note methods (getDocumentNotes,createDocumentNote,deleteDocumentNote) lack JSDoc.📝 Suggested JSDoc additions
// Document note operations + /** + * Retrieve all notes attached to a document. + * `@param` id - The document ID. + * `@returns` The document's notes. + */ async getDocumentNotes(id: number): Promise<Note[]> { return this.request<Note[]>(`/documents/${id}/notes/`); } + /** + * Create a note on a document and return the updated notes list. + * `@param` id - The document ID. + * `@param` note - The note text to add. + * `@returns` The document's full notes list after creation. + */ async createDocumentNote(id: number, note: string): Promise<Note[]> { return this.request<Note[]>(`/documents/${id}/notes/`, { method: "POST", body: JSON.stringify({ note }), }); } + /** + * Delete a note from a document by note ID and return the remaining notes. + * `@param` id - The document ID. + * `@param` noteId - The ID of the note to delete. + * `@returns` The document's remaining notes after deletion. + */ async deleteDocumentNote(id: number, noteId: number): Promise<Note[]> { return this.request<Note[]>(`/documents/${id}/notes/?id=${noteId}`, { method: "DELETE", }); }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/api/PaperlessAPI.ts` around lines 224 - 241, The new note-related methods in PaperlessAPI lack the required JSDoc documentation. Add concise JSDoc comments for getDocumentNotes, createDocumentNote, and deleteDocumentNote in PaperlessAPI.ts, matching the style used by the other API methods and describing each method’s purpose and parameters so they follow the project’s coding guidelines.Source: Coding guidelines
README.md (1)
322-334: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueAdd destructive warning to
delete_document_noteREADME section.If the tool description is updated to include a destructive warning (per coding guidelines), the README should reflect this as well. Consider adding a note that deletion is irreversible.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 322 - 334, The README section for delete_document_note needs the same destructive warning required by the tool description. Update the delete_document_note documentation to clearly state that this action is irreversible, keeping the warning aligned with the rest of the delete-related docs and the delete_document_note example/parameter block.src/tools/notes.ts (2)
13-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDuplicate response construction across all three handlers.
Each handler repeats the same
{ content: [{ type: "text", text: JSON.stringify(notes) }] }pattern. Extracting a small helper would reduce duplication and make future response format changes easier.Also applies to: 34-45, 55-66
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/tools/notes.ts` around lines 13 - 24, The three handlers in notes.ts all build the same JSON text response inline after fetching notes, so extract that repeated response-shaping logic into a small helper and reuse it from each withErrorHandling callback. Keep the API fetches in place, but have the helper return the standard { content: [{ type: "text", text: JSON.stringify(...) }] } structure so any future format change is centralized.
13-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider using
arrayNotEmptyfor empty notes handling.As per coding guidelines, use transformation utilities (
arrayNotEmpty,objectNotEmpty) fromtools/utils/empty.tsfor empty value handling. When a document has no notes, the current response is"[]"— usingarrayNotEmptywould provide a clearer user-facing message.Also applies to: 34-45, 55-66
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/tools/notes.ts` around lines 13 - 24, Update the notes tool handler in the withErrorHandling block so empty note arrays are handled through the arrayNotEmpty utility from tools/utils/empty.ts instead of returning JSON.stringify(notes) as "[]". Locate the logic in the notes tool implementation and apply the same empty-value transformation pattern to the other affected branches mentioned in the review, so the user-facing response is clearer when api.getDocumentNotes(args.id) returns no notes.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/tools/notes.test.ts`:
- Around line 153-171: The create_document_note test is asserting the wrong
failure mode: tool validation errors from client.callTool return a
CallToolResult with isError set to true rather than rejecting. Update the test
in notes.test.ts to follow the same pattern as the other tool tests by checking
the returned result from create_document_note for isError instead of using
assert.rejects, while still verifying that calls.createDocumentNote remains
unused when validation fails.
In `@src/tools/notes.ts`:
- Around line 48-56: The delete tool in delete_document_note is missing the
required safety guard for destructive actions. Update the server.tool definition
for delete_document_note to add an explicit confirmation parameter in the schema
(for example a boolean confirm field) and make the tool description clearly warn
that the deletion is irreversible. Then enforce the confirmation check inside
the withErrorHandling callback before any delete logic runs, using the existing
api and args flow.
---
Nitpick comments:
In `@README.md`:
- Around line 322-334: The README section for delete_document_note needs the
same destructive warning required by the tool description. Update the
delete_document_note documentation to clearly state that this action is
irreversible, keeping the warning aligned with the rest of the delete-related
docs and the delete_document_note example/parameter block.
In `@src/api/PaperlessAPI.ts`:
- Around line 224-241: The new note-related methods in PaperlessAPI lack the
required JSDoc documentation. Add concise JSDoc comments for getDocumentNotes,
createDocumentNote, and deleteDocumentNote in PaperlessAPI.ts, matching the
style used by the other API methods and describing each method’s purpose and
parameters so they follow the project’s coding guidelines.
In `@src/tools/notes.ts`:
- Around line 13-24: The three handlers in notes.ts all build the same JSON text
response inline after fetching notes, so extract that repeated response-shaping
logic into a small helper and reuse it from each withErrorHandling callback.
Keep the API fetches in place, but have the helper return the standard {
content: [{ type: "text", text: JSON.stringify(...) }] } structure so any future
format change is centralized.
- Around line 13-24: Update the notes tool handler in the withErrorHandling
block so empty note arrays are handled through the arrayNotEmpty utility from
tools/utils/empty.ts instead of returning JSON.stringify(notes) as "[]". Locate
the logic in the notes tool implementation and apply the same empty-value
transformation pattern to the other affected branches mentioned in the review,
so the user-facing response is clearer when api.getDocumentNotes(args.id)
returns no notes.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: e7b541be-dce2-4ac6-b89e-6e1e7e4b278b
📒 Files selected for processing (6)
.changeset/document-notes-tools.mdREADME.mdsrc/api/PaperlessAPI.tssrc/server.tssrc/tools/notes.test.tssrc/tools/notes.ts
|
Hey @baruchiro, thanks for maintaining this project! Heads-up that the CI workflows likely need your approval to run, since I'm a first-time contributor. Locally everything is green:
This closes #124 and follows the existing |
- delete_document_note now requires confirm: true and warns it is irreversible (matches the other destructive tools). - Add JSDoc to the three new PaperlessAPI note methods. - Extract a shared notesResult() helper to de-duplicate the tool response construction. - Make the empty-note test accept either a protocol rejection or an isError result (the pinned MCP SDK rejects zod violations with -32602; newer SDKs return isError), and add a delete-without-confirm test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014EoK17h8dBErKg9cwNFoLn
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014EoK17h8dBErKg9cwNFoLn
What
Adds MCP tools for Paperless document notes, backed by the
/api/documents/{id}/notes/endpoint:list_document_notes(id)→GET /documents/{id}/notes/create_document_note(id, note)→POST /documents/{id}/notes/delete_document_note(id, note_id)→DELETE /documents/{id}/notes/?id={note_id}Why
There was no way to add a note/comment to a document via the MCP, so the only workaround was calling the REST API directly with a token. Notes are the natural place for an audit trail (e.g. "invoice paid on X from account Y") or progress notes on an action item.
Closes #124
Implementation notes
src/tools/notes.tsfollows the existingregisterXToolspattern (withErrorHandling, zod schemas), wired insrc/server.ts.src/api/PaperlessAPI.ts; reuses the existingNotetype insrc/api/types.ts.create_document_notevalidates a non-empty note; all three return the document's notes array (matching Paperless behaviour).Tests
src/tools/notes.test.ts(4 tests) using the in-memory MCP client harness: create/list/delete call-through and empty-note rejection.tsc --noEmitclean,npm run buildclean.minorchangeset.🤖 Generated with Claude Code
https://claude.ai/code/session_014EoK17h8dBErKg9cwNFoLn
Summary by CodeRabbit
confirmusage).confirm: truebefore deletion.