mcpField
P
Paperless-NGX MCP Server

Paperless-NGX MCP Server

ローカル
github.com/baruchiroファイル・ストレージ1486 週間前に更新

Paperless-NGX MCP Server について

Paperless-NGX MCP Server は、REST API を通じて Paperless-NGX インスタンスの文書、タグ、取引先、文書タイプを管理する MCP サーバーです。スキャン文書の検索、アップロード、整理を AI アシスタントに任せたい利用者を想定しています。STDIO と Docker による HTTP の両方の方式で実行できます。

主な機能

  1. 01文書の検索、取得、ダウンロード
  2. 02Base64 データまたはファイルパスによる文書のアップロード
  3. 03タグ、取引先、文書タイプ、カスタムフィールドの管理
  4. 04取引先の設定や統合などの一括編集
  5. 05文書へのノートの追加と削除

活用シーン

  1. 01タグや日付で請求書や領収書を検索
  2. 02スキャン文書に一括でタグを付け、文書タイプを設定
  3. 03許可されたサーバーディレクトリからスキャンファイルを Paperless-NGX にアップロード

MCP 対応

本プロジェクトは MCP サーバーであり、Paperless-NGX の文書、タグ、取引先の操作をツールとして MCP クライアントに公開します。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"paperless": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"compose"
]
}
}
}
起動コマンドdocker run -i --rm compose

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
ocicompose

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

Paperless-NGX MCP サーバー

CodeRabbit Pull Request Reviews

Paperless-NGX API サーバーと連携するための MCP(Model Context Protocol)サーバーです。このサーバーは、お使いの Paperless-NGX インスタンスでドキュメント、タグ、連絡先、ドキュメント種別を管理するツールを提供します。

クイックスタート

MCP サーバーをインストール

インストール

MCP 設定ファイルに以下を追加します。

// STDIO モード(ローカルまたは 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 モード(Docker またはリモートでの使用に推奨)

"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"
  }
}
  1. API トークンを取得します。

    1. Paperless-NGX インスタンスにログインします
    2. 右上にあるユーザー名をクリックします
    3. 「My Profile」を選択します
    4. 円形の矢印ボタンをクリックして、新しいトークンを生成します
  2. MCP 設定のプレースホルダーを置き換えます。

    • http://your-paperless-instance:8000 を Paperless-NGX の URL に置き換えます
    • your-api-token を生成したトークンに置き換えます
    • https://your-public-domain.com を Paperless-NGX の公開 URL に置き換えます(任意。指定しない場合は PAPERLESS_URL が使用されます)
環境変数
変数必須デフォルト説明
PAPERLESS_URLはい—Paperless-NGX インスタンスのベース URL
PAPERLESS_API_KEYはい—Paperless-NGX プロフィールにある API トークン
PAPERLESS_PUBLIC_URLいいえPAPERLESS_URLドキュメントリンク用の公開 URL
PAPERLESS_API_VERSIONいいえ9Paperless-ngx REST API のバージョンです。9 は Paperless-ngx v2.x(最近のバージョン)および v3.x で動作します。Paperless-ngx v3.0.0 では 9 未満のバージョンのサポートが廃止されたため、古いデフォルト値では HTTP 406 が返されるようになりました。HTTP 406 エラーが発生する場合は、サーバーがサポートするバージョンを設定してください。
PAPERLESS_MCP_UPLOAD_PATHSいいえ—file_path によるアップロードを許可するディレクトリのコロン区切りリストです。セキュリティ上、設定を推奨します。 例:/var/uploads:/tmp/scans

以上です。これで Claude に Paperless-NGX のドキュメント管理を依頼できます。

使用例

Claude には、次のような操作を依頼できます。

  • 「Invoice」タグが付いたすべてのドキュメントを表示する
  • 「tax return」を含むドキュメントを検索する
  • 色が #FF0000 の「Receipts」という新しいタグを作成する
  • ドキュメント #123 をダウンロードする
  • すべての連絡先を一覧表示する
  • 「Bank Statement」という新しいドキュメント種別を作成する

