zipnative MCP — ZIP creation, inspection, secure extraction & verification
ローカルzipnative MCP — ZIP creation, inspection, secure extraction & verification について
zipnative-mcpは、ZIPアーカイブの作成、検査、検証、展開、変更を行うMCPサーバーです。安全対策を既定で有効にした展開、再現可能なアーカイブ処理、展開せずに行うエントリー読み取りを備え、オフラインでZIPを扱うMCPクライアント向けです。
主な機能
- 01再現可能なZIPアーカイブの作成
- 02アーカイブ検査とエントリー一覧
- 03エントリーとバイト範囲の読み取り
- 04構造とCRCの検証
- 05パスとサイズを保護した展開
- 06正規化、結合、変更
活用シーン
- 01CIゲートでアーカイブの整合性を確認
- 02ZIPを展開せずにファイルを読み取り
- 03サンドボックスへ安全にアーカイブを展開
- 04再圧縮せずにアーカイブを結合
MCP 対応
MCPクライアントにZIP関連の15ツールと7プロンプトを提供します。アーカイブの入出力には設定済みのローカルサンドボックスを使用でき、ネットワークには接続しません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y zipnative-mcpZIPNATIVE_MCP_OUTPUT_DIRAbsolute path of the one sandbox directory: zipPath / sourcePath inputs are read from it and outputMode='file' / outputDir outputs are written under it (never overwritten; the real path of every file read and of every parent written must stay inside — a planted symlink or junction is SECURITY_VIOLATION). Unset: every tool works on base64 only (no file I/O beyond the opt-in cache).ZIPNATIVE_MCP_CACHE_DIROpt-in content-addressed response cache directory (absolute path) (SHA-256 keyed, 1h TTL, 256 MiB, oldest-written evicted first, plaintext at rest). Never caches zipPath / sourcePath inputs, file output, defaultDate='now', parallel, describe_engine or draft_governance_issue.ZIPNATIVE_MCP_PORTServe Streamable HTTP on this loopback port (POST /mcp) instead of stdio (MCP 2026-07-28, stateless, legacy fallback). Unauthenticated unless ZIPNATIVE_MCP_HTTP_TOKEN is set.ZIPNATIVE_MCP_HTTP_TOKENシークレットOpt-in bearer token for the HTTP transport (>= 16 chars, no whitespace; a weaker value refuses to start). When set, /mcp requires 'Authorization: Bearer <token>' or answers 401. Compared constant-time, never logged.ZIPNATIVE_MCP_MAX_UNCOMPRESSED_BYTESOperator ceiling for limits.maxEntryUncompressedSize, limits.maxTotalUncompressedSize and limits.maxEntryCompressedSize in bytes (default 8589934592 = 8 GiB, the engine default). Integer >= 1024, read once at startup; an invalid value refuses to start. A per-call value above it is refused with LIMIT_CEILING_EXCEEDED.ZIPNATIVE_MCP_MAX_ENTRIESOperator ceiling for limits.maxEntries and scan_zip_forward maxEntries (default 100000, the engine default; the scanner's default budget of 10000 is clamped to it, only an explicit value above it is refused). Integer >= 1, read once at startup; an invalid value refuses to start.ZIPNATIVE_MCP_WORKERSOperator ceiling for create_zip parallel.workers (default 8; with no explicit workers the engine default max(1, min(cores - 1, 8)) applies, bounded by this ceiling; 0 disables worker threads and keeps compression on the calling thread). Integer >= 0, read once at startup; an invalid value refuses to start.ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTESOperator ceiling for every file written in outputMode='file' (create_zip, modify_zip, canonicalize_zip, merge_zip, extract_zip, inflate_raw), enforced while streaming (default 4294967296 = 4 GiB, the 1.0.0 behaviour). Integer >= 1048576, read once at startup; an invalid value refuses to start. Raise it to write Zip64 archives above 4 GiB into the sandbox (create_zip stream entries with zip64: true).ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
13掲載時のツール一覧 · 1 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| check | array | いいえ | レポートに対して評価される CI アサーション:deterministic、epoch-timestamps、canonical-order、utf8-names、no-data-descriptor、canonical-layout、no-zip64、zip64、no-encryption、no-symlinks、safe-names、no-duplicates、no-diagnostics、store-only、deflate-only。結果:`checks[]` + `checksPassed`。 |
| assert | object | いいえ | パラメーター化されたアサーション(各項目が `checks[]` の 1 行になります)。 |
| assert.has | array | いいえ | 存在必須のエントリー名(完全一致)。 |
| assert.method | enum | いいえ | すべてのエントリーがこの方式を使用する必要があります。store | deflate |
| assert.maxRatio | number | いいえ | 許可されるエントリーごとの最大展開/圧縮比。 |
| assert.maxEntries | integer | いいえ | アーカイブに含められるエントリー数の上限。 |
| assert.minEntries | integer | いいえ | アーカイブに含める必要があるエントリー数の下限。 |
| assert.maxUncompressedBytes | integer | いいえ | 宣言された展開後サイズの合計がこの値を超えてはなりません。 |
| fields | array | いいえ | verbosity 適用後に使うドットパス射影(例:['entryCount', 'entries.name'])。配列のセグメントは各要素にマップされ、一致しないパスは _meta.unmatchedFields に報告されます。 |
| limits | object | いいえ | この呼び出しに限り、zipnative の名前付きセキュリティ上限を上書きします(CWE-400 / CWE-409 対策)。すべてのキーは任意です。指定されていないキーにはエンジンのデフォルト値が適用されます(maxEntries 100000、maxEntryUncompressedSize 1 GiB、maxTotalUncompressedSize 8 GiB、maxCompressionRatio 1024、maxNameBytes 4096、maxExtraFieldBytes 65535、maxCommentBytes 65535、maxCentralDirectoryBytes 256 MiB)。運用者の上限(ZIPNATIVE_MCP_MAX_UNCOMPRESSED_BYTES、ZIPNATIVE_MCP_MAX_ENTRIES)を超える値は拒否され、LIMIT_CEILING_EXCEEDED が返されます。信頼できる入力に限り、上限を引き上げてください。 |
| limits.maxEntries | integer | いいえ | 中央ディレクトリのエントリー数の上限。 |
| limits.maxNameBytes | integer | いいえ | エントリー名の最大バイト長。 |
| limits.maxCommentBytes | integer | いいえ | コメントの最大バイト長。 |
| limits.maxExtraFieldBytes | integer | いいえ | 追加フィールドブロックの最大バイト長。 |
| limits.maxCompressionRatio | number | いいえ | 圧縮サイズが 1 KiB 以上のエントリに対する最大宣言解凍/圧縮比(ZIP 爆弾対策)。 |
| limits.maxCentralDirectoryBytes | integer | いいえ | セントラルディレクトリの最大サイズ(バイト)。 |
| limits.maxEntryUncompressedSize | integer | いいえ | 1 エントリの最大解凍サイズ(バイト)。 |
| limits.maxTotalUncompressedSize | integer | いいえ | 1 回の展開における全エントリの最大解凍合計サイズ(バイト)。 |
| strict | boolean | いいえ | エンジンの最初の診断情報(先行データ、重複名、名前の不一致など)を報告する代わりに、ZIP_STRICT_DIAGNOSTIC エラーに昇格させます。 |
| zipPath | string | いいえ | ZIPNATIVE_MCP_OUTPUT_DIR サンドボックス内にあるアーカイブの相対パス(絶対パスや '..' は不可。コンテナー拡張子のみ:.zip .jar .docx .epub …)。zipBase64 とは併用できません。作成/変更 → 検証/展開のチェーンで、バイト列の再送を避けられます。 |
| validate | enum | いいえ | 'eager'(デフォルト)はすべてのローカルヘッダーと重複テーブルを事前に照合し、不正な構造をここで拒否します。'lazy' は最初の読み取りまで照合を遅らせます(大きなアーカイブで低コスト)。eager | lazy |
| verbosity | enum | いいえ | 'summary' はスカラーの判定フィールドのみを返し(配列とペイロードを省略)、トークンを節約します。full | summary |
| zipBase64 | string | いいえ | アーカイブのバイト列を base64 で指定します(1 回のみ。data: URI プレフィックスも許容)。zipPath とは併用できません。デコード後のサイズは ≤ 128 MiB。 |
詳細
zipnative-mcp
ZIP アーカイブ用 MCP サーバー — 展開せずに決定論的な作成、検査、一覧表示を行い、エントリーをランダムアクセスで読み取り(メモリ内、またはメモリを超えるサイズのサンドボックスアーカイブではバイト範囲を指定)、デフォルトで安全な展開、1 回の呼び出しによる検証、切り詰められたストリームの前方スキャン、再圧縮せずに増分変更、正規化、マージ、CRC-32 および raw-DEFLATE の展開に対応します — ゼロ依存で、CI で ISO/IEC 21320-1 への適合性が検証されたエンジン zipnative を基盤とする 15 個のツールと 7 個のプロンプトを提供し、Claude Desktop、Cursor、ChatGPT、およびあらゆる MCP クライアントで利用できます。ネットワーク通信は一切行いません。
✨ 特長
zipnative 1.1.0 を基盤とする zipnative-mcp 1.1.0 は、あらゆる MCP ホストに 15 個のツールを公開します。ここでは tools/list の順に掲載しています。利用者向けの仕様(カタログ、判断ツリー、トークンの使用効率、レシピ、完全なエラー一覧)は docs/AGENT_CONTRACT.md をご覧ください。
| ツール | 機能 | 読み取り専用 |
|---|---|---|
inspect_zip | 1 回の呼び出しでアーカイブをレポートします。サイズ、エントリ/ファイル/ディレクトリ数、Zip64、コメント、圧縮後と圧縮前の合計サイズ、圧縮方式ごとの数、暗号化/シンボリックリンク/データディスクリプター/Zip64/cp437/重複/危険な名前の数、日付範囲、決定性の判定(エンジンの analyzeDeterminism() から取得。デフォルトの判定は 1.0.0 の計算式で、エポックのタイムスタンプ+正規順序+UTF-8 フラグです)、およびエンジンのすべての診断情報を返します。先読みして開くため、エントリの重複、中央ディレクトリへの侵入や EOF を越えるエントリ、Zip64 の偽装は ZIP_* コードで拒否されます。check: […] と assert: {…} を指定すると CI ゲートとして動作します。determinismReport: true を指定すると、エンジンのより厳格な正規形式の判定と、違反しているすべてのエントリが追加されます。 | ✓ |
list_zip_entries | 展開せずに中央ディレクトリの目録をページ単位で取得します。すべてのエントリを完全な行として返します(サイズ、CRC-32、方式、タイムスタンプ、フラグ、Unix モード、シンボリックリンク、Zip64、オフセット、追加フィールド、展開時に使われるサニタイズ済みパス、生の名前バイト列。オプションで拡張タイムスタンプと Unix 所有者 ID も取得可能)。名前/プレフィックス/glob による filter、offset と limit(デフォルトは 200、最大 2000)を指定できます。 | ✓ |
read_zip_entry | 展開せずに name または index でエントリを 1 つ読み取ります。展開済みコンテンツを base64 または UTF-8 テキストで取得(CRC 検証済み)、チャンクストリームを通じたバイト単位の range、生の圧縮ペイロード(mode: 'raw')、または例外を発生させない整合性チェック(mode: 'verify'。エンジンの skipped 理由を含む)が可能です。 | ✓ |
verify_zip | 1 回の呼び出しで詳細な検証を行います。エンジンの verifyZip レポートをそのまま返します。構造、各エントリの CRC-32/サイズ/ローカルヘッダーとの一致、および検証できない各エントリとその skipped 理由('encrypted'、'stream-only-codec'、'unsupported-method')が含まれます。アーカイブの問題で isError になることはありません。ok と error.code に基づいて分岐してください。 | ✓ |
extract_zip | デフォルトで安全です。zip-slip/デバイス名、シンボリックリンク、パスの重複、宣言サイズや比率を悪用した爆弾、エントリの重複、中央ディレクトリとローカルヘッダーの不一致は、固定された ZIP_* コードで拒否されます。緩和する場合は名前付き入力で明示する必要があり、エントリを出力せずスキップします。ファイルをインラインで返す(includeData: false はドライランです。先読みして開き、計画を返す前にエントリの重複、CD 内へのオフセット、Zip64 の偽装を含むアーカイブを拒否します)か、サンドボックスにストリーミングしてリソースリンクを返します。 | |
scan_zip_forward | メモリ使用量を抑えながら、ローカルヘッダーをストリーム順に走査します。ダウンロードが途中で切れた場合や、ローカルヘッダーから始まる切断済み/シーク不可のストリームに対応する唯一のツールであり、結果が権威あるものではない(trust: 'local-headers-only')唯一のツールです。tolerateTruncation: true を指定すると、部分的な目録とエラーを返します。SFX/先頭に追加されたプレフィックスをスキップすることはできず、その場合は拒否されます(ZIP_SIGNATURE_MISMATCH)。inspect_zip はその情報を報告し(prependedData、ZIP_PREPENDED_DATA)、modify_zip mode: 'compact' は削除します。 | ✓ |
sanitize_entry_paths | 名前のリストを対象に、エンジンの単一のトラバーサル判定を行います。それぞれに対応する安全な / 相対形式、または null と該当したルール(トラバーサル、絶対パス、ドライブ、UNC、NUL、ADS、デバイス名)を返します。アーカイブは不要です。 | ✓ |
create_zip | インラインのテキスト/base64/サンドボックスファイルから ZIP を作成します(最大 100 000 エントリ。65 535 を超えると Zip64 に自動昇格)。デフォルトで再現可能(正規順序、UTC で書き込まれる DOS エポックのタイムスタンプ、UTF-8 の名前)です。すべてのランタイムで同一バイト列にするには compression.deterministic: true を指定します。この場合のみ summary.deterministic は true になります。アーカイブまたはエントリ単位で store/deflate を指定可能です。EPUB/JAR には order: 'insertion' を指定できます。コメント、Unix モード、追加フィールド、ストリーミングソース(zip64: true を指定するとストリーミングエントリが 4 GiB を超えられます)、ワーカープール(並列処理、バイト単位で同一の結果)、base64 とファイルモードでの includeSha256 証明にも対応します。 | |
modify_zip | 再圧縮せずに追加/置換/削除/名前変更/コメント設定を行います。mode: 'append' は元のバイト列をそのまま保持します(削除した内容は復元可能なままです。データ残留に注意してください)。mode: 'compact' は書き換えて完全に削除し、canonical: {…} を指定すると書き換え後の形式を正準かつ決定的にします。どちらのモードでも入力は先読みして開きます。 | |
canonicalize_zip | あらゆるアーカイブを再現可能にします。エンジンの canonicalizeZip() は、Gradle、Maven、zip、Explorer、7-Zip のアーカイブを、ペイロードを再圧縮せずに正準かつ決定的な形式(生の名前バイト列でソート、単一のタイムスタンプ、UTF-8 フラグ、Zip64 専用の追加フィールド、固定の version-made-by、データディスクリプターなし)に書き換えます。冪等です。summary.canonicalForm は、出力に対するエンジン独自の analyzeDeterminism() の判定です。 | |
merge_zip | 1~32 個のソースアーカイブを、再圧縮せずに 1 つにまとめます(ZipWriter.addFromReader)。verify: true(デフォルト)では、各エントリをコピー前に 1 回展開し、CRC とサイズを検証します。検証できない方式(store/deflate 以外)のエントリは拒否されます(ZIP_UNSUPPORTED_METHOD)。ソースごとに filter を指定でき、名前の競合は onConflict: 'error'(デフォルト、ZIP_DUPLICATE_ENTRY_NAME)/'first'/'last' で処理し、削除されたエントリを報告します。暗号化されたエントリは拒否されます。 | |
compute_crc32 | テキスト、base64、またはサンドボックスファイルの ZIP チェックサム(IEEE 802.3 CRC-32、エンジンの slice-by-8)を、1 MiB のチャンクでストリーミング計算します。seed でチャンクを連結し、expect で比較できます。 | ✓ |
inflate_raw | 必須の maxOutput 上限を指定して、エンジンの再開可能なインフレーターで生の DEFLATE(RFC 1951)を展開します。正確な bytesConsumed と、末尾に残るバイト列を leftover として返します。read_zip_entry mode: 'raw' の出力を入力してください。 | |
describe_engine | オフラインの事前確認です。バージョン、deflate の段階、ランタイムのコーデック(incremental を含む)とワーカー、エンジンのデフォルト制限、4 つのオペレーター上限、すべてのサーバー上限、サンドボックス/キャッシュの状態、39 個のエラーコードと 12 個の診断コード、意図的に公開されていないエンジンのエクスポートを確認できます。network は常に 'none' です。 | ✓ |
draft_governance_issue | 人間が確認して送信するための、ガバナンスに準拠した GitHub issue の下書きをローカルで作成します。送信は行わず、ネットワークも GitHub への書き込み経路もありません。 | |
| すべてのツールが保証すること: |
- 🔐 デフォルトで安全 — エンジンのすべてのガードが有効です。緩和する場合は、明示的に名前を指定した入力(
rejectTraversal、rejectSymlinks、onDuplicate、limits)を指定します。この入力により対象がスキップされることはあっても、安全でないパスが出力されたり、リンクが実体化されたりすることはありません。重複、中央ディレクトリとローカルヘッダーの不一致、Zip64 の偽装には、オプトアウト手段が一切ありません。 - 🌐 ネットワークは一切使用しません — サーバーにネットワークコードパスはありません。テレメトリー、GitHub、引数からの URL、リモートのバイト範囲ソース、オペレーターが設定できるエンドポイントはありません。ファイルシステムの境界は
ZIPNATIVE_MCP_OUTPUT_DIRのみです。 - 🔁 デフォルトで再現可能、要求に応じて決定論的 — オプトアウトしない限り、
create_zipは正規の順序、DOS エポックのタイムスタンプ、UTF-8 の名前を使用します。また、すべての DOS 日付は UTC で書き込み、読み取ります(dosTimeMode: 'utc')。そのため、日付を固定すれば、パリでも UTC のランナーでも同じバイト列になります。compression.deterministic: trueを指定すると、純粋な TypeScript エンコーダーが固定され、どのランタイムでも同じ SHA-256 が得られます。summary.deterministicがtrueになるのは、この設定を指定した場合のみです。canonicalize_zipは外部のアーカイブを正規形式に変換し、parallelはバイト単位で同一の結果を生成します。 - 🧭 固定された
ZIP_*エラーコードをそのまま返します — エンジンの 39 種類のコード語彙は、(エントリー名、発生した制限、両方の CRC などとともに)変更されずに_meta.error.codeで返されます。さらに、それぞれに対処法を示すラッパーコードが 17 種類あります。メッセージではなくコードを基準に分岐してください。 - 🪙 トークン消費を抑える投影 — 読み取りツールは
verbosity: 'summary'とfields: […]を受け付けます。生成されたアーカイブは埋め込みのresourceブロックとして返され、structuredContentには含まれません(このブロックにはblob内のバイト列と、それを繰り返すdata:URI が含まれるため、サイズの大きなアーカイブにはトークン消費を抑えられるoutputMode: 'file'(resource_link)が適しています)。 - ⏹ キャンセル可能で、進捗も通知します — リクエストのキャンセルシグナルと、クライアントが
progressTokenを送信した場合は進捗通知先が、入力に応じて処理量が増えるすべてのツールに渡されます。ただしverify_zipは例外です(zipnative のverifyZipは同期処理でシグナルを受け取らないため、検証は最後まで実行され、レポートを返します)。キャンセルされた呼び出しはキャッシュされず、出力途中のファイルは削除されます。MCP 経由では、SDK はキャンセルされたリクエストに応答を送りません(プロセス内でのコードはCANCELLEDです)。 - 📏 ISO/IEC 21320-1 準拠ゲート — ツールが書き込むすべてのアーカイブは、Linux と Windows の CI で、エンジンに依存しないバリデーター(veraZIP)により条項ごとに検証され、公開前にも再度検証されます。
アーカイブを生成するすべてのツール(create_zip、modify_zip、canonicalize_zip、merge_zip。生バイト列の場合は inflate_raw)は、次の 2 つの出力モードに対応しています。
-
base64(デフォルト) — アーカイブは埋め込みのresourceコンテンツブロックとして返されます。バイト列はresource.blobに格納され、resource.uriにもdata:application/zip;base64,…URI として繰り返し格納されます(1.0.0 から変更されていないため、URI をデコードするクライアントも引き続き動作します)。そのため、ブロック内をアーカイブが 2 回分転送されます。structuredContentには{ mode, sizeBytes, summary, diagnostics, diagnosticCounts }が含まれ、バイト列は含まれません。 -
file— アーカイブは、ZIPNATIVE_MCP_OUTPUT_DIRで設定したサンドボックス化されたディレクトリにストリーミングされます(デフォルトで ≤ 4 GiB。ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTESで上限を変更できます。既存のファイルは上書きされません)。結果にはresource_linkが含まれます(最も応答コストを抑えられる形式です。structuredContent.filePathとテキスト行には、1.0.0 と同様にホスト上の絶対パスが記載されます)。この変数が設定されていない場合、ファイル I/O は無効です。絶対パス、パストラバーサル、コンテナー以外の拡張子、NUL バイトはすべて拒否されます。また、読み取るすべてのファイルの実際のパスと、書き込みを行うすべての親ディレクトリは、サンドボックス内にとどまる必要があります(仕込まれたシンボリックリンクまたはジャンクションは、どちらの側でもSECURITY_VIOLATIONになります)。同じサンドボックスはzipPath/sourcePathの入力にも使われるため、create_zip → modify_zip → verify_zip → extract_zipの一連の処理でバイト列を再送する必要はありません。 トークンを節約した読み取り。 読み取りツール(inspect_zip、list_zip_entries、read_zip_entry、verify_zip、scan_zip_forward、sanitize_entry_paths、describe_engine)とextract_zipは、2 つの省略可能な入力を受け付けます。 -
verbosity: 'summary'— スカラー値のみの簡潔な判定結果です(行とペイロードは省略されます)。例:verify_zip→{ ok, error, entryCount, verifiedCount, failedCount, skippedCount, diagnosticCount }。inspect_zipではdeterministic、canonicalLayout、checksPassedが保持されます。 -
fields: ['a', 'b.c']— 構造化された結果を、名前付きのドットパス(最大 16 個)に絞り込みます。verbosityの適用後に処理されます。一致しないパスは省略され、_meta.unmatchedFields(および_meta.availableFields)に報告されます。パスに__proto__、constructor、prototypeのいずれかのセグメントが含まれる場合はVALIDATION_ERRORになります。
「このアーカイブは破損していないか」を確認する最小のプローブ:verify_zip に { "zipBase64": "…", "verbosity": "summary", "fields": ["ok", "error", "failedCount"] } を指定します。
メモリに収まらない大きさのアーカイブ。 inspect_zip、list_zip_entries、read_zip_entry は access: 'auto' | 'memory' | 'range' を受け付けます。1 GiB のインメモリ上限を超えるサンドボックス内の zipPath は、バイト範囲を使って開かれます(既定値の 'auto'、または常に範囲アクセスを使う 'range')。エンジンの openZipRange はサンドボックスファイル自体のハンドルを使って末尾レコードとセントラルディレクトリを読み取り、その後はアクセス対象のエントリのみを読み取ります。URL やリモートソースを読み取ることはありません。詳しくは docs/guides/LARGE_ARCHIVES.md を参照してください。
このサーバーには7 つの MCP プロンプト(secure_extraction、reproducible_archive、incremental_update、forensic_scan、verify_before_trust、governance_contract、draft_issue_workflow)も付属しており、サンドボックス内のすべてのファイルを zipnative://output/{+path} リソースとして公開します。
zipnative を選ぶ理由
zipnative-mcp は、基盤となるエンジンのすべての保証を引き継ぎます。
- エンジンに実行時依存関係なし — 純粋な TypeScript で、ネイティブバインディングも
evalもありません。Node ≥ 22、ブラウザー、Deno、Bun、Workers で共通の API を使用できます(このサーバーが追加するのは MCP SDK と zod のみで、実行時依存関係は合計 3 つです)。 - 既定で安全 — パストラバーサル、シンボリックリンク、重複名、解凍爆弾、重複するエントリ、パーサー間の差異を悪用する偽装、Zip64 のなりすましを推測で処理せず、拒否します。すべてのパーサーループは、名前と CWE タグが付与され、呼び出し元が設定できる上限(9 つの
ZipLimitsキー)内で実行されます。 - ランダムアクセスとストリーミング — メモリ内またはバイト範囲ソースを通じて、数ギガバイトのアーカイブ全体に触れることなく 1 つのエントリを読み取れます。シークできないストリームも、メモリ使用量を制限して反復処理できます。
- 決定論的 — 明文化された決定性の契約があります。レイアウトは常に再現可能で、既定では環境ごとにバイト単位で安定し、
compression.deterministic: trueではすべてのランタイムで同じ SHA-256 が得られます。また、あらゆるアーカイブを再圧縮せずに変換できる標準形式を備えています。 - 増分変更 — 未変更の 99 % を再圧縮せずに(追記のみで)エントリを置換、削除、追加、名前変更できます。完全に削除する場合はコンパクト化し、アーカイブ間でエントリを移植できます。
- 固定された 39 種類のエラーコード体系と
verifyZip()— 1 回の呼び出しで、アーカイブの問題があっても例外を投げない、機械可読なレポートを返します。 - 初の、ISO/IEC 21320-1:2015 を条項ごとに検証するオープンなバリデーター。CI でブロックします。
- 対応しないこと: 暗号化と復号(エンジン 1.x では AES 非対応 — AES はエンジン 2.0 の候補です。ZipCrypto は安全ではありません)、その他のアーカイブ形式、マルチディスクアーカイブ、アーカイブの修復、エンジン内でのファイルシステム I/O、ネットワークアクセスは一切ありません。
🚀 インストール
# Run directly with npx (recommended for MCP clients)
npx -y zipnative-mcp
# Or install globally
npm install -g zipnative-mcp
zipnative-mcp
要件:Node.js ≥ 22。ソースからインストールする場合:git clone https://github.com/Nizoka/zipnative-mcp.git && cd zipnative-mcp && npm ci --ignore-scripts && npm run build && node dist/cli.js。
⚙️ 設定
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json(macOS)または %APPDATA%\Claude\claude_desktop_config.json(Windows)を編集します。
{
"mcpServers": {
"zipnative": {
"command": "npx",
"args": ["-y", "zipnative-mcp"],
"env": {
"ZIPNATIVE_MCP_OUTPUT_DIR": "/Users/you/Documents/mcp-archives"
}
}
}
}
Claude Code
プロジェクトのルートにある .mcp.json(リポジトリには、dist/cli.js からビルド済みサーバーを起動する設定が同梱されています):
{
"mcpServers": {
"zipnative": {
"type": "stdio",
"command": "npx",
"args": ["-y", "zipnative-mcp"],
"env": { "ZIPNATIVE_MCP_OUTPUT_DIR": "${CLAUDE_PROJECT_DIR}/.mcp-archives" }
}
}
}
Cursor / Continue / Zed / Windsurf / Cline / Roo Code
stdio サーバーに対応した MCP 互換クライアントであれば、どれでも動作します。同じ command + args + env の組み合わせを使用します。Cursor の例(~/.cursor/mcp.json):
{
"mcpServers": {
"zipnative": {
"command": "npx",
"args": ["-y", "zipnative-mcp"],
"env": { "ZIPNATIVE_MCP_OUTPUT_DIR": "/Users/you/Documents/mcp-archives" }
}
}
}
Windsurf / Cline / Roo Code では、それぞれの MCP 設定ファイル内で同じ形式を使用します。
VS Code
.vscode/mcp.json:
{
"servers": {
"zipnative": {
"type": "stdio",
"command": "npx",
"args": ["-y", "zipnative-mcp"],
"env": { "ZIPNATIVE_MCP_OUTPUT_DIR": "${workspaceFolder}/.mcp-archives" }
}
}
}
🌐 対応する AI エコシステムとクライアント
zipnative-mcp は MCP ネイティブ環境向けに設計されており、stdio または Streamable HTTP 経由の MCP に対応したクライアントで動作します。Claude Desktop、Claude Code、Cursor、Continue、Zed、Windsurf、Cline、Roo Code、VS Code、ChatGPT(Streamable HTTP)、MCP Inspector、および MCP TypeScript / Python SDK で構築されたあらゆるクライアントに対応しています。サーバーが独自にソケットを開くことはないため、エアギャップ環境や外部への通信が制限されたホスト内でも安全に実行できます。
pdfnative-mcp(PDF)や pkinative-mcp(PKI)と同じ「ネイティブ」系サーバーに属しており、薄いラッパーのアーキテクチャ、サンドボックス、キャッシュ、投影、ガバナンスの規約を共有しています。同じエンジンは、コマンドラインでは zipnative-cli として利用できます。
🔌 MCP プロトコルへの準拠
このサーバーは MCP TypeScript SDK v2(@modelcontextprotocol/server ^2.3.1)を基盤としており、MCP 2026-07-28 に対応しています:
- ステートレスなサービス提供 —
server/discoverがセッションのハンドシェイクに代わり、すべての結果にresultTypeと_metaのserverInfoエンベロープが含まれます。HTTP では、2026-07-28 クライアントは各POST /mcpでMcp-Method/Mcp-NameヘッダーとMCP-Protocol-Versionヘッダーを送信します(これを含まない 2026-07-28 リクエストは、SDK によって 400/-32020で拒否されます)。 - キャッシュヒント —
tools/listとprompts/listはttlMsが 24 時間のpublic、server/discoverは 1 時間のpublic、resources/list/resources/templates/list/resources/readはttlMs: 0のprivateです(サンドボックスファイルはホストごとのユーザーデータです)。 - プロトコルエラー — 不明なツール名を指定した
tools/callは、isErrorの結果ではなく JSON-RPC エラー(-32602、[UNKNOWN_TOOL] Unknown tool: …)になります。不明または不正な形式のリソース URI は、仕様の要件どおり-32602(Invalid params、UNKNOWN_RESOURCE)になります。isError: trueは実行時の失敗に限られます。 - キャンセルと進捗 —
notifications/cancelled(または接続を切断した HTTP クライアント)を受け取ると、入力に応じて処理量が増えるすべてのツールで、チャンク間の処理が停止します。アーカイブツールではエンジンが、compute_crc32とinflate_rawではツール独自のチャンクループが停止します。何もキャッシュされず、部分的な出力ファイルは削除されます。例外はverify_zipです。zipnative のverifyZipは同期処理でシグナルを受け取らないため(エンジンの制約)、検証は最後まで実行され、結果が返されます。sanitize_entry_paths、describe_engine、draft_governance_issueにはキャンセルする価値のある処理はありません。MCP のキャンセルルールに従い、キャンセルされたリクエストに対して SDK は応答を送りません。CANCELLED(data.remedy: 'retry')はプロセス内でツールが返す値(callToolDirect)であり、サーバーはこれを stderr に出力しません。_meta.progressTokenを含むリクエストにはnotifications/progressが送信され、そのprogressは呼び出し全体を通じて厳密に増加します。送信頻度は 200 ms に 1 回に制限され、既知のエントリ数が完了したときにも送信されます。トークンがない場合、通知は送信されません。 - レガシーへの自動フォールバック —
initializeで接続するクライアントには、SDK がネゴシエートするすべてのリビジョン(レガシーの 2024-10-07、2024-11-05、2025-03-26、2025-06-18、2025-11-25 と、モダンの 2026-07-28)において、stdio と HTTP の両方で SDK のレガシーパスが適用されます。既存のホストには変更はありません。tests/protocol-revisions.test.tsは、各レガシーリビジョンでそのリビジョンが正確にネゴシエートされ、15 個のツールが提供されることを検証します。tests/stdio-modern.test.tsとtests/http-modern.test.tsは、stdio と HTTP での 2026-07-28 パスを検証します。 - HTTP —
POST /mcpのみを受け付けます。GET/DELETE /mcpは 405 を返します(SSE の再開には対応しません。サーバーはステートレスです)。127.0.0.1にバインドされ、Host/Originガードが適用されます(外部の値には 403 を返し、Originのポートはサーバーのポートと一致する必要があります)。ZIPNATIVE_MCP_HTTP_TOKENを設定すると、任意でベアラートークンによるゲートが有効になります(トークンがない場合は401とWWW-Authenticateを返します)。どちらのチェックもリクエストボディの読み取り前に実行されます。最大 256 MiB のボディを受け付け、それを超える場合は 413 を返します。ヘッダーのタイムアウトは 30 秒、リクエストのタイムアウトは 300 秒、キープアライブのタイムアウトは 5 秒で、リクエストヘッダーは最大 100 個です。すべてのレスポンスにX-Content-Type-Options: nosniffとCache-Control: no-storeが含まれます。 - stdio — 複数 MiB の base64 アーカイブを 1 回の
tools/callで処理できるよう、SDK のデフォルトの 10 MiB フレーム上限を 256 MiB に引き上げています。すべての SDK リリースと同様、initializeより前に送信されたリクエストは、レガシーパスでは応答なしで破棄されます。 - 出力スキーマ — すべての
structuredContentは、ツールのoutputSchemaに照らして検証されます(2026-07-28 では必須)。これにはverbosity: 'summary'とfieldsによる投影も含まれます。読み取りツールでは投影可能なスキーマを宣言します(すべてのプロパティを省略可能にし、additionalProperties: falseは維持します)。ポリシーにより、入力スキーマに$schemaキーワードおよび$refは含めません(ホストによっては、未知のキーワードを拒否する関数呼び出し API にinputSchemaが転送されるためです)。serverInfoにはwebsiteUrlが含まれます。リソーステンプレートはzipnative://output/{+path}です。 2026-07-28 のパスとレガシーパスでは、tools/callのペイロード(content、structuredContent、isError)は同一です。tests/http-modern.test.tsでこれを検証し、tests/schema-conformance.test.tsでは SDK の JSON Schema 2020-12 バリデーターを使用してstructuredContentを検証します。
| クライアント | トランスポート | ネゴシエートされるプロトコル |
|---|---|---|
| Claude Desktop、Cursor、Continue、Zed、Windsurf、Cline | stdio | レガシー initialize(2024-xx / 2025-xx)— 変更なし |
| ChatGPT およびその他の Streamable HTTP ホスト | HTTP POST /mcp | レガシーのステートレスな streamable HTTP — 変更なし |
MCP 2026-07-28 クライアント(SDK v2 Client、現行 MCP Inspector) | stdio / HTTP | server/discover、キャッシュヒント、_meta エンベロープ |
互換性マトリクス — 両方のトランスポートでネゴシエートされるすべてのリビジョンと、それを証明するテスト:
| リビジョン | 世代 | stdio | HTTP POST /mcp | 証明するテスト |
|---|---|---|---|---|
| 2024-10-07 | レガシー initialize | ✓ | ✓ | tests/protocol-revisions.test.ts |
| 2024-11-05 | レガシー initialize | ✓ | ✓ | tests/protocol-revisions.test.ts |
| 2025-03-26 | レガシー initialize(JSON-RPC バッチは HTTP では受け付け、stdio では拒否) | ✓ | ✓ | tests/protocol-revisions.test.ts、tests/cli-stdio.test.ts、tests/http-modern.test.ts |
| 2025-06-18 | レガシー initialize | ✓ | ✓ | tests/protocol-revisions.test.ts、tests/cli-stdio.test.ts、tests/http-modern.test.ts、tests/http-transport.test.ts |
| 2025-11-25 | レガシー initialize | ✓ | ✓ | tests/protocol-revisions.test.ts、tests/cli-stdio.test.ts、tests/http-modern.test.ts、tests/autonomy.test.ts |
| 2026-07-28 | モダン(server/discover、_meta エンベロープ、キャッシュヒント) | ✓ | ✓(+ bearer token) | tests/stdio-modern.test.ts、tests/http-modern.test.ts、tests/autonomy.test.ts |
自律性の証明。 tests/autonomy.test.ts は、スクリプト化されたエージェントのシナリオ(S0 ハンドシェイク → S1 tools/list → S2 describe_engine → S3 create_zip ファイル / base64 / 並列処理 → S4 verify_zip → S5 inspect_zip チェック → S6 list_zip_entries → S7 read_zip_entry / inflate_raw / compute_crc32 → S8 modify_zip で追加後にコンパクト化 → S9 extract_zip のドライラン後にファイルを展開 → S10 resources/* → S11 scan_zip_forward → S12 悪意ある要求の拒否 → S13 上限 → S14 プロトコルエラー → S15 draft_governance_issue → S16 prompts/get → S17 正常なシャットダウン)を、サンドボックスとキャッシュディレクトリの下、ZIPNATIVE_MCP_MAX_ENTRIES=5000 および ZIPNATIVE_MCP_WORKERS=2 の設定で、ビルド済みの dist/cli.js に対して4種類のトランスポート(stdio レガシー、stdio モダン、HTTP レガシー、ZIPNATIVE_MCP_HTTP_TOKEN を使った HTTP モダン)で再生します。このテストでは、ユーザーとの対話がないこと、予期しない isError がないこと、拒否のたびにコードと対処法が示されること、通信経由でキャッシュヒットが確認できること、stdout が JSON のみであること、正常に終了することを検証します。tests/cancellation.test.ts は MCP 経由でキャンセルと進捗を実行します。Claude Code、Claude Desktop、または MCP Inspector から手動でシナリオを再生する方法については、docs/guides/LOCAL_TESTING.md §「Claude Code / Claude Desktop / MCP Inspector から操作する」を参照してください(リポジトリにはすぐに使える .mcp.json が含まれています)。
環境変数
8つすべてが server.json で宣言され、起動時に検証されます。無効な値の場合は起動を拒否し、暗黙のフォールバックは行いません(ZIPNATIVE_MCP_PORT が 1~65535 の範囲外または整数でない、ZIPNATIVE_MCP_OUTPUT_DIR または ZIPNATIVE_MCP_CACHE_DIR が相対パス、上限値の形式が不正、トークンが弱い場合)。運用者向けの4つの上限値は起動時に一度だけ読み込まれます。変数を変更するには、サーバーを再起動してください。トークンがログに記録されることはありません。stderr の起動ログには、HTTP の動作モードと適用中の上限値が記録されます。
| 変数 | デフォルト | 意味 |
|---|---|---|
ZIPNATIVE_MCP_OUTPUT_DIR | (未設定) | 単一のサンドボックスディレクトリの絶対パスです。zipPath / sourcePath 入力はこのディレクトリから読み込まれ、outputMode: 'file' / outputDir の出力はこのディレクトリ内に書き込まれます(排他的に作成され、上書きされません)。読み込むすべてのファイルの実際のパスと、書き込み先すべての親パスが、このディレクトリ内にある必要があります。サンドボックス内に設置されたシンボリックリンクまたはジャンクションは、書き込み時だけでなく、zipPath / sourcePath / resources/read でも SECURITY_VIOLATION になります。すべての読み込みでは、ファイルの実パスにデバイス番号と inode で結び付けた単一のオープンハンドルを使用します。そのため、検査と読み込みの間にファイルが差し替えられたり拡大されたりした場合は拒否され、内容が提供されることはありません。未設定の場合、すべてのパス入力とファイル出力が拒否され、ツールは base64 のみを扱います。 |
ZIPNATIVE_MCP_CACHE_DIR | (未設定) | 永続的な SHA-256 キー付き結果キャッシュを有効にする場合の絶対パスです(相対パスを指定すると起動が拒否されます)。有効期限は 1 時間、容量は 256 MiB で、最も古く書き込まれたエントリーから削除されます(キャッシュヒットしてもエントリーの有効期限は更新されません。平文で保存されます。キーはツール API +パッケージ+エンジンバージョンと、オペレーターが設定した 4 つの上限を名前空間として使用するため、上限を引き下げた場合に以前の結果が使われることはありません)。zipPath / sourcePath 入力(zipPath による merge_zip のソースを含む)、ファイル出力、defaultDate: 'now'、parallel、describe_engine、draft_governance_issue、キャンセルされた呼び出しはキャッシュされません。キャッシュヒット時は _meta.cached: true が付与されます。 |
ZIPNATIVE_MCP_PORT | (未設定 → stdio) | 有効なポート(1~65535)を設定すると、stdio の代わりに http://127.0.0.1:<port>/mcp で Streamable HTTP を提供します。それ以外の値を設定すると起動が拒否されます。ループバックのみで、DNS リバインディング対策が有効です(外部の Host / Origin → 403)。GET / DELETE → 405、リクエストボディの上限は 256 MiB です。ZIPNATIVE_MCP_HTTP_TOKEN が設定されていない限り、認証はありません。ほかのローカルプロセスからエンドポイントにアクセスできます。 |
ZIPNATIVE_MCP_HTTP_TOKEN | (未設定) | (シークレット) HTTP トランスポート用のベアラートークンを任意で設定します(16 文字以上で、空白を含まないこと。条件を満たさない値を指定すると起動が中止されます)。設定すると、すべての /mcp リクエストに Authorization: Bearer <token> が必要です。それ以外の場合は 401 と WWW-Authenticate: Bearer realm="zipnative-mcp" が返されます(資格情報が送信された場合に限り、error="invalid_token" が含まれます。RFC 6750 §3.1)。定数時間で比較され、ログには記録されません。 |
ZIPNATIVE_MCP_MAX_UNCOMPRESSED_BYTES | 8589934592 (8 GiB) | limits.maxEntryUncompressedSize、limits.maxTotalUncompressedSize、limits.maxEntryCompressedSize に対するオペレーター上限です。整数で 1024 以上を指定してください。呼び出し単位の値がこの上限を超えると LIMIT_CEILING_EXCEEDED になります。エンジンのデフォルト値より低い上限を設定すると、デフォルト値は通知なく引き下げられます。 |
ZIPNATIVE_MCP_MAX_ENTRIES | 100000 | limits.maxEntries および scan_zip_forward の maxEntries に対するオペレーター上限です(デフォルト値 10 000 は上限に合わせて調整され、明示的に指定した値が上限を超える場合に限り LIMIT_CEILING_EXCEEDED になります)。整数で 1 以上を指定してください。 |
ZIPNATIVE_MCP_WORKERS | 8 | create_zip の parallel.workers に対するオペレーター上限です。workers が明示的に指定されていない場合は、エンジンのデフォルト値 max(1, min(cores − 1, 8)) が適用され、この上限の範囲内になります。0 を指定するとワーカースレッドが無効になり、圧縮は呼び出し元のスレッドで実行されます。整数で 0 以上を指定してください。 |
ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTES | 4294967296 (4 GiB) | outputMode: 'file'(create_zip、modify_zip、canonicalize_zip、merge_zip、extract_zip、inflate_raw)で書き込むすべてのファイルに対するオペレーター上限です。ストリーミング中に適用されます。整数で 1048576 以上を指定してください。デフォルト値は 1.0.0 の上限です。4 GiB を超えるアーカイブをサンドボックスに書き込むには、この値を引き上げてください(create_zip のストリームエントリーでは zip64: true を指定します)。 |
オペレーターによる上限設定。 エンジンの名前付き ZipLimits 上限9項目は、信頼できる入力に限り、limits フラグメントを通じて呼び出し単位で引き上げられます。そのうち4つのキーは、上記の上限のうち2つによって制限されます。ZIPNATIVE_MCP_MAX_UNCOMPRESSED_BYTES(maxEntryUncompressedSize、maxEntryCompressedSize、maxTotalUncompressedSize)と ZIPNATIVE_MCP_MAX_ENTRIES(maxEntries と、scan_zip_forward の maxEntries 入力)です。ZIPNATIVE_MCP_WORKERS は create_zip の parallel.workers を制限します。呼び出し単位の値が対応する上限を超えると、LIMIT_CEILING_EXCEEDED で拒否され、data.env にオペレーターが引き上げる変数名が示されます。4つ目の上限である ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTES は入力を制限しません。ファイルモードで書き込まれるすべてのファイルに上限を設けます(OUTPUT_TOO_LARGE)。「無制限」の設定はなく、ツール引数で変更できる上限もありません。describe_engine はデフォルト値、上限(ceilings.env に4つの変数を列挙)と、現在適用されているすべての上限を報告します。 |
🛠 ツールリファレンス
アーカイブを扱う各ツールでは、zipBase64(アーカイブを生の Base64 として1回だけ指定。data:…;base64, プレフィックスも許容。デコード後は ≤ 128 MiB)または zipPath(サンドボックス内の相対パス。コンテナ形式の拡張子のみ — .zip .jar .war .ear .docx .xlsx .pptx .odt .ods .odp .epub .vsix .nupkg .whl .apk .ipa .xpi .crx .kmz。バッファーへの読み込みは ≤ 1 GiB、それを超える場合はランダムアクセス対応の3つのツールで access: 'range' を使用)のいずれか1つだけを指定します。エンジンにアクセスする各ツールでは、limits(名前付き ZipLimits 上限9項目 — maxEntries、maxEntryUncompressedSize、maxEntryCompressedSize、maxTotalUncompressedSize、maxCompressionRatio、maxNameBytes、maxExtraFieldBytes、maxCommentBytes、maxCentralDirectoryBytes。オペレーターによる上限を超える値は LIMIT_CEILING_EXCEEDED)と strict(最初の診断を ZIP_STRICT_DIAGNOSTIC に格上げ)を指定します。読み取りツールでは verbosity('full' | 'summary')と fields(ドット区切りパスを ≤ 16 個)を指定します。すべてのアーカイブツールの結果には diagnostics[] が含まれます。診断はコードとエントリごとに重複排除され、最大200行に制限されます(上限に達すると diagnosticsTruncated: true)。また、verify_zip を除くすべてのツールに、コードごとの正確な件数を示す diagnosticCounts が含まれます。verify_zip は 1.0.0 の形式を維持します。エラー結果は次のとおりです。content[0].text = "<tool> failed [CODE]: message"、isError: true、_meta.error = { code, message, data? }。キャンセルされた呼び出しはプロセス内では CANCELLED で終了します(MCP 経由では、キャンセルされたリクエストに応答は返されません)。verify_zip は検証開始後に中断できません。入力と出力の完全なスキーマは tools/list で通知されます。エラーの完全な一覧は docs/AGENT_CONTRACT.md にあります。
日付は UTC です。 エンジンの呼び出しはすべて dosTimeMode: 'utc' で実行されます。Z またはオフセット付きの日付入力は UTC に変換されます。オフセットのない日時は UTC の壁時計時刻として読み取られます(UTC ホスト上で 1.0.0 が書き込んだ DOS フィールドと同じです)。lastModified と earliestDate / latestDate は UTC の時点として読み戻されます。そのため、日付を固定すれば、タイムゾーンに関係なく、どのホストでも同じバイト列になります(tests/reproducible-build.test.ts では、ビルド済みサーバーを2つのタイムゾーンで実行します)。UTC 以外のホストでは、どちらの面でも 1.0.0 から変更されています。Z / オフセット付きの日付は、そのホスト上で 1.0.0 が書き込んだものとは異なる DOS フィールドを書き込みます(compression.deterministic: true のバイト列も同様ですが、UTC ホスト上では 1.0.0 のものと一致します)。また、すべてのアーカイブの日付はタイムゾーンのオフセット分ずれて読み戻されます(DOS エポックは 1980-01-01T00:00:00.000Z と読み取られますが、パリでの 1.0.0 は 1979-12-31T23:00:00.000Z と報告していました)。別のツールがローカル時刻で書き込んだアーカイブは、その書き込み元のオフセット分ずれて読み取られます。
inspect_zip
1 回の呼び出しで読み取り専用のアーカイブレポートを出力します。zipnative inspect --json の形式で、サイズ、エントリ/ファイル/ディレクトリ数、Zip64、コメント(および commentHex)、圧縮後と圧縮前の合計サイズおよび圧縮率、メソッドごとの数、暗号化/シンボリックリンク/データディスクリプター/Zip64/cp437/重複/安全でない名前の数、最古/最新の日付、prependedData / multipleEocd、determinism の判定(epochTimestamps、canonicalOrder、utf8Flags、noDataDescriptors、canonicalLayout、deterministic)、およびすべての診断が含まれます。サブチェックはエンジンの analyzeDeterminism() によるものです。デフォルトの deterministic は 1.0.0 の計算式を維持します(エポックタイムスタンプ+正規順序+UTF-8 フラグ。ストリーミングアーカイブは再現可能ですが正規形式ではありません。固定されたエポック以外の日付は再現可能ですが、ここでは deterministic: false と報告されます。これは create_zip.summary.deterministic とは異なる、構造上の判定です)。そのため、既存の CI ゲートには影響しません。determinismReport: true を指定すると、より厳格な正規形式の判定(Zip64 のみの追加フィールドと固定の version-made-by も対象)が追加され、違反したすべてのエントリと該当ルールが報告されます(最大 200 行、件数は正確です)。デフォルトではアーカイブを即時に開きます。エントリの重複領域、中央ディレクトリ内や EOF を超えるエントリ、Zip64 の偽装は要約されず、それぞれの ZIP_* コードで拒否されます。中央ディレクトリとローカルヘッダーの間でメソッド/CRC/サイズに不一致があっても、領域の問題ではありません。これを 1 回の呼び出しで検査するゲートは verify_zip(localHeaderMatch)です。エントリの読み取り時に read_zip_entry / extract_zip が ZIP_CD_LFH_MISMATCH / ZIP_SIZE_MISMATCH を送出します。check / assert を指定すると CI ゲートとして使用できます。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | どちらか一方のみ |
access | 'auto' | 'memory' | 'range' | 'auto' | 'range'(または 'auto' で 1 GiB を超える zipPath)では、バイト範囲で読み取ります。この場合、determinism は出力されず、その理由を示して決定性チェックが失敗し、determinismReport / canonicalDate は VALIDATION_ERROR になります(data.remedy: "access:'memory'") |
validate | 'eager' | 'lazy' | 'eager' | lazy はローカルヘッダーの相互チェックを初回読み取りまで遅らせます(巨大なアーカイブではより効率的です) |
check | string[] ≤ 18 | — | deterministic、epoch-timestamps、canonical-order、utf8-names、no-data-descriptor、canonical-layout、no-zip64、zip64、no-encryption、no-symlinks、safe-names、no-duplicates、no-diagnostics、store-only、deflate-only、およびエンジンの正規形式チェックである canonical-form、canonical-extras、canonical-version-made-by |
determinismReport | boolean | false | determinismReport を追加します(deterministic、7 つのサブ判定、pinnedDate、offenderCount、offenders[]) |
canonicalDate | string | — | アーカイブを正規化した日付(canonicalize_zip の date、modify_zip の canonical.date)です。指定すると、正規形式の判定では DOS エポックの代わりにそのタイムスタンプを期待します。UTC として読み取ります |
assert | object | — | maxEntries、minEntries、maxUncompressedBytes(0 以上の整数)、maxRatio(1 以上の数値。エントリごとの最大比率)、has(完全一致する名前を最大 100 個)、method('store' | 'deflate') |
strict、limits、verbosity、fields | 共通の設定項目 |
出力には、上記のレポートに加え、check / assert が指定されている場合は checks[]({ check, ok, detail })と checksPassed が含まれます。要求に応じて determinismReport が含まれます。バイト範囲リーダーが呼び出しを処理した場合は access: 'range' が含まれます。また、diagnostics[] も含まれます。概要:archiveBytes、entryCount、isZip64、compressedBytes、uncompressedBytes、encryptedCount、unsafeNameCount、duplicateNameCount、deterministic、canonicalLayout、diagnosticCount、checksPassed。
{
"zipBase64": "<base64 ZIP>",
"check": ["deterministic", "no-encryption", "safe-names", "no-symlinks"],
"assert": { "maxEntries": 5000, "maxRatio": 100, "has": ["manifest.json"] },
"fields": ["checksPassed", "checks"]
}
(fields のみを指定すると checks[] の行は残ります。verbosity: 'summary' を指定するとそれらは省略され、checksPassed のみが残ります。)
エラー:VALIDATION_ERROR、INPUT_TOO_LARGE、INPUT_NOT_FOUND、SECURITY_VIOLATION、INVALID_EXTENSION、IO_ERROR、LIMIT_CEILING_EXCEEDED、ZIP_STRICT_DIAGNOSTIC、および構造上の拒否を示す ZIP_*(ZIP_EOCD_NOT_FOUND、ZIP_EOCD_INCONSISTENT、ZIP_CD_INCONSISTENT、ZIP_RECORD_TRUNCATED、ZIP_SIGNATURE_MISMATCH、ZIP_ZIP64_LOCATOR_MISSING、ZIP_ZIP64_EOCD_MISPLACED、ZIP_ZIP64_CONTRADICTION、ZIP_ENTRY_OVERLAP、ZIP_CD_LFH_MISMATCH、ZIP_VALUE_UNREPRESENTABLE、ZIP_UNSUPPORTED_MULTI_DISK、ZIP_LIMIT_EXCEEDED)。
list_zip_entries
何も展開せず、読み取り専用でセントラルディレクトリを一覧表示します。ディレクトリ内の順序に従い、すべてのエントリ(重複を含む)を完全な行として表示します。各行には index、name、nameEncoding、isDirectory、isSymlink、method / methodName、compressedSize、uncompressedSize、ratio、crc32、lastModified(UTC)、isEncrypted、usesZip64、usesDataDescriptor、unixMode、sanitizedPath(null の場合、展開ゲートで拒否されます)、comment、デコード済みの flags、versionMadeBy / versionNeeded、hostSystem、属性、localHeaderOffset、DOS 日付 / 時刻、名前付き extraFields、rawNameHex、commentHex が含まれます。ページ分割されるため、100 000 件のエントリを含むアーカイブでもトークン数を抑えられます。nameEncoding は 'utf-8' または 'cp437' です(エンジンの 'custom' は nameDecoder からのみ設定できますが、このサーバーでは公開されていません)。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | どちらか一方を指定 |
access | 'auto' | 'memory' | 'range' | 'auto' | inspect_zip と同様です。バイト範囲リーダーがデータを読み取った場合、結果には access: 'range' が含まれます |
offset | integer ≥ 0 | 0 | 一致するエントリを指定数だけスキップします |
limit | integer 1–2000 | 200 | ページ分割が必要な場合は hasMore で確認できます |
filter | object | — | names(完全一致、最大 1000 件)、prefix、glob(最大 32 個、それぞれ最大 1024 文字。セグメント内では *、セグメントをまたぐ場合は **、任意の 1 文字には ?、文字クラスには [a-z] を使用します。/ がない場合はすべての階層が対象となり、末尾に / がある場合はサブツリーが対象になります。線形時間で照合されます。1024 文字を超えるリテラル名(最大 4096 バイトまで指定可能)には、glob ではなく names または prefix を使用してください)、includeDirectories(フィルターを指定しない場合、ディレクトリも一覧表示されます) |
includeExtraData | boolean | false | 追加フィールドのペイロードを base64 で返します(フォレンジック用) |
includeExtendedTimestamps | boolean | false | 各行に extendedTimestamps を含めます(mtime / atime / ctime は UTC の ISO-8601 形式または null、source は 'ut' → 'ntfs' → 'dos' の順です) |
includeUnixIds | boolean | false | 各行に unixIds を含めます(Info-ZIP の 0x7875 追加フィールドから取得した { uid, gid }、または null) |
validate | 'lazy' | 'eager' | 'lazy' | |
strict、limits、verbosity、fields | 共通の設定項目 |
出力:entryCount、matchedCount、offset、limit、returnedCount、hasMore、isZip64、entries[]、access(バイト範囲読み取りの場合のみ)、diagnostics[]。概要:件数と names(このページ)。
{ "zipBase64": "<base64 ZIP>", "filter": { "prefix": "src/", "glob": ["**/*.json"] }, "limit": 50, "fields": ["entries.name", "entries.uncompressedSize", "hasMore"] }
エラー:inspect_zip と同様です(構造上の拒否は validate: 'eager' の場合、またはセントラルディレクトリ自体に破損がある場合に発生します)。無効な glob([z-a] のように文字クラスの範囲が逆転しているもの)は VALIDATION_ERROR になります。
read_zip_entry
アーカイブを展開せずに、name(完全一致、大文字と小文字を区別。同名のエントリが複数ある場合は最後のもの)または index(セントラルディレクトリ内の位置。重複エントリを区別できます)で指定したエントリを1つ読み取ります。mode: 'data'(デフォルト)では、展開後の内容をCRC検証したうえで、dataBase64 として、または encoding: 'utf8' を指定して text として返します。range を指定すると、チャンクストリームを介してバイト範囲を読み取ります(メモリ使用量を抑えられますが、範囲に対するCRC検証は行いません)。mode: 'raw' では、圧縮データをそのまま返します(コピーは発生しません。inflate_raw に渡して展開できます)。mode: 'verify' では、verification: { ok, crcMatch, sizeMatch, localHeaderMatch, skipped? } のみを返します。これはエンジンの判定結果で、デコードできないエントリでも実際のローカルヘッダーとの比較を行い、skipped は 'encrypted' | 'stream-only-codec' | 'unsupported-method' のいずれかです。暗号化されたエントリは、data モードと raw モードでは拒否されます(ZIP_UNSUPPORTED_ENCRYPTION — このエンジンでは復号できません)。バイト範囲リーダー(access: 'range'、または1 GiBを超える zipPath)では、読み取るエントリのバイトのみが取得されます。limits.maxEntryCompressedSize により、取得する1つのペイロードのサイズが制限されます。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | いずれか一方のみ |
name / index | string / integer ≥ 0 | — | いずれか一方のみ |
access | 'auto' | 'memory' | 'range' | 'auto' | inspect_zip と同様 |
mode | 'data' | 'raw' | 'verify' | 'data' | |
encoding | 'base64' | 'utf8' | 'base64' | data モードのみ。有効な UTF-8 ではない場合は ENTRY_NOT_UTF8 |
verifyCrc | boolean | true | range を指定しない data モード |
range | { offset ≥ 0, length 1–16777216 } | — | data モードのみ |
includeExtendedTimestamps / includeUnixIds | boolean | false | list_zip_entries と同様に、entry 行に適用 |
strict、limits、verbosity、fields | 共通フラグメント |
出力:entry(行全体)、mode、sizeBytes、crcVerified、encoding、dataBase64 / text + textLength、range: { offset, length, returned }、verification、access(バイト範囲読み取りのみ)、diagnostics[]。インラインの上限はエントリごとに16 MiBです(ENTRY_TOO_LARGE、data.remedy: 'range')。mode: 'data' では range ウィンドウを読み取るか、ファイルモードの extract_zip を使用してください。上限を超える raw ペイロードはインラインでは取得できません。同じ方法で取得できるのは、展開後の内容です。範囲外の index は、有効な範囲を示す ZIP_ENTRY_NOT_FOUND になります(data.remedy: 'list_zip_entries')。
{ "zipBase64": "<base64 ZIP>", "name": "META-INF/MANIFEST.MF", "encoding": "utf8" }
エラー:ZIP_ENTRY_NOT_FOUND、ENTRY_TOO_LARGE、ENTRY_NOT_UTF8、ZIP_UNSUPPORTED_ENCRYPTION、ZIP_UNSUPPORTED_METHOD、ZIP_CRC_MISMATCH、ZIP_SIZE_MISMATCH、ZIP_DEFLATE_CORRUPT、ZIP_DEFLATE_TRUNCATED、ZIP_INFLATE_OUTPUT_OVERFLOW、ZIP_CD_LFH_MISMATCH、ZIP_ENTRY_OVERLAP、ZIP_RECORD_TRUNCATED(バイト範囲ソースが要求されたバイト数より少ないバイトしか返さない場合)、および上記の構造上の拒否とラッパーコード。
verify_zip
1 回の呼び出しで詳細に検証します。zipnative の verifyZip レポートをそのまま返します。まず構造を先行検証し、その後、すべてのエントリの CRC-32/サイズ/ローカルヘッダーの一致を確認します。構造が有効で、かつ検証可能なすべてのエントリが検証に合格した場合、ok は true になります。このツールはアーカイブに問題があっても失敗しません。構造上の理由で処理が拒否された場合は error: { code: 'ZIP_*', message } に記録され、検証できないエントリには skipped の理由が記録されます。件数はエンジンのアーカイブルールに従います。ローカルヘッダーと中央ディレクトリが一致する暗号化エントリ、またはストリーム専用コーデックのエントリはスキップされ、アーカイブの失敗にはなりません。このサーバーにコーデックがない方式のエントリ(skipped: 'unsupported-method'。方式は 0(無圧縮)または 8(deflate)のみ)と、ローカルヘッダーが中央ディレクトリと一致しない暗号化エントリは失敗となり(ok: false)、アーカイブ全体の検証も失敗します。呼び出し側の誤り(不正な制限値、不正な入力)のみが isError になります。信頼する前に検証してください。信頼できないソースから取得したアーカイブは、extract_zip の前に必ずこのツールで検証してください。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | いずれか一方のみ |
entries | 'all' | 'failed' | 'skipped' | 'none' | 'all' | 返すエントリごとの行 |
maxEntries | integer 1–100000 | 1000 | 返す行数の上限(entriesTruncated)。件数には常にすべてのエントリが含まれます |
limits、verbosity、fields | 共通フラグメント |
出力:ok、error(または null)、entryCount、verifiedCount、failedCount、skippedCount、entries[]({ name, ok, crcMatch, sizeMatch, localHeaderMatch, skipped? })、entriesTruncated、diagnostics[](コードとエントリごとに重複を除去したもの。最大 200 行で、上限に達した場合のみ diagnosticsTruncated: true。1.0.0 の形式を維持するため diagnosticCounts はありません)。このサーバーにコーデックがない方式(0(無圧縮)または 8(deflate)以外。Zstandard、LZMA など)で保存されたエントリは、skipped: 'unsupported-method' および ok: false として返され、failedCount に計上されます。「破損」ではなく「未チェック」として扱ってください(verify: true の場合、merge_zip はそのようなエントリを拒否します)。検証は開始後に中断できません。zipnative の verifyZip は同期処理でシグナルを受け取らないため、実行中に届いたキャンセルは無視され、呼び出しは完了まで続行されます。
{ "zipBase64": "<base64 ZIP>", "entries": "failed", "verbosity": "summary" }
エラー(呼び出し側の誤りのみ):VALIDATION_ERROR、INPUT_TOO_LARGE、INPUT_NOT_FOUND、SECURITY_VIOLATION、INVALID_EXTENSION、IO_ERROR、LIMIT_CEILING_EXCEEDED、ZIP_LIMIT_INVALID。
extract_zip
すべてのエンジンガードを有効にして展開します。緩和する場合は、その内容を指定してください。zip-slip/絶対パス/ドライブパス/UNC/NUL/ADS/Windowsデバイス名 → ZIP_PATH_TRAVERSAL(rejectTraversal: false にするとスキップされ、skipped に列挙されます。安全でないパスが出力されることはありません);シンボリックリンク → ZIP_SYMLINK_REJECTED(rejectSymlinks: false にすると、リンクではなくターゲットのテキストをデータとして展開します);サニタイズ後のパスの重複 → ZIP_EXTRACT_DUPLICATE_PATH(onDuplicate);宣言サイズ/比率が limits を超過 → ZIP_LIMIT_EXCEEDED。重複するエントリと中央/ローカルの不一致は常に拒否されます。どちらのモードでも、計画の作成前にアーカイブが先に開かれるため、ドライランでも展開時と同じオープン時ガードが実行されます。エントリの重複、中央ディレクトリへの侵入や EOF を越えるエントリ、Zip64 の偽装は、計画の行が 1 つも返される前に、それぞれの ZIP_* コードで拒否されます(ファイルモードでの展開は最初の書き込み前に失敗し、data.writtenCount: 0 になります)。メソッド、CRC、サイズの中央/ローカル不一致はエントリの読み取り時に検出されます。これを 1 回の呼び出しで確認するには、verify_zip(localHeaderMatch)を使用します。base64 モードでは、その後、ペイロードに触れずに計画(フィルター、サニタイズ、シンボリックリンクのポリシー、重複、上限)を算出します。includeData: false を指定すると、その計画がドライランとして返されます。ファイルモードでは、各ファイルをサンドボックス内の outputDir にストリーミングします。結合するのはエンジンがサニタイズしたパスだけで、親ディレクトリの実パスを確認し、ファイルは排他的に開きます。また、rejectSymlinks: false によって受け入れられたシンボリックリンクは、リンク先を保持する通常のファイルとして書き込まれます。アーカイブ自体はメモリ上に読み込まれます(zipPath の場合は最大 1 GiB)。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | どちらか一方のみ |
outputMode | 'base64' | 'file' | 'base64' | ファイルごとにインライン出力は最大 16 MiB、合計で最大 32 MiB。ファイルモードは ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTES による上限あり |
outputDir | string | — | ファイルモード:サンドボックス内の相対ディレクトリ(作成されます。上書きはしません) |
includeData | boolean | true | base64 モード:false = ドライラン(パス、サイズを返し、解凍はしません。悪意のある範囲は先に拒否されます) |
filter | object | — | list_zip_entries と同じ(includeDirectories を指定しない限り、ディレクトリは除外) |
rejectTraversal | boolean | true | false にすると、安全でない名前を skipped に入れてスキップします |
rejectSymlinks | boolean | true | false にすると、ターゲットのテキストをデータとして書き込みます |
onDuplicate | 'error' | 'first' | 'last' | 'error' | 2 つのエントリ → 1 つのサニタイズ済みパス |
emptyDirectories | boolean | false | ファイルモード:ファイルを含まない明示的なディレクトリエントリを作成します |
strict、limits、verbosity、fields | 共通フラグメント |
出力:mode、dryRun、fileCount、totalBytes、entries[]({ path, entryName, index, sizeBytes, crc32, method, dataBase64? | filePath? })、skipped[]({ entryName, reason: 'unsafe-path' })、outputDir、directoriesCreated、diagnostics[]。ファイルモードでは最大 50 個の resource_link コンテンツブロックが追加されます。概要:mode、dryRun、fileCount、totalBytes、skippedCount、paths。
{ "zipBase64": "<base64 ZIP>", "outputMode": "file", "outputDir": "unpacked/report", "filter": { "glob": ["docs/", "*.json"] } }
エラー:ZIP_PATH_TRAVERSAL、ZIP_SYMLINK_REJECTED、ZIP_EXTRACT_DUPLICATE_PATH、ZIP_LIMIT_EXCEEDED、ZIP_ENTRY_OVERLAP、ZIP_CD_LFH_MISMATCH、ZIP_UNSUPPORTED_ENCRYPTION、ZIP_UNSUPPORTED_METHOD、ZIP_CRC_MISMATCH、ZIP_SIZE_MISMATCH、ZIP_DEFLATE_CORRUPT、ZIP_DEFLATE_TRUNCATED、ENTRY_TOO_LARGE、OUTPUT_TOO_LARGE、OUTPUT_EXISTS、IO_ERROR、MISSING_OUTPUT_PATH、SECURITY_VIOLATION、CANCELLED、および構造上の拒否やラッパーのコード。
scan_zip_forward
メモリ使用量を抑えながら、ローカルヘッダーをストリーム順に走査します(zipnative の中央ディレクトリを必要としないリーダー iterateZipEntries)。途中で切れたアーカイブや、ストリームが途中で切断された場合にも機能する唯一のツールです。ただし、ストリームはローカルヘッダーから始まる必要があります。SFX/先頭に付加されたプレフィックスをスキップできず、プレフィックスがある場合は ZIP_SIGNATURE_MISMATCH で拒否します(プレフィックス付きアーカイブには、prependedData/ZIP_PREPENDED_DATA を報告し、オフセットを調整する inspect_zip を使用してください。modify_zip mode: 'compact' はプレフィックスを削除します)。また、このツールだけは結果が確定的ではありません。前方走査ではローカルヘッダーだけを信頼するため、悪意のあるアーカイブは、inspect_zip/list_zip_entries が報告する内容とは異なる内容をここで提示できます(アップロードスキャナーの差異)。アーカイブ全体を利用できる場合は、常にこれらのツールを優先してください。フォレンジックにはこのツールを使用します。名前はサニタイズされません。sanitizedPath には、展開ゲートが使用するパスが示されます。zipPath は、1 GiB のバッファー上限を適用せず、1 つのオープンハンドルを通してディスクからストリーミングされます。ラッパーは PK 署名を読み取りません。stoppedAt はバイト数の計測から導出されます(中央ディレクトリに到達すると、エンジンはストリームの残りを未読のままにします)。破損した deflate データは、すべてのランタイム階層で ZIP_DEFLATE_CORRUPT/ZIP_DEFLATE_TRUNCATED になります(1.0.0 ではここで ZIP_DECOMPRESSION_FAILED と報告されていました)。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | いずれか一方のみ |
data | 'none' | 'verify' | 'include' | 'none' | none はペイロードをスキップします(データディスクリプターを持つエントリでは、展開して破棄する処理が必要です)。verify は CRC を検証します。include はコンテンツを返します(インライン上限あり) |
filter | object | — | list_zip_entries と同様(フィルターを指定しない場合はディレクトリも含まれます) |
maxEntries | integer ≥ 1 | 10000 | デフォルト値は ZIPNATIVE_MCP_MAX_ENTRIES の上限に合わせてクランプされます。上限を超える値を明示的に指定すると LIMIT_CEILING_EXCEEDED になります(data.remedy: 'maxEntries ≤ N') |
tolerateTruncation | boolean | false | true の場合:ストリームが切断または破損していると、失敗する代わりに stoppedAt: 'error' と error を返して走査を終了します |
strict、limits、verbosity、fields | 共通フラグメント |
出力:trust: 'local-headers-only'、entryCount、keptCount、entries[](kept と data: { verified, bytesProduced, dataBase64? } を含む行。isSymlink/usesZip64/unixMode は null)、stoppedAt('central-directory' — リーダーが中央ディレクトリに到達し、残りを未読のままにした | 'eof' — 中央ディレクトリがない状態でストリーム全体を消費した:切断されているか、中央ディレクトリがない | 'max-entries' — 上限を超えてローカルヘッダーが残っていた(エントリ数が maxEntries とちょうど同じアーカイブは 'central-directory' で終了します) | 'error')、truncated、inputBytes、bytesDelivered、maxEntries(クランプ後に適用される上限)、error、diagnostics[]。
{ "zipBase64": "<base64 of a truncated download>", "tolerateTruncation": true, "verbosity": "summary" }
エラー:ZIP_STREAM_TRUNCATED、ZIP_SIGNATURE_MISMATCH、ZIP_RECORD_TRUNCATED、ZIP_DESCRIPTOR_MISMATCH、ZIP_UNSUPPORTED_CD_LESS_DESCRIPTOR、ZIP_UNSUPPORTED_ENCRYPTION、ZIP_UNSUPPORTED_METHOD、ZIP_CRC_MISMATCH、ZIP_SIZE_MISMATCH、ZIP_DEFLATE_CORRUPT、ZIP_DEFLATE_TRUNCATED、ZIP_INFLATE_OUTPUT_OVERFLOW、ZIP_LIMIT_EXCEEDED、ENTRY_TOO_LARGE、OUTPUT_TOO_LARGE、LIMIT_CEILING_EXCEEDED(tolerateTruncation: true の場合、すべてのエンジンコードは error に入ります)。
sanitize_entry_paths
名前のリストに zipnative の単一のトラバーサルゲート sanitizeEntryPath() を適用します。各名前に対応する安全な / 区切りの相対形式(展開ルートの下に結合してください。元の名前は絶対に使用しないでください)、または該当したルールとともに null を返します。別のツールで展開する場合や、外部ファイルシステムへの出力を計画する場合に使用してください。アーカイブは不要です。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
names | string[] 1–10000 | — | 各名前は 4096 文字以下。アーカイブに保存されている形式 |
verbosity, fields | 射影 |
出力:count、rejectedCount、results[]({ name, sanitized, rejected, reason? }。reason は empty、nul、absolute、drive、unc、traversal、ads、device-name、no-segments のいずれか)。概要:count、rejectedCount、rejectedNames。
{ "names": ["docs/readme.md", "../../etc/passwd", "C:\\Windows\\win.ini", "aux.txt", "a/./b//c.txt"] }
エラー:VALIDATION_ERROR。
create_zip
インラインエントリ(サンドボックス内の dataBase64 | text | sourcePath、または directory: true)から ZIP を書き込みます。デフォルトでは再現可能です。正規順序(生の UTF-8 名前バイト)、DOS エポックのタイムスタンプ(日付はすべて UTC で書き込み)、UTF-8 の名前、固定属性を使用します。defaultDate: 'now' を指定するとこの動作は無効になり(診断 ZIP_TIMESTAMP_NOT_PINNED)、compression.deterministic: true を指定すると純粋な TS エンコーダーが固定され、すべてのランタイムでバイト列が同一になります(summary.deflateTier: 'pure-pinned')。デフォルトの node-zlib ティアでは、同じ環境内でのみバイト列が安定します。決定性に関する判定は 3 種類あります。該当する箇所で確認してください。summary.deterministic が true になるのは、すべてのエントリで compression.deterministic: true が指定され、かつ現在時刻の日付がない場合のみです(ランタイムをまたいだ同一性。デフォルトの呼び出しでは、同じランタイム上でバイト列が再現可能でも false と報告されます)。summary.sha256(includeSha256、base64 モードとファイルモードの両方)がその証明になります。inspect_zip.determinism.deterministic は、正規のデフォルト(エポックタイムスタンプ+正規順序+UTF-8 フラグ)に照らした構造上の判定です(エポック以外の日付を固定すると再現可能になりますが、ここでは false と報告されます)。order: 'insertion' を指定すると、EPUB / JAR 向けに呼び出し順序を維持します(mimetype を先頭にし、格納方式を使用)。sourcePath に対する stream: true は、1 つのオープンハンドルから addStream を通じてファイルを読み込みます(データディスクリプター形式で、メモリ使用量を抑制)。ストリーミング中のエントリが 4 GiB を超えると ZIP_UNSUPPORTED_ZIP64_STREAMING になります。ただし zip64: true を指定すると、Zip64 ストリーミング形式(APPNOTE 4.3.9.2)を使用します。parallel を指定するとワーカープールで圧縮します。出力のバイト列は同一です。workers を指定しない場合、エンジンのデフォルト max(1, min(cores − 1, 8)) が適用され、ZIPNATIVE_MCP_WORKERS によって上限が設定されます。Zip64 はフィールドがあふれる場合に限り出力されます。ここでは 1 回の呼び出しで最大 100 000 エントリまで扱えます(エンジンのデフォルト maxEntries と ZIPNATIVE_MCP_MAX_ENTRIES の上限が実質的な制限として残るため、65 536 エントリのアーカイブは自動的に Zip64 に切り替わります)。末尾が / の名前はディレクトリを表し、ペイロードを持てません(VALIDATION_ERROR。末尾のスラッシュを削除するか、directory: true を指定してください)。このツールが書き込むアーカイブはすべて ISO/IEC 21320-1 に準拠しています(CI で検証済み)。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
entries | 配列 0–100000 | — | 必須。各エントリは name(1–4096、/ 区切り。末尾の / はディレクトリを意味し、ペイロードを受け付けません)、dataBase64 / text / sourcePath のいずれか1つ、または directory: true を指定します。エントリごとに compression、date(ISO-8601、pattern ^\d{4}-\d{2}-\d{2}、1980–2107、UTC として読み取り)、comment(≤ 65535)、unixMode(pattern ^(?:0o)?[0-7]{3,4}$ — '0644'、'755'、'0o755' などの3~4桁の8進数。前後に空白を含めない)または externalAttributes(uint32)のいずれか一方、extraFields(≤ 16 個の { id 0–65535 except 1, dataBase64 })、stream(sourcePath と併用)、zip64(stream: true の場合のみ。そうでない場合は VALIDATION_ERROR)を指定できます。 |
order | 'canonical' | 'insertion' | 'canonical' | |
defaultDate | 文字列 | DOS エポック | ISO-8601 または 'now'(pattern ^(?:now|\d{4}-\d{2}-\d{2})) |
compression | オブジェクト | deflate 6 | method('store' | 'deflate')、level 0–9、deterministic(ストリーミング対象エントリを2 GiBに制限) |
comment | 文字列 ≤ 65535 | — | アーカイブのコメント |
chunkSize | 整数 1024–16777216 | 64 KiB | ファイルモードのストリーミングチャンク。バイト列は変化しません |
parallel | オブジェクト | — | workers 0–64(≤ ZIPNATIVE_MCP_WORKERS。省略時はエンジンのデフォルト max(1, min(cores − 1, 8)) を上限値で制限)、minWorkerJobSize ≥ 1、jobTimeout 1000–600000 ms |
includeSha256 | ブール値 | false | base64 形式の summary.sha256 とファイルモードでの SHA-256(ストリーミング中にハッシュを計算し、決定性を証明) |
outputMode / outputPath | 'base64' | ファイルモード:コンテナー拡張子で終わる相対パス | |
strict、limits | 共通フラグメント |
4 GiB 未満の zip64: true エントリにも Zip64 レコードが含まれます。一部のストリーミングリーダー(Java の ZipInputStream など)では読み取れないため、4 GiB を超える可能性のあるエントリに限って指定し、結果をサンドボックスに書き込むには ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTES を引き上げてください。
出力:埋め込み resource(≤ 50 MiB)または resource_link としてのアーカイブ。structuredContent:mode、sizeBytes、filePath、summary(ツールの outputSchema で型指定:entryCount、fileCount、directoryCount、streamedCount、uncompressedBytes、order、deterministic、deflateTier、parallel: { requested, workers }、sha256)、diagnostics[]。
{
"entries": [
{ "name": "mimetype", "text": "application/epub+zip", "compression": { "method": "store" } },
{ "name": "META-INF/container.xml", "text": "<container/>" },
{ "name": "OEBPS/", "directory": true }
],
"order": "insertion",
"compression": { "deterministic": true },
"includeSha256": true,
"outputMode": "file",
"outputPath": "books/sample.epub"
}
エラー:VALIDATION_ERROR、INPUT_TOO_LARGE、INPUT_NOT_FOUND、OUTPUT_TOO_LARGE、OUTPUT_EXISTS、IO_ERROR、MISSING_OUTPUT_PATH、INVALID_PATH、INVALID_EXTENSION、SECURITY_VIOLATION、LIMIT_CEILING_EXCEEDED、CANCELLED、ZIP_INVALID_ENTRY_NAME、ZIP_INVALID_OPTION、ZIP_LIMIT_EXCEEDED、ZIP_UNSUPPORTED_ZIP64_STREAMING、ZIP_INPUT_TOO_LARGE、ZIP_STRICT_DIAGNOSTIC、ZIP_API_MISUSE。
modify_zip
既存のアーカイブを再圧縮せずに編集します。operations の add/replace/remove/rename/setComment を順番に適用します。どちらのモードでも入力は先行して開かれます。操作を実行する前に、オーバーラップテーブルと各エントリの範囲がすべてチェックされるため、オーバーラップのあるアーカイブやヘッダーが途中で切れているアーカイブは、mode: 'append' でも拒否されます。append モードで保存する前には、暗号化されていない各エントリについて、ローカルヘッダーと宣言サイズとの整合性もチェックされます(圧縮解除を伴わない生データの読み取りです)。そのため、圧縮方式/CRC/サイズの不一致(ZIP_CD_LFH_MISMATCH)や宣言サイズによる爆弾(ZIP_LIMIT_EXCEEDED)がある場合、mode: 'compact' とその他の書き込み処理では拒否されます。ペイロードはそれ以外の場合、そのままコピーされ、デコードされません。破損したペイロードや、アーカイブ内にすでに存在する安全でない名前(../../evil.txt)も、出力に変更されず引き継がれます。ただし、extract_zip はそのような名前を引き続き拒否します。mode: 'append'(デフォルト)=save():元のバイト列はそのまま保持され、編集内容が追記されます。高速でバイト列を保持できますが、削除または置換されたペイロードはファイル内に残ります(データ残留:誰でも復元可能です。不要なバイトが 50 % を超えると ZIP_DEAD_BYTES_RATIO 診断が発生します。また、7-Zip は古いペイロードを読み取ることが知られています)。mode: 'compact'=saveCompact():再圧縮せずに書き換え、エントリを生の名前バイト列でソートします(挿入順のレイアウト、つまり EPUB の mimetype を先頭に置く形式や JAR のマニフェストを先頭に置く形式は保持されません。そのようなコンテナーは create_zip の order: 'insertion' で再構築してください)。削除したデータは完全に消去され、SFX プレフィックスも削除されます。編集後に正規の決定的な形式で書き込むには、canonical: {…} を追加してください(ルールは canonicalize_zip を参照)。編集がなく、コメントも変更されていない場合は、同じバイト列を返します(summary.noOp)。エントリ名が重複するアーカイブは拒否されます。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | どちらか一方のみ |
operations | array 1–1000 | — | { op: 'add' | 'replace', name, dataBase64 | text | sourcePath, compression?, date?, comment?, unixMode? | externalAttributes?, extraFields?, directory? (add only) }、{ op: 'remove', name }、{ op: 'rename', from, to }、{ op: 'setComment', comment } — ペイロードのルールと pattern は create_zip と同じです(ペイロードを含む / 終端の名前は VALIDATION_ERROR です) |
mode | 'append' | 'compact' | 'append' | |
canonical | object | — | mode: 'compact' の場合のみ指定できます(それ以外は VALIDATION_ERROR):{ date?, keepComments? (false), keepExternalAttributes? (true) }。{} を指定するとデフォルトが適用されます |
compression | object | エンジンのデフォルト | 新しいペイロード用(create_zip と同じ形式:method、level、deterministic) |
defaultDate | string | DOS エポック | 新しいペイロード用。ISO-8601 または 'now'(pattern ^(?:now|\d{4}-\d{2}-\d{2})。'now' → ZIP_TIMESTAMP_NOT_PINNED) |
includeSha256 | boolean | false | |
outputMode / outputPath | 'base64' | ||
strict、limits | 共通フラグメント |
出力:埋め込みの resource または resource_link としてのアーカイブ、summary(saveMode、operationsApplied、entryCountBefore、entryCountAfter、inputBytes、outputBytes、grewByBytes、noOp、正規形式を書き込んだ場合に含まれる canonical、sha256)、diagnostics[]。
{ "zipBase64": "<base64 ZIP>", "operations": [{ "op": "remove", "name": ".env" }, { "op": "rename", "from": "config.json", "to": "config/app.json" }], "mode": "compact", "canonical": {} }
エラー:ZIP_ENTRY_NOT_FOUND、ZIP_ENTRY_EXISTS、ZIP_DUPLICATE_ENTRY_NAME、ZIP_INVALID_ENTRY_NAME、ZIP_ENTRY_OVERLAP、ZIP_CD_LFH_MISMATCH、ZIP_RECORD_TRUNCATED、ZIP_LIMIT_EXCEEDED、ZIP_STRICT_DIAGNOSTIC に加え、構造上の拒否、出力コード、ラッパーコードが発生します(data.operationIndex/data.op は、失敗した操作の名前を示します)。
canonicalize_zip
あらゆるアーカイブを再現可能にします。zipnative の canonicalizeZip() は、自分で作成していないアーカイブ(Gradle、Maven、zip、Windows Explorer、7-Zip、bsdtar など)を、エンジン独自のライターが出力する正規の決定論的な形式に書き換えます。エントリーは名前の生バイト順に並べ替えられ、すべて同じタイムスタンプ(DOS エポック、または固定された date)になり、すべての名前で UTF-8 フラグが有効になり、Zip64 以外の追加フィールドはなく、version-made-by は固定値(0x032D)になり、データディスクリプターは付きません。ペイロードの再圧縮やデコードは一切行いません。圧縮済みバイトはビット単位でそのままコピーされるため、破損したエントリーや暗号化されたエントリーも変更されずに引き継がれます。また、名前もそのままコピーされるため、../../evil.txt のような安全でない名前も出力に残ります(canonicalForm が true になる場合でも、extract_zip はその名前を拒否し、名前を検証済みライター経由で書き込む merge_zip は ZIP_INVALID_ENTRY_NAME で拒否します)。コーデックが実行されないため、実行環境が異なっても結果のバイト列は安定します。冪等性があり、出力を再度正規化しても同じバイト列になります(summary.alreadyCanonical)。出力は、同じ固定日付を使ってエンジンの analyzeDeterminism() でもう一度検査され、判定結果は summary.canonicalForm に示されます。後から inspect_zip { check: ['canonical-form'], canonicalDate } で検証できます。エントリー名が重複するアーカイブは、modify_zip と同様に拒否されます。コンテンツの変更と正規化を一度に行うには、canonical を指定して modify_zip mode: 'compact' を使用してください。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
zipBase64 / zipPath | string | — | どちらか一方のみ |
date | string | DOS epoch | すべてのエントリーに書き込むタイムスタンプ(ISO-8601、1980-01-01 ~ 2107-12-31、UTC として読み取り、DOS の粒度は 2 秒) |
keepComments | boolean | false | アーカイブのコメントとエントリーのコメントを保持します(正規形式ではコメントは付きません) |
keepExternalAttributes | boolean | true | Unix のモード/DOS 属性を保持します。false の場合、正規のデフォルト値(ファイルは 0o100644、ディレクトリは 0o40755)を書き込みます |
includeSha256 | boolean | false | 生成したバイト列の summary.sha256 |
outputMode / outputPath | 'base64' | ファイルモード:コンテナー拡張子で終わる相対パス | |
strict, limits | 共通フラグメント |
出力:埋め込み resource(50 MiB 以下)または resource_link と、summary(entryCount、inputBytes、outputBytes、alreadyCanonical、canonicalForm、pinnedDate(UTC の ISO-8601、DOS エポックの場合は null)、keepComments、keepExternalAttributes、sha256)、diagnostics[]。
{ "zipBase64": "<base64 ZIP>", "date": "2026-10-08T00:00:00Z", "keepExternalAttributes": false, "includeSha256": true }
エラー:VALIDATION_ERROR(不正または範囲外の date)、INPUT_TOO_LARGE、INPUT_NOT_FOUND、SECURITY_VIOLATION、INVALID_EXTENSION、IO_ERROR、LIMIT_CEILING_EXCEEDED、OUTPUT_TOO_LARGE、OUTPUT_EXISTS、MISSING_OUTPUT_PATH、CANCELLED、ZIP_DUPLICATE_ENTRY_NAME、ZIP_LIMIT_EXCEEDED、ZIP_STRICT_DIAGNOSTIC、および構造上の ZIP_* 拒否。
merge_zip
複数のアーカイブを、何も再圧縮せずに1つにまとめます。zipnative の ZipWriter.addFromReader() は、各エントリーの圧縮済みバイト列を、圧縮方式、CRC、サイズ、タイムスタンプ、属性、コメント、追加フィールドとともに移植します(Zip64 は再計算されます)。verify: true(デフォルト)の場合は、コピー前にすべてのエントリーを一度展開し、CRC とサイズを照合します。そのため、破損したペイロードは伝播されず、固定コードとともに拒否されます。このサーバーでは展開できないエントリー(方式 0 の store/方式 8 の deflate 以外)は、未検証のままコピーされず、ZIP_UNSUPPORTED_METHOD で拒否されます(verify: false の場合はそのままコピーされ、summary.verified で検証が有効だったかどうかを確認できます)。各名前にはライターの名前ルールが適用されるため、ライターが拒否するソースエントリー(bsdtar が書き込む ./ ディレクトリーエントリー、.. セグメント、デバイス名)があると、data.sourceIndex とともにマージが ZIP_INVALID_ENTRY_NAME で失敗します。そのソースの filter で除外してください。暗号化されたエントリーは拒否されます(ZIP_UNSUPPORTED_ENCRYPTION — 生の状態では読み取れません)。残りをマージするには、これらをフィルターで除外してください。名前が衝突した場合、onConflict: 'error'(デフォルト)では、エンジンが2つ目の出現を拒否します(ZIP_DUPLICATE_ENTRY_NAME)。'first'/'last' では、ソースの順序に従って最初/最後の出現を残し、それ以外を報告します。公開されているのは、検証済みの移植方法のみです。エンジンの addRaw()(呼び出し元が CRC とサイズを保証する方式)は公開されないため、エージェントがこのツールを通じて整合性のないアーカイブを偽造することはできません。結果の順序は create_zip と同様です(デフォルトは order: 'canonical')。完全な正規形式にするには、その結果に対して canonicalize_zip を実行してください。すべてのソースはメモリー上で開かれます。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
sources | 配列 1~32 件 | — | 必須。各要素は { zipBase64 | zipPath, filter? }(filter は list_zip_entries と同じです。フィルターで除外されない限り、ディレクトリーは保持されます)。合計 ≤ 1 GiB、インラインペイロードはすべて合わせて ≤ 128 MiB |
onConflict | 'error' | 'first' | 'last' | 'error' | 同じ名前のエントリーが2つある場合の処理 |
verify | boolean | true | false の場合、ソースを信頼します。バイト列はそのまま渡されます |
order | 'canonical' | 'insertion' | 'canonical' | 'insertion':ソースの順序に従い、その後、各ソースのセントラルディレクトリーの順序に従います |
comment | 65535 文字以下の string | — | 結果のアーカイブコメント(ソースのコメントはマージされません) |
includeSha256 | boolean | false | |
outputMode / outputPath | 'base64' | ファイルモードでは、結果をサンドボックスにストリーミングします | |
strict、limits | 共通フラグメント |
出力:埋め込み resource または resource_link としてのアーカイブ、summary(sourceCount、entryCount、inputBytes、outputBytes、onConflict、verified、order、perSource[]({ index, label, entryCount, taken, filteredOut, dropped })、dropped[]({ name, source }、最大 200 行)、sha256)、diagnostics[]。拒否された場合は、data.sourceIndex にソースが示されます。
{ "sources": [{ "zipBase64": "<base64 ZIP A>" }, { "zipBase64": "<base64 ZIP B>", "filter": { "prefix": "assets/" } }], "onConflict": "last", "includeSha256": true }
エラー:VALIDATION_ERROR、INPUT_TOO_LARGE、INPUT_NOT_FOUND、SECURITY_VIOLATION、INVALID_EXTENSION、IO_ERROR、LIMIT_CEILING_EXCEEDED、OUTPUT_TOO_LARGE、OUTPUT_EXISTS、MISSING_OUTPUT_PATH、CANCELLED、ZIP_DUPLICATE_ENTRY_NAME、ZIP_INVALID_ENTRY_NAME(ライターが拒否するソース名。フィルターで除外してください)、ZIP_CRC_MISMATCH、ZIP_SIZE_MISMATCH、ZIP_DEFLATE_CORRUPT、ZIP_DEFLATE_TRUNCATED、ZIP_UNSUPPORTED_METHOD(この環境にコーデックがない方式で verify: true を指定した場合)、ZIP_UNSUPPORTED_ENCRYPTION、ZIP_CD_LFH_MISMATCH、ZIP_ENTRY_OVERLAP、ZIP_LIMIT_EXCEEDED、ZIP_STRICT_DIAGNOSTIC、および構造上の ZIP_* 拒否。
compute_crc32
インラインのバイト列/テキスト、またはサンドボックス内のファイル(1 つのハンドルを開いたまま 1 MiB 単位でストリーミング、最大 1 GiB)の ZIP チェックサム(IEEE 802.3 CRC-32、エンジンの slice-by-8 実装)です。seed を使うと連続するチャンク間で CRC を引き継ぎ、expect を使うと既知の値と比較できます。list_zip_entries のエントリーの crc32 とディスク上のファイルを照合するために使用します。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
dataBase64 / text / sourcePath | string | — | いずれか 1 つ |
seed | integer 0–4294967295 | 0 | 引き継ぐ CRC |
expect | string | — | 1~8 桁の 16 進数。0x は省略可能(pattern ^(?:0x)?[0-9a-fA-F]{1,8}$) |
出力:crc32(符号なし)、hex(小文字 8 桁)、byteLength、seed、matches(expect が指定された場合)。
{ "text": "hello world", "expect": "0d4a1185" }
エラー:VALIDATION_ERROR、INPUT_TOO_LARGE、INPUT_NOT_FOUND、SECURITY_VIOLATION、IO_ERROR、CANCELLED(1 MiB 単位のチャンク間で確認)。
inflate_raw
raw DEFLATE(RFC 1951)ストリームを解凍します。たとえば、read_zip_entry mode: 'raw' で取得したペイロードが対象です。zipnative の再開可能なインフレーターを使用し、必須の maxOutput 上限を設けます(メモリー使用量は一定、bytesConsumed は正確に計測され、末尾のバイトは leftover として報告されます。上限を超えると ZIP_INFLATE_OUTPUT_OVERFLOW が発生します)。method: 'store' は上限付きのパススルーです。数値のメソッド ID は登録済みのコーデックを選択します(このサーバーでは 0/8 以外は非対応のため、ZIP_UNSUPPORTED_METHOD が発生します)。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
dataBase64 / sourcePath | string | — | いずれか 1 つ |
maxOutput | integer ≥ 1 | — | 必須。インラインの結果はさらに 50 MiB、ファイルの結果は ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTES に制限されます |
method | string | 'deflate' | 'deflate'、'store'、または数値 ID(pattern ^(?:deflate|store|[0-9]+)$) |
allowTrailing | boolean | false | ストリーム後のバイトを無視して受け入れます(常に leftover として報告されます) |
outputMode / outputPath | 'base64' | ファイルモード:.bin .dat .txt .json .xml .md .csv .html .zip .tar .raw |
出力:解凍されたバイト列を埋め込み resource(application/octet-stream)または resource_link として返します。summary(method、methodName、bytesIn、bytesOut、bytesConsumed、leftover、finished、maxOutput、trailingWarning)も返します。
{ "dataBase64": "<raw deflate payload>", "maxOutput": 1048576 }
エラー:ZIP_INFLATE_OUTPUT_OVERFLOW、ZIP_DEFLATE_CORRUPT、ZIP_DEFLATE_TRUNCATED、ZIP_UNSUPPORTED_METHOD、ZIP_UNSUPPORTED_CODEC_MODE、ZIP_API_MISUSE、CANCELLED(入力チャンク間で確認)、入力ラッパーのコード、およびファイルモードのコード(OUTPUT_EXISTS、MISSING_OUTPUT_PATH、INVALID_EXTENSION)。maxOutput がインラインまたはファイルの上限を超える場合は、その上限まで引き下げられます。そのため、結果が大きすぎる場合は OUTPUT_TOO_LARGE ではなく ZIP_INFLATE_OUTPUT_OVERFLOW が発生します(data.configured = 適用される上限)。
describe_engine
オフラインの事前確認(アーカイブ不要):サーバー/エンジン/ツール API のバージョンとプロトコル文字列、ツール数、使用中の deflate ティアと固定された決定論的ティア、ランタイムのコーデック(node:zlib、CompressionStream、DecompressionStream)とワーカースレッド、コーデックレジストリ(sync、stream、incrementalを含むcodecs[] — 前方読み取りとバイト範囲読み取りがコーデックをチャンク単位でデコードするかどうか)、エンジンのデフォルトのlimits(9 個のキー)、4 つのオペレーター上限(maxUncompressedBytes、maxEntries、maxWorkers、maxFileOutputBytes。envには変数名を指定)、すべてのサーバー上限、サンドボックスとキャッシュが有効かどうか、39 個の固定されたZIP_*エラーコードと 12 個の診断コード、エンジンがエクスポートするものの、このサーバーでは意図的に公開していない項目とその理由(nameDecoder、addRaw、registerCodec、ワーカー URL など)。networkは常に'none'です。キャッシュされません。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
verbosity、fields | 投影のみ |
出力:server、engine、capabilities、codecs[]、defaultLimits、ceilings、caps、sandbox、network、errorCodes[]、diagnosticCodes[]、unexposed[]。
{ "fields": ["defaultLimits", "ceilings", "caps", "sandbox"] }
エラー:VALIDATION_ERROR。
draft_governance_issue
ガバナンスに準拠した GitHub issue をローカルで下書きし、人間が確認して送信できるようにします。対象はzipnative(エンジンの動作:解析、書き込み、制限、コーデック)またはzipnative-mcp(ラッパーの動作:スキーマ、サンドボックス、トランスポート)です。サーバーが GitHub に連絡することはありません。ネットワークを利用するコードパスは一切なく、下書きの Markdown と機械可読なコンプライアンスレポートを返します。両方をユーザーに提示した後、停止してください。ユーザー本人が確認し、自身のアカウントで送信します。
| 入力 | 型 | デフォルト | 備考 |
|---|---|---|---|
title | string 8–160 | — | 必須 |
summary | string ≥ 16 | — | 必須。自由記述フィールドは 16,384 文字に制限されます |
issueType | 'bug' | 'feature' | 'security' | 'docs' | 'performance' | — | 必須 |
targetRepo | string 1–100 | 'zipnative-mcp' | ドキュメントのみ |
reproduction | { command, result } | — | 必須。両方とも空でないこと |
expectedBehavior | string ≥ 4 | — | 必須 |
actualBehavior | string | 再現結果 | |
affectedPackages | string[] ≤ 16 | ['zipnative-mcp'] | |
duplicateSearchPerformed | boolean | — | 必須。trueでなければなりません |
outputMode / outputPath | 'inline' | 'file' | 'inline' | file モードでは、ZIPNATIVE_MCP_OUTPUT_DIR内に相対パスの.mdファイルも書き込みます(確認用に.github/drafts/へコピーしてください。このツールがそこへ書き込むことはありません) |
出力:title、issueType、targetRepo、outputMode、filePath、sizeBytes、draftMarkdown、warnings[]、compliance(zeroDependencyConfirmed、reproductionCommand、reproductionResult、duplicateSearchPerformed、affectedPackages、identityReminderShown、humanGate、environment)。
{
"title": "list_zip_entries: an optional sort order for the returned page",
"issueType": "feature",
"targetRepo": "zipnative-mcp",
"summary": "Paging through a 70 000-entry archive returns rows in central-directory order only; finding the largest entries means reading every page.",
"reproduction": { "command": "list_zip_entries { zipPath: 'big.zip', limit: 200, fields: ['entries.name', 'entries.uncompressedSize'] }", "result": "rows in central-directory order; no input sorts them by size or name" },
"expectedBehavior": "An optional sort input (name or uncompressedSize, ascending or descending) applied before offset and limit.",
"affectedPackages": ["zipnative-mcp"],
"duplicateSearchPerformed": true
}
ランタイム依存関係を提案する下書き、またはduplicateSearchPerformed: falseを設定した下書きはGOVERNANCE_VIOLATIONで拒否されます。必須入力のreproductionがない場合はVALIDATION_ERRORになります。その他のエラー:VALIDATION_ERROR、MISSING_OUTPUT_PATH、INVALID_EXTENSION、OUTPUT_EXISTS、SECURITY_VIOLATION。人間が介在するプロセスの完全な契約については、governance_contractおよびdraft_issue_workflowプロンプトとdocs/guides/AI_GOVERNANCE.mdを参照してください。
🔐 セキュリティモデル
zipnative-mcpはホストプロセス内で実行され、stdio MCP サーバー(またはループバック専用 HTTP エンドポイント)を公開します。すべてのアーカイブを信頼できない入力として扱い、ZIPNATIVE_MCP_CACHE_DIR下のオプトイン方式のレスポンスキャッシュを除き、設定されたサンドボックスの外部で I/O を実行しません。
| 脅威 | 防御策 | CWE |
|---|---|---|
Zip-slip パストラバーサル(../、絶対パス、ドライブ文字、UNC、バックスラッシュ、NUL、NTFS ADS)と Windows の予約デバイス名(CON、NUL、AUX、COM1…LPT9) | デフォルトでは rejectTraversal: true → ZIP_PATH_TRAVERSAL。false にするとスキップし、出力はしません。sanitize_entry_paths では外部シンクに対して同じゲートを適用できます。ライターも同様の名前を拒否します | CWE-22 / CWE-67 |
| 解凍爆弾(宣言サイズ、合計サイズ、比率、エントリーの大量投入) | 9 つの ZipLimits の上限を、解凍後ではなく解凍中に適用します → ZIP_LIMIT_EXCEEDED。呼び出しごとの limits がオペレーターの上限を超えることはありません。inflate_raw には必須の maxOutput があります | CWE-400 / CWE-409 |
| バイト範囲リーダーが取得するサイズ超過のペイロード | limits.maxEntryCompressedSize(デフォルトでは 1 GiB + 1 MiB。ZIPNATIVE_MCP_MAX_UNCOMPRESSED_BYTES による上限あり) | CWE-770 |
| 抽出先をリダイレクトするシンボリックリンクエントリー | デフォルトでは rejectSymlinks: true → ZIP_SYMLINK_REJECTED。false にするとリンク先のテキストを通常のファイルとして書き込み、リンクが実体化されることはありません | CWE-59 |
| エントリーの重複(複数のエントリーが同一のペイロードを要求する) | 常に重複を検出します → ZIP_ENTRY_OVERLAP。無効化はできません。modify_zip は入力を先行して開くため、追記パスでも検査されます | CWE-405 |
| パーサー差異を利用したすり抜け(中央ディレクトリとローカルヘッダー間) | 中央ディレクトリを正とします。方式/サイズ/CRC の不一致 → ZIP_CD_LFH_MISMATCH(無効化不可)、名前の不一致 → ZIP_NAME_MISMATCH 診断。scan_zip_forward は trust: 'local-headers-only' と示します | CWE-436 |
| Zip64 センチネルの偽装 | Zip64 レコードを、センチネルではないすべての従来フィールドと照合します → ZIP_ZIP64_CONTRADICTION。無効化はできません | CWE-1288 |
| エントリー名の重複(抽出時のシャドーイング) | デフォルトでは onDuplicate: 'error' → ZIP_EXTRACT_DUPLICATE_PATH。'first'/'last' を指定すると、意図的に解決できます | CWE-694 |
| 曖昧な EOCD/末尾のガーベジ、2^53 を超える 64 ビットフィールド | 拒否します(ZIP_EOCD_NOT_FOUND、ZIP_VALUE_UNREPRESENTABLE)。推測で補うことはありません | CWE-190 |
| 悪意のあるエントリー名による壊滅的なバックトラッキング | glob は Thompson NFA にコンパイルされます。一致判定は 1 回あたり O(名前 × パターン)で、パターンは 1,024 文字以下です。ガバナンスポリシーのパターンも線形です | CWE-1333 |
| チェックから読み取りまでの間にサンドボックス内のファイルが差し替えられる | すべての読み取りで 1 つのオープンハンドルを使用します。その実パスがサンドボックス内にあることを確認し、デバイスと inode によってハンドルに紐付けます。読み取り中にファイルが変更されると IO_ERROR になります | CWE-367 |
- サンドボックス(
ZIPNATIVE_MCP_OUTPUT_DIR)は、読み取り(zipPath、sourcePath、resources/read、merge_zipのソース、前方スキャナーのストリーム、バイト範囲リーダー)と書き込み(outputPath、outputDir、展開されたファイル、ガバナンス用ドラフト)に対する唯一のファイルシステム境界です。パスは相対パスでなければなりません。絶対パス、UNC パス、..、NUL バイト、コンテナー形式以外の拡張子は拒否されます。読み取るファイルの実際のパスと、書き込み先の親パスは、サンドボックス内にとどまる必要があります(サンドボックス内に仕掛けられたシンボリックリンクやジャンクションは、読み取り・書き込みのどちらでもSECURITY_VIOLATIONになります。読み取りではファイル自体を検査するため、親ディレクトリだけを検査する場合のようにファイルのシンボリックリンクがすり抜けることはありません)。ファイルは排他的に開かれ、上書きされることはありません(OUTPUT_EXISTS)。書き込みに失敗するかキャンセルされた場合、部分ファイルは削除されます。未設定の場合は base64 のみとなります(ZIPNATIVE_MCP_CACHE_DIRによるオプトイン式の応答キャッシュだけが、これ以外のファイル I/O を行います)。 - 入力は、すべてのツールの境界で厳格な JSON スキーマと Zod に照らして検証されます。未知のキーやスペルミスのあるキー(トップレベルまたはネストされたもの)は
VALIDATION_ERRORになります。パーサーの実行前に base64 の妥当性を確認し(data:プレフィックスは許容されますが、base64 の二重エンコードは拒否されます)、fieldsのパスではプロトタイプのセグメントを拒否し、プロジェクションでは自身のプロパティのみをたどります。 - エラー境界 — すべての
ZipErrorは固定されたコードを保持します。エンジンまたはランタイムから漏れたそれ以外のエラーはdata.errorClass: 'internal'を伴うENGINE_ERRORとなり、メッセージから絶対パスが取り除かれます。エラーテキストにホストのパスが含まれることはありません。 - 暗号化は一切行われません。ローカルヘッダーが一致する場合、暗号化されたエントリーは検出され、
verify_zipによってskippedとなります。読み取り経路およびmerge_zipではZIP_UNSUPPORTED_ENCRYPTIONとして拒否されます。パスワード入力はありません。 - すべてのエンジン診断はシンクを経由します。stdio トランスポートでは、標準出力に何も出力されません。
- HTTP トランスポート(
ZIPNATIVE_MCP_PORT)は、Host / Origin ガード、リクエストタイムアウト、ヘッダー数の上限を設けたうえで、ループバックのみにバインドします。ZIPNATIVE_MCP_HTTP_TOKENが設定されていない限り、認証はありません(設定されている場合、有効なベアラートークンがなければ401になります)。
完全な脅威モデル、サプライチェーン、再現性に関する約束については SECURITY.md を、CWE ID とともに記載された防御策については docs/guides/SECURITY.md をご覧ください。
ネットワークと外部への通信
一切ありません。 サーバーにネットワークを使用するコードパスはありません。テレメトリー、GitHub、更新チェック、ツール引数からの URL、リモートのバイト範囲ソース(エンジンの openZipRange はサンドボックスのファイルハンドル上でのみ実行されます)はなく、PDF 版の兄弟ツールとは異なり、オペレーターが設定できるエンドポイントも一切ありません。describe_engine は network: 'none' を報告し、tests/no-network.test.ts はソースツリーがこの条件を守っているかを検証します。アーカイブのバイト列が外部に出るのは、JSON-RPC レスポンスとして返される場合か、サンドボックスに書き込まれる場合のみです。エンジン自体がソケットを開いたり、ファイルシステムにアクセスしたり、eval を実行したりすることはありません。
| 上限 | 値 |
|---|---|
| stdio フレーム/HTTP ボディ | 256 MiB |
呼び出しごとのデコード済み zipBase64/インラインペイロード | 128 MiB |
バッファーに読み込む zipPath/sourcePath | 1 GiB(scan_zip_forward は上限なしで zipPath をストリーミングします。access: 'range' は、より大きな zipPath をバイト範囲単位で読み込みます) |
| インライン出力(アーカイブ、展開後のバイト列、リソース読み取り) | 50 MiB |
| ファイル出力 | デフォルトで 4 GiB(ZIPNATIVE_MCP_MAX_FILE_OUTPUT_BYTES。ストリーミング中に適用されます) |
インラインエントリー(read_zip_entry、extract_zip、scan_zip_forward) | 16 MiB |
| インライン展開の合計 | 32 MiB |
list_zip_entries のページ | デフォルト 200/最大 2000 |
create_zip のエントリー数/modify_zip の操作数/sanitize_entry_paths の名前数 | 100000/1000/10000 |
merge_zip のソース数/ソースの合計サイズ | 32/1 GiB |
filter.names/filter.glob/glob の長さ/エントリーごとの extraFields/fields のパス | 1000/32/1024/16/16 |
scan_zip_forward の maxEntries デフォルト値/read_zip_entry の範囲の長さ/extract_zip のリソースリンク数 | 10000(上限値に制限されます)/16 MiB/50 |
inspect_zip の決定性に関する問題数/draft_governance_issue の自由記述 | 200 行/16 384 文字 |
resources/list のエントリー数/走査の深さ/resources/read | 1000/8/50 MiB |
レスポンスキャッシュ(ZIPNATIVE_MCP_CACHE_DIR)の TTL/サイズ | 3600 秒/256 MiB |
| 結果ごとの診断 | 200 件(コードとエントリーの組み合わせで重複を排除) |
エンジンのデフォルト値(limits) | 100000 エントリー · エントリーごとに 1 GiB · 取得するエントリーごとに圧縮サイズ 1 GiB + 1 MiB · 合計 8 GiB · 比率 1024 · 名前 4096 バイト · 追加フィールドとコメント 65535 バイト · セントラルディレクトリ 256 MiB |
すべての上限値は src/caps.ts の定数であり、describe_engine.caps(stdioMaxFrameBytes、maxBase64InputBytes、maxPathInputBytes、maxBase64OutputBytes、maxFileOutputBytes、maxEntryInlineBytes、maxExtractInlineTotalBytes、maxListLimit、defaultListLimit、maxCreateEntries、maxModifyOperations、maxMergeSources、maxMergeInputBytes、maxSanitizeNames、maxDiagnostics、maxDeterminismOffenders、maxFilterNames、maxFilterGlobs、maxGlobLength、maxExtraFields、maxIssueTextChars、maxFieldsPaths、defaultScanMaxEntries、maxResourceLinks、maxRangeLength、maxListedResources、maxResourceWalkDepth、maxResourceReadBytes、cacheTtlSeconds、cacheMaxBytes)で公開されています。有効なファイル出力上限は describe_engine.ceilings.maxFileOutputBytes です。
脆弱性の責任ある開示プロセスについては、SECURITY.md を参照してください。
🧪 適合性(veraZIP)
ZIP には veraPDF に相当するものがありませんでした。JHOVE に ZIP モジュールは提供されたことがなく、ISO/IEC 21320-1 のバリデーターも存在しませんでした。そのため、zipnative エコシステムでは独自のゲート、veraZIPを提供しています。これは ISO/IEC 21320-1:2015(Document Container File)バリデーターで、エンジンの 1.1.0 コミット時点の実装をベンダー化したものです(scripts/verazip-core.mjs)。独自の EOCD/セントラルディレクトリ/ローカルヘッダーリーダーを使ってバイト列を直接解析し、zipnative は一切インポートしません。エンジンと同じパーサーを共有するバリデーターでは、エンジン自身を検証することになってしまうためです。
npm run validate:zip はサーバーをビルドし、実際の tools/call ハンドラーを実行します(create_zip、modify_zip、canonicalize_zip、merge_zip のすべての書き込み経路:バッファリング、stream: true、Zip64 ストリームエントリー、parallel、compression.deterministic、order: 'insertion'、追加フィールド、コメント、Unix モード、追記、compact、compact と canonical の併用、追記モードのアーカイブの正規化(冪等性を検証)、固定日付での正規化、マージ)。さらに、バイト列から直接作成したファイルも使って 43 個のアーカイブからなるコーパスを作成し、すべてのファイルを条項ごとに検証します(チェック ID は 23 個)。適合する 39 個のアーカイブには、悪意ある内容だが適合しているものが 4 個含まれます(zip-slip、Windows のデバイス名、パスの重複、シンボリックリンクエントリー)。ISO プロファイルが制約するのはコンテナーであり、名前の意味ではないため、これらはバリデーターに合格しますが、extract_zip は拒否しなければなりません。このゲートでは両方を確認します。バイト列から直接作成した 4 個のネガティブカナリアは、宣言された条項 ID とともに拒否されなければなりません。想定される結果は 39 件の PASS と 4 件の XFAIL です。レベル 0(ISO 条項)では外部ツールは不要で、常に実行されます。レベル 1 では、マシン上で利用可能な外部の整合性検証ツール(unzip -t、7z t、python -m zipfile -t、tar -tf、jar tf)を使って適合するアーカイブをすべて再テストし、利用できないツールは明示的にスキップします。CI で設定される VERAZIP_REQUIRED=1 は、利用できない場合に失敗します。コーパスの定義は docs/data/verazip.json に、各実行のマニフェストは test-output/zip/manifest.json に記録されます。
PASS は、このサーバーが書き込むすべてのアーカイブが、適切に構成された ISO/IEC 21320-1 ドキュメントコンテナーであることを証明します。すなわち、自己整合性のあるセントラルディレクトリ終端レコードが 1 つあること、セントラルディレクトリがすべてのローカルヘッダーと一致すること、使用する圧縮方式が store/deflate のみであること、暗号化がないこと、マルチディスクフィールドがないこと、フィールドがあふれる場合に限って適切な Zip64 レコードがあること、データ記述子の幅がローカルヘッダーの Zip64 追加フィールドと一致することを示します。これは認証ではなく、特定のバリデーターのリビジョンに基づく検証証拠です。また、適合していることは安全であることを意味しません。セキュリティーガードは適合性に加えて設けられています。
このゲートは必須チェックです。ci ワークフローは、Linux(Node 22 および 24)、Windows、macOS で scripts/gate.ts --ci --require-all の一環として実行します。verazip.yml でも、main へのプッシュおよびプルリクエストごと(手動実行時も含む)に Linux と Windows で繰り返し実行し、すべての公開前にも実行します。テストがツールを通じて生成するすべてのアーカイブは、assertValidZip(ISO 適合性の検証を含む)にも合格しなければなりません。docs/guides/CONFORMANCE.md を参照してください。
🧪 ローカル開発
git clone https://github.com/Nizoka/zipnative-mcp.git
cd zipnative-mcp
npm ci --ignore-scripts # .npmrc sets ignore-scripts=true: nothing builds on install
npm run gate:fast # before every commit: typecheck:all, lint, test, server-json, verify:docs
npm run gate # the CI profile: + build, dist checks, stdio smoke test, tool shape, samples, coverage, docs, the veraZIP corpus, examples
npx tsx scripts/gate.ts --publish --require-all # release branches: every step, a skipped step fails
npm run gate(scripts/gate.ts)は、すべてのチェックが成功した状態を定義する唯一のものです。79 個のテストファイルにわたる 1643 件のテスト、vitest.config.ts のカバレッジしきい値(94 / 90 / 95 / 94)、および stdio 経由で実行するビルド済みサーバーが対象です。サーバーの stdout には JSON-RPC フレームのみが出力される必要があります。各ステップにつき 1 行を出力し、ログは test-output/.gate/<step>.log に書き込みます。--only <step> は 1 つのステップだけを実行し、--from <step> はそのステップから再開し、--json は機械処理向けの出力を返します(フラグを渡すにはスクリプトを直接呼び出してください。PowerShell では npm run の後の単独の -- が無視されます)。ゲートは外部環境に依存しません。TZ=UTC を設定し、継承した ZIPNATIVE_MCP_* 変数をすべて除去し、ネットワークを使用しません。個別のステップには通常の npm スクリプトを使います。
| スクリプト | 実行内容 |
|---|---|
npm run typecheck:all | src/ と tests/ に対して tsc --noEmit を実行し、その後 scripts/ に対して実行します |
npm run lint | eslint src --max-warnings 0 を実行します。警告があると失敗します(no-console:stdout は stdio チャネルです) |
npm test / npm run test:coverage | vitest を実行します/v8 カバレッジ付きで実行します。しきい値は vitest.config.ts にあります |
npm run build | tsc -p tsconfig.build.json を実行し、dist/ に出力します |
npm run examples:check | 38 個の examples/*.json を tools/call ハンドラー経由で実際に実行します(複数ステップの例は連鎖して実行します) |
npm run test:generate / npm run verify:samples | 54 サンプルのベースラインです。外部環境に依存しない環境でビルド済みサーバーを実行し、test-output/samples/ に出力します。tests/_fixtures/samples.sha256.json に照らして検証します(各出力が属するリリースを示す since チェーンを含みます) |
npm run corpus:zip / npm run validate:zip | veraZIP コーパスを test-output/zip/ に書き込み、レベル 0 と 1 で検証します(外部ツールが見つからない場合、VERAZIP_REQUIRED=1 を設定すると失敗します) |
npm run verify:tool-shape | ビルド済みの tools/list の構造を tests/_fixtures/tool-shape.json と照合し、カタログの 192 KiB および説明文の 8 KiB の上限を検証します(意図的なスキーマ変更を行った場合に限り、npx tsx scripts/tool-shape.ts --write を実行します) |
npm run verify:docs | ドキュメント内のすべての件数、バージョン、ツール、コード、運用者向け変数、リンク、アンカーを docs/assets/ecosystem.json およびソースツリーと照合します |
npm run verify:issue | ガバナンス用ドラフトのチェッカーです |
npm run agents:rules | .github/instructions/*.instructions.md から .claude/rules/*.md を再生成します |
npm run release:prepare | バージョンを機械的に更新します(コミット、タグ付け、公開は行いません) |
npm run hooks:install / hooks:uninstall | オプトインの git フック(pre-commit および pre-push)を設定/解除します |
stdio 経由でサーバーのスモークテストを実行します。
node dist/cli.js
# In another terminal, send a JSON-RPC initialize request via stdin (e.g. with the MCP Inspector).
npx @modelcontextprotocol/inspector --cli node dist/cli.js --method tools/list
リポジトリの .mcp.json を使って Claude Code からビルド済みサーバーを実行します(先に npm run build を実行してください。初回使用時に Claude Code が承認を求め、${CLAUDE_PROJECT_DIR} を挿入します)。または、絶対パスを指定して Claude Desktop から、あるいは MCP Inspector から実行します。再生するシナリオと期待される結果は、docs/guides/LOCAL_TESTING.md の「Drive it from Claude Code / Claude Desktop / MCP Inspector」に記載されています。
ベアラートークンとサンドボックスを使って HTTP 経由で実行します。
ZIPNATIVE_MCP_PORT=3000 ZIPNATIVE_MCP_HTTP_TOKEN=change-me-to-a-real-secret ZIPNATIVE_MCP_OUTPUT_DIR=/tmp/zips npx zipnative-mcp
# POST http://127.0.0.1:3000/mcp with Authorization: Bearer …
貢献者の方へ: まず
AGENTS.md(すべてのコーディングエージェントと貢献者が共有するリポジトリのルール)を確認し、ワークフロー全体については CONTRIBUTING.md をご覧ください。ゲート、テストとしてのサンプル、サンプルのベースライン、テストで書き込むすべてのアーカイブに対するassertValidZipの使用、veraZIP コーパス、MCP Inspector について説明しています。
📣 リリースプロセス
zipnative-mcp は、zipnative、pdfnative-mcp、pkinative-mcp と同じリリース方式に従います。
- タグごとに
release-notes/vX.Y.Z.mdにリリースノートファイルを1つ作成します(絵文字は使用しません)。CHANGELOG.mdには各リリースの箇条書きを反映し、GitHub Release の本文にはリリースノートをコピーします npx tsx scripts/release-prepare.ts --version X.Y.Zは、バージョン更新の機械的な部分を適用します(コミット、タグ付け、公開は行いません)。バージョンはpackage.json、src/version.ts、server.json、CITATION.cff(tests/metadata.test.ts)間で同期し、docs/assets/ecosystem.json(npm run verify:docs)にも反映します。TOOL_API_VERSIONはスキーマまたはエラーコードが変更された場合にのみ更新します- リリースブランチは
npx tsx scripts/gate.ts --publish --require-allに合格する必要があります。veraZIP コーパスを含むすべてのステップを省略せず実行します - npm への公開は、
NPM_TOKENを使わず、GitHub Actions Trusted Publishing(OIDC)で行います。publish.ymlはverify(公開ゲート、npm packを1回実行、CycloneDX SBOM、ダイジェスト)→publish(保護されたnpm-publish環境、引き継いだ tarball を--provenance付きで公開)→attest(レジストリのバイト列を照合し、tarball と SBOM のビルド来歴アテステーションを作成して、両方をリリースに添付)→registry(SHA-256 で固定されたmcp-publisherを通じてserver.jsonを MCP レジストリに登録)を実行します - すべてのジョブは
step-security/harden-runnerから開始します(このアクションが対応していない macOS ではスキップします)。persist-credentials: falseを指定してチェックアウトし、npm ci --ignore-scriptsでインストールし、最小権限のpermissionsで実行します。アクションはコミット SHA で固定されています - 人間が関与するプロセスです。コーディングエージェントが準備と検証を行い、メンテナーがプッシュ、プルリクエストの作成、タグ付け、公開を行います(
.github/AGENT_RULES.md)
正式な構成と公開チェックリストについては release-notes/TEMPLATE.md を、リリース手順については CONTRIBUTING.md をご覧ください。
📚 プロジェクト構成
src/
├── cli.ts # entrypoint: stdio (default, 256 MiB frames) or Streamable HTTP (ZIPNATIVE_MCP_PORT); reads the four ceilings once
├── http.ts # Node http <-> Web Request/Response bridge, 256 MiB body cap, Host/Origin loopback guard, timeouts, security headers
├── auth.ts # opt-in HTTP bearer token (ZIPNATIVE_MCP_HTTP_TOKEN)
├── server.ts # Server factory, TOOLS registry, dispatchOutput, cache gate, cancellation / progress wiring, SERVER_INSTRUCTIONS, 7 prompts, resources
├── call-context.ts # per-call context: the cancellation signal, the progress reporter, CANCELLED
├── caps.ts # every byte / count cap + the operator ceilings (MAX_UNCOMPRESSED_BYTES, MAX_ENTRIES, WORKERS, MAX_FILE_OUTPUT_BYTES)
├── limits.ts # the nine ZipLimits bounds as an input fragment; LIMIT_CEILING_EXCEEDED
├── sandbox.ts # the single filesystem boundary (ZIPNATIVE_MCP_OUTPUT_DIR): container extensions, one-handle reads, realpath checks, wx writes
├── archive-input.ts # zipBase64 XOR zipPath; buffered load, streamed source, access auto / memory / range (openZipRange over the file handle)
├── canonical.ts # the canonical-form options shared by canonicalize_zip and modify_zip canonical
├── base64.ts # base64 boundary decoding with agent-facing diagnostics
├── zip-errors.ts # ZipError -> ToolError (the 39 frozen ZIP_* codes verbatim), guard(), the 12 diagnostic codes
├── wrapper-codes.ts # the 17 wrapper error codes with meaning and remedy
├── diagnostics.ts # engine diagnostic sink (dosTimeMode utc, signal, onProgress; de-duplicated, capped at 200) -> diagnostics[]
├── entry.ts # EntryView: the CLI's --json row shape (flags, unixMode, sanitizedPath, extra fields, rawNameHex, opt-in timestamps / ids)
├── filter.ts # names / prefix / glob entry filter (linear-time Thompson NFA)
├── entry-spec.ts # create / modify payloads: compression, dates (UTC), unixMode / externalAttributes, extra fields
├── engine.ts # initNodeZipCodecs once; runtime capability probe
├── output.ts # base64 emitter / sandboxed exclusive file writer (buffered + streamed, partial file removed)
├── resources.ts # zipnative://output/{+path} over every sandbox file (MIME by extension)
├── projection.ts # verbosity / fields projection for the read tools (prototype segments refused)
├── cache.ts # opt-in SHA-256 response cache (ZIPNATIVE_MCP_CACHE_DIR)
├── governance.ts # AI-governance / HITL contract text + draft validation (linear-time patterns)
├── errors.ts # ToolError, SecurityError, GovernanceError, absolute-path redaction
├── version.ts # ZIPNATIVE_MCP_VERSION, TOOL_API_VERSION
├── index.ts # public library exports
└── tools/
├── _shared.ts # parseInput, ProjectionShape, EngineOptionsShape, sha256Hex
├── inspect-zip.ts
├── list-zip-entries.ts
├── read-zip-entry.ts
├── verify-zip.ts
├── extract-zip.ts
├── scan-zip-forward.ts
├── sanitize-entry-paths.ts
├── create-zip.ts
├── modify-zip.ts
├── canonicalize-zip.ts
├── merge-zip.ts
├── compute-crc32.ts
├── inflate-raw.ts
├── describe-engine.ts
└── draft-governance-issue.ts
scripts/
├── gate.ts # THE quality gate (npm run gate / gate:fast; --publish --require-all on release branches)
├── verify-docs.ts # npm run verify:docs — the docs held to docs/assets/ecosystem.json and the source tree
├── release-prepare.ts # mechanical version bump (never commits, tags or publishes)
├── tool-shape.ts # structural tools/list fingerprint and size budgets (--write refreshes the fixture, --check, --stats)
├── generate-samples.ts # npm run test:generate — the examples through the built server -> test-output/samples/
├── verify-samples.ts # npm run verify:samples — the sample baseline (tests/_fixtures/samples.sha256.json)
├── build-claude-rules.ts # npm run agents:rules — .github/instructions/ -> .claude/rules/
├── install-git-hooks.mjs # npm run hooks:install / hooks:uninstall
├── verazip-core.mjs # vendored engine-independent ISO/IEC 21320-1 validator (never imports zipnative)
├── verazip-core.d.mts # its type declarations
├── generate-zip-corpus.mjs # writes the veraZIP corpus through the real tools + raw-crafted canaries (npm run corpus:zip)
├── validate-zip.mjs # the veraZIP gate: level 0 (ISO clauses) + level 1 (foreign integrity tools)
├── verify-issue.mjs # governance draft checker (npm run verify:issue)
├── helpers/
│ ├── zip-corpus.mjs # the corpus definition (every writer path + the hostile-but-conformant quartet + the canaries)
│ ├── zip-corpus.d.mts # its type declarations
│ ├── raw-zip-builder.mjs # engine-independent raw ZIP writer for the crafted canaries (vendored from zipnative)
│ ├── interop-tools.mjs # unzip / 7z / python zipfile / tar / jar probes for level 1
│ ├── hermetic.ts # the hermetic environment (TZ=UTC, ZIPNATIVE_MCP_* scrubbed)
│ ├── tz.ts # time-zone helpers for the hermetic runs
│ ├── io.ts # file helpers of the scripts
│ └── server.ts # drives the built server from the scripts
└── lib/
├── tool-shape.ts # the fingerprint and the 192 KiB / 8 KiB budgets
├── sample-fingerprint.ts # bytes / semantic fingerprints of the samples
├── example-runner.ts # runs an examples/*.json sequence
├── mcp-surface.ts # tools, codes and variables read from the source tree
├── markdown-anchors.ts # heading anchors for the link checks
├── agent-config.ts # .claude/ settings, guard hook and PR template checks
├── prose-language.ts # the English-only rule
├── secret-needles.ts # the no-secret-material needles
└── json-schema-lite.ts # offline server.json validation against the vendored registry schema
docs/
├── AGENT_CONTRACT.md # the consumer contract for agents that USE the server (catalogue, decision tree, recipes, error reference)
├── AI_GUIDE.md # decision tree + pitfalls for agents
├── API_STABILITY.md # the tool-API stability charter (versioning, bump rules, per-tool matrix)
├── KNOWLEDGE_BASE.md # architecture reference + the 106-export coverage ledger (§8)
├── guides/AI_GOVERNANCE.md # the human-in-the-loop contract, narrated
├── guides/CONFORMANCE.md # the veraZIP gate explained
├── guides/DETERMINISM.md # the determinism levels, canonicalisation and how to prove them
├── guides/INCREMENTAL.md # modify_zip: append vs compact, remanence, the 7-Zip differential
├── guides/LARGE_ARCHIVES.md # byte-range access, Zip64 streaming, the file-output ceiling
├── guides/LOCAL_TESTING.md # the gate, assertValidZip, veraZIP locally, driving the server from Claude Code / Inspector
├── guides/SECURITY.md # threat model and defences with CWE ids
├── data/errors.json # the 39 codes + 12 diagnostics (copy of the engine registry)
├── data/core-exports.json # the 106 exports of zipnative 1.1.0 and their reach
├── data/verazip.json # the corpus counts
└── assets/ecosystem.json # the single source of every count and version quoted in the docs
examples/ # 38 executable tool invocations (npm run examples:check)
tests/ # vitest suites, one per tool / module (<tool>.test.ts, <module>.test.ts) plus:
├── _zip-fixtures.ts # benign archives via the engine + hostile ones via _fixtures/raw-zip-builder.ts (vendored)
├── _zip-assert.ts # assertValidZip / assertIsoConformant / expectCheck
├── _mcp-harness.ts # in-memory legacy-handshake client (captures notifications)
├── _http-fixture.ts # loopback HTTP fixture (2026-07-28 envelope + legacy initialize)
├── _agent-client.ts # the scripted MCP client of the autonomy scenario (stdio / HTTP × legacy / modern)
├── _fuzz.ts # seeded PRNG and mutators (deterministic; not coverage-guided)
├── autonomy.test.ts # S0–S17 agent scenario on stdio legacy / stdio modern / HTTP legacy / HTTP modern + bearer token
├── protocol-revisions.test.ts # the five legacy revisions (2024-10-07 … 2025-11-25) negotiated on both transports
├── stdio-modern.test.ts # 2026-07-28 server/discover + _meta envelope over the built CLI
├── http-modern.test.ts # 2026-07-28 over HTTP: cache hints, Mcp-Method / Mcp-Name, -32602, batches
├── http-hardening.test.ts # body cap, timeouts, header bound, security headers
├── http-shutdown.test.ts # SIGTERM in HTTP mode exits cleanly and releases the port
├── cancellation.test.ts # CANCELLED and notifications/progress over MCP
├── range-access.test.ts # access 'range' / 'auto' through the byte-range reader
├── zip64-streaming.test.ts # create_zip zip64 on stream entries and the file-output ceiling
├── zip64.test.ts # 70 000-entry reads and a 65 536-entry create_zip (auto-promotion)
├── reproducible-build.test.ts # identical bytes from the built server under two time zones
├── zip-fuzz.test.ts # the seeded hostile-input suite over every tool
├── no-network.test.ts # the no-network doctrine over src/
├── schema-lockstep.test.ts # Zod input schemas ↔ advertised JSON Schemas (keys, required, enums, defaults, bounds, patterns)
├── catalogue-parity.test.ts # tools/list vs tests/_fixtures/tool-shape.json
├── catalogue-superset.test.ts # tools/list is a superset of the frozen tests/_fixtures/tool-shape.v1.0.0.json
├── docs-consistency.test.ts # counts / names / codes quoted in the docs, the SFX guard, the export ledger, the veraZIP corpus counts, this tree
├── diagnostics-inventory.test.ts # every reachable diagnostic produced by a tool call
├── tools/ # the repository tooling suites (gate, verify-docs, release-prepare, workflows, guard, …)
└── fixtures/ # interop archives (bsdtar, PowerShell), the frozen example inputs, SHA256SUMS, PROVENANCE.md
AGENTS.md, CLAUDE.md # repository rules for coding agents; .github/instructions/ holds the per-area rules
.claude/ # shared agent settings, the fail-closed guard hook, generated rules, the release-audit skill
.mcp.json # drives the built server from Claude Code (stdio, sandbox under test-output/mcp-sandbox)
.github/workflows/ci.yml # the gate (--ci --require-all) on Linux (Node 22 / 24), Windows and macOS
.github/workflows/verazip.yml # BLOCKING veraZIP job on Linux and Windows (VERAZIP_REQUIRED=1)
.github/workflows/sample-regression.yml # the sample baseline on every pull request that can change an output
.github/workflows/publish.yml # verify -> publish -> attest -> registry (Trusted Publishing, provenance, SBOM, attestation, MCP registry)
.github/workflows/docs.yml # verify:docs on docs changes and weekly; the manifest against npm
.github/workflows/codeql.yml # CodeQL security-extended
.github/workflows/scorecard.yml # OpenSSF Scorecard
.github/workflows/dependency-review.yml # licence and advisory gate on dependency changes
.github/workflows/audit.yml # weekly npm audit (full tree and runtime tree)
.github/workflows/node-current.yml # the gate on the current Node line (advisory)
.github/rulesets/ # branch and tag rulesets to import
🗺 ロードマップ
v1.1.0 は zipnative 1.1.0 に基づく最初のマイナーリリースです。2つの新しいツール(canonicalize_zip、merge_zip)、バイト範囲読み取り、Zip64 ストリーミングのオプトイン、キャンセルと進捗、UTC タイムスタンプ、そして凍結された 1.0.0 のカタログを包含することを確認したライブカタログが含まれます。リリース済みのマイルストーン、上流の事情で保留中の項目、長期的な方針を含む全計画は ROADMAP.md に記載されています。
設計上、公開していない機能:
- 暗号化と復号 — エンジン 1.x にはありません(ZipCrypto は破損しており、AES はエンジン 2.0 の候補です)。パスワード入力をここで提供するのは、その後になります。
nameEncoding/nameDecoder— UTF-8 以外のレガシーな名前は仕様どおり cp437 としてデコードします。エージェントが指定するデコーダーは公開していません。addRaw、カスタムコーデック、リモートバイト範囲ソース —merge_zipは検証済みの移植機能であり、registerCodecは実行可能コードで、サーバーにはネットワーク経路がありません。
機能のアイデアがありますか?イシューまたは PR を作成してください。または、エージェントに draft_governance_issue で下書きを作成させ、自分で提出することもできます。
⭐ プロジェクトにスターを付ける
zipnative-mcp が役に立ったら、このリポジトリに ⭐ を付けてください。また、基盤となるエンジン Nizoka/zipnative にもスターを付けていただけると幸いです。スターは、ほかの人がプロジェクトを見つける助けとなり、継続的な開発の励みになります。
🤝 貢献
貢献を歓迎します。CONTRIBUTING.md をお読みのうえ、未解決のイシューを確認し、行動規範に従ってください。
📄 ライセンス
MIT © 2026 Nizoka。サードパーティ素材については、THIRD-PARTY-NOTICES.md をご覧ください。
zipnative-mcp は zipnative と Model Context Protocol TypeScript SDK を基盤として構築されています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。