@baruchiro/paperless-mcp 2.0.0 → 2.0.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/README.md CHANGED
@@ -66,7 +66,7 @@ Add these to your MCP config file:
66
66
  | `PAPERLESS_URL` | Yes | — | Base URL of your Paperless-NGX instance |
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
- | `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`. |
69
+ | `PAPERLESS_API_VERSION` | No | `9` | Paperless-ngx REST API version. `9` works on Paperless-ngx v2.x (recent) and v3.x. Paperless-ngx v3.0.0 dropped support for versions below `9`, so older defaults now return HTTP 406. If you see HTTP 406 errors, set this to a version your server supports. |
70
70
  | `PAPERLESS_MCP_UPLOAD_PATHS` | No | — | Colon-separated list of allowed directories for `file_path` uploads. **Recommended for security.** Example: `/var/uploads:/tmp/scans` |
71
71
 
72
72
  That's it! Now you can ask Claude to help you manage your Paperless-NGX documents.
@@ -22,7 +22,7 @@ class PaperlessAPI {
22
22
  this.token = token;
23
23
  this.baseUrl = baseUrl;
24
24
  this.token = token;
25
- this.apiVersion = process.env.PAPERLESS_API_VERSION || "5";
25
+ this.apiVersion = process.env.PAPERLESS_API_VERSION || "9";
26
26
  }
27
27
  request(path_1) {
28
28
  return __awaiter(this, arguments, void 0, function* (path, options = {}) {
@@ -57,7 +57,7 @@ class PaperlessAPI {
57
57
  catch (error) {
58
58
  if (axios_1.default.isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 406) {
59
59
  throw new Error(`HTTP 406: Paperless-ngx rejected API version ${this.apiVersion}. ` +
60
- `Set the PAPERLESS_API_VERSION environment variable to match your server's API version (e.g., "10" for Paperless-ngx v3+).`);
60
+ `Set the PAPERLESS_API_VERSION environment variable to a version your server supports (e.g., "9" or "10" for Paperless-ngx v3+, or a lower value for older servers).`);
61
61
  }
62
62
  console.error({
63
63
  error: "Error executing request",
@@ -121,7 +121,7 @@ class PaperlessAPI {
121
121
  catch (error) {
122
122
  if (axios_1.default.isAxiosError(error) && ((_a = error.response) === null || _a === void 0 ? void 0 : _a.status) === 406) {
123
123
  throw new Error(`HTTP 406: Paperless-ngx rejected API version ${this.apiVersion}. ` +
124
- `Set the PAPERLESS_API_VERSION environment variable to match your server's API version (e.g., "10" for Paperless-ngx v3+).`);
124
+ `Set the PAPERLESS_API_VERSION environment variable to a version your server supports (e.g., "9" or "10" for Paperless-ngx v3+, or a lower value for older servers).`);
125
125
  }
126
126
  throw error;
127
127
  }
@@ -412,7 +412,7 @@ function registerDocumentTools(server, api) {
412
412
  ],
413
413
  };
414
414
  })));
415
- server.tool("update_document", "Update a specific document with new values. This tool allows you to modify any document field including title, correspondent, document type, storage path, tags, custom fields, and more. Only the fields you specify will be updated.", {
415
+ server.tool("update_document", "Update a specific document with new values (title, correspondent, document type, storage path, tags, custom fields, and more). Top-level fields you omit are left unchanged. IMPORTANT: custom_fields is the exception — see its parameter description; it replaces the document's entire custom-field set.", {
416
416
  id: zod_1.z.number().describe("The ID of the document to update"),
417
417
  title: zod_1.z
418
418
  .string()
@@ -469,13 +469,13 @@ function registerDocumentTools(server, api) {
469
469
  .describe(descriptions_1.CUSTOM_FIELD_VALUE_DESCRIPTION),
470
470
  }))
471
471
  .optional()
472
- .describe("Array of custom field values to assign"),
472
+ .describe("Custom field values for the document. ⚠️ REPLACES the document's entire custom-field set — any field not included here will be CLEARED. To update or add a single field without losing the others, first call get_document to read the existing custom_fields, then pass the full merged array. To add/set fields additively without fetching, use bulk_edit_documents with method 'modify_custom_fields' instead."),
473
473
  }, (0, middlewares_1.withErrorHandling)((args, extra) => __awaiter(this, void 0, void 0, function* () {
474
474
  if (!api)
475
475
  throw new Error("Please configure API connection first");
476
476
  const { id } = args, updateData = __rest(args, ["id"]);
477
477
  (0, monetary_1.validateCustomFields)(updateData.custom_fields);
478
- updateData.custom_fields = yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, updateData.custom_fields, "index");
478
+ updateData.custom_fields = yield (0, selectFields_1.resolveSelectCustomFieldValues)(api, updateData.custom_fields, "stored");
479
479
  const response = yield api.updateDocument(id, updateData);
480
480
  return (0, documentEnhancer_1.convertDocsWithNames)(response, api);
481
481
  })));