利用可能なツール

ドキュメント操作
list_documents

シンプルなフィルターを使用して、ドキュメントのページ分けされた一覧を取得します。単純な一覧表示にはこのツールを使用してください。全文検索、カスタムフィールドの構造化フィルタリング、高度な Paperless フィルターには、query_documents を使用してください。

パラメーター:

  • page(任意):ページ番号
  • page_size(任意):1 ページあたりのドキュメント数
  • search(任意):シンプルな Paperless 検索語
  • correspondent(任意):連絡先 ID
  • document_type(任意):ドキュメント種別 ID
  • tag(任意):タグ ID
  • storage_path(任意):保存先パス ID
  • created__date__gte(任意):YYYY-MM-DD 以降に作成された日付
  • created__date__lte(任意):YYYY-MM-DD 以前に作成された日付
  • ordering(任意):Paperless の並べ替えフィールド
  • archive_serial_number(任意):アーカイブ通し番号
  • archive_serial_number__isnull(任意):アーカイブ通し番号が空かどうか
  • custom_field_query(任意):Paperless カスタムフィールドクエリをエンコードした生の JSON 文字列
  • custom_fields__icontains(任意):カスタムフィールドの値全体を対象とした、大文字と小文字を区別しない部分文字列一致
list_documents({
  page: 1,
  page_size: 25
})
query_documents

標準のドキュメントクエリツールです。全文検索、Paperless の簡易検索、カスタムフィールドフィルター、ドキュメント化されている /api/documents/ の Paperless クエリパラメーターに対応しています。

パラメーター:

  • page(任意):ページ番号
  • page_size(任意):1 ページあたりのドキュメント数
  • ordering(任意):Paperless の並べ替えフィールド
  • query(任意):全文検索クエリ文字列
  • search(任意):Paperless の簡易検索語句
  • more_like_id(任意):このドキュメント ID に類似するドキュメントを検索
  • correspondent(任意):取引先 ID
  • document_type(任意):ドキュメント種別 ID
  • tag(任意):タグ ID
  • storage_path(任意):ストレージパス ID
  • created__date__gte(任意):YYYY-MM-DD 以降の作成日
  • created__date__lte(任意):YYYY-MM-DD 以前の作成日
  • custom_field_query(任意):[field_name_or_id, operator, value] のリーフ、または ["AND" | "OR", [clause1, clause2]] のグループを使用した、構造化された Paperless カスタムフィールドクエリ
  • paperless_filters(任意):追加のドキュメント化された /api/documents/ の Paperless クエリパラメーターを、キーと値のペアとして渡します
// 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]
  }
})
get_document

ID を指定して特定のドキュメントを取得します。

パラメーター:

  • id:ドキュメント ID
get_document({
  id: 123
})
search_documents

全文検索用の非推奨の互換ラッパーです。新しい連携では query_documents({ query: ... }) を使用してください。

パラメーター:

  • query:検索クエリ文字列
search_documents({
  query: "invoice 2024"
})
download_document

ID を指定してドキュメントファイルをダウンロードします。

パラメーター:

  • id:ドキュメント ID
  • original(任意):true の場合、アーカイブ版ではなく元のファイルをダウンロードします
download_document({
  id: 123,
  original: false
})
get_document_thumbnail

ID を指定してドキュメントのサムネイル(画像プレビュー)を取得します。サムネイルは、Base64 エンコードされた WebP 画像リソースとして返されます。

パラメーター:

  • id:ドキュメント ID
get_document_thumbnail({
  id: 123
})
bulk_edit_documents

複数のドキュメントに対して一括操作を行います。

