@orellbuehler/paperless-mcp 1.0.1 → 1.1.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 +3 -1
- package/dist/paperless/format.js +1 -4
- package/dist/tools/core.js +59 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ This fetches `GET /api/schema/` and overwrites `paperless-openapi.yaml`. Run it
|
|
|
96
96
|
| Search | `search_documents`, `search_autocomplete` |
|
|
97
97
|
| Documents | `list_documents`, `get_document`, `get_documents`, `download_document`, `update_document`, `delete_document`, `upload_document` |
|
|
98
98
|
| Document details | `get_document_metadata`, `get_document_suggestions`, `get_document_notes`, `add_document_note`, `delete_document_note` |
|
|
99
|
-
| Bulk operations | `bulk_edit_documents`, `get_next_asn`
|
|
99
|
+
| Bulk operations | `bulk_edit_documents`, `bulk_set_object_permissions`, `get_next_asn` |
|
|
100
100
|
| Correspondents | `list_correspondents`, `get_correspondent`, `create_correspondent`, `update_correspondent`, `delete_correspondent` |
|
|
101
101
|
| Document types | `list_document_types`, `get_document_type`, `create_document_type`, `update_document_type`, `delete_document_type` |
|
|
102
102
|
| Tags | `list_tags`, `get_tag`, `create_tag`, `update_tag`, `delete_tag` |
|
|
@@ -111,6 +111,8 @@ This fetches `GET /api/schema/` and overwrites `paperless-openapi.yaml`. Run it
|
|
|
111
111
|
> **Note:** `list_documents` and `search_documents` return document metadata only (no OCR text) to keep responses small. Use `get_document` (single) or `get_documents` (batch) to retrieve full content.
|
|
112
112
|
>
|
|
113
113
|
> Saved views, users/groups, and workflows support read + create + update only — no delete tools (use the Paperless web UI to delete). User management covers accounts and group membership; it does not set per-document permissions. Notes support add and delete only (no edit), so there is no note-editing tool.
|
|
114
|
+
>
|
|
115
|
+
> The `update_*` tools for tags, correspondents, document types, storage paths, saved views, and custom fields accept `owner` and `set_permissions` (`{ view, change }` → `{ users, groups }`) to share objects. `bulk_set_object_permissions` sets owner/permissions on many tags, correspondents, document types, or storage paths in one call (saved views and custom fields are not supported by the bulk endpoint — share those individually).
|
|
114
116
|
|
|
115
117
|
### Extended Tools
|
|
116
118
|
|
package/dist/paperless/format.js
CHANGED
|
@@ -6,10 +6,7 @@ export function buildQS(params) {
|
|
|
6
6
|
if (Array.isArray(v)) {
|
|
7
7
|
if (v.length === 0)
|
|
8
8
|
continue;
|
|
9
|
-
|
|
10
|
-
sp.set(k, v.join(","));
|
|
11
|
-
else
|
|
12
|
-
v.forEach((item) => sp.append(k, String(item)));
|
|
9
|
+
sp.set(k, v.join(","));
|
|
13
10
|
}
|
|
14
11
|
else {
|
|
15
12
|
sp.set(k, String(v));
|
package/dist/tools/core.js
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
import { readFile } from "node:fs/promises";
|
|
3
3
|
import { buildQS, ok, err, summarizeDocs } from "../paperless/format.js";
|
|
4
|
+
const permissionGrant = z.object({
|
|
5
|
+
users: z.array(z.number()).optional().describe("User IDs"),
|
|
6
|
+
groups: z.array(z.number()).optional().describe("Group IDs"),
|
|
7
|
+
});
|
|
8
|
+
const permissionMap = z.object({
|
|
9
|
+
view: permissionGrant.optional(),
|
|
10
|
+
change: permissionGrant.optional(),
|
|
11
|
+
});
|
|
12
|
+
const ownerField = z
|
|
13
|
+
.number()
|
|
14
|
+
.nullable()
|
|
15
|
+
.optional()
|
|
16
|
+
.describe("Owner user ID, or null to make it unowned (visible to everyone)");
|
|
17
|
+
const setPermissionsField = permissionMap
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Grant view (read) and change (edit) access to users and groups");
|
|
4
20
|
export function registerCoreTools(server, client) {
|
|
5
21
|
// --- System ---
|
|
6
22
|
server.tool("get_status", "Get Paperless-ngx server status", {}, async () => {
|
|
@@ -243,6 +259,37 @@ export function registerCoreTools(server, client) {
|
|
|
243
259
|
return err(e);
|
|
244
260
|
}
|
|
245
261
|
});
|
|
262
|
+
server.tool("bulk_set_object_permissions", "Set owner and/or view/change permissions on many tags, correspondents, document types or storage paths at once (e.g. share a whole taxonomy with a household group). Saved views and custom fields are not supported here — update those individually with set_permissions.", {
|
|
263
|
+
object_type: z.enum(["tags", "correspondents", "document_types", "storage_paths"]),
|
|
264
|
+
objects: z.array(z.number()).describe("IDs of the objects to update"),
|
|
265
|
+
owner: ownerField,
|
|
266
|
+
permissions: setPermissionsField,
|
|
267
|
+
merge: z
|
|
268
|
+
.boolean()
|
|
269
|
+
.optional()
|
|
270
|
+
.describe("Merge with existing permissions instead of replacing them (default false)"),
|
|
271
|
+
}, async ({ object_type, objects, owner, permissions, merge }) => {
|
|
272
|
+
try {
|
|
273
|
+
const body = {
|
|
274
|
+
objects,
|
|
275
|
+
object_type,
|
|
276
|
+
operation: "set_permissions",
|
|
277
|
+
};
|
|
278
|
+
if (owner !== undefined)
|
|
279
|
+
body.owner = owner;
|
|
280
|
+
if (permissions !== undefined)
|
|
281
|
+
body.permissions = permissions;
|
|
282
|
+
if (merge !== undefined)
|
|
283
|
+
body.merge = merge;
|
|
284
|
+
return ok(await client.fetch("/api/bulk_edit_objects/", {
|
|
285
|
+
method: "POST",
|
|
286
|
+
body: JSON.stringify(body),
|
|
287
|
+
}));
|
|
288
|
+
}
|
|
289
|
+
catch (e) {
|
|
290
|
+
return err(e);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
246
293
|
server.tool("get_next_asn", "Get the next available archive serial number", {}, async () => {
|
|
247
294
|
try {
|
|
248
295
|
return ok(await client.fetch("/api/documents/next_asn/"));
|
|
@@ -301,6 +348,8 @@ export function registerCoreTools(server, client) {
|
|
|
301
348
|
.optional()
|
|
302
349
|
.describe("1=any, 2=all, 3=literal, 4=regex, 5=fuzzy, 6=auto"),
|
|
303
350
|
is_insensitive: z.boolean().optional(),
|
|
351
|
+
owner: ownerField,
|
|
352
|
+
set_permissions: setPermissionsField,
|
|
304
353
|
}, async ({ id, ...body }) => {
|
|
305
354
|
try {
|
|
306
355
|
return ok(await client.fetch(`/api/correspondents/${id}/`, {
|
|
@@ -370,6 +419,8 @@ export function registerCoreTools(server, client) {
|
|
|
370
419
|
.optional()
|
|
371
420
|
.describe("1=any, 2=all, 3=literal, 4=regex, 5=fuzzy, 6=auto"),
|
|
372
421
|
is_insensitive: z.boolean().optional(),
|
|
422
|
+
owner: ownerField,
|
|
423
|
+
set_permissions: setPermissionsField,
|
|
373
424
|
}, async ({ id, ...body }) => {
|
|
374
425
|
try {
|
|
375
426
|
return ok(await client.fetch(`/api/document_types/${id}/`, {
|
|
@@ -444,6 +495,8 @@ export function registerCoreTools(server, client) {
|
|
|
444
495
|
.optional()
|
|
445
496
|
.describe("1=any, 2=all, 3=literal, 4=regex, 5=fuzzy, 6=auto"),
|
|
446
497
|
is_insensitive: z.boolean().optional(),
|
|
498
|
+
owner: ownerField,
|
|
499
|
+
set_permissions: setPermissionsField,
|
|
447
500
|
}, async ({ id, ...body }) => {
|
|
448
501
|
try {
|
|
449
502
|
return ok(await client.fetch(`/api/tags/${id}/`, {
|
|
@@ -513,6 +566,8 @@ export function registerCoreTools(server, client) {
|
|
|
513
566
|
sort_field: z.string().optional(),
|
|
514
567
|
sort_reverse: z.boolean().optional(),
|
|
515
568
|
page_size: z.number().optional(),
|
|
569
|
+
owner: ownerField,
|
|
570
|
+
set_permissions: setPermissionsField,
|
|
516
571
|
}, async ({ id, ...body }) => {
|
|
517
572
|
try {
|
|
518
573
|
return ok(await client.fetch(`/api/saved_views/${id}/`, {
|
|
@@ -575,6 +630,8 @@ export function registerCoreTools(server, client) {
|
|
|
575
630
|
.optional()
|
|
576
631
|
.describe("1=any, 2=all, 3=literal, 4=regex, 5=fuzzy, 6=auto"),
|
|
577
632
|
is_insensitive: z.boolean().optional(),
|
|
633
|
+
owner: ownerField,
|
|
634
|
+
set_permissions: setPermissionsField,
|
|
578
635
|
}, async ({ id, ...body }) => {
|
|
579
636
|
try {
|
|
580
637
|
return ok(await client.fetch(`/api/storage_paths/${id}/`, {
|
|
@@ -640,6 +697,8 @@ export function registerCoreTools(server, client) {
|
|
|
640
697
|
id: z.number(),
|
|
641
698
|
name: z.string().optional(),
|
|
642
699
|
extra_data: z.record(z.unknown()).optional(),
|
|
700
|
+
owner: ownerField,
|
|
701
|
+
set_permissions: setPermissionsField,
|
|
643
702
|
}, async ({ id, ...body }) => {
|
|
644
703
|
try {
|
|
645
704
|
return ok(await client.fetch(`/api/custom_fields/${id}/`, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orellbuehler/paperless-mcp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "Model Context Protocol server for Paperless-ngx: documents, organization, saved views, users, workflows, and optional semantic search.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|