@baruchiro/paperless-mcp 2.1.0 → 2.2.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/build/api/PaperlessAPI.d.ts +1 -1
- package/build/api/types.d.ts +2 -2
- package/build/tools/correspondents.js +3 -15
- package/build/tools/customFields.js +3 -3
- package/build/tools/documentTypes.js +4 -16
- package/build/tools/documents.js +6 -1
- package/build/tools/documents.test.js +17 -0
- package/build/tools/mail.js +6 -6
- package/build/tools/schemaCompat.test.d.ts +1 -0
- package/build/tools/schemaCompat.test.js +59 -0
- package/build/tools/tags.js +4 -16
- package/build/tools/utils/documentQuery.d.ts +4 -4
- package/build/tools/utils/documentQuery.js +1 -1
- package/build/tools/utils/matchingAlgorithm.d.ts +2 -0
- package/build/tools/utils/matchingAlgorithm.js +15 -0
- package/package.json +3 -3
- package/paperless-mcp.dxt +0 -0
|
@@ -7,7 +7,7 @@ export declare class PaperlessAPI {
|
|
|
7
7
|
constructor(baseUrl: string, token: string);
|
|
8
8
|
request<T = any>(path: string, options?: RequestInit): Promise<T>;
|
|
9
9
|
bulkEditDocuments(documents: number[], method: string, parameters?: BulkEditParameters): Promise<BulkEditDocumentsResult>;
|
|
10
|
-
postDocument(document: Buffer, filename: string, metadata?: Record<string, string | string[] | number | number[]>): Promise<string>;
|
|
10
|
+
postDocument(document: Buffer, filename: string, metadata?: Record<string, string | string[] | number | number[] | undefined>): Promise<string>;
|
|
11
11
|
getDocuments(query?: string): Promise<DocumentsResponse>;
|
|
12
12
|
getDocument(id: number): Promise<Document>;
|
|
13
13
|
updateDocument(id: number, data: Partial<Document>): Promise<Document>;
|
package/build/api/types.d.ts
CHANGED
|
@@ -68,7 +68,7 @@ export interface Document {
|
|
|
68
68
|
id: number;
|
|
69
69
|
correspondent: number | null;
|
|
70
70
|
document_type: number | null;
|
|
71
|
-
storage_path:
|
|
71
|
+
storage_path: number | null;
|
|
72
72
|
title: string;
|
|
73
73
|
content: string | null;
|
|
74
74
|
tags: number[];
|
|
@@ -77,7 +77,7 @@ export interface Document {
|
|
|
77
77
|
modified: string;
|
|
78
78
|
added: string;
|
|
79
79
|
deleted_at: string | null;
|
|
80
|
-
archive_serial_number:
|
|
80
|
+
archive_serial_number: number | null;
|
|
81
81
|
original_file_name: string;
|
|
82
82
|
archived_file_name: string;
|
|
83
83
|
owner: number | null;
|
|
@@ -22,8 +22,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.registerCorrespondentTools = registerCorrespondentTools;
|
|
24
24
|
const zod_1 = require("zod");
|
|
25
|
-
const types_1 = require("../api/types");
|
|
26
25
|
const utils_1 = require("../api/utils");
|
|
26
|
+
const matchingAlgorithm_1 = require("./utils/matchingAlgorithm");
|
|
27
27
|
const middlewares_1 = require("./utils/middlewares");
|
|
28
28
|
const queryString_1 = require("./utils/queryString");
|
|
29
29
|
function registerCorrespondentTools(server, api) {
|
|
@@ -64,13 +64,7 @@ function registerCorrespondentTools(server, api) {
|
|
|
64
64
|
server.tool("create_correspondent", "Create a new correspondent with optional matching pattern and algorithm for automatic document assignment.", {
|
|
65
65
|
name: zod_1.z.string(),
|
|
66
66
|
match: zod_1.z.string().optional(),
|
|
67
|
-
matching_algorithm:
|
|
68
|
-
.number()
|
|
69
|
-
.int()
|
|
70
|
-
.min(0)
|
|
71
|
-
.max(6)
|
|
72
|
-
.optional()
|
|
73
|
-
.describe(types_1.MATCHING_ALGORITHM_DESCRIPTION),
|
|
67
|
+
matching_algorithm: matchingAlgorithm_1.matchingAlgorithmSchema.optional(),
|
|
74
68
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
75
69
|
if (!api)
|
|
76
70
|
throw new Error("Please configure API connection first");
|
|
@@ -86,13 +80,7 @@ function registerCorrespondentTools(server, api) {
|
|
|
86
80
|
id: zod_1.z.number(),
|
|
87
81
|
name: zod_1.z.string(),
|
|
88
82
|
match: zod_1.z.string().optional(),
|
|
89
|
-
matching_algorithm:
|
|
90
|
-
.number()
|
|
91
|
-
.int()
|
|
92
|
-
.min(0)
|
|
93
|
-
.max(6)
|
|
94
|
-
.optional()
|
|
95
|
-
.describe(types_1.MATCHING_ALGORITHM_DESCRIPTION),
|
|
83
|
+
matching_algorithm: matchingAlgorithm_1.matchingAlgorithmSchema.optional(),
|
|
96
84
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
97
85
|
if (!api)
|
|
98
86
|
throw new Error("Please configure API connection first");
|
|
@@ -33,7 +33,7 @@ function registerCustomFieldTools(server, api) {
|
|
|
33
33
|
name__iexact: zod_1.z.string().optional(),
|
|
34
34
|
name__istartswith: zod_1.z.string().optional(),
|
|
35
35
|
ordering: zod_1.z.string().optional(),
|
|
36
|
-
}, (0, middlewares_1.withErrorHandling)((
|
|
36
|
+
}, (0, middlewares_1.withErrorHandling)((args) => __awaiter(this, void 0, void 0, function* () {
|
|
37
37
|
if (!api)
|
|
38
38
|
throw new Error("Please configure API connection first");
|
|
39
39
|
const queryString = (0, queryString_1.buildQueryString)(args);
|
|
@@ -68,7 +68,7 @@ function registerCustomFieldTools(server, api) {
|
|
|
68
68
|
"documentlink",
|
|
69
69
|
"select",
|
|
70
70
|
]),
|
|
71
|
-
extra_data: zod_1.z.record(zod_1.z.unknown()).nullable().optional(),
|
|
71
|
+
extra_data: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).nullable().optional(),
|
|
72
72
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
73
73
|
if (!api)
|
|
74
74
|
throw new Error("Please configure API connection first");
|
|
@@ -93,7 +93,7 @@ function registerCustomFieldTools(server, api) {
|
|
|
93
93
|
"select",
|
|
94
94
|
])
|
|
95
95
|
.optional(),
|
|
96
|
-
extra_data: zod_1.z.record(zod_1.z.unknown()).nullable().optional(),
|
|
96
|
+
extra_data: zod_1.z.record(zod_1.z.string(), zod_1.z.unknown()).nullable().optional(),
|
|
97
97
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
98
98
|
if (!api)
|
|
99
99
|
throw new Error("Please configure API connection first");
|
|
@@ -22,8 +22,8 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.registerDocumentTypeTools = registerDocumentTypeTools;
|
|
24
24
|
const zod_1 = require("zod");
|
|
25
|
-
const types_1 = require("../api/types");
|
|
26
25
|
const utils_1 = require("../api/utils");
|
|
26
|
+
const matchingAlgorithm_1 = require("./utils/matchingAlgorithm");
|
|
27
27
|
const middlewares_1 = require("./utils/middlewares");
|
|
28
28
|
const queryString_1 = require("./utils/queryString");
|
|
29
29
|
function registerDocumentTypeTools(server, api) {
|
|
@@ -35,7 +35,7 @@ function registerDocumentTypeTools(server, api) {
|
|
|
35
35
|
name__iexact: zod_1.z.string().optional(),
|
|
36
36
|
name__istartswith: zod_1.z.string().optional(),
|
|
37
37
|
ordering: zod_1.z.string().optional(),
|
|
38
|
-
}, (0, middlewares_1.withErrorHandling)((
|
|
38
|
+
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
39
39
|
if (!api)
|
|
40
40
|
throw new Error("Please configure API connection first");
|
|
41
41
|
const queryString = (0, queryString_1.buildQueryString)(args);
|
|
@@ -62,13 +62,7 @@ function registerDocumentTypeTools(server, api) {
|
|
|
62
62
|
server.tool("create_document_type", "Create a new document type with optional matching pattern and algorithm for automatic document classification.", {
|
|
63
63
|
name: zod_1.z.string(),
|
|
64
64
|
match: zod_1.z.string().optional(),
|
|
65
|
-
matching_algorithm:
|
|
66
|
-
.number()
|
|
67
|
-
.int()
|
|
68
|
-
.min(0)
|
|
69
|
-
.max(6)
|
|
70
|
-
.optional()
|
|
71
|
-
.describe(types_1.MATCHING_ALGORITHM_DESCRIPTION),
|
|
65
|
+
matching_algorithm: matchingAlgorithm_1.matchingAlgorithmSchema.optional(),
|
|
72
66
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
73
67
|
if (!api)
|
|
74
68
|
throw new Error("Please configure API connection first");
|
|
@@ -82,13 +76,7 @@ function registerDocumentTypeTools(server, api) {
|
|
|
82
76
|
id: zod_1.z.number(),
|
|
83
77
|
name: zod_1.z.string(),
|
|
84
78
|
match: zod_1.z.string().optional(),
|
|
85
|
-
matching_algorithm:
|
|
86
|
-
.number()
|
|
87
|
-
.int()
|
|
88
|
-
.min(0)
|
|
89
|
-
.max(6)
|
|
90
|
-
.optional()
|
|
91
|
-
.describe(types_1.MATCHING_ALGORITHM_DESCRIPTION),
|
|
79
|
+
matching_algorithm: matchingAlgorithm_1.matchingAlgorithmSchema.optional(),
|
|
92
80
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
93
81
|
if (!api)
|
|
94
82
|
throw new Error("Please configure API connection first");
|
package/build/tools/documents.js
CHANGED
|
@@ -188,6 +188,7 @@ function registerDocumentTools(server, api) {
|
|
|
188
188
|
.describe("For set_permissions: view/change permissions to apply. Omitted actions (view/change) and omitted users/groups lists are left untouched; an empty list [] removes all (unless merge is true). Omit entirely for owner-only changes."),
|
|
189
189
|
owner: zod_1.z
|
|
190
190
|
.number()
|
|
191
|
+
.int()
|
|
191
192
|
.nullable()
|
|
192
193
|
.optional()
|
|
193
194
|
.describe("For set_permissions: new owner user ID, or null to remove the owner. Unless merge is true, omitting owner also clears the current owner."),
|
|
@@ -295,7 +296,7 @@ function registerDocumentTools(server, api) {
|
|
|
295
296
|
throw new Error("Please configure API connection first");
|
|
296
297
|
const validationResult = postDocumentSchema.safeParse(args);
|
|
297
298
|
if (!validationResult.success) {
|
|
298
|
-
throw new Error(validationResult.error.
|
|
299
|
+
throw new Error(validationResult.error.issues.map(e => e.message).join("; "));
|
|
299
300
|
}
|
|
300
301
|
let document;
|
|
301
302
|
let filename;
|
|
@@ -451,16 +452,19 @@ function registerDocumentTools(server, api) {
|
|
|
451
452
|
.describe("The new title for the document (max 128 characters)"),
|
|
452
453
|
correspondent: zod_1.z
|
|
453
454
|
.number()
|
|
455
|
+
.int()
|
|
454
456
|
.nullable()
|
|
455
457
|
.optional()
|
|
456
458
|
.describe("The ID of the correspondent to assign"),
|
|
457
459
|
document_type: zod_1.z
|
|
458
460
|
.number()
|
|
461
|
+
.int()
|
|
459
462
|
.nullable()
|
|
460
463
|
.optional()
|
|
461
464
|
.describe("The ID of the document type to assign"),
|
|
462
465
|
storage_path: zod_1.z
|
|
463
466
|
.number()
|
|
467
|
+
.int()
|
|
464
468
|
.nullable()
|
|
465
469
|
.optional()
|
|
466
470
|
.describe("The ID of the storage path to assign"),
|
|
@@ -482,6 +486,7 @@ function registerDocumentTools(server, api) {
|
|
|
482
486
|
.describe("The archive serial number (0-4294967295)"),
|
|
483
487
|
owner: zod_1.z
|
|
484
488
|
.number()
|
|
489
|
+
.int()
|
|
485
490
|
.nullable()
|
|
486
491
|
.optional()
|
|
487
492
|
.describe("The ID of the user who owns the document"),
|
|
@@ -639,3 +639,20 @@ const OBJECT_SELECT_FIELD = {
|
|
|
639
639
|
strict_1.default.equal(calls.bulkEditDocuments.length, 0);
|
|
640
640
|
}));
|
|
641
641
|
});
|
|
642
|
+
(0, node_test_1.describe)("nullable foreign keys can still be cleared (#138)", () => {
|
|
643
|
+
(0, node_test_1.test)("update_document forwards an explicit null so a foreign key can be cleared", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
644
|
+
const { api, calls } = createDocumentApi([]);
|
|
645
|
+
yield withDocumentClient(api, (client) => __awaiter(void 0, void 0, void 0, function* () {
|
|
646
|
+
var _a;
|
|
647
|
+
const result = (yield client.callTool({
|
|
648
|
+
name: "update_document",
|
|
649
|
+
arguments: { id: 42, correspondent: null, owner: null },
|
|
650
|
+
}));
|
|
651
|
+
strict_1.default.ok(!result.isError, (_a = parseToolText(result)) === null || _a === void 0 ? void 0 : _a.error);
|
|
652
|
+
}));
|
|
653
|
+
strict_1.default.equal(calls.updateDocument.length, 1);
|
|
654
|
+
const [, data] = calls.updateDocument[0];
|
|
655
|
+
strict_1.default.equal(data.correspondent, null);
|
|
656
|
+
strict_1.default.equal(data.owner, null);
|
|
657
|
+
}));
|
|
658
|
+
});
|
package/build/tools/mail.js
CHANGED
|
@@ -35,10 +35,10 @@ const mailRuleFields = {
|
|
|
35
35
|
account: zod_1.z.number().int().optional(),
|
|
36
36
|
enabled: zod_1.z.boolean().optional(),
|
|
37
37
|
folder: zod_1.z.string().optional(),
|
|
38
|
-
filter_from: zod_1.z.string().nullable().optional(),
|
|
39
|
-
filter_to: zod_1.z.string().nullable().optional(),
|
|
40
|
-
filter_subject: zod_1.z.string().nullable().optional(),
|
|
41
|
-
filter_body: zod_1.z.string().nullable().optional(),
|
|
38
|
+
filter_from: zod_1.z.string().max(256).nullable().optional(),
|
|
39
|
+
filter_to: zod_1.z.string().max(256).nullable().optional(),
|
|
40
|
+
filter_subject: zod_1.z.string().max(256).nullable().optional(),
|
|
41
|
+
filter_body: zod_1.z.string().max(256).nullable().optional(),
|
|
42
42
|
filter_attachment_filename_include: zod_1.z.string().nullable().optional(),
|
|
43
43
|
filter_attachment_filename_exclude: zod_1.z.string().nullable().optional(),
|
|
44
44
|
maximum_age: zod_1.z.number().int().min(0).optional(),
|
|
@@ -96,7 +96,7 @@ function registerMailTools(server, api) {
|
|
|
96
96
|
server.tool("list_mail_accounts", "List Paperless mail accounts for selecting the account ID needed by mail rules. Does not expose account passwords.", {
|
|
97
97
|
page: zod_1.z.number().optional(),
|
|
98
98
|
page_size: zod_1.z.number().optional(),
|
|
99
|
-
}, (0, middlewares_1.withErrorHandling)((
|
|
99
|
+
}, (0, middlewares_1.withErrorHandling)((args) => __awaiter(this, void 0, void 0, function* () {
|
|
100
100
|
if (!api)
|
|
101
101
|
throw new Error("Please configure API connection first");
|
|
102
102
|
const queryString = (0, queryString_1.buildQueryString)(args);
|
|
@@ -132,7 +132,7 @@ function registerMailTools(server, api) {
|
|
|
132
132
|
server.tool("list_mail_rules", "List Paperless mail rules with optional pagination.", {
|
|
133
133
|
page: zod_1.z.number().optional(),
|
|
134
134
|
page_size: zod_1.z.number().optional(),
|
|
135
|
-
}, (0, middlewares_1.withErrorHandling)((
|
|
135
|
+
}, (0, middlewares_1.withErrorHandling)((args) => __awaiter(this, void 0, void 0, function* () {
|
|
136
136
|
if (!api)
|
|
137
137
|
throw new Error("Please configure API connection first");
|
|
138
138
|
const queryString = (0, queryString_1.buildQueryString)(args);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
16
|
+
const node_test_1 = require("node:test");
|
|
17
|
+
const index_js_1 = require("@modelcontextprotocol/sdk/client/index.js");
|
|
18
|
+
const inMemory_js_1 = require("@modelcontextprotocol/sdk/inMemory.js");
|
|
19
|
+
const server_1 = require("../server");
|
|
20
|
+
// Strict MCP clients and gateways reject an array-valued `type` and silently drop
|
|
21
|
+
// the whole tool (#138). A JSON Schema converter reaches that form by collapsing a
|
|
22
|
+
// union of unchecked primitives: `zod-to-json-schema` (the zod v3 path) always does
|
|
23
|
+
// it, and zod's own converter did it again from 4.5.0 on. The tools are only free
|
|
24
|
+
// of it because the server is on the zod v4 path with zod pinned to 4.4.x, so this
|
|
25
|
+
// walks every advertised schema rather than a field list: bumping that pin, moving
|
|
26
|
+
// off zod v4, or adding a construct that reintroduces the form fails here.
|
|
27
|
+
function arrayFormTypes(node, path = "") {
|
|
28
|
+
if (Array.isArray(node)) {
|
|
29
|
+
return node.flatMap((item, i) => arrayFormTypes(item, `${path}[${i}]`));
|
|
30
|
+
}
|
|
31
|
+
if (!node || typeof node !== "object") {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
return Object.entries(node).flatMap(([key, value]) => key === "type" && Array.isArray(value)
|
|
35
|
+
? [`${path}.type = ${JSON.stringify(value)}`]
|
|
36
|
+
: arrayFormTypes(value, `${path}.${key}`));
|
|
37
|
+
}
|
|
38
|
+
(0, node_test_1.test)("no tool advertises an array-form `type` (#138)", () => __awaiter(void 0, void 0, void 0, function* () {
|
|
39
|
+
const server = (0, server_1.createMcpServer)({
|
|
40
|
+
baseUrl: "http://paperless.test",
|
|
41
|
+
token: "test-token",
|
|
42
|
+
version: "0.0.0-test",
|
|
43
|
+
publicUrl: "http://paperless.test",
|
|
44
|
+
});
|
|
45
|
+
const [clientTransport, serverTransport] = inMemory_js_1.InMemoryTransport.createLinkedPair();
|
|
46
|
+
const client = new index_js_1.Client({ name: "schema-compat-test", version: "1.0.0" });
|
|
47
|
+
yield Promise.all([server.connect(serverTransport), client.connect(clientTransport)]);
|
|
48
|
+
try {
|
|
49
|
+
const { tools } = yield client.listTools();
|
|
50
|
+
const found = tools
|
|
51
|
+
.flatMap((tool) => arrayFormTypes(tool.inputSchema).map((hit) => `${tool.name} ${hit}`))
|
|
52
|
+
.sort();
|
|
53
|
+
strict_1.default.deepEqual(found, []);
|
|
54
|
+
}
|
|
55
|
+
finally {
|
|
56
|
+
yield client.close();
|
|
57
|
+
yield server.close();
|
|
58
|
+
}
|
|
59
|
+
}));
|
package/build/tools/tags.js
CHANGED
|
@@ -11,8 +11,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.registerTagTools = registerTagTools;
|
|
13
13
|
const zod_1 = require("zod");
|
|
14
|
-
const types_1 = require("../api/types");
|
|
15
14
|
const utils_1 = require("../api/utils");
|
|
15
|
+
const matchingAlgorithm_1 = require("./utils/matchingAlgorithm");
|
|
16
16
|
const middlewares_1 = require("./utils/middlewares");
|
|
17
17
|
const queryString_1 = require("./utils/queryString");
|
|
18
18
|
function registerTagTools(server, api) {
|
|
@@ -24,7 +24,7 @@ function registerTagTools(server, api) {
|
|
|
24
24
|
name__iexact: zod_1.z.string().optional(),
|
|
25
25
|
name__istartswith: zod_1.z.string().optional(),
|
|
26
26
|
ordering: zod_1.z.string().optional(),
|
|
27
|
-
}, (0, middlewares_1.withErrorHandling)((
|
|
27
|
+
}, (0, middlewares_1.withErrorHandling)((args) => __awaiter(this, void 0, void 0, function* () {
|
|
28
28
|
if (!api)
|
|
29
29
|
throw new Error("Please configure API connection first");
|
|
30
30
|
const queryString = (0, queryString_1.buildQueryString)(args);
|
|
@@ -46,13 +46,7 @@ function registerTagTools(server, api) {
|
|
|
46
46
|
.regex(/^#[0-9A-Fa-f]{6}$/)
|
|
47
47
|
.optional(),
|
|
48
48
|
match: zod_1.z.string().optional(),
|
|
49
|
-
matching_algorithm:
|
|
50
|
-
.number()
|
|
51
|
-
.int()
|
|
52
|
-
.min(0)
|
|
53
|
-
.max(6)
|
|
54
|
-
.optional()
|
|
55
|
-
.describe(types_1.MATCHING_ALGORITHM_DESCRIPTION),
|
|
49
|
+
matching_algorithm: matchingAlgorithm_1.matchingAlgorithmSchema.optional(),
|
|
56
50
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
57
51
|
if (!api)
|
|
58
52
|
throw new Error("Please configure API connection first");
|
|
@@ -75,13 +69,7 @@ function registerTagTools(server, api) {
|
|
|
75
69
|
.regex(/^#[0-9A-Fa-f]{6}$/)
|
|
76
70
|
.optional(),
|
|
77
71
|
match: zod_1.z.string().optional(),
|
|
78
|
-
matching_algorithm:
|
|
79
|
-
.number()
|
|
80
|
-
.int()
|
|
81
|
-
.min(0)
|
|
82
|
-
.max(6)
|
|
83
|
-
.optional()
|
|
84
|
-
.describe(types_1.MATCHING_ALGORITHM_DESCRIPTION),
|
|
72
|
+
matching_algorithm: matchingAlgorithm_1.matchingAlgorithmSchema.optional(),
|
|
85
73
|
}, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
|
|
86
74
|
if (!api)
|
|
87
75
|
throw new Error("Please configure API connection first");
|
|
@@ -6,8 +6,8 @@ export type CustomFieldQuery = [fieldNameOrId: string | number, operator: string
|
|
|
6
6
|
clauses: CustomFieldQuery[]
|
|
7
7
|
];
|
|
8
8
|
export declare const customFieldQuerySchema: z.ZodType<CustomFieldQuery>;
|
|
9
|
-
export declare const paperlessFilterValueSchema: z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]
|
|
10
|
-
export declare const paperlessFiltersSchema: z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]
|
|
9
|
+
export declare const paperlessFilterValueSchema: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>;
|
|
10
|
+
export declare const paperlessFiltersSchema: z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>;
|
|
11
11
|
export declare const LIST_DOCUMENTS_ARGS_SHAPE: {
|
|
12
12
|
custom_field_query: z.ZodOptional<z.ZodString>;
|
|
13
13
|
page: z.ZodOptional<z.ZodNumber>;
|
|
@@ -27,8 +27,8 @@ export declare const LIST_DOCUMENTS_ARGS_SHAPE: {
|
|
|
27
27
|
export declare const QUERY_DOCUMENTS_ARGS_SHAPE: {
|
|
28
28
|
query: z.ZodOptional<z.ZodString>;
|
|
29
29
|
more_like_id: z.ZodOptional<z.ZodNumber>;
|
|
30
|
-
custom_field_query: z.ZodOptional<z.ZodType<CustomFieldQuery, z.
|
|
31
|
-
paperless_filters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<[z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<[z.ZodString, z.ZodNumber, z.ZodBoolean]
|
|
30
|
+
custom_field_query: z.ZodOptional<z.ZodType<CustomFieldQuery, unknown, z.core.$ZodTypeInternals<CustomFieldQuery, unknown>>>;
|
|
31
|
+
paperless_filters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>]>>>;
|
|
32
32
|
page: z.ZodOptional<z.ZodNumber>;
|
|
33
33
|
page_size: z.ZodOptional<z.ZodNumber>;
|
|
34
34
|
search: z.ZodOptional<z.ZodString>;
|
|
@@ -68,7 +68,7 @@ exports.paperlessFilterValueSchema = zod_1.z.union([
|
|
|
68
68
|
paperlessFilterScalarSchema,
|
|
69
69
|
zod_1.z.array(paperlessFilterScalarSchema),
|
|
70
70
|
]);
|
|
71
|
-
exports.paperlessFiltersSchema = zod_1.z.record(exports.paperlessFilterValueSchema);
|
|
71
|
+
exports.paperlessFiltersSchema = zod_1.z.record(zod_1.z.string(), exports.paperlessFilterValueSchema);
|
|
72
72
|
const DOCUMENT_QUERY_BASE_ARGS_SHAPE = {
|
|
73
73
|
page: zod_1.z.number().optional(),
|
|
74
74
|
page_size: zod_1.z.number().optional(),
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.matchingAlgorithmSchema = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const types_1 = require("../../api/types");
|
|
6
|
+
// The 0-6 range the API declares is exactly the set `MatchingAlgorithm`
|
|
7
|
+
// enumerates, so narrowing to it after the check lets the PaperlessAPI request
|
|
8
|
+
// types take the parsed value without a cast at every call site.
|
|
9
|
+
exports.matchingAlgorithmSchema = zod_1.z
|
|
10
|
+
.number()
|
|
11
|
+
.int()
|
|
12
|
+
.min(0)
|
|
13
|
+
.max(6)
|
|
14
|
+
.transform((value) => value)
|
|
15
|
+
.describe(types_1.MATCHING_ALGORITHM_DESCRIPTION);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baruchiro/paperless-mcp",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for interacting with Paperless-NGX document management system. Enables AI assistants to manage documents, tags, correspondents, and document types through the Paperless-NGX API.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -44,12 +44,12 @@
|
|
|
44
44
|
"url": "https://github.com/baruchiro/paperless-mcp/issues"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
47
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
48
48
|
"axios": "^1.9.0",
|
|
49
49
|
"express": "^5.1.0",
|
|
50
50
|
"form-data": "^4.0.2",
|
|
51
51
|
"typescript": "^5.8.3",
|
|
52
|
-
"zod": "
|
|
52
|
+
"zod": "~4.4.3"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@anthropic-ai/dxt": "^0.2.6",
|
package/paperless-mcp.dxt
CHANGED
|
Binary file
|