パラメーター:

  • documents:ドキュメント ID の配列
  • method:次のいずれか:
    • set_correspondent:ドキュメントの取引先を設定
    • set_document_type:ドキュメントの種別を設定
    • set_storage_path:ドキュメントのストレージパスを設定
    • add_tag:ドキュメントにタグを追加
    • remove_tag:ドキュメントからタグを削除
    • modify_tags:複数のタグを追加および/または削除
    • delete:ドキュメントを削除
    • reprocess:ドキュメントを再処理
    • set_permissions:ドキュメントの権限を設定
    • merge:複数のドキュメントを結合
    • split:ドキュメントを複数のドキュメントに分割
    • rotate:ドキュメントのページを回転
    • delete_pages:ドキュメントの特定のページを削除
  • method に応じた追加パラメーター:
    • correspondent:set_correspondent 用の ID
    • document_type:set_document_type 用の ID
    • storage_path:set_storage_path 用の ID
    • tag:add_tag/remove_tag 用の ID
    • add_tags:modify_tags 用のタグ ID の配列
    • remove_tags:modify_tags 用のタグ ID の配列
    • set_permissions:set_permissions 用のオブジェクト。閲覧/変更ユーザーとグループを指定します({"view": {"users": [], "groups": []}, "change": {...}})。省略されたアクション/リストは変更されません
    • owner:set_permissions 用のユーザー ID(または削除する場合は null)。merge が true でない場合、owner を省略すると現在の所有者がクリアされます
    • merge:set_permissions 用のブール値。true の場合は既存の権限に追加し、所有者を維持します。false(デフォルト)の場合は、指定されたユーザー/グループを置き換えます
    • metadata_document_id:結合時にメタデータのソースを指定する ID
    • delete_originals:結合/分割時に使用するブール値
    • pages:分割用の文字列 "[1,2-3,4,5-7]"、または delete_pages 用の文字列 "[2,3,4]"
    • degrees:rotate 用の数値(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: []
})
post_document

Paperless-NGX に新しいドキュメントをアップロードします。

2 つのアップロードモード:

  1. Base64 モード(従来型):file(Base64 エンコードされたコンテンツ)と filename を指定します
  2. ファイルシステムモード(効率的):file_path(サーバー上の絶対パス)を指定します

セキュリティに関する注意: file_path を使用する場合は、PAPERLESS_MCP_UPLOAD_PATHS 環境変数(許可するディレクトリをコロン区切りで指定)を設定し、アップロード先を特定の場所に制限してください。設定しない場合、サーバーのファイルシステム上にある任意のファイルをアップロードできてしまいます。

パラメーター:

  • file(任意):Base64 エンコードされたファイルコンテンツ。file または file_path のいずれかが必要です。
  • file_path(任意):サーバーのファイルシステム上にあるファイルの絶対パス。file または file_path のいずれかが必要です。
  • filename(任意):ファイル名。file と併用する場合は必須で、file_path と併用する場合は任意です(パスから取得されます)。
  • title(任意):ドキュメントのタイトル
  • created(任意):ドキュメントの作成日時(例:"2024-01-19" または "2024-01-19 06:15:00+02:00")
  • correspondent(任意):取引先の ID
  • document_type(任意):ドキュメントタイプの ID
  • storage_path(任意):ストレージパスの ID
  • tags(任意):タグ ID の配列
  • archive_serial_number(任意):アーカイブシリアル番号
  • custom_fields(任意):カスタムフィールド 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]
})
ドキュメントのメモ
list_document_notes

ドキュメントに添付されたすべてのメモを一覧表示します。

パラメーター:

  • id:ドキュメント ID
list_document_notes({
  id: 123
})
create_document_note

ドキュメントにメモを追加します。ドキュメントのすべてのメモを返します。

パラメーター:

  • id:ドキュメント ID
  • note:追加するメモのテキスト
create_document_note({
  id: 123,
  note: "Invoice paid on 2026-06-30 from Commerzbank account."
})
delete_document_note

