@baruchiro/paperless-mcp 0.5.0 → 0.5.1
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/tools/documents.js +3 -2
- package/build/tools/utils/resourceUri.d.ts +24 -0
- package/build/tools/utils/resourceUri.js +32 -0
- package/build/tools/utils/resourceUri.test.d.ts +1 -0
- package/build/tools/utils/resourceUri.test.js +50 -0
- package/package.json +1 -1
- package/paperless-mcp.dxt +0 -0
package/build/tools/documents.js
CHANGED
|
@@ -28,6 +28,7 @@ const empty_1 = require("./utils/empty");
|
|
|
28
28
|
const middlewares_1 = require("./utils/middlewares");
|
|
29
29
|
const monetary_1 = require("./utils/monetary");
|
|
30
30
|
const descriptions_1 = require("./utils/descriptions");
|
|
31
|
+
const resourceUri_1 = require("./utils/resourceUri");
|
|
31
32
|
/**
|
|
32
33
|
* Builds Paperless-NGX bulk edit parameters from base parameters plus optional
|
|
33
34
|
* custom field updates.
|
|
@@ -282,7 +283,7 @@ function registerDocumentTools(server, api) {
|
|
|
282
283
|
{
|
|
283
284
|
type: "resource",
|
|
284
285
|
resource: {
|
|
285
|
-
uri: filename,
|
|
286
|
+
uri: (0, resourceUri_1.buildDocumentResourceUri)(args.id, filename),
|
|
286
287
|
blob: Buffer.from(response.data).toString("base64"),
|
|
287
288
|
mimeType: "application/pdf",
|
|
288
289
|
},
|
|
@@ -301,7 +302,7 @@ function registerDocumentTools(server, api) {
|
|
|
301
302
|
{
|
|
302
303
|
type: "resource",
|
|
303
304
|
resource: {
|
|
304
|
-
uri:
|
|
305
|
+
uri: (0, resourceUri_1.buildThumbnailResourceUri)(args.id),
|
|
305
306
|
blob: Buffer.from(response.data).toString("base64"),
|
|
306
307
|
mimeType: "image/webp",
|
|
307
308
|
},
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource URI builders for document/thumbnail downloads.
|
|
3
|
+
*
|
|
4
|
+
* URIs mirror the Paperless REST API paths under a custom `paperless://`
|
|
5
|
+
* scheme, so the same identifiers can later back proper MCP resources
|
|
6
|
+
* (`resources/list` / `resources/read`) without a second naming scheme.
|
|
7
|
+
*
|
|
8
|
+
* The scheme also keeps the URI well-formed regardless of filename
|
|
9
|
+
* content, which Python MCP clients (pydantic-validated) require.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Builds a resource URI for a downloaded document.
|
|
13
|
+
*
|
|
14
|
+
* Mirrors `GET /api/documents/{id}/download/`. The original filename is
|
|
15
|
+
* preserved as a `filename` query parameter (URL-encoded) so clients
|
|
16
|
+
* that need the human-readable name can still recover it.
|
|
17
|
+
*/
|
|
18
|
+
export declare function buildDocumentResourceUri(id: number, filename: string): string;
|
|
19
|
+
/**
|
|
20
|
+
* Builds a resource URI for a document thumbnail.
|
|
21
|
+
*
|
|
22
|
+
* Mirrors `GET /api/documents/{id}/thumb/`.
|
|
23
|
+
*/
|
|
24
|
+
export declare function buildThumbnailResourceUri(id: number): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Resource URI builders for document/thumbnail downloads.
|
|
4
|
+
*
|
|
5
|
+
* URIs mirror the Paperless REST API paths under a custom `paperless://`
|
|
6
|
+
* scheme, so the same identifiers can later back proper MCP resources
|
|
7
|
+
* (`resources/list` / `resources/read`) without a second naming scheme.
|
|
8
|
+
*
|
|
9
|
+
* The scheme also keeps the URI well-formed regardless of filename
|
|
10
|
+
* content, which Python MCP clients (pydantic-validated) require.
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.buildDocumentResourceUri = buildDocumentResourceUri;
|
|
14
|
+
exports.buildThumbnailResourceUri = buildThumbnailResourceUri;
|
|
15
|
+
/**
|
|
16
|
+
* Builds a resource URI for a downloaded document.
|
|
17
|
+
*
|
|
18
|
+
* Mirrors `GET /api/documents/{id}/download/`. The original filename is
|
|
19
|
+
* preserved as a `filename` query parameter (URL-encoded) so clients
|
|
20
|
+
* that need the human-readable name can still recover it.
|
|
21
|
+
*/
|
|
22
|
+
function buildDocumentResourceUri(id, filename) {
|
|
23
|
+
return `paperless://documents/${id}/download?filename=${encodeURIComponent(filename)}`;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Builds a resource URI for a document thumbnail.
|
|
27
|
+
*
|
|
28
|
+
* Mirrors `GET /api/documents/{id}/thumb/`.
|
|
29
|
+
*/
|
|
30
|
+
function buildThumbnailResourceUri(id) {
|
|
31
|
+
return `paperless://documents/${id}/thumb`;
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const node_test_1 = require("node:test");
|
|
7
|
+
const strict_1 = __importDefault(require("node:assert/strict"));
|
|
8
|
+
const resourceUri_1 = require("./resourceUri");
|
|
9
|
+
(0, node_test_1.test)("buildDocumentResourceUri mirrors the REST download path", () => {
|
|
10
|
+
const uri = (0, resourceUri_1.buildDocumentResourceUri)(1, "doc.pdf");
|
|
11
|
+
strict_1.default.match(uri, /^paperless:\/\/documents\/1\/download(\?|$)/);
|
|
12
|
+
});
|
|
13
|
+
(0, node_test_1.test)("buildDocumentResourceUri puts the filename in a query parameter", () => {
|
|
14
|
+
const uri = (0, resourceUri_1.buildDocumentResourceUri)(1, "invoice 2026.pdf");
|
|
15
|
+
strict_1.default.equal(uri, "paperless://documents/1/download?filename=invoice%202026.pdf");
|
|
16
|
+
});
|
|
17
|
+
(0, node_test_1.test)("buildDocumentResourceUri encodes RFC-3986 reserved chars in the filename", () => {
|
|
18
|
+
const uri = (0, resourceUri_1.buildDocumentResourceUri)(42, "weird ?#&=+name.pdf");
|
|
19
|
+
const url = new URL(uri);
|
|
20
|
+
// The path stays canonical — only the literal `?` that separates
|
|
21
|
+
// path from query is allowed; nothing from the filename should
|
|
22
|
+
// bleed into the path or break query parsing.
|
|
23
|
+
strict_1.default.equal(url.pathname, "/42/download");
|
|
24
|
+
strict_1.default.equal(url.searchParams.get("filename"), "weird ?#&=+name.pdf");
|
|
25
|
+
});
|
|
26
|
+
(0, node_test_1.test)("buildDocumentResourceUri encodes path separators inside filename", () => {
|
|
27
|
+
// A filename containing a slash must not become an extra path segment.
|
|
28
|
+
const uri = (0, resourceUri_1.buildDocumentResourceUri)(7, "sub/dir/file.pdf");
|
|
29
|
+
const url = new URL(uri);
|
|
30
|
+
strict_1.default.equal(url.pathname, "/7/download");
|
|
31
|
+
strict_1.default.equal(url.searchParams.get("filename"), "sub/dir/file.pdf");
|
|
32
|
+
});
|
|
33
|
+
(0, node_test_1.test)("buildDocumentResourceUri preserves unicode filenames", () => {
|
|
34
|
+
const original = "Rechnüng — März.pdf";
|
|
35
|
+
const uri = (0, resourceUri_1.buildDocumentResourceUri)(1, original);
|
|
36
|
+
// Roundtrip via URL parsing should recover the original name.
|
|
37
|
+
const url = new URL(uri);
|
|
38
|
+
strict_1.default.equal(url.searchParams.get("filename"), original);
|
|
39
|
+
});
|
|
40
|
+
(0, node_test_1.test)("buildDocumentResourceUri produces a valid URL", () => {
|
|
41
|
+
const uri = (0, resourceUri_1.buildDocumentResourceUri)(1, "Some File.pdf");
|
|
42
|
+
strict_1.default.doesNotThrow(() => new URL(uri));
|
|
43
|
+
});
|
|
44
|
+
(0, node_test_1.test)("buildThumbnailResourceUri mirrors the REST thumb path", () => {
|
|
45
|
+
strict_1.default.equal((0, resourceUri_1.buildThumbnailResourceUri)(1), "paperless://documents/1/thumb");
|
|
46
|
+
strict_1.default.equal((0, resourceUri_1.buildThumbnailResourceUri)(123), "paperless://documents/123/thumb");
|
|
47
|
+
});
|
|
48
|
+
(0, node_test_1.test)("buildThumbnailResourceUri produces a valid URL", () => {
|
|
49
|
+
strict_1.default.doesNotThrow(() => new URL((0, resourceUri_1.buildThumbnailResourceUri)(99)));
|
|
50
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@baruchiro/paperless-mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.1",
|
|
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": {
|
package/paperless-mcp.dxt
CHANGED
|
Binary file
|