@baruchiro/paperless-mcp
Version:
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.
71 lines (64 loc) • 3.65 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.createMcpServer = createMcpServer;
exports.getBearerToken = getBearerToken;
exports.sendUnauthorized = sendUnauthorized;
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
const PaperlessAPI_1 = require("./api/PaperlessAPI");
const documents_1 = require("./resources/documents");
const correspondents_1 = require("./tools/correspondents");
const customFields_1 = require("./tools/customFields");
const documents_2 = require("./tools/documents");
const documentTypes_1 = require("./tools/documentTypes");
const mail_1 = require("./tools/mail");
const notes_1 = require("./tools/notes");
const tags_1 = require("./tools/tags");
function createMcpServer({ baseUrl, token, version, publicUrl, }) {
const api = new PaperlessAPI_1.PaperlessAPI(baseUrl, token);
const server = new mcp_js_1.McpServer({ name: "paperless-ngx", version }, { instructions: buildInstructions(publicUrl) });
(0, documents_2.registerDocumentTools)(server, api);
(0, documents_1.registerDocumentResources)(server, api);
(0, notes_1.registerNoteTools)(server, api);
(0, tags_1.registerTagTools)(server, api);
(0, correspondents_1.registerCorrespondentTools)(server, api);
(0, documentTypes_1.registerDocumentTypeTools)(server, api);
(0, customFields_1.registerCustomFieldTools)(server, api);
(0, mail_1.registerMailTools)(server, api);
return server;
}
function getBearerToken(req, options) {
const authHeader = req.headers["authorization"];
if (authHeader && authHeader.startsWith("Bearer ")) {
return authHeader.slice(7);
}
if (options.allowAnonymous) {
return options.fallbackToken || undefined;
}
return undefined;
}
function sendUnauthorized(res) {
// Log operator-facing guidance server-side; keep the wire response minimal so
// we don't echo configuration hints back to unauthenticated callers.
console.error("[paperless-mcp] Rejected request with no 'Authorization: Bearer <paperless-ngx-api-token>' header. " +
"As of v2.0.0, HTTP mode requires a per-request Bearer token and no longer falls back to the " +
"server-configured token for unauthenticated requests. Have clients send their Paperless-NGX API " +
"token as a Bearer token, or restart the server with --no-auth to use the server token for " +
"unauthenticated requests (trusted/local networks only).");
res
.status(401)
.set("WWW-Authenticate", 'Bearer realm="paperless-mcp"')
.json({ error: "unauthorized" });
}
function buildInstructions(publicUrl) {
return `
Paperless-NGX MCP Server Instructions
⚠️ CRITICAL: Always differentiate between operations on specific documents vs operations on the entire system:
- REMOVE operations (e.g., remove_tag in bulk_edit_documents): Affect only the specified documents, items remain in the system
- DELETE operations (e.g., delete_tag, delete_correspondent): Permanently delete items from the entire system, affecting ALL documents that use them
When a user asks to "remove" something, prefer operations that affect specific documents. Only use DELETE operations when explicitly asked to delete from the system.
To view documents in your Paperless-NGX web interface, construct URLs using this pattern:
${publicUrl}/documents/{document_id}/
Example: If your base URL is "http://localhost:8000", the web interface URL would be "http://localhost:8000/documents/123/" for document ID 123.
The document tools return JSON data with document IDs that you can use to construct these URLs.
`;
}