⚠️ note ID を指定して、ドキュメントから単一のメモを削除します。この操作は取り消せません。

パラメーター:

  • id:ドキュメント ID
  • note_id:削除するメモの ID
  • confirm:この破壊的な操作を確認するには true を指定する必要があります
delete_document_note({
  id: 123,
  note_id: 5,
  confirm: true
})
タグ操作
list_tags

すべてのタグを取得します。

list_tags()
create_tag

新しいタグを作成します。

パラメーター:

  • name:タグ名
  • color(任意):16 進数のカラーコード(例:"#ff0000")
  • match(任意):照合するテキストパターン
  • matching_algorithm(任意):0 から 6 までの数値: 0 - なし 1 - いずれかの単語 2 - すべての単語 3 - 完全一致 4 - 正規表現 5 - あいまいな単語 6 - 自動
create_tag({
  name: "Invoice",
  color: "#ff0000",
  match: "invoice",
  matching_algorithm: 5
})
取引先操作
list_correspondents

すべての取引先を取得します。

list_correspondents()
create_correspondent

新しい取引先を作成します。

パラメーター:

  • name:取引先名
  • match(任意):照合するテキストパターン
  • matching_algorithm(任意):0 から 6 までの数値: 0 - なし 1 - いずれかの単語 2 - すべての単語 3 - 完全一致 4 - 正規表現 5 - あいまいな単語 6 - 自動
create_correspondent({
  name: "ACME Corp",
  match: "ACME",
  matching_algorithm: 5
})
ドキュメントタイプ操作
list_document_types

すべてのドキュメントタイプを取得します。

list_document_types()
create_document_type

新しいドキュメントタイプを作成します。

パラメーター:

  • name:ドキュメントタイプ名
  • match(任意):照合するテキストパターン
  • matching_algorithm(任意):0 から 6 までの数値: 0 - なし 1 - いずれかの単語 2 - すべての単語 3 - 完全一致 4 - 正規表現 5 - あいまいな単語 6 - 自動
create_document_type({
  name: "Invoice",
  match: "invoice total amount due",
  matching_algorithm: 1
})
カスタムフィールド操作
list_custom_fields

すべてのカスタムフィールドを取得します。

list_custom_fields()
get_custom_field

ID を指定して、特定のカスタムフィールドを取得します。

パラメーター:

  • id:カスタムフィールド ID
get_custom_field({
  id: 1
})
create_custom_field

新しいカスタムフィールドを作成します。

パラメーター:

  • name:カスタムフィールド名
  • data_type:"string"、"url"、"date"、"boolean"、"integer"、"float"、"monetary"、"documentlink"、"select" のいずれか
  • extra_data(任意):選択肢など、カスタムフィールドの追加データ
create_custom_field({
  name: "Invoice Number",
  data_type: "string"
})
update_custom_field

既存のカスタムフィールドを更新します。

パラメーター:

  • id:カスタムフィールド ID
  • name(任意):新しいカスタムフィールド名
  • data_type(任意):新しいデータ型
  • extra_data(任意):カスタムフィールドの追加データ
update_custom_field({
  id: 1,
  name: "Updated Invoice Number",
  data_type: "string"
})
delete_custom_field

カスタムフィールドを削除します。

パラメーター:

  • id:カスタムフィールド ID
delete_custom_field({
  id: 1
})
bulk_edit_custom_fields

複数のカスタムフィールドに対して一括操作を実行します。

パラメーター:

  • custom_fields:カスタムフィールド ID の配列
  • operation:「delete」のいずれか
bulk_edit_custom_fields({
  custom_fields: [1, 2, 3],
  operation: "delete"
})
メール操作

Paperless のメールアカウントと、自動メール取り込みを制御するメールルールを管理するツールです。アカウントのパスワード/トークンが公開されることはありません。すべてのツールの応答で伏せ字になります。

list_mail_accounts

メールアカウントを一覧表示します。メールルールの作成時に必要なアカウント ID を選択できます。パスワードは伏せ字になります。

