关于 Paperless-ngx
paperless-ngx-mcp 通过 MCP 服务向 AI 助手开放 Paperless-ngx 文档管理操作,涵盖文档、元数据、工作流、邮件和系统任务等 REST API 功能。删除等破坏性操作设有确认保护。
主要功能
- 01搜索、读取、上传和编辑文档
- 02管理标签及文档元数据
- 03配置工作流和邮件规则
- 04访问任务、笔记和回收站
- 05破坏性操作要求确认
适用场景
- 01查找并整理扫描的发票
- 02为收件箱文档建议元数据并分流
- 03为新收文档创建工作流
- 04检查邮件规则和处理任务
MCP 相关
该 MCP 服务将 Paperless-ngx REST API 封装为工具,并注册 `triage_inbox` 等可复用提示词。它通过 `PAPERLESS_URL` 和 `PAPERLESS_API_KEY` 连接实例。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
npx -y paperless-ngx-mcpPAPERLESS_URLBase URL of your Paperless-ngx instance, e.g. https://paperless.example.comPAPERLESS_API_KEY密钥Paperless-ngx API token (My Profile → generate token)PAPERLESS_PUBLIC_URLPublic URL used for browser links to documents. Defaults to PAPERLESS_URL.本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
109收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| all | boolean | 否 | 选择 `filters` 匹配的所有文档,而不是逐一列出 ID |
| tag | number | 否 | |
| merge | boolean | 否 | 与 set_permissions 搭配且设为 true 时,与现有权限合并,而不是替换。 |
| owner | number|null | 否 | 用于 set_permissions 方法的所有者用户 ID(null 会清除所有者)。 |
| pages | string | 否 | |
| method | enum | 是 | set_correspondent | set_document_type | set_storage_path | add_tag | remove_tag | modify_tags | modify_custom_fields | delete | reprocess | set_permissions | merge | split | rotate | delete_pages | edit_pdf | remove_password |
| confirm | boolean | 否 | 当 method 为 'delete' 时必须为 true,以确认破坏性操作 |
| degrees | number | 否 | |
| filters | object | 否 | 当 all=true 时(此时必填):Paperless 文档筛选条件,例如 {"correspondent__id": 12}、{"tags__id__all": "3,4"}、{"document_type__id": 5}、{"title_content": "invoice"}。这不是 list_documents 工具的参数:请使用 correspondent__id,而不是 correspondent。未知键会被拒绝。 |
| add_tags | array | 否 | |
| password | string | 否 | remove_password:PDF 的密码 |
| documents | array | 否 | 要更改的文档 ID。使用 all + filters 进行选择时省略。 |
| operations | array | 否 | 用于 edit_pdf method 的逐页操作。每个条目:{page, rotate?, doc?}。 |
| remote_ocr | boolean | 否 | reprocess:使用 Paperless 中配置的远程 OCR 引擎而非本地引擎进行 OCR(默认 false) |
| remove_tags | array | 否 | |
| storage_path | number | 否 | |
| correspondent | number | 否 | |
| document_type | number | 否 | |
| delete_original | boolean | 否 | remove_password / edit_pdf:写入单独的新文档后删除原文档(当 update_document=true 时忽略) |
| set_permissions | object | 否 | set_permissions method 的权限授予。view/change 分别接受用户和组 ID 列表。 |
| set_permissions.view | object | 是 | |
| set_permissions.view.users | array | 否 | |
| set_permissions.view.groups | array | 否 | |
| set_permissions.change | object | 是 | |
| set_permissions.change.users | array | 否 | |
| set_permissions.change.groups | array | 否 | |
| update_document | boolean | 否 | edit_pdf / remove_password:将结果存储为同一文档的新版本,而不是创建新文档(默认 false)。 |
| delete_originals | boolean | 否 | |
| include_metadata | boolean | 否 | edit_pdf / remove_password:将元数据复制到新文档(默认 true)。 |
| add_custom_fields | array | 否 | |
| excluded_documents | array | 否 | 当 all=true 时:从选择结果中排除的 ID |
| metadata_document_id | number | 否 | |
| remove_custom_fields | array | 否 |
详细介绍
paperless-ngx-mcp
适用于 Paperless-NGX 的 Model Context Protocol 服务。向 AI 助手提供完整的 Paperless-NGX REST API:文档、标签、联系人、文档类型、自定义字段、存储路径、已保存视图、共享链接和捆绑包、工作流、邮件账户和规则、文档版本、备注、回收站和任务。