@@ -416,7 +416,7 @@ const OBJECT_SELECT_FIELD = {
416
416
  const [, data] = calls.updateDocument[0];
417
417
  strict_1.default.deepEqual(data.custom_fields, [{ field: 2, value: 0 }]);
418
418
  }));
419
- (0, node_test_1.test)("update_document translates a select label to its option index (Paperless 2.17+)", () => __awaiter(void 0, void 0, void 0, function* () {
419
+ (0, node_test_1.test)("update_document sends the option id for 2.17+ select fields (stored form)", () => __awaiter(void 0, void 0, void 0, function* () {
420
420
  const { api, calls } = createDocumentApi([OBJECT_SELECT_FIELD]);
421
421
  yield withDocumentClient(api, (client) => __awaiter(void 0, void 0, void 0, function* () {
422
422
  var _a;
@@ -427,7 +427,7 @@ const OBJECT_SELECT_FIELD = {
427
427
  strict_1.default.ok(!result.isError, (_a = parseToolText(result)) === null || _a === void 0 ? void 0 : _a.error);
428
428
  }));
429
429
  const [, data] = calls.updateDocument[0];
430
- strict_1.default.deepEqual(data.custom_fields, [{ field: 3, value: 1 }]);
430
+ strict_1.default.deepEqual(data.custom_fields, [{ field: 3, value: "def456" }]);
431
431
  }));
432
432
  (0, node_test_1.test)("bulk_edit_documents translates a select label in add_custom_fields", () => __awaiter(void 0, void 0, void 0, function* () {
433
433
  const { api, calls } = createDocumentApi([LEGACY_SELECT_FIELD]);
@@ -1,9 +1,11 @@
1
1
  import { PaperlessAPI } from "../../api/PaperlessAPI";
2
2
  import { CustomField, CustomFieldInstanceRequest, CustomFieldValue } from "../../api/types";
3
3
  /**
4
- * Encoding Paperless expects for a select value: `update_document` takes the
5
- * option index; `bulk_edit` writes `value_select` directly so it needs the
6
- * stored form (option id on 2.17+, index on pre-2.17 string options).
4
+ * Encoding Paperless expects for a select value. On the supported API versions
5
+ * (v9+) both `update_document` and `bulk_edit` take the option's stored form:
6
+ * the option id on 2.17+ fields, or the index on pre-2.17 string-option fields.
7
+ * The bare `index` form is retained for older API versions whose document
8
+ * endpoint accepted the option index directly.
7
9
  */
8
10
  export type SelectValueEncoding = "index" | "stored";
9
11
  /** Translates a select value (label, option id, or index) to the `encoding` Paperless expects; throws on no match. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@baruchiro/paperless-mcp",
3
- "version": "2.0.0",
3
+ "version": "2.0.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