パラメーター:

  • page(任意):ページ番号
  • page_size(任意):1 ページあたりの結果数
list_mail_accounts()
get_mail_account

ID を指定して単一のメールアカウントを取得します。パスワード/トークンのフィールドは伏せ字になります。

パラメーター:

  • id:メールアカウント ID
get_mail_account({
  id: 1
})
process_mail_account

アカウントを指定して、Paperless のメール処理を手動で実行します。有効なメールルールに一致するメールが処理される場合があります。

パラメーター:

  • id:メールアカウント ID
process_mail_account({
  id: 1
})
list_mail_rules

ページネーションを指定してメールルールを一覧表示します。

パラメーター:

  • page(任意):ページ番号
  • page_size(任意):1 ページあたりの結果数
list_mail_rules()
get_mail_rule

ID を指定して単一のメールルールを取得します。

パラメーター:

  • id:メールルール ID
get_mail_rule({
  id: 1
})
create_mail_rule

メールルールを作成します。最初に list_mail_accounts を使ってアカウントを選択してください。

必須パラメーター:

  • name:ルール名
  • account:メールアカウント ID
  • folder:スキャンする IMAP フォルダー(例:「INBOX」)

主な任意パラメーター:

  • enabled(既定値は true):ルールを有効にするかどうか
  • filter_from / filter_to / filter_subject / filter_body:受信メールの照合条件
  • maximum_age:この日数より新しいメールのみを処理
  • action:1=削除、2=フォルダーへ移動、3=既読にする、4=フラグを付ける、5=タグを付ける
  • action_parameter:選択したアクションの対象フォルダー/タグ
  • assign_title_from:1=件名、2=添付ファイル名、3=割り当てない
  • assign_tags / assign_correspondent / assign_document_type:適用するメタデータ
  • assign_correspondent_from:1=なし、2=メールアドレス、3=送信者名、4=assign_correspondent を使用
  • attachment_type:1=添付ファイルのみ、2=インラインを含むすべてのファイル
  • consumption_scope:1=添付ファイルのみ、2=メール全体を .eml として処理、3=両方
  • pdf_layout:0=システム既定、1=テキスト+HTML、2=HTML+テキスト、3=HTML のみ、4=テキストのみ
create_mail_rule({
  name: "Invoices",
  account: 1,
  folder: "INBOX",
  filter_subject: "invoice",
  action: 3,
  attachment_type: 1
})
update_mail_rule

既存のメールルールにパッチを適用します。指定したフィールドのみが変更されます。

パラメーター:

  • id:メールルール ID
  • ...更新する create_mail_rule のフィールド
update_mail_rule({
  id: 1,
  enabled: false
})
delete_mail_rule

メールルールを削除します。明示的な確認フラグが必要です。今後のメール取り込み動作は変更されますが、既存のドキュメントは削除されません。

パラメーター:

  • id:メールルール ID
  • confirm:削除を確認するには true を指定する必要があります
delete_mail_rule({
  id: 1,
  confirm: true
})

エラー処理

次の場合、サーバーは明確なエラーメッセージを表示します:

  • Paperless-NGX の URL または API トークンが正しくない
  • Paperless-NGX サーバーに接続できない
  • 要求された操作に失敗した
  • 指定されたパラメーターが無効である

テスト

単体テスト

単体テストスイートを実行します(外部依存関係は不要です):

npm test
E2E テスト

E2E テストスイートは空の Paperless-ngx インスタンスを起動し、コンパイル済みの MCP サーバーを実行して、tools/call リクエストを通じた決定論的な逐次シナリオを実行します。タグ、コレスポンデント、ドキュメントタイプを作成し、PDF をアップロードした後、同じドキュメントに対して一覧表示/取得/検索/ダウンロード/サムネイル/一括編集をテストします。LLM や、MCP の外部にある Paperless REST クライアントは使用しません。

