@baruchiro/paperless-mcp 0.5.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +334 -11
- package/build/api/PaperlessAPI.d.ts +29 -2
- package/build/api/PaperlessAPI.js +97 -8
- package/build/api/types.d.ts +47 -0
- package/build/index.js +28 -5
- package/build/resources/documents.d.ts +7 -0
- package/build/resources/documents.js +119 -0
- package/build/resources/documents.test.d.ts +1 -0
- package/build/resources/documents.test.js +124 -0
- package/build/server.d.ts +14 -1
- package/build/server.js +21 -5
- package/build/server.test.d.ts +1 -0
- package/build/server.test.js +54 -0
- package/build/tools/documents.d.ts +3 -1
- package/build/tools/documents.js +170 -67
- package/build/tools/documents.test.js +404 -0
- package/build/tools/mail.d.ts +3 -0
- package/build/tools/mail.js +187 -0
- package/build/tools/mail.test.d.ts +1 -0
- package/build/tools/mail.test.js +212 -0
- package/build/tools/notes.d.ts +3 -0
- package/build/tools/notes.js +55 -0
- package/build/tools/notes.test.d.ts +1 -0
- package/build/tools/notes.test.js +177 -0
- package/build/tools/utils/descriptions.d.ts +1 -1
- package/build/tools/utils/descriptions.js +1 -1
- package/build/tools/utils/documentQuery.d.ts +71 -0
- package/build/tools/utils/documentQuery.js +270 -0
- package/build/tools/utils/resourceUri.d.ts +12 -7
- package/build/tools/utils/resourceUri.js +13 -8
- package/build/tools/utils/resourceUri.test.js +12 -12
- package/build/tools/utils/selectFields.d.ts +11 -0
- package/build/tools/utils/selectFields.js +91 -0
- package/build/tools/utils/selectFields.test.d.ts +1 -0
- package/build/tools/utils/selectFields.test.js +164 -0
- package/package.json +2 -1
- package/paperless-mcp.dxt +0 -0
package/README.md
CHANGED
|
@@ -67,6 +67,7 @@ Add these to your MCP config file:
|
|
|
67
67
|
| `PAPERLESS_API_KEY` | Yes | — | API token from your Paperless-NGX profile |
|
|
68
68
|
| `PAPERLESS_PUBLIC_URL` | No | `PAPERLESS_URL` | Public-facing URL for document links |
|
|
69
69
|
| `PAPERLESS_API_VERSION` | No | `5` | Paperless-ngx REST API version. Use `10` for Paperless-ngx v3+. If you see HTTP 406 errors, set this to `10`. |
|
|
70
|
+
| `PAPERLESS_MCP_UPLOAD_PATHS` | No | — | Colon-separated list of allowed directories for `file_path` uploads. **Recommended for security.** Example: `/var/uploads:/tmp/scans` |
|
|
70
71
|
|
|
71
72
|
That's it! Now you can ask Claude to help you manage your Paperless-NGX documents.
|
|
72
73
|
|
|
@@ -86,11 +87,23 @@ Here are some things you can ask Claude to do:
|
|
|
86
87
|
### Document Operations
|
|
87
88
|
|
|
88
89
|
#### list_documents
|
|
89
|
-
Get a paginated list of
|
|
90
|
+
Get a paginated list of documents with simple filters. Use this for straightforward listing tasks. For full-text queries, structured custom field filtering, or advanced Paperless filters, use `query_documents`.
|
|
90
91
|
|
|
91
92
|
Parameters:
|
|
92
93
|
- page (optional): Page number
|
|
93
94
|
- page_size (optional): Number of documents per page
|
|
95
|
+
- search (optional): Simple Paperless search term
|
|
96
|
+
- correspondent (optional): Correspondent ID
|
|
97
|
+
- document_type (optional): Document type ID
|
|
98
|
+
- tag (optional): Tag ID
|
|
99
|
+
- storage_path (optional): Storage path ID
|
|
100
|
+
- created__date__gte (optional): Created date on or after YYYY-MM-DD
|
|
101
|
+
- created__date__lte (optional): Created date on or before YYYY-MM-DD
|
|
102
|
+
- ordering (optional): Paperless ordering field
|
|
103
|
+
- archive_serial_number (optional): Archive serial number
|
|
104
|
+
- archive_serial_number__isnull (optional): Whether the archive serial number is empty
|
|
105
|
+
- custom_field_query (optional): Raw JSON-encoded Paperless custom field query string
|
|
106
|
+
- custom_fields__icontains (optional): Case-insensitive substring match across custom field values
|
|
94
107
|
|
|
95
108
|
```typescript
|
|
96
109
|
list_documents({
|
|
@@ -99,6 +112,70 @@ list_documents({
|
|
|
99
112
|
})
|
|
100
113
|
```
|
|
101
114
|
|
|
115
|
+
#### query_documents
|
|
116
|
+
Canonical document query tool. Supports full-text querying, simple Paperless search, custom field filters, and documented `/api/documents/` Paperless query parameters.
|
|
117
|
+
|
|
118
|
+
Parameters:
|
|
119
|
+
- page (optional): Page number
|
|
120
|
+
- page_size (optional): Number of documents per page
|
|
121
|
+
- ordering (optional): Paperless ordering field
|
|
122
|
+
- query (optional): Full-text query string
|
|
123
|
+
- search (optional): Simple Paperless search term
|
|
124
|
+
- more_like_id (optional): Find documents similar to this document ID
|
|
125
|
+
- correspondent (optional): Correspondent ID
|
|
126
|
+
- document_type (optional): Document type ID
|
|
127
|
+
- tag (optional): Tag ID
|
|
128
|
+
- storage_path (optional): Storage path ID
|
|
129
|
+
- created__date__gte (optional): Created date on or after YYYY-MM-DD
|
|
130
|
+
- created__date__lte (optional): Created date on or before YYYY-MM-DD
|
|
131
|
+
- custom_field_query (optional): Structured Paperless custom field query using `[field_name_or_id, operator, value]` leaves or `["AND" | "OR", [clause1, clause2]]` groups
|
|
132
|
+
- paperless_filters (optional): Additional documented `/api/documents/` Paperless query parameters, passed as key/value pairs
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
// Full-text query
|
|
136
|
+
query_documents({
|
|
137
|
+
query: "invoice 2024"
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
// Simple search term
|
|
141
|
+
query_documents({
|
|
142
|
+
search: "acme"
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
// Custom field exact match
|
|
146
|
+
query_documents({
|
|
147
|
+
custom_field_query: ["Invoice Number", "exact", "12345"]
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
// Custom field empty
|
|
151
|
+
query_documents({
|
|
152
|
+
custom_field_query: ["OR", [
|
|
153
|
+
["Invoice Number", "isnull", true],
|
|
154
|
+
["Invoice Number", "exact", ""]
|
|
155
|
+
]]
|
|
156
|
+
})
|
|
157
|
+
|
|
158
|
+
// Custom field missing
|
|
159
|
+
query_documents({
|
|
160
|
+
custom_field_query: ["Invoice Number", "exists", false]
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
// Combined filters
|
|
164
|
+
query_documents({
|
|
165
|
+
query: "invoice",
|
|
166
|
+
tag: 5,
|
|
167
|
+
created__date__gte: "2024-01-01",
|
|
168
|
+
custom_field_query: ["Invoice Number", "exists", true]
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
// One documented Paperless filter that is not a first-class argument
|
|
172
|
+
query_documents({
|
|
173
|
+
paperless_filters: {
|
|
174
|
+
id__in: [101, 202, 303]
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
102
179
|
#### get_document
|
|
103
180
|
Get a specific document by ID.
|
|
104
181
|
|
|
@@ -112,7 +189,7 @@ get_document({
|
|
|
112
189
|
```
|
|
113
190
|
|
|
114
191
|
#### search_documents
|
|
115
|
-
|
|
192
|
+
Deprecated compatibility wrapper for full-text search. Prefer `query_documents({ query: ... })` for new integrations.
|
|
116
193
|
|
|
117
194
|
Parameters:
|
|
118
195
|
- query: Search query string
|
|
@@ -244,9 +321,17 @@ bulk_edit_documents({
|
|
|
244
321
|
#### post_document
|
|
245
322
|
Upload a new document to Paperless-NGX.
|
|
246
323
|
|
|
324
|
+
**Two upload modes:**
|
|
325
|
+
|
|
326
|
+
1. **Base64 mode** (traditional): Provide `file` (base64-encoded content) + `filename`
|
|
327
|
+
2. **Filesystem mode** (efficient): Provide `file_path` (absolute path on server)
|
|
328
|
+
|
|
329
|
+
**Security Note:** When using `file_path`, set the `PAPERLESS_MCP_UPLOAD_PATHS` environment variable (colon-separated list of allowed directories) to restrict uploads to specific locations. Without this, any file on the server's filesystem could be uploaded.
|
|
330
|
+
|
|
247
331
|
Parameters:
|
|
248
|
-
- file: Base64 encoded file content
|
|
249
|
-
-
|
|
332
|
+
- file (optional): Base64 encoded file content. Either `file` or `file_path` required.
|
|
333
|
+
- file_path (optional): Absolute path to file on server's filesystem. Either `file` or `file_path` required.
|
|
334
|
+
- filename (optional): Name of the file. Required with `file`, optional with `file_path` (derives from path).
|
|
250
335
|
- title (optional): Title for the document
|
|
251
336
|
- created (optional): DateTime when the document was created (e.g. "2024-01-19" or "2024-01-19 06:15:00+02:00")
|
|
252
337
|
- correspondent (optional): ID of a correspondent
|
|
@@ -256,7 +341,10 @@ Parameters:
|
|
|
256
341
|
- archive_serial_number (optional): Archive serial number
|
|
257
342
|
- custom_fields (optional): Array of custom field IDs
|
|
258
343
|
|
|
344
|
+
**File size limit:** 100MB for both modes
|
|
345
|
+
|
|
259
346
|
```typescript
|
|
347
|
+
// Base64 mode (traditional)
|
|
260
348
|
post_document({
|
|
261
349
|
file: "base64_encoded_content",
|
|
262
350
|
filename: "invoice.pdf",
|
|
@@ -268,6 +356,59 @@ post_document({
|
|
|
268
356
|
archive_serial_number: "2024-001",
|
|
269
357
|
custom_fields: [1, 2]
|
|
270
358
|
})
|
|
359
|
+
|
|
360
|
+
// Filesystem mode (more efficient for large files)
|
|
361
|
+
post_document({
|
|
362
|
+
file_path: "/var/uploads/invoice.pdf",
|
|
363
|
+
title: "January Invoice",
|
|
364
|
+
correspondent: 1,
|
|
365
|
+
document_type: 2,
|
|
366
|
+
tags: [1, 3]
|
|
367
|
+
})
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Document Notes
|
|
371
|
+
|
|
372
|
+
#### list_document_notes
|
|
373
|
+
List all notes attached to a document.
|
|
374
|
+
|
|
375
|
+
Parameters:
|
|
376
|
+
- id: Document ID
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
list_document_notes({
|
|
380
|
+
id: 123
|
|
381
|
+
})
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
#### create_document_note
|
|
385
|
+
Add a note to a document. Returns the document's full list of notes.
|
|
386
|
+
|
|
387
|
+
Parameters:
|
|
388
|
+
- id: Document ID
|
|
389
|
+
- note: The note text to add
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
create_document_note({
|
|
393
|
+
id: 123,
|
|
394
|
+
note: "Invoice paid on 2026-06-30 from Commerzbank account."
|
|
395
|
+
})
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
#### delete_document_note
|
|
399
|
+
⚠️ Delete a single note from a document by its note ID. This operation is irreversible.
|
|
400
|
+
|
|
401
|
+
Parameters:
|
|
402
|
+
- id: Document ID
|
|
403
|
+
- note_id: The ID of the note to delete
|
|
404
|
+
- confirm: Must be `true` to confirm this destructive operation
|
|
405
|
+
|
|
406
|
+
```typescript
|
|
407
|
+
delete_document_note({
|
|
408
|
+
id: 123,
|
|
409
|
+
note_id: 5,
|
|
410
|
+
confirm: true
|
|
411
|
+
})
|
|
271
412
|
```
|
|
272
413
|
|
|
273
414
|
### Tag Operations
|
|
@@ -447,6 +588,133 @@ bulk_edit_custom_fields({
|
|
|
447
588
|
})
|
|
448
589
|
```
|
|
449
590
|
|
|
591
|
+
### Mail Operations
|
|
592
|
+
|
|
593
|
+
Tools for managing Paperless mail accounts and the mail rules that drive
|
|
594
|
+
automatic email ingestion. Account passwords/tokens are never exposed: they are
|
|
595
|
+
redacted from every tool response.
|
|
596
|
+
|
|
597
|
+
#### list_mail_accounts
|
|
598
|
+
List mail accounts so you can pick the account ID needed when creating a mail
|
|
599
|
+
rule. Passwords are redacted.
|
|
600
|
+
|
|
601
|
+
Parameters:
|
|
602
|
+
- page (optional): Page number
|
|
603
|
+
- page_size (optional): Number of results per page
|
|
604
|
+
|
|
605
|
+
```typescript
|
|
606
|
+
list_mail_accounts()
|
|
607
|
+
```
|
|
608
|
+
|
|
609
|
+
#### get_mail_account
|
|
610
|
+
Get a single mail account by ID. Password/token fields are redacted.
|
|
611
|
+
|
|
612
|
+
Parameters:
|
|
613
|
+
- id: Mail account ID
|
|
614
|
+
|
|
615
|
+
```typescript
|
|
616
|
+
get_mail_account({
|
|
617
|
+
id: 1
|
|
618
|
+
})
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
#### process_mail_account
|
|
622
|
+
Manually trigger Paperless mail processing for one account. This can consume
|
|
623
|
+
matching mails according to the account's enabled mail rules.
|
|
624
|
+
|
|
625
|
+
Parameters:
|
|
626
|
+
- id: Mail account ID
|
|
627
|
+
|
|
628
|
+
```typescript
|
|
629
|
+
process_mail_account({
|
|
630
|
+
id: 1
|
|
631
|
+
})
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
#### list_mail_rules
|
|
635
|
+
List mail rules with optional pagination.
|
|
636
|
+
|
|
637
|
+
Parameters:
|
|
638
|
+
- page (optional): Page number
|
|
639
|
+
- page_size (optional): Number of results per page
|
|
640
|
+
|
|
641
|
+
```typescript
|
|
642
|
+
list_mail_rules()
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
#### get_mail_rule
|
|
646
|
+
Get a single mail rule by ID.
|
|
647
|
+
|
|
648
|
+
Parameters:
|
|
649
|
+
- id: Mail rule ID
|
|
650
|
+
|
|
651
|
+
```typescript
|
|
652
|
+
get_mail_rule({
|
|
653
|
+
id: 1
|
|
654
|
+
})
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
#### create_mail_rule
|
|
658
|
+
Create a mail rule. Use `list_mail_accounts` first to choose the account.
|
|
659
|
+
|
|
660
|
+
Required parameters:
|
|
661
|
+
- name: Rule name
|
|
662
|
+
- account: Mail account ID
|
|
663
|
+
- folder: IMAP folder to scan (e.g. "INBOX")
|
|
664
|
+
|
|
665
|
+
Common optional parameters:
|
|
666
|
+
- enabled (default true): Whether the rule is active
|
|
667
|
+
- filter_from / filter_to / filter_subject / filter_body: Match incoming mail
|
|
668
|
+
- maximum_age: Only process mail newer than this many days
|
|
669
|
+
- action: 1=Delete, 2=Move to folder, 3=Mark as read, 4=Flag, 5=Tag
|
|
670
|
+
- action_parameter: Target folder/tag for the chosen action
|
|
671
|
+
- assign_title_from: 1=Subject, 2=Attachment filename, 3=Do not assign
|
|
672
|
+
- assign_tags / assign_correspondent / assign_document_type: Metadata to apply
|
|
673
|
+
- assign_correspondent_from: 1=None, 2=Mail address, 3=Sender name, 4=Use assign_correspondent
|
|
674
|
+
- attachment_type: 1=Attachments only, 2=All files incl. inline
|
|
675
|
+
- consumption_scope: 1=Attachments only, 2=Full mail as .eml, 3=Both
|
|
676
|
+
- pdf_layout: 0=System default, 1=Text+HTML, 2=HTML+text, 3=HTML only, 4=Text only
|
|
677
|
+
|
|
678
|
+
```typescript
|
|
679
|
+
create_mail_rule({
|
|
680
|
+
name: "Invoices",
|
|
681
|
+
account: 1,
|
|
682
|
+
folder: "INBOX",
|
|
683
|
+
filter_subject: "invoice",
|
|
684
|
+
action: 3,
|
|
685
|
+
attachment_type: 1
|
|
686
|
+
})
|
|
687
|
+
```
|
|
688
|
+
|
|
689
|
+
#### update_mail_rule
|
|
690
|
+
Patch an existing mail rule. Only the fields you supply are changed.
|
|
691
|
+
|
|
692
|
+
Parameters:
|
|
693
|
+
- id: Mail rule ID
|
|
694
|
+
- ...any of the `create_mail_rule` fields to update
|
|
695
|
+
|
|
696
|
+
```typescript
|
|
697
|
+
update_mail_rule({
|
|
698
|
+
id: 1,
|
|
699
|
+
enabled: false
|
|
700
|
+
})
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
#### delete_mail_rule
|
|
704
|
+
Delete a mail rule. Requires an explicit confirmation flag. This changes future
|
|
705
|
+
mail ingestion behavior but does not delete any existing documents.
|
|
706
|
+
|
|
707
|
+
Parameters:
|
|
708
|
+
- id: Mail rule ID
|
|
709
|
+
- confirm: Must be `true` to confirm deletion
|
|
710
|
+
|
|
711
|
+
```typescript
|
|
712
|
+
delete_mail_rule({
|
|
713
|
+
id: 1,
|
|
714
|
+
confirm: true
|
|
715
|
+
})
|
|
716
|
+
```
|
|
717
|
+
|
|
450
718
|
## Error Handling
|
|
451
719
|
|
|
452
720
|
The server will show clear error messages if:
|
|
@@ -455,6 +723,52 @@ The server will show clear error messages if:
|
|
|
455
723
|
- The requested operation fails
|
|
456
724
|
- The provided parameters are invalid
|
|
457
725
|
|
|
726
|
+
## Testing
|
|
727
|
+
|
|
728
|
+
### Unit tests
|
|
729
|
+
|
|
730
|
+
Run the unit test suite (no external dependencies required):
|
|
731
|
+
|
|
732
|
+
```bash
|
|
733
|
+
npm test
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### E2E tests
|
|
737
|
+
|
|
738
|
+
The E2E suite boots an empty Paperless-ngx instance, runs the compiled MCP server, and drives a deterministic serial scenario through `tools/call` requests — creating a tag, correspondent, and document type, uploading a PDF, then exercising list / get / search / download / thumbnail / bulk-edit on the same document. No LLM and no Paperless REST client outside MCP.
|
|
739
|
+
|
|
740
|
+
**Prerequisites:** Docker, Docker Compose, and `jq`.
|
|
741
|
+
|
|
742
|
+
```bash
|
|
743
|
+
# 1. Build the MCP server
|
|
744
|
+
npm run build
|
|
745
|
+
|
|
746
|
+
# 2. Start Paperless-ngx
|
|
747
|
+
docker compose -f docker-compose.e2e.yml up -d
|
|
748
|
+
|
|
749
|
+
# 3. Wait for Paperless to be ready, then get a token
|
|
750
|
+
TOKEN=$(curl -s -X POST http://localhost:8000/api/token/ \
|
|
751
|
+
-H 'Content-Type: application/json' \
|
|
752
|
+
-d '{"username":"admin","password":"admin123"}' | jq -r '.token')
|
|
753
|
+
|
|
754
|
+
# 4. Start the MCP server
|
|
755
|
+
node build/index.js --http --port 3001 \
|
|
756
|
+
--baseUrl http://localhost:8000 --token "$TOKEN" &
|
|
757
|
+
MCP_PID=$!
|
|
758
|
+
|
|
759
|
+
# 5. Run the E2E tests
|
|
760
|
+
MCP_URL=http://localhost:3001/mcp \
|
|
761
|
+
PAPERLESS_URL=http://localhost:8000 \
|
|
762
|
+
PAPERLESS_TOKEN="$TOKEN" \
|
|
763
|
+
npm run test:e2e
|
|
764
|
+
|
|
765
|
+
# 6. Cleanup
|
|
766
|
+
kill "$MCP_PID"
|
|
767
|
+
docker compose -f docker-compose.e2e.yml down -v
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
E2E tests also run automatically in CI on every pull request and push to `main`, covering both the `build/index.js` CLI and the published Docker image.
|
|
771
|
+
|
|
458
772
|
## Development
|
|
459
773
|
|
|
460
774
|
Want to contribute or modify the server? Here's what you need to know:
|
|
@@ -505,19 +819,28 @@ npm run start -- <baseUrl> <token> --http --port 3000
|
|
|
505
819
|
|
|
506
820
|
#### Per-request API token (HTTP/Docker mode)
|
|
507
821
|
|
|
508
|
-
In HTTP mode, clients
|
|
822
|
+
In HTTP mode, clients authenticate by supplying a Paperless-NGX API token via the standard `Authorization` header:
|
|
509
823
|
|
|
510
824
|
```
|
|
511
825
|
Authorization: Bearer <paperless-ngx-api-token>
|
|
512
826
|
```
|
|
513
827
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
828
|
+
The token is passed straight through to Paperless-NGX, so each client's own Paperless permissions are enforced end-to-end. This lets a single server instance serve multiple users, each with their own token. The same behaviour applies to both `/mcp` and `/sse` endpoints.
|
|
829
|
+
|
|
830
|
+
> **⚠️ Breaking change in v2.0.0 — HTTP mode is now authenticated by default.**
|
|
831
|
+
>
|
|
832
|
+
> Previously, a request with no `Authorization` header silently fell back to the server-configured `PAPERLESS_API_KEY`, which left the HTTP endpoint open to anyone who could reach the port. As of v2.0.0, requests without a `Bearer` token are rejected with `401 Unauthorized`. The server token is **never** used for unauthenticated requests unless you explicitly opt in with `--no-auth`.
|
|
833
|
+
|
|
834
|
+
| Scenario | `--no-auth` off (default) | `--no-auth` on |
|
|
835
|
+
|---|---|---|
|
|
836
|
+
| Client sends `Authorization: Bearer <tok>` | `<tok>` (client-supplied) | `<tok>` (client-supplied) |
|
|
837
|
+
| No header, `PAPERLESS_API_KEY` / `--token` set | `401 Unauthorized` | server token |
|
|
838
|
+
| No header, no server token | `401 Unauthorized` | `401 Unauthorized` |
|
|
839
|
+
|
|
840
|
+
**Migrating from v1.x:** if you relied on the old fallback (a single shared `PAPERLESS_API_KEY` with clients that don't send a token), you have two options:
|
|
519
841
|
|
|
520
|
-
|
|
842
|
+
1. **Recommended:** have each client send `Authorization: Bearer <paperless-token>`.
|
|
843
|
+
2. **Restore the old behaviour** (trusted/local networks only): start the server with the `--no-auth` flag, e.g. append it to the Docker `command`/args or your CLI invocation. This requires a server token (`PAPERLESS_API_KEY` or `--token`) to be configured.
|
|
521
844
|
|
|
522
845
|
<details>
|
|
523
846
|
<summary>Docker Deployment</summary>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AxiosResponse } from "axios";
|
|
2
|
-
import { BulkEditDocumentsResult, BulkEditParameters, Correspondent, CustomField, Document, DocumentsResponse, DocumentType, GetCorrespondentsResponse, GetCustomFieldsResponse, GetDocumentTypesResponse, GetTagsResponse, Tag } from "./types";
|
|
2
|
+
import { BulkEditDocumentsResult, BulkEditParameters, Correspondent, CustomField, Document, DocumentsResponse, DocumentType, GetCorrespondentsResponse, GetCustomFieldsResponse, GetDocumentTypesResponse, GetMailAccountsResponse, GetMailRulesResponse, MailAccount, MailRule, GetTagsResponse, Note, Tag } from "./types";
|
|
3
3
|
export declare class PaperlessAPI {
|
|
4
4
|
private readonly baseUrl;
|
|
5
5
|
private readonly token;
|
|
@@ -11,9 +11,28 @@ export declare class PaperlessAPI {
|
|
|
11
11
|
getDocuments(query?: string): Promise<DocumentsResponse>;
|
|
12
12
|
getDocument(id: number): Promise<Document>;
|
|
13
13
|
updateDocument(id: number, data: Partial<Document>): Promise<Document>;
|
|
14
|
-
searchDocuments(query: string): Promise<DocumentsResponse>;
|
|
15
14
|
downloadDocument(id: number, asOriginal?: boolean): Promise<AxiosResponse<ArrayBuffer>>;
|
|
16
15
|
getThumbnail(id: number): Promise<AxiosResponse<ArrayBuffer>>;
|
|
16
|
+
/**
|
|
17
|
+
* Retrieve all notes attached to a document.
|
|
18
|
+
* @param documentId - The document ID.
|
|
19
|
+
* @returns The document's notes.
|
|
20
|
+
*/
|
|
21
|
+
getDocumentNotes(documentId: number): Promise<Note[]>;
|
|
22
|
+
/**
|
|
23
|
+
* Create a note on a document.
|
|
24
|
+
* @param documentId - The document ID.
|
|
25
|
+
* @param note - The note text to add.
|
|
26
|
+
* @returns The document's full notes list after creation.
|
|
27
|
+
*/
|
|
28
|
+
createDocumentNote(documentId: number, note: string): Promise<Note[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Delete a note from a document by its note ID.
|
|
31
|
+
* @param documentId - The document ID.
|
|
32
|
+
* @param noteId - The ID of the note to delete.
|
|
33
|
+
* @returns The document's remaining notes after deletion.
|
|
34
|
+
*/
|
|
35
|
+
deleteDocumentNote(documentId: number, noteId: number): Promise<Note[]>;
|
|
17
36
|
getTags(): Promise<GetTagsResponse>;
|
|
18
37
|
createTag(data: Partial<Tag>): Promise<Tag>;
|
|
19
38
|
updateTag(id: number, data: Partial<Tag>): Promise<Tag>;
|
|
@@ -27,6 +46,14 @@ export declare class PaperlessAPI {
|
|
|
27
46
|
createDocumentType(data: Partial<DocumentType>): Promise<DocumentType>;
|
|
28
47
|
updateDocumentType(id: number, data: Partial<DocumentType>): Promise<DocumentType>;
|
|
29
48
|
deleteDocumentType(id: number): Promise<void>;
|
|
49
|
+
getMailAccounts(queryString?: string): Promise<GetMailAccountsResponse>;
|
|
50
|
+
getMailAccount(id: number): Promise<MailAccount>;
|
|
51
|
+
processMailAccount(id: number): Promise<void>;
|
|
52
|
+
getMailRules(queryString?: string): Promise<GetMailRulesResponse>;
|
|
53
|
+
getMailRule(id: number): Promise<MailRule>;
|
|
54
|
+
createMailRule(data: Partial<MailRule>): Promise<MailRule>;
|
|
55
|
+
updateMailRule(id: number, data: Partial<MailRule>): Promise<MailRule>;
|
|
56
|
+
deleteMailRule(id: number): Promise<void>;
|
|
30
57
|
getCustomFields(): Promise<GetCustomFieldsResponse>;
|
|
31
58
|
getCustomField(id: number): Promise<CustomField>;
|
|
32
59
|
createCustomField(data: Partial<CustomField>): Promise<CustomField>;
|
|
@@ -42,7 +42,7 @@ class PaperlessAPI {
|
|
|
42
42
|
console.error({
|
|
43
43
|
error: "Error executing request",
|
|
44
44
|
url,
|
|
45
|
-
options,
|
|
45
|
+
method: options.method || "GET",
|
|
46
46
|
status: response.status,
|
|
47
47
|
response: body,
|
|
48
48
|
});
|
|
@@ -63,7 +63,7 @@ class PaperlessAPI {
|
|
|
63
63
|
error: "Error executing request",
|
|
64
64
|
message: error instanceof Error ? error.message : String(error),
|
|
65
65
|
url,
|
|
66
|
-
options,
|
|
66
|
+
method: options.method || "GET",
|
|
67
67
|
responseData: axios_1.default.isAxiosError(error) ? (_b = error.response) === null || _b === void 0 ? void 0 : _b.data : undefined,
|
|
68
68
|
status: axios_1.default.isAxiosError(error) ? (_c = error.response) === null || _c === void 0 ? void 0 : _c.status : undefined,
|
|
69
69
|
});
|
|
@@ -145,12 +145,6 @@ class PaperlessAPI {
|
|
|
145
145
|
});
|
|
146
146
|
});
|
|
147
147
|
}
|
|
148
|
-
searchDocuments(query) {
|
|
149
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
150
|
-
const response = yield this.request(`/documents/?query=${encodeURIComponent(query)}`);
|
|
151
|
-
return response;
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
148
|
downloadDocument(id_1) {
|
|
155
149
|
return __awaiter(this, arguments, void 0, function* (id, asOriginal = false) {
|
|
156
150
|
const query = asOriginal ? "?original=true" : "";
|
|
@@ -174,6 +168,44 @@ class PaperlessAPI {
|
|
|
174
168
|
return response;
|
|
175
169
|
});
|
|
176
170
|
}
|
|
171
|
+
// Document note operations
|
|
172
|
+
/**
|
|
173
|
+
* Retrieve all notes attached to a document.
|
|
174
|
+
* @param documentId - The document ID.
|
|
175
|
+
* @returns The document's notes.
|
|
176
|
+
*/
|
|
177
|
+
getDocumentNotes(documentId) {
|
|
178
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
179
|
+
return this.request(`/documents/${documentId}/notes/`);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Create a note on a document.
|
|
184
|
+
* @param documentId - The document ID.
|
|
185
|
+
* @param note - The note text to add.
|
|
186
|
+
* @returns The document's full notes list after creation.
|
|
187
|
+
*/
|
|
188
|
+
createDocumentNote(documentId, note) {
|
|
189
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
190
|
+
return this.request(`/documents/${documentId}/notes/`, {
|
|
191
|
+
method: "POST",
|
|
192
|
+
body: JSON.stringify({ note }),
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Delete a note from a document by its note ID.
|
|
198
|
+
* @param documentId - The document ID.
|
|
199
|
+
* @param noteId - The ID of the note to delete.
|
|
200
|
+
* @returns The document's remaining notes after deletion.
|
|
201
|
+
*/
|
|
202
|
+
deleteDocumentNote(documentId, noteId) {
|
|
203
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
204
|
+
return this.request(`/documents/${documentId}/notes/?id=${noteId}`, {
|
|
205
|
+
method: "DELETE",
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
}
|
|
177
209
|
// Tag operations
|
|
178
210
|
getTags() {
|
|
179
211
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -269,6 +301,63 @@ class PaperlessAPI {
|
|
|
269
301
|
});
|
|
270
302
|
});
|
|
271
303
|
}
|
|
304
|
+
// Mail account operations
|
|
305
|
+
getMailAccounts(queryString) {
|
|
306
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
307
|
+
const url = queryString
|
|
308
|
+
? `/mail_accounts/?${queryString}`
|
|
309
|
+
: "/mail_accounts/";
|
|
310
|
+
return this.request(url);
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
getMailAccount(id) {
|
|
314
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
315
|
+
return this.request(`/mail_accounts/${id}/`);
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
processMailAccount(id) {
|
|
319
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
320
|
+
return this.request(`/mail_accounts/${id}/process/`, {
|
|
321
|
+
method: "POST",
|
|
322
|
+
body: JSON.stringify({}),
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
// Mail rule operations
|
|
327
|
+
getMailRules(queryString) {
|
|
328
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
329
|
+
const url = queryString ? `/mail_rules/?${queryString}` : "/mail_rules/";
|
|
330
|
+
return this.request(url);
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
getMailRule(id) {
|
|
334
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
335
|
+
return this.request(`/mail_rules/${id}/`);
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
createMailRule(data) {
|
|
339
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
340
|
+
return this.request("/mail_rules/", {
|
|
341
|
+
method: "POST",
|
|
342
|
+
body: JSON.stringify(data),
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
updateMailRule(id, data) {
|
|
347
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
348
|
+
return this.request(`/mail_rules/${id}/`, {
|
|
349
|
+
method: "PATCH",
|
|
350
|
+
body: JSON.stringify(data),
|
|
351
|
+
});
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
deleteMailRule(id) {
|
|
355
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
356
|
+
return this.request(`/mail_rules/${id}/`, {
|
|
357
|
+
method: "DELETE",
|
|
358
|
+
});
|
|
359
|
+
});
|
|
360
|
+
}
|
|
272
361
|
// Custom field operations
|
|
273
362
|
getCustomFields() {
|
|
274
363
|
return __awaiter(this, void 0, void 0, function* () {
|
package/build/api/types.d.ts
CHANGED
|
@@ -125,6 +125,53 @@ export interface DocumentType {
|
|
|
125
125
|
}
|
|
126
126
|
export interface GetDocumentTypesResponse extends PaginationResponse<DocumentType> {
|
|
127
127
|
}
|
|
128
|
+
export interface MailAccount {
|
|
129
|
+
id: number;
|
|
130
|
+
name: string;
|
|
131
|
+
imap_server: string;
|
|
132
|
+
imap_port: number | null;
|
|
133
|
+
imap_security: number;
|
|
134
|
+
username: string;
|
|
135
|
+
password?: string;
|
|
136
|
+
character_set: string;
|
|
137
|
+
is_token: boolean;
|
|
138
|
+
owner: number | null;
|
|
139
|
+
user_can_change: boolean;
|
|
140
|
+
account_type: number;
|
|
141
|
+
expiration: string | null;
|
|
142
|
+
}
|
|
143
|
+
export interface GetMailAccountsResponse extends PaginationResponse<MailAccount> {
|
|
144
|
+
}
|
|
145
|
+
export interface MailRule {
|
|
146
|
+
id: number;
|
|
147
|
+
name: string;
|
|
148
|
+
account: number;
|
|
149
|
+
enabled: boolean;
|
|
150
|
+
folder: string;
|
|
151
|
+
filter_from: string | null;
|
|
152
|
+
filter_to: string | null;
|
|
153
|
+
filter_subject: string | null;
|
|
154
|
+
filter_body: string | null;
|
|
155
|
+
filter_attachment_filename_include: string | null;
|
|
156
|
+
filter_attachment_filename_exclude: string | null;
|
|
157
|
+
maximum_age: number;
|
|
158
|
+
action: number;
|
|
159
|
+
action_parameter: string | null;
|
|
160
|
+
assign_title_from: number;
|
|
161
|
+
assign_tags: Array<number | null>;
|
|
162
|
+
assign_correspondent_from: number;
|
|
163
|
+
assign_correspondent: number | null;
|
|
164
|
+
assign_document_type: number | null;
|
|
165
|
+
assign_owner_from_rule: boolean;
|
|
166
|
+
order: number;
|
|
167
|
+
attachment_type: number;
|
|
168
|
+
consumption_scope: number;
|
|
169
|
+
pdf_layout: number;
|
|
170
|
+
owner: number | null;
|
|
171
|
+
user_can_change: boolean;
|
|
172
|
+
}
|
|
173
|
+
export interface GetMailRulesResponse extends PaginationResponse<MailRule> {
|
|
174
|
+
}
|
|
128
175
|
export interface BulkEditDocumentsResult {
|
|
129
176
|
result: string;
|
|
130
177
|
}
|