为什么选择它?
- 功能完整,始终如此。 CI 测试会检查 Paperless 的
/api/schema/中的每个端点,并与这里的工具进行比对;如果上游新增的端点既未封装,也未被有意跳过,测试就会失败。 - 经过真实 Paperless 测试。 端到端测试套件会在运行中的 Paperless-ngx 3.2.1 容器上执行这些工具,而不是使用模拟对象。
- 操作前会征求确认。 每个
delete_*工具、empty_trash、merge_documents_as_versions和批量delete都要求设置confirm: true;对“所有匹配文档”进行批量编辑时,如果筛选条件会被 Paperless 静默忽略,就会拒绝操作;而triage_inbox提示词会先提出更改建议,并等待你批准后才会写入任何内容。 - 便于设置允许列表。 以动词开头的工具名称(
list_*、get_*、delete_*……)可分别归入一个权限通配符。 - 按你的方式安装: 使用
npx、Docker 镜像、一键安装 Claude Desktop 扩展,或通过官方 MCP Registry 安装。
兼容性
目标版本为 Paperless-ngx 3.2(已在 3.2.1 上测试)。不支持更早版本的 Paperless——Paperless 2.x 请使用 [email protected]。此软件包的主版本号与其目标 Paperless-ngx 主版本保持一致;没有 1.x 或 2.x 版本。
快速开始
该服务以 paperless-ngx-mcp 的名称发布到 npm。你可以使用 npx 运行,无需克隆或构建。
Claude Code
claude mcp add paperless --scope user \
--env PAPERLESS_URL=https://your-paperless-instance \
--env PAPERLESS_API_KEY=your-api-token \
-- npx -y paperless-ngx-mcp
省略 --scope user 即可仅为当前项目安装。更多选项请参阅 claude mcp add --help。
Codex CLI
codex mcp add paperless \
--env PAPERLESS_URL=https://your-paperless-instance \
--env PAPERLESS_API_KEY=your-api-token \
-- npx -y paperless-ngx-mcp
此操作会将条目写入 ~/.codex/config.toml。
Claude Desktop(扩展)
从最新版本下载 paperless-ngx-mcp.mcpb 并双击,或从 设置 → 扩展 中安装。Claude Desktop 会询问你的 Paperless URL 和 API 令牌。
Claude Desktop、Cursor、Cline 和其他 MCP 客户端
这些按钮会安装占位值;之后请替换 PAPERLESS_URL 和 PAPERLESS_API_KEY。或者将以下内容添加到客户端的 MCP 配置文件中(例如 claude_desktop_config.json、~/.cursor/mcp.json、~/.config/cline/mcp.json):
{
"mcpServers": {
"paperless": {
"command": "npx",
"args": ["-y", "paperless-ngx-mcp"],
"env": {
"PAPERLESS_URL": "https://your-paperless-instance",
"PAPERLESS_API_KEY": "your-api-token",
"PAPERLESS_PUBLIC_URL": "https://your-public-domain"
}
}
}
}
Docker
多架构镜像(amd64、arm64)已发布到 ghcr.io/cubinet-code/paperless-ngx-mcp。在任何 MCP 客户端配置中将其用作 stdio 服务:
{
"mcpServers": {
"paperless": {
"command": "docker",
"args": ["run", "-i", "--rm", "-e", "PAPERLESS_URL", "-e", "PAPERLESS_API_KEY", "ghcr.io/cubinet-code/paperless-ngx-mcp"],
"env": {
"PAPERLESS_URL": "https://your-paperless-instance",
"PAPERLESS_API_KEY": "your-api-token"
}
}
}
}
也可以将其用作长期运行的 Streamable HTTP 服务。它没有身份验证,因此请勿将其部署在不可信的网络中:
docker run -d -p 127.0.0.1:3000:3000 \
-e PAPERLESS_URL=https://your-paperless-instance \
-e PAPERLESS_API_KEY=your-api-token \
ghcr.io/cubinet-code/paperless-ngx-mcp --http --port 3000
获取 Paperless-NGX API 令牌
- 登录你的 Paperless-NGX 实例。
- 点击你的用户名(右上角)→ 我的个人资料。
- 点击圆形箭头按钮以生成新令牌。
配置
| 变量 | 必填 | 用途 |
|---|---|---|
PAPERLESS_URL | 是 | MCP 服务用于与 Paperless-NGX 通信的基础 URL。 |
PAPERLESS_API_KEY | 是 | API 令牌(见上文)。 |
PAPERLESS_PUBLIC_URL | 否 | 助手用于构建文档浏览器链接的公共 URL。未设置时会回退到 PAPERLESS_URL。 |
CLI 标志(--baseUrl、--token、--publicUrl、--http、--port,以及 HTTP 会话限制)的优先级高于环境变量。
使用示例
你可以这样向 Claude(或任何支持 MCP 的助手)提问:
- “显示所有标记为‘Invoice’的文档”
- “搜索包含‘tax return’的文档”
- “创建一个名为‘Receipts’、颜色为 #FF0000 的新标签”
- “下载文档 #123”
- “列出所有往来联系人”
- “创建一个名为‘Bank Statement’的新文档类型”
- “清空回收站”
- “显示待处理的文档导入任务”
- “将往来联系人‘ACME GmbH (mail)’的所有文档移到‘ACME GmbH’”
- “移除文档 #55 的密码,并将解锁后的文件保留为新版本”
- “创建一个工作流,为上传的银行对账单移除 PDF 密码”
- “哪条邮件规则会为每个发件人创建新的往来联系人?”
可用工具
该服务会注册涵盖十二个领域的工具。
文档
list_documents、get_document、get_document_content、search_documents、download_document、download_documents_bulk、get_document_thumbnail、get_document_preview、get_document_history、get_document_metadata、update_document、post_document、email_document、edit_documents_bulk、delete_document、search_autocomplete、get_document_suggestions、get_document_ai_suggestions、get_next_asn、upload_document_version、update_document_version、delete_document_version、merge_documents_as_versions
标签
list_tags、get_tag、create_tag、update_tag、delete_tag、edit_tags_bulk
往来联系人
list_correspondents、get_correspondent、create_correspondent、update_correspondent、delete_correspondent、edit_correspondents_bulk
文档类型
list_document_types、get_document_type、create_document_type、update_document_type、delete_document_type、edit_document_types_bulk
自定义字段
list_custom_fields、get_custom_field、create_custom_field、update_custom_field、delete_custom_field、edit_custom_fields_bulk
存储路径
list_storage_paths、get_storage_path、create_storage_path、update_storage_path、delete_storage_path、test_storage_path
已保存视图
list_saved_views、get_saved_view、create_saved_view、update_saved_view、delete_saved_view
分享链接
list_share_links、list_document_share_links、get_share_link、create_share_link、delete_share_link、list_share_link_bundles、get_share_link_bundle、create_share_link_bundle、rebuild_share_link_bundle、delete_share_link_bundle
工作流
list_workflows、get_workflow、create_workflow、update_workflow、delete_workflow、list_workflow_actions、get_workflow_action、create_workflow_action、update_workflow_action、delete_workflow_action、list_workflow_triggers、get_workflow_trigger、create_workflow_trigger、update_workflow_trigger、delete_workflow_trigger
邮件
list_mail_accounts、get_mail_account、create_mail_account、update_mail_account、delete_mail_account、test_mail_account、process_mail_account、list_mail_rules、get_mail_rule、create_mail_rule、update_mail_rule、delete_mail_rule
系统 / 备注 / 回收站 / 任务
get_statistics、get_system_status、get_filing_options、list_document_notes、create_document_note、delete_document_note、list_trash、restore_from_trash、empty_trash、list_tasks、list_active_tasks、get_task_status_counts、get_task_summary、acknowledge_tasks
工具命名约定(用于权限允许列表)
工具名称采用动词优先的形式,因此基于通配符的权限规则可以按操作清晰分组:
| 通配符 | 包含范围 |
|---|---|
mcp__paperless__list_* | 所有列表 / 索引读取操作 |
mcp__paperless__get_* | 所有单项读取操作 |
mcp__paperless__search_* | 全文搜索和自动补全 |
mcp__paperless__download_* | download_document 和 download_documents_bulk |
mcp__paperless__create_* | 所有创建端点 |
mcp__paperless__update_* | 单项 PATCH 更新 |
mcp__paperless__edit_*_bulk | 跨实体类型的所有批量编辑操作 |
mcp__paperless__delete_* | ⚠️ 具有破坏性——系统范围内的删除 |
mcp__paperless__test_* | 试运行检查:test_storage_path、test_mail_account |
mcp__paperless__upload_* | upload_document_version |
mcp__paperless__rebuild_* | rebuild_share_link_bundle |
mcp__paperless__merge_* | ⚠️ merge_documents_as_versions——合并后的文档将不再独立存在 |
mcp__paperless__process_* | process_mail_account——立即获取邮件并运行相应规则(这些规则可能会删除或移动服务器上的邮件) |
因此,只读允许列表为:list_*、get_*、search_*、download_*、test_*。若要允许写入但不允许破坏性操作,请添加 create_*、update_*、edit_*_bulk、upload_*、rebuild_*、post_document、email_document、restore_from_trash、acknowledge_tasks。delete_*、merge_*、process_* 和 empty_trash 应要求用户明确批准。
提示词
该服务还会注册 MCP 提示词——可重复使用、带参数的指令,会在 Claude Code 等客户端中显示为斜杠命令(例如 /mcp__paperless__triage_inbox)。
triage_inbox
引导助手完成收件箱整理:收集现有标签 / 联系人 / 文档类型,为每份收件箱文档建议元数据,优先使用现有条目,展示确认表格,并且仅在用户回复 apply 后应用更改。新的联系人 / 类型 / 标签会标记为 (NEW),以便你在创建之前否决。
参数:
limit(可选,默认值为25):单次整理的收件箱文档数量上限。
值得注意的工具细节
edit_documents_bulk
对多个文档执行批量操作。
参数:
- 选择方式:
documents(ID 数组),或all: true+filters,并可选提供excluded_documents。filters使用 Paperless 文档筛选器名称,例如correspondent__id、tags__id__all、document_type__id、title_content或query,而不是list_documents的工具参数。Paperless 不认识的键会被拒绝(否则它会忽略这些键并选中所有文档);预览查询会捕获无效值,结果会报告matched_documents。all: true不支持merge、split、delete_pages、edit_pdf或remove_password。 method:以下选项之一:set_correspondent、set_document_type、set_storage_path、add_tag、remove_tag、modify_tags、modify_custom_fields、delete、reprocess、set_permissions、merge、split、rotate、delete_pages、edit_pdf、remove_password- 方法专用参数:
correspondent、document_type、storage_path、tag、add_tags、remove_tags、add_custom_fields、remove_custom_fields、set_permissions、owner、merge、metadata_document_id、delete_originals、pages、degrees、operations、update_document、include_metadata、password、delete_original、remote_ocr
// Add a tag to multiple documents
edit_documents_bulk({ documents: [1, 2, 3], method: "add_tag", tag: 5 })
// Merge documents
edit_documents_bulk({
documents: [6, 7, 8],
method: "merge",
metadata_document_id: 6,
delete_originals: true,
})
// Split a document into parts
edit_documents_bulk({ documents: [9], method: "split", pages: "[1-2,3-4,5]" })
// Modify multiple tags at once
edit_documents_bulk({
documents: [10, 11],
method: "modify_tags",
add_tags: [1, 2],
remove_tags: [3, 4],
})
// Move every document from a duplicate correspondent (12) to the canonical one (34)
edit_documents_bulk({ all: true, filters: { correspondent__id: 12 }, method: "set_correspondent", correspondent: 34 })
// Unlock a password-protected PDF, keeping the result as a new version
edit_documents_bulk({ documents: [55], method: "remove_password", password: "…", update_document: true })
即使 Paperless 跳过某个文档(其最新版本未加密)或密码错误,remove_password 仍会返回 OK,因此请之后检查文档的 versions。
工作流
工作流由触发器及其执行的操作组成,是 Paperless 实际执行的内容;create_workflow 可通过一次调用创建工作流。独立的触发器和操作(create_workflow_trigger / create_workflow_action)本身不会执行任何操作;每当更新任何工作流时,Paperless 都会删除未关联的触发器和操作。
- 操作类型:1 分配,2 移除,3 电子邮件,4 Webhook,5 移除密码,6 移至回收站,7 远程 OCR,8 应用 AI 建议。远程 OCR 需要一个已开始处理的触发器;AI 建议需要一个处理开始触发器以外的触发器。
update_workflow只会更改你传入的内容,但triggers或actions列表会替换整个列表:带有id的条目会被更新,不带id的条目会被创建,未提供的条目会被删除。可以编辑get_workflow的输出并直接传回。- 移除密码操作中的 PDF 密码始终会以掩码形式返回(
**********)。传回掩码列表会保留已存储的密码;新操作则需要提供真实密码。 - 触发器检查哪些筛选条件取决于触发器类型:
sources、filter_path和filter_mailrule仅适用于处理开始触发器(类型 1);标签、往来对象、类型、存储路径筛选条件、filter_custom_field_query和内容匹配仅适用于已添加/已更新/计划执行的触发器(类型 2–4);filter_filename适用于所有类型。
文档版本
upload_document_version 会向现有文档添加新文件(例如已签名的副本或更正后的扫描件),而 merge_documents_as_versions 会将重复文档合并为一个文档。内容、搜索、下载和 get_document_metadata 使用最新版本,但 page_count 以及 get_document 中的文件名描述的是原始(根)版本;请检查 get_document_content,以确认当前版本是否可读取。
阅读和编辑单个文档
get_filing_options一次调用即可返回所有标签、联系人、文档类型、存储路径和自定义字段(id + 名称)——归档前先获取一次,避免猜测 ID。update_document接受add_tags/remove_tags,可更改单个标签而不影响其他标签。tags会替换整个列表。每次标签变更都会返回tag_changes: { added, removed }。list_documents接受ids,可在一次调用中读取多个已知文档;也接受fields(get_document也支持),仅返回所需内容,例如["title", "tags"]。get_document_content接受max_chars和offset,用于处理长文档;结果会报告total_chars和truncated。Paperless 存储的文本没有分页边界,因此切片按字符计算。search_documents搜索全文索引(mode:高级语法使用query——这是默认值;普通词语使用text;仅搜索标题使用title)。索引可能有延迟;使用search调用list_documents会直接从数据库匹配子字符串。
post_document
上传新文档。
参数:file、filename,以及可选的 title、created、correspondent、document_type、storage_path、tags、archive_serial_number、custom_fields、poll、poll_timeout_seconds。
file 接受经过 base64 编码的内容(通用方法,适用于任何部署,因为字节会通过网络传输),或者接受服务器从自身文件系统读取的绝对文件路径。路径选项仅在 MCP 服务与文件位于同一台机器上时有效(本地/stdio 部署);对于远程服务,请使用 base64。
上传是异步的。默认情况下,工具会返回任务 UUID(通过 list_tasks 跟踪)。设置 poll: true 可等待使用方完成,并在一次调用中获取结果——成功时返回新的 document_id,失败时返回使用方错误。poll_timeout_seconds(默认值为 30,最大值为 300)限制等待时长;对于 OCR 较慢的大型扫描件,请调高此值。
匹配算法
create_tag、create_correspondent、create_document_type 和 create_storage_path 接受 matching_algorithm(0–6)。工作流触发器接受 0–5(不含 Automatic):
| 值 | 含义 |
|---|---|
| 0 | 无 |
| 1 | 任意词语 |
| 2 | 所有词语 |
| 3 | 完全匹配 |
| 4 | 正则表达式 |
| 5 | 模糊词语 |
| 6 | 自动 |
从 Paperless-ngx 3.2 起,只有在分类器置信度足够高时,自动匹配才会分配项目(PAPERLESS_CLASSIFIER_MATCH_THRESHOLD,默认值为 0.6);正则表达式匹配会在 PAPERLESS_MATCH_REGEX_TIMEOUT_SECONDS(默认值为 0.1 s)后放弃——如果正则表达式规则无法匹配较长的文档,请调高此值。
运行 MCP 服务
stdio(默认)
默认模式。服务通过 stdio 通信——快速入门中的每个 MCP 客户端配置都使用此模式。通常无需手动运行;MCP 客户端会为你启动它。
如果确实要直接运行(例如用于调试):
# via env vars (recommended)
PAPERLESS_URL=http://localhost:8000 PAPERLESS_API_KEY=xxx npx -y paperless-ngx-mcp
# or via CLI flags
npx -y paperless-ngx-mcp --baseUrl http://localhost:8000 --token xxx
HTTP(Streamable HTTP 传输)
使用 --http 标志通过 HTTP 暴露服务。--port 的默认值为 3000。
npx -y paperless-ngx-mcp --baseUrl http://localhost:8000 --token xxx --http --port 3000
- MCP API 可通过所选端口上的
POST /mcp访问,并由StreamableHTTPServerTransport以有状态模式提供支持。 - 第一个请求(
initialize调用)会创建会话并返回Mcp-Session-Id标头;后续请求必须发送该标头,以复用同一会话。传输会保存在内存中的Map中,因此仅适用于单实例部署。 GET /mcp会为会话传输由服务器发起的消息;DELETE /mcp会终止会话并将其从映射中移除。两者都需要有效的Mcp-Session-Id标头。- 此外,还提供旧版
GET /sse+POST /messagesSSE 传输,供尚不支持流式传输的客户端使用。
会话限制
每个会话都持有自己的 MCP 服务实例(约 3.5 MB),且 HTTP 端口没有身份验证,因此会话数量受到限制:
| 标志 | 环境变量 | 默认值 | 用途 |
|---|---|---|---|
--maxSessions | PAPERLESS_MAX_SESSIONS | 50 | 允许的并发会话数。超过此数量后,initialize 会被拒绝,并返回 HTTP 503。 |
--sessionIdleMinutes | PAPERLESS_SESSION_IDLE_MINUTES | 30 | 会话无活动达到此时长后,将其逐出。 |
处于活动连接状态的客户端(包括保持 GET /mcp 流打开的客户端)永远不会被逐出,无论其空闲多久。只有真正被弃用的会话才会被回收。
由于会话存储在内存中,--http 仅适用于单实例部署。请勿将端口暴露给不可信网络:此服务没有身份验证,并且会绑定所有网络接口。
错误处理
工具调用会在以下情况下返回明确的错误:
PAPERLESS_URL或PAPERLESS_API_KEY缺失或不正确- 无法连接到 Paperless-NGX 服务
- 底层 API 拒绝操作时,会原样传递 Paperless 自身的消息(例如
{"non_field_errors":["password not specified"]} (HTTP 400));HTML 错误页面则会简化为状态行 - Paperless 调用未能在 90 秒内完成(下载除外);对于超时的写入操作,错误会警告更改可能已经生效
- 工具参数未通过验证
开发
只有在修改服务本身时才需要阅读本节。最终用户应改为遵循快速入门——无需克隆或构建。
git clone https://github.com/cubinet-code/paperless-ngx-mcp.git
cd paperless-ngx-mcp
npm install # install dependencies
npm run start # run the server with tsx (no build step)
npm run build # compile TypeScript to build/
npm test # unit tests (node:test + tsx)
npm run inspect # build, then launch @modelcontextprotocol/inspector
npm run start 接受与构建后的二进制文件相同的标志和环境变量。
端到端测试
E2E 测试会通过 Docker Compose 启动一个真实的 Paperless-NGX 容器:
npm run test:e2e:up # start the test stack (paperless + redis)
npm run test:e2e # run the e2e suite against it
npm run test:e2e:down # tear down and remove volumes
使用 ghcr.io/paperless-ngx/paperless-ngx:3.2.1 运行测试。
基于以下项目构建:
- @modelcontextprotocol/sdk — MCP 服务 SDK
- zod — 架构验证
- axios — HTTP 客户端(使用 keep-alive Agent、60s 空闲超时和 90s 单请求截止时间)
API 文档
此 MCP 服务封装了 Paperless-NGX REST API 的端点。有关底层行为和字段语义的详细信息,请参阅官方 API 文档。
许可证
ISC。请参阅 LICENSE。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。