前提条件: Docker、Docker Compose、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 テストは、すべてのプルリクエストと main へのプッシュ時に CI でも自動実行され、build/index.js CLI と公開済み Docker イメージの両方をテストします。

開発

サーバーへの貢献や変更をお考えですか?必要な情報をご紹介します。

  1. リポジトリをクローンします
  2. 依存関係をインストールします:
npm install
  1. server.js を変更します
  2. ローカルでテストします:
node server.js http://localhost:8000 your-test-token

サーバーは以下を使用して構築されています:

  • litemcp:MCP サーバーを構築するための TypeScript フレームワーク
  • zod:TypeScript を第一に考えたスキーマ検証ライブラリ

API ドキュメント

この MCP サーバーは Paperless-NGX REST API のエンドポイントを実装しています。基盤となる API の詳細については、公式ドキュメントをご覧ください。

MCP サーバーの実行

MCP サーバーは 2 つのモードで実行できます。

1. stdio(デフォルト)

これはデフォルトのモードです。サーバーは stdio 経由で通信し、CLI や直接的な統合に適しています。

npm run start -- <baseUrl> <token>
2. HTTP(Streamable HTTP トランスポート)

サーバーを HTTP サービスとして実行するには、--http フラグを使用します。--port でポートを指定することもできます(デフォルト:3000)。このモードでは Express が必要です(依存関係に含まれています)。

npm run start -- <baseUrl> <token> --http --port 3000
  • MCP API は、指定したポートの POST /mcp で利用できます。
  • 各リクエストは、StreamableHTTPServerTransport のパターンに従い、ステートレスで処理されます。
  • /mcp への GET および DELETE リクエストには、405 Method Not Allowed が返されます。
リクエストごとの API トークン(HTTP/Docker モード)

HTTP モードでは、クライアントは標準の Authorization ヘッダーで Paperless-NGX API トークンを指定して認証します。

Authorization: Bearer <paperless-ngx-api-token>

トークンはそのまま Paperless-NGX に渡されるため、各クライアント固有の Paperless 権限がエンドツーエンドで適用されます。これにより、1 つのサーバーインスタンスで、それぞれが独自のトークンを持つ複数のユーザーにサービスを提供できます。同じ動作が /mcp と /sse の両方のエンドポイントに適用されます。

⚠️ 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 Unauthorized401 Unauthorized

v1.x からの移行: 以前のフォールバック(トークンを送信しないクライアントに対し、共有の PAPERLESS_API_KEY を使用)を利用していた場合、次の 2 つの方法があります。

  1. 推奨: 各クライアントに Authorization: Bearer <paperless-token> を送信させます。
  2. 以前の動作に戻す(信頼できるネットワーク/ローカルネットワークのみ):--no-auth フラグを付けてサーバーを起動します。たとえば、Docker の command/args または CLI の呼び出しに追加します。この場合、サーバートークン(PAPERLESS_API_KEY または --token)の設定が必要です。
Docker によるデプロイ

MCP サーバーは Docker および Docker Compose を使用してデプロイできます。Docker イメージは、ポート 3000 で SSE(Server-Sent Events)をサポートする HTTP モードで自動的に実行されます。

Docker Compose の設定

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
### Continue VS Code 拡張機能での使用

Continue VS Code 拡張機能を使用している場合は、SSE 経由で Docker 化された 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 コンテナが環境変数を使用して認証を処理するため、Continue の設定に認証情報は必要ありません
  • SSE エンドポイントは、設定したポート(デフォルト:3000)の /sse で利用できます

クレジット

このプロジェクトは nloui/paperless-mcp のフォークです。元の作者の取り組みに心より感謝します。貢献や改善は上流に還元される場合があります。

デバッグ

VS Code で 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));

これにより、サーバーがすぐに終了するのを防ぎ、ブレークポイントを設定してコードをデバッグできるようになります。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。