无纸- NGX MCP 服务器
一个用于与无纸-NGX API服务器交互的MCP(模式上下文协议)服务器. 此服务器为您在无纸- NGX 实例中管理文档、 标记、 通讯员和文档类型提供了工具 .
快速启动
安装
将这些添加到您的 MCP 配置文件 :
// STIO 模式(建议用于当地或CLI)
"paperless": {
"command": "npx",
"args": [
"-y",
"@baruchiro/paperless-mcp@latest",
],
"env": {
"PAPERLESS_URL": "http://your-paperless-instance:8000",
"PAPERLESS_API_KEY": "your-api-token",
"PAPERLESS_PUBLIC_URL": "https://your-public-domain.com"
}
}
// HTTP 模式(推荐用于多克或远程使用)
"paperless": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"ghcr.io/baruchiro/paperless-mcp:latest",
],
"env": {
"PAPERLESS_URL": "http://your-paperless-instance:8000",
"PAPERLESS_API_KEY": "your-api-token",
"PAPERLESS_PUBLIC_URL": "https://your-public-domain.com"
}
}
-
获取您的 API 令牌 :
- 登录到您的无纸- NGX 实例
- 在右上方单击您的用户名
- 选择“ 我的配置”
- 单击圆形箭头按钮生成新符号
-
替换您 MCP 配置中的占位符 :
http://your-paperless-instance:8000使用您的无纸- NGX URLyour-api-token带着你刚刚创造的标志https://your-public-domain.com使用您的公开无纸- NGX URL( 可选的, 返回 PAPERLESS URL)
环境变量
| 变量 | 需求 | 默认 | 说明 |
|---|---|---|---|
PAPERLESS_URL | 对 | —— 说 | 您的无纸- NGX 实例的基础 URL |
PAPERLESS_API_KEY | 对 | —— 说 | 来自您的无纸- NGX 配置文件的 API 令牌 |
PAPERLESS_PUBLIC_URL | 没有 | PAPERLESS_URL | 文档链接的公用 URL |
PAPERLESS_API_VERSION | 没有 | 9 | 无纸-ngx REST API版本. 9 用于无纸-ngx v2.x (最近)和 v3.x. 无纸-ngx v3.0.0 下方版本已放弃支持 9,因此旧的默认值现在返回 HTTP 406. 如果您看到 HTTP 406 出错, 请将此设定为您服务器支持的版本 . |
PAPERLESS_MCP_UPLOAD_PATHS | 没有 | —— 说 | 被隔离的允许目录列表 file_path 上传. 安保建议. 示例 /var/uploads:/tmp/scans |
就这样! 现在你可以请克洛德帮助你管理你的无纸-NGX文档.
示例使用
有件事你可以请克洛德去做:
- 给我看所有标有"发票"的文件
- 搜索包含“ 税收返还” 的文件
- "用#FF000"来创建名为"Recepts"的新标签
- "下载文档 #123"
- "把所有记者都登记"
- 创建名为“ 银行声明” 的新文档类型
可用工具
文件操作
列表文档( d)
获得一个带有简单过滤器的相加文档列表。 用于直接列出任务 。 对于全文查询,使用结构化自定义字段过滤或高级无纸过滤器 query_documents。 。 。 .
参数:
- 页面( 可选) : 页码
- 页面大小( 可选) : 每页文档数
- 搜索( 可选的): 简单的无纸搜索名词
- 通讯员( 可选的): 通讯员 ID
- 文档 类型 (可选): 文档类型 ID
- 标记 (可选): 标记 ID
- 存储路径 (可选) : 存储路径 ID
- 创建 日期 gte (可选): YYYY- MM- DD 上或之后创建的日期
- 创建 date lte (可选): YYYY- MM- DD 上或之前创建的日期
- 命令( 可选) : 无纸命令字段
- 归档 serial 数字(可选):存档序列号
- 存档 序列 数字 insnull( 可选) : 归档序列号是否为空
- 自定义 field query (可选) : Raw JSON 编码为无纸自定义字段查询字符串
- 自定义 fields icontains (可选): 大小写不敏感子字符串匹配自定义字段值
list_documents({
page: 1,
page_size: 25
})
查询 文档
Canonical 文档查询工具 。 支持全文查询、简单的无纸搜索、自定义字段过滤器和文档 /api/documents/ 无纸查询参数.
参数:
- 页面( 可选) : 页码
- 页面大小( 可选) : 每页文档数
- 命令( 可选) : 无纸命令字段
- 查询( 可选) : 全文查询字符串
- 搜索( 可选的): 简单的无纸搜索名词
- 更接近 like id(可选) : 查找类似此文档的文档 ID
- 通讯员( 可选的): 通讯员 ID
- 文档 类型 (可选): 文档类型 ID
- 标记 (可选): 标记 ID
- 存储路径 (可选) : 存储路径 ID
- 创建 日期 gte (可选): YYYY- MM- DD 上或之后创建的日期
- 创建 date lte (可选): YYYY- MM- DD 上或之前创建的日期
- 自定义 field query (可选): 使用结构化的无纸自定义字段查询
[field_name_or_id, operator, value]叶子或["AND" | "OR", [clause1, clause2]]组 - 无纸过滤器( 可选) : 附加文件
/api/documents/无纸查询参数,作为密钥/值对传递
// Full-text query
query_documents({
query: "invoice 2024"
})
// Simple search term
query_documents({
search: "acme"
})
// Custom field exact match
query_documents({
custom_field_query: ["Invoice Number", "exact", "12345"]
})
// Custom field empty
query_documents({
custom_field_query: ["OR", [
["Invoice Number", "isnull", true],
["Invoice Number", "exact", ""]
]]
})
// Custom field missing
query_documents({
custom_field_query: ["Invoice Number", "exists", false]
})
// Combined filters
query_documents({
query: "invoice",
tag: 5,
created__date__gte: "2024-01-01",
custom_field_query: ["Invoice Number", "exists", true]
})
// One documented Paperless filter that is not a first-class argument
query_documents({
paperless_filters: {
id__in: [101, 202, 303]
}
})
获取文档
以身份证获取特定文件.
参数:
- 编号:文档ID
get_document({
id: 123
})
搜索文档
已折旧的相容性包装符用于全文搜索 。 偏爱 query_documents({ query: ... }) 为了新的融合.
参数:
- 查询: 搜索查询字符串
search_documents({
query: "invoice 2024"
})
下载( d)
通过ID下载文档文件 .
参数:
- 编号:文档ID
- 原始( 可选) : 如果真实, 下载原始文件而不是存档版本
download_document({
id: 123,
original: false
})
获取文档 thumbnail
通过 ID 获取文档缩略图(图像预览) 。 返回缩略图为基准64-编码的WebP图像资源.
参数:
- 编号:文档ID
get_document_thumbnail({
id: 123
})
大块编辑器 文件
对多份文件进行散装操作.
参数:
- 文档: 文档编号阵列
- 方法:
- 设置( C):为文档设置通讯员
- 设置 文档类型:为文档设置文档类型
- set storage path: 为文档设置存储路径
- 添加 tag: 在文档中添加标签
- 删除( tag): 从文档中删除标签
- 修改( tag): 添加和/或去除多个标签
- 删除: 删除文档
- 重新处理: 重新处理文档
- 设置权限( P): 设置文档权限
- 合并: 合并多个文档
- 拆分:将文档拆分成多个文档
- 旋转: 旋转文档页面
- 删除页: 从文档中删除特定页
- 基于方法的其他参数:
- 通讯员: 设置的ID 通讯员
- 文档 类型: set document 类型标识
- 存储( P): 设置的编号 storage path
- 标记: 添加/ remove tag 的ID
- 添加 tags:用于修改 tags的标签标识组
- 删除 tag: 修改 tags 的标签ID阵列
- 设置( permissions):带有视图/更改用户和组的设定对象
{"view": {"users": [], "groups": []}, "change": {...}}) (中文(简体) ). 已公布的行动/清单未受影响 - 拥有者:用于设置 permissions的用户ID(或无效去除). 除非合并为真, 否则删除所有者清除当前所有者
- 合并: boolean for set permissions — 真实添加到已有权限并保存所有者;假(默认)替换列出的用户/组
- 元数据 文档 id: 用于合并以指定元数据源的ID
- 删除 原件: 合并/分割的布尔
- 页面:分页字符串“[1,2-3,4,5-7]”或删除 页“[2,3,4]”
- 度数:旋转的数字(90、180或270)
实例:
// Add a tag to multiple documents
bulk_edit_documents({
documents: [1, 2, 3],
method: "add_tag",
tag: 5
})
// Set correspondent and document type
bulk_edit_documents({
documents: [4, 5],
method: "set_correspondent",
correspondent: 2
})
// Merge documents
bulk_edit_documents({
documents: [6, 7, 8],
method: "merge",
metadata_document_id: 6,
delete_originals: true
})
// Split document into parts
bulk_edit_documents({
documents: [9],
method: "split",
pages: "[1-2,3-4,5]"
})
// Modify multiple tags at once
bulk_edit_documents({
documents: [10, 11],
method: "modify_tags",
add_tags: [1, 2],
remove_tags: [3, 4]
})
// Modify custom fields
bulk_edit_documents({
documents: [12, 13],
method: "modify_custom_fields",
add_custom_fields: [
{ field: 2, value: "year" }
],
remove_custom_fields: []
})
// Set an empty custom field value, e.g. a date field used as a pending marker
bulk_edit_documents({
documents: [14],
method: "modify_custom_fields",
add_custom_fields: [
{ field: 9, value: "" }
],
remove_custom_fields: []
})
后文档
上传新文档到无纸-NGX.
两个上传模式 :
- Base64 模式 (传统):提供
file(基准64-编码内容)+filename - 文件系统模式 (效率):提供
file_path(服务器上的绝对路径)
安全说明: 使用时 file_path,设置 PAPERLESS_MCP_UPLOAD_PATHS 环境变量(所允许目录的分号列表)以限制上传到特定位置. 没有这个,服务器文件系统中的任何文件都可以被上传.
参数:
- 文件(可选):Base64已编码文件内容. 无论是
file或者说file_path所需经费. - file path (optional): 服务器文件系统中文件的绝对路径. 无论是
file或者说file_path所需经费. - 文件名( 可选) : 文件名 。 要求为
file选项file_path(从道取出. - 标题( 可选) : 文件标题
- 创建( 可选) : 创建文档的时间( 如"2024-01-19" 或"2024-01-19 06: 15:00+02: 00")
- 通讯员( 可选): 通讯员的身份
- 文档 类型 (可选): 文档类型的ID
- 存储路径 (可选) : 存储路径的ID
- 标记 (可选): 标记 ID 阵列
- 归档 serial 数字(可选):存档序列号
- 自定义字段 (可选): 自定义字段 ID 的矩阵
文件大小限制 : 两种模式的100MB
// Base64 mode (traditional)
post_document({
file: "base64_encoded_content",
filename: "invoice.pdf",
title: "January Invoice",
created: "2024-01-19",
correspondent: 1,
document_type: 2,
tags: [1, 3],
archive_serial_number: "2024-001",
custom_fields: [1, 2]
})
// Filesystem mode (more efficient for large files)
post_document({
file_path: "/var/uploads/invoice.pdf",
title: "January Invoice",
correspondent: 1,
document_type: 2,
tags: [1, 3]
})
文档注释
列表 文档 注释
列出文件所附的所有注释.
参数:
- 编号:文档ID
list_document_notes({
id: 123
})
创建 文档 注释
在文档中添加注释。 返回文档完整的注释列表.
参数:
- 编号:文档ID
- 注:要添加的说明案文
create_document_note({
id: 123,
note: "Invoice paid on 2026-06-30 from Commerzbank account."
})
删除文档( n)
⚠️ 从文档中用注释ID去掉单个注释. 这一行动是不可逆转的.
参数:
- 编号:文档ID
- 注:要删除的注解的ID
- 确认:必须是
true证实这次破坏行动
delete_document_note({
id: 123,
note_id: 5,
confirm: true
})
标记操作
列表标签( t)
得到所有的标签.
list_tags()
创建( t)
创建新标签 .
参数:
- 名称: 标签名称
- 颜色( 可选的): 十六进制颜色代码( 如 “ # ff000” )
- 匹配( 可选) : 要匹配的文本模式
- 匹配( algorthm (可选): 0 到 6 之间的数字 : 0 - 无 1 - 任何单词 2 - 所有单词 3 - 准确匹配 4. 正则表达式 5 - 模糊词 6 - 自动
create_tag({
name: "Invoice",
color: "#ff0000",
match: "invoice",
matching_algorithm: 5
})
通讯业务
列表( c)
找所有记者.
list_correspondents()
创建响应( c)
创建新通讯员 .
参数:
- 名称: 通讯名
- 匹配( 可选) : 要匹配的文本模式
- 匹配( algorthm (可选): 0 到 6 之间的数字 : 0 - 无 1 - 任何单词 2 - 所有单词 3 - 准确匹配 4. 正则表达式 5 - 模糊词 6 - 自动
create_correspondent({
name: "ACME Corp",
match: "ACME",
matching_algorithm: 5
})
文件类型操作
列表 文档 类型
获取所有文档类型 .
list_document_types()
创建 文档 类型
创建新文档类型.
参数:
- 名称: 文档类型名称
- 匹配( 可选) : 要匹配的文本模式
- 匹配( algorthm (可选): 0 到 6 之间的数字 : 0 - 无 1 - 任何单词 2 - 所有单词 3 - 准确匹配 4. 正则表达式 5 - 模糊词 6 - 自动
create_document_type({
name: "Invoice",
match: "invoice total amount due",
matching_algorithm: 1
})
自定义字段操作
列表( c)
取出所有自定义字段.
list_custom_fields()
获取自定义( f)
通过ID获取特定的自定义字段.
参数:
- id: 自定义字段ID
get_custom_field({
id: 1
})
创建( c)
创建新自定义字段 .
参数:
- 名称: 自定义字段名称
- 数据 类型:"字符串","url","日期","boole","整数","浮动","货币","文件链接","选择"之一
- extra data (可选): 自定义字段的额外数据, 如所选选项
create_custom_field({
name: "Invoice Number",
data_type: "string"
})
更新( c)
更新已有的自定义字段 .
参数:
- id: 自定义字段ID
- 名称 (可选): 新建自定义字段名称
- 数据 类型 (可选): 新数据类型
- 额外数据 (可选): 自定义字段的额外数据
update_custom_field({
id: 1,
name: "Updated Invoice Number",
data_type: "string"
})
删除( c)
删除自定义字段.
参数:
- id: 自定义字段ID
delete_custom_field({
id: 1
})
大块 编辑 定制 字段
在多个自定义字段进行批量操作.
参数:
- 自定义字段: 自定义字段编号阵列
- 操作: “去除” 之一
bulk_edit_custom_fields({
custom_fields: [1, 2, 3],
operation: "delete"
})
邮件操作
管理无纸邮件账户和驱动邮件规则的工具 自动接收电子邮件。 账户密码/托盘从未被曝光:它们是 从每个工具响应中编辑 .
列表( m)
列出邮件账户, 以便您在创建邮件时选择所需的账户ID 规则。 密码已编辑 .
参数:
- 页面( 可选) : 页码
- 页面大小 (可选): 每页结果数
list_mail_accounts()
获取邮件 账户
凭身份证得到一个邮件账户 密码/托肯字段被编辑 .
参数:
- 编号: 邮件账户 ID
get_mail_account({
id: 1
})
进程( m)
手动触发一个账户的无纸邮件处理. 这能消耗 根据账户允许的邮件规则匹配邮件.
参数:
- 编号: 邮件账户 ID
process_mail_account({
id: 1
})
列表( m)
列出带有可选页标的邮件规则 .
参数:
- 页面( 可选) : 页码
- 页面大小 (可选): 每页结果数
list_mail_rules()
获取邮件 rule
获得一个单一的邮件规则 通过ID.
参数:
- 编号: 邮件规则 ID
get_mail_rule({
id: 1
})
创建 mail rule
创建邮件规则 。 使用 list_mail_accounts 首先选择账户.
所需参数 :
- 名称: 规则名称
- 账户: 邮件账户ID
- 文件夹:要扫描的 IMAP 文件夹( 如“ INBOX ”)
共同的可选参数 :
- 启用( 默认为真) : 该规则是否活动
- 过滤器 从 / 过滤器 到 / 过滤器 主题/ 过滤器 实体: 匹配收到的邮件
- 最大年龄: 只有处理邮件更新于此多天
- 动作:1=删除,2=移动到文件夹,3=马克读取,4=旗帜,5=塔克
- 动作( 参数):选定动作的目标文件夹/标签
- adition title from: 1=对象, 2=附件文件名, 3=不指定
- 指定 tags / 指定 对应 / 指定 文档 类型: 要应用的元数据
- 指派 通讯员 来自:1=无,2=邮件地址,3=发件人名,4=使用指派 通讯员
- 附件 类型: 1=仅附图, 2=包括内含的全部文件
- 消耗 镜像:1=仅附图,2=全信为.eml,3=双相
- pdf layout: 0=系统默认, 1=Text+HTML, 2=HTML+text, 3=HTML只, 4=text
create_mail_rule({
name: "Invoices",
account: 1,
folder: "INBOX",
filter_subject: "invoice",
action: 3,
attachment_type: 1
})
更新( m)
补齐已有的邮件规则 。 只有您提供的字段被更改 .
参数:
- 编号: 邮件规则 ID
- ...任何一个
create_mail_rule要更新的字段
update_mail_rule({
id: 1,
enabled: false
})
删除( m)
删除邮件规则 。 需要明确的确认旗. 这改变了未来 邮件摄取行为,但不删除任何已存在的文档.
参数:
- 编号: 邮件规则 ID
- 确认:必须是
true确认删除
delete_mail_rule({
id: 1,
confirm: true
})
处理错误
如果 :
- 无纸- NGX URL 或 API 令牌不正确
- 无纸- NGX 服务器无法访问
- 请求的操作失败
- 提供的参数无效
测试
单位测试
运行单元测试套件( 不需要外部依赖):
npm test
E2E测试
E2E套件靴子是一个空的无纸-ngx实例,运行已编译的 MCP 服务器,并驱动一个决定性的序列方案通过 tools/call 请求 —— 创建标签、 通讯员和文档类型, 上传 PDF, 然后在同一文档上执行列表 / 获取/ 搜索/ 下载/ 缩略语 / 批量编辑 。 MCP之外没有LLM和无纸REST客户端.
先决条件: 杜克,杜克编曲,和 jq。 。 。 .
# 1. Build the MCP server
npm run build
# 2. Start Paperless-ngx
docker compose -f docker-compose.e2e.yml up -d
# 3. Wait for Paperless to be ready, then get a token
TOKEN=$(curl -s -X POST http://localhost:8000/api/token/ \
-H 'Content-Type: application/json' \
-d '{"username":"admin","password":"admin123"}' | jq -r '.token')
# 4. Start the MCP server
node build/index.js --http --port 3001 \
--baseUrl http://localhost:8000 --token "$TOKEN" &
MCP_PID=$!
# 5. Run the E2E tests
MCP_URL=http://localhost:3001/mcp \
PAPERLESS_URL=http://localhost:8000 \
PAPERLESS_TOKEN="$TOKEN" \
npm run test:e2e
# 6. Cleanup
kill "$MCP_PID"
docker compose -f docker-compose.e2e.yml down -v
E2E测试也会在CI中自动运行,每一次拉出请求并推到 main,涵盖两个 build/index.js CLI和已出版的多克图像.
发展
要贡献还是修改服务器? 这是你需要知道的:
- 清除仓库
- 安装依赖性 :
npm install
- 更改您的服务器( J)
- 本地测试 :
node server.js http://localhost:8000 your-test-token
服务器的构建方式为:
API 文档
这个MCP服务器执行来自无纸-NGX REST API的端点. 有关相关API的更详细信息,请参见: 正式文件。 。 。 .
运行 MCP 服务器
MCP服务器可以以两种方式运行:
1. stdio(违约)
这是默认模式 。 服务器通过stdio通信,适合CLI和直接集成.
npm run start -- <baseUrl> <token>
2. HTTP(可硬化的HTTP运输)
要将服务器运行为 HTTP 服务, 请使用 --http 旗帜。 您也可以指定端口 --port (默认: 3000). 此模式需要 快递 将安装(它作为附属物列入).
npm run start -- <baseUrl> <token> --http --port 3000
- MCP API将在
POST /mcp在指定的端口上. - 每项请求均按下列方式处理: 可流式HTTPServer 运输 模式.
- 获取和删除请求
/mcp将返回 405 方法不允许.
每个请求 API 令牌( HTTP/ Docker 模式)
在HTTP模式下,客户端通过标准提供无纸-NGX API 令牌进行认证 Authorization 页眉 :
Authorization: Bearer <paperless-ngx-api-token>
令牌被直接传递到无纸-NGX,因此每个客户端自己的无纸权限被强制进行端到端. 这使得一个单一的服务器实例为多个用户服务,每个用户都有自己的代号. 同样的行为适用于双方 /mcp 财务报告和审定财务报表 /sse 结束点.
QQ 在 v2. 0.0 中突破更改—— HTTP 模式现在默认被认证 .
之前,一个请求没有
Authorization页眉悄悄倒回服务器配置PAPERLESS_API_KEY,使HTTP端点对到达港口的任何人开放。 截至v2.0.0,请求无Bearer符号以401 Unauthorized。服务器代号是 永远 用于非认证请求,除非您明确选择使用--no-auth。 。 。 .
| 假设 | --no-auth 关闭( 默认) | --no-auth 打开 |
|---|---|---|
客户端发送 Authorization: Bearer <tok> | <tok> (客户提供) | <tok> (客户提供) |
没有信头, PAPERLESS_API_KEY 编号 : --token 设定 | 401 Unauthorized | 服务器令牌 |
| 没有信头, 没有服务器代号 | 401 Unauthorized | 401 Unauthorized |
从 v1. x 移动 : 如果你们依恋旧的归宿 PAPERLESS_API_KEY 如果客户没有寄出信物,你有两种选择:
- 建议: 让每个客户端发送
Authorization: Bearer <paperless-token>。 。 。 . - 恢复旧行为 (仅受委托/本地网络):以
--no-auth旗,例如将其附加到 Docker 上command/args或你的CLI引用。 这需要服务器代号( NamePAPERLESS_API_KEY或者说--token待配置.
Docker 部署
MCP服务器可以使用多克和多克编曲部署. Docker图像在端口3000上自动以HTTP模式运行并有SSE(Server-Sent Events)支持.
Docker 编译配置
创建一个 docker-compose.yml 文件 :
services:
paperless-mcp:
container_name: paperless-mcp
image: ghcr.io/baruchiro/paperless-mcp:latest
environment:
- PAPERLESS_URL=http://your-paperless-ngx-server:8000
- PAPERLESS_API_KEY=your-paperless-api-key
- PAPERLESS_PUBLIC_URL=https://paperless-ngx.yourpublicurl.com
ports:
- "3000:3000"
restart: unless-stopped
然后运行 :
docker-compose up -d
继续使用 VS 代码扩展
如果你正在使用这个 继续 VS 代码扩展,您可以通过 SSE 配置它来使用 Dockerized MCP 服务器.
创建或编辑 .continue/mcpServers/paperless-mcp.yaml 在工作空间根 :
name: Paperless
version: 0.0.1
schema: v1
mcpServers:
- name: Paperless
type: sse
url: http://localhost:3000/sse
注释:
- 替换
localhost如果在远程服务器上运行, 则使用您的 Docker 主机的 IP 地址或主机名 - Docker 容器通过环境变量处理认证, 因此在“ 继续配置” 中不需要证书
- SSE 端点为
/sse在所配置的端口上( 默认: 3000)
贷项
这个项目是一个叉子 nloui/ 无纸- mcp多亏了原作者的作品。 捐款和改善措施可退回上游.
调试
要调试 VS 代码中的 MCP 服务器,请使用以下发射配置 :
{
"type": "node",
"request": "launch",
"name": "Debug Paperless MCP (HTTP, ts-node ESM)",
"program": "${workspaceFolder}/node_modules/ts-node/dist/bin.js",
"args": [
"--esm",
"src/index.ts",
"--http",
"--baseUrl",
"http://your-paperless-instance:8000",
"--token",
"your-api-token",
"--port",
"3002"
],
"env": {
"NODE_OPTIONS": "--loader ts-node/esm",
},
"console": "integratedTerminal",
"skipFiles": [
"<node_internals>/**"
]
}
重要内容: 调试前,请在 src/index.ts (约第175行):
// await new Promise((resolve) => setTimeout(resolve, 1000000));
这使得服务器无法立即退出,并允许您设置断点并调试代码.