Skip to main content
Glama
zipnative-mcp

zipnative-mcp

Inspect archive (facts, determinism verdict, CI checks)

inspect_zip
Read-onlyIdempotent

Generate a read-only ZIP report in one call: counts, sizes, methods, encryption, symlinks, unsafe names, duplicates, determinism verdict, and diagnostics for inspection or CI checks.

Instructions

Read-only archive report in ONE call: size, entry / file / directory counts, Zip64, comment, compressed vs uncompressed totals, per-method counts, encrypted / symlink / data-descriptor / Zip64 / cp437 / duplicate / unsafe-name counts, date range, a determinism verdict (epoch timestamps + canonical order + UTF-8 flags ⇒ reproducible; canonicalLayout = no data descriptors) and every engine diagnostic (prepended SFX data, name mismatches, …). Opens EAGERLY by default: every entry's real extent is checked up front — overlapping entries, entries reaching into the central directory or past EOF, and Zip64 spoofing — and refused with their ZIP_* code rather than summarised (a method / CRC / size divergence between central and local headers is caught by verify_zip and on read, not here). check:[…] / assert:{…} turn it into a CI gate → checks[] + checksPassed. Token-frugal: verbosity:'summary', fields:[…]. Input: zipBase64 or zipPath (sandbox).

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "inspect_zip"
  }
}

Input Schema

NameRequiredDescriptionDefault
checkNoCI assertions evaluated over the report: 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, and the engine's canonical form (canonical-form = zipnative's analyzeDeterminism verdict: epoch or pinned timestamps, canonical order, UTF-8 flags, Zip64-only extras, version-made-by 0x032D; canonical-extras; canonical-version-made-by). Result: `checks[]` + `checksPassed`.
accessNo'auto' (default): in memory, and a zipPath above 1073741824 bytes by byte ranges. 'range': always by byte ranges over the sandbox file (never a URL; memory ≈ the central directory). 'memory': always buffered (INPUT_TOO_LARGE above the cap).auto
assertNoParametrised assertions (each becomes a `checks[]` row).
fieldsNoDot-paths to keep, after verbosity (e.g. ['entryCount', 'entries.name']); unmatched ones are listed in _meta.unmatchedFields.
limitsNoPer-call override of zipnative's security bounds (CWE-400/409); absent keys keep the engine defaults (describe_engine.defaultLimits). A value above its operator ceiling is LIMIT_CEILING_EXCEEDED. Raise only for trusted input.
strictNoTurn the first engine diagnostic into a ZIP_STRICT_DIAGNOSTIC error.
zipPathNoArchive path relative to the ZIPNATIVE_MCP_OUTPUT_DIR sandbox (container extensions: .zip .jar .docx .epub …). Exclusive with zipBase64; saves re-sending bytes between calls.
validateNo'eager' (default) cross-checks every local header and the overlap table up front — hostile shapes are refused here; 'lazy' defers to first read (cheaper on huge archives).eager
verbosityNo'summary': scalar verdict fields only (the token-frugal form).full
zipBase64NoArchive bytes, base64 (≤ 128 MiB decoded). Exclusive with zipPath.
canonicalDateNoThe date the archive was canonicalised with (canonicalize_zip `date`, modify_zip `canonical.date`): the canonical-form verdict then expects that timestamp on every entry instead of the DOS epoch. Read as UTC, like every date this server writes.
determinismReportNotrue adds `determinismReport`: zipnative's analyzeDeterminism() verdict in full — the stricter canonical form canonicalize_zip produces (also Zip64-only extras and the constant version-made-by) and every offending entry with the rule it breaks.

Output Schema

NameRequiredDescriptionDefault
ratioNo
accessNoPresent when the archive was read by byte ranges (access 'range', or a zipPath above the in-memory cap): `determinism` is then absent and the determinism checks fail with that reason.
checksNo
commentNoArchive comment (UTF-8, lossy).
isZip64NoA Zip64 end-of-central-directory record is present.
methodsNo
fileCountNo
commentHexNo
entryCountNo
latestDateNo
determinismNo`deterministic` = reproducible (epoch timestamps + canonical order + UTF-8 flags); `canonicalLayout` = the buffered layout (no data descriptors) — a streamed archive is reproducible but not canonical.
diagnosticsNoNon-fatal engine concerns (de-duplicated by code + entry, ≤ 200; codes in describe_engine.diagnosticCodes). Empty for a clean archive.
archiveBytesNo
checksPassedNoPresent when check / assert was supplied: true when every assertion holds.
commentBytesNo
earliestDateNo
multipleEocdNo
symlinkCountNo
deterministicNosummary only: the determinism verdict.
prependedDataNoSFX-style prefix before the first local header (offsets shifted).
utf8NameCountNo
cp437NameCountNo
directoryCountNo
encryptedCountNo
canonicalLayoutNosummary only: buffered (no data descriptor) layout.
compressedBytesNo
diagnosticCountNosummary only: number of distinct diagnostics.
unsafeNameCountNoNames sanitizeEntryPath() refuses (traversal, absolute, drive/UNC, NUL, ADS, device names).
zip64EntryCountNo
diagnosticCountsNoOccurrences per code, duplicates included.
determinismReportNoPresent with determinismReport: true — zipnative's analyzeDeterminism() report. `deterministic` here is the engine's canonical form (stricter than determinism.deterministic: also no extra field but Zip64 and version-made-by 0x032D).
uncompressedBytesNo
duplicateNameCountNo
dataDescriptorCountNo
diagnosticsTruncatedNotrue when rows beyond 200 were dropped.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed27 schema fields changedv1.0.1
    • addedInput schema / properties / access
      Added value: +{
      +  "default": "auto",
      +  "description": "'auto' (default): in memory, and a zipPath above 1073741824 bytes by byte ranges. 'range': always by byte ranges over the sandbox file (never a URL; memory ≈ the central directory). 'memory': always buffered (INPUT_TOO_LARGE above the cap).",
      +  "enum": [
      +    "auto",
      +    "memory",
      +    "range"
      +  ],
      +  "type": "string"
      +}
    • addedInput schema / properties / canonicalDate
      Added value: +{
      +  "description": "The date the archive was canonicalised with (canonicalize_zip `date`, modify_zip `canonical.date`): the canonical-form verdict then expects that timestamp on every entry instead of the DOS epoch. Read as UTC, like every date this server writes.",
      +  "pattern": "^\\d{4}-\\d{2}-\\d{2}",
      +  "type": "string"
      +}
    • changedInput schema / properties / check / description
      Previous value: -"CI assertions evaluated over the report: 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. Result: `checks[]` + `checksPassed`."New value: +"CI assertions evaluated over the report: 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, and the engine's canonical form (canonical-form = zipnative's analyzeDeterminism verdict: epoch or pinned timestamps, canonical order, UTF-8 flags, Zip64-only extras, version-made-by 0x032D; canonical-extras; canonical-version-made-by). Result: `checks[]` + `checksPassed`."
    • changedInput schema / properties / check / items / enum
      Previous value: -[
      -  "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"
      -]New value: +[
      +  "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"
      +]
    • changedInput schema / properties / check / maxItems
      Previous value: -15New value: +18
    • addedInput schema / properties / determinismReport
      Added value: +{
      +  "default": false,
      +  "description": "true adds `determinismReport`: zipnative's analyzeDeterminism() verdict in full — the stricter canonical form canonicalize_zip produces (also Zip64-only extras and the constant version-made-by) and every offending entry with the rule it breaks.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / fields / description
      Previous value: -"Dot-path projection applied after verbosity (e.g. ['entryCount', 'entries.name']); array segments map over elements; unmatched paths are reported in _meta.unmatchedFields."New value: +"Dot-paths to keep, after verbosity (e.g. ['entryCount', 'entries.name']); unmatched ones are listed in _meta.unmatchedFields."
    • addedInput schema / properties / fields / items / pattern
      Added value: +"^(?!(?:[^.]*\\.)*(?:__proto__|constructor|prototype)(?:\\.|$)).+$"
    • changedInput schema / properties / limits / description
      Previous value: -"Override zipnative's named security bounds for this call (CWE-400 / CWE-409 guards). Every key is optional; absent keys keep the engine defaults (maxEntries 100000, maxEntryUncompressedSize 1 GiB, maxTotalUncompressedSize 8 GiB, maxCompressionRatio 1024, maxNameBytes 4096, maxExtraFieldBytes 65535, maxCommentBytes 65535, maxCentralDirectoryBytes 256 MiB). Values above the operator ceilings (ZIPNATIVE_MCP_MAX_UNCOMPRESSED_BYTES, ZIPNATIVE_MCP_MAX_ENTRIES) are refused with LIMIT_CEILING_EXCEEDED. Raise a bound for trusted input only."New value: +"Per-call override of zipnative's security bounds (CWE-400/409); absent keys keep the engine defaults (describe_engine.defaultLimits). A value above its operator ceiling is LIMIT_CEILING_EXCEEDED. Raise only for trusted input."
    • changedInput schema / properties / limits / properties / maxCentralDirectoryBytes / description
      Previous value: -"Maximum central-directory size in bytes."New value: +"Bytes."
    • changedInput schema / properties / limits / properties / maxCommentBytes / description
      Previous value: -"Maximum comment length in bytes."New value: +"Bytes."
    • changedInput schema / properties / limits / properties / maxCompressionRatio / description
      Previous value: -"Maximum declared uncompressed/compressed ratio for entries >= 1 KiB compressed (zip-bomb guard)."New value: +"Declared ratio (entries ≥ 1 KiB compressed)."
    • changedInput schema / properties / limits / properties / maxEntries / description
      Previous value: -"Maximum central-directory entry count."New value: +"Entries."
    • addedInput schema / properties / limits / properties / maxEntryCompressedSize
      Added value: +{
      +  "description": "Bytes, one compressed payload fetched by the byte-range reader (access range).",
      +  "minimum": 1,
      +  "type": "integer"
      +}
    • changedInput schema / properties / limits / properties / maxEntryUncompressedSize / description
      Previous value: -"Maximum decompressed size of one entry, bytes."New value: +"Bytes, one entry decompressed."
    • changedInput schema / properties / limits / properties / maxExtraFieldBytes / description
      Previous value: -"Maximum extra-field block length in bytes."New value: +"Bytes."
    • changedInput schema / properties / limits / properties / maxNameBytes / description
      Previous value: -"Maximum entry-name length in bytes."New value: +"Bytes."
    • changedInput schema / properties / limits / properties / maxTotalUncompressedSize / description
      Previous value: -"Maximum total decompressed size across an extraction, bytes."New value: +"Bytes, all entries decompressed."
    • changedInput schema / properties / strict / description
      Previous value: -"Escalate the first engine diagnostic (prepended data, duplicate name, name mismatch, …) to a ZIP_STRICT_DIAGNOSTIC error instead of reporting it."New value: +"Turn the first engine diagnostic into a ZIP_STRICT_DIAGNOSTIC error."
    • changedInput schema / properties / verbosity / description
      Previous value: -"'summary' returns only the scalar verdict fields (drops arrays and payloads) — the token-frugal form."New value: +"'summary': scalar verdict fields only (the token-frugal form)."
    • changedInput schema / properties / zipBase64 / description
      Previous value: -"The archive bytes as base64 (exactly once; a data: URI prefix is tolerated). Exclusive with zipPath. Decoded size ≤ 128 MiB."New value: +"Archive bytes, base64 (≤ 128 MiB decoded). Exclusive with zipPath."
    • changedInput schema / properties / zipPath / description
      Previous value: -"Relative path of an archive inside the ZIPNATIVE_MCP_OUTPUT_DIR sandbox (no absolute paths, no '..'; container extensions only: .zip .jar .docx .epub …). Exclusive with zipBase64. Lets a create/modify → verify/extract chain avoid re-sending the bytes."New value: +"Archive path relative to the ZIPNATIVE_MCP_OUTPUT_DIR sandbox (container extensions: .zip .jar .docx .epub …). Exclusive with zipBase64; saves re-sending bytes between calls."
    • addedOutput schema / properties / access
      Added value: +{
      +  "description": "Present when the archive was read by byte ranges (access 'range', or a zipPath above the in-memory cap): `determinism` is then absent and the determinism checks fail with that reason.",
      +  "enum": [
      +    "range"
      +  ],
      +  "type": "string"
      +}
    • addedOutput schema / properties / determinismReport
      Added value: +{
      +  "additionalProperties": false,
      +  "description": "Present with determinismReport: true — zipnative's analyzeDeterminism() report. `deterministic` here is the engine's canonical form (stricter than determinism.deterministic: also no extra field but Zip64 and version-made-by 0x032D).",
      +  "properties": {
      +    "canonicalExtras": {
      +      "description": "No extra field other than Zip64 (0x0001) on any entry.",
      +      "type": "boolean"
      +    },
      +    "canonicalOrder": {
      +      "type": "boolean"
      +    },
      +    "canonicalVersionMadeBy": {
      +      "description": "Every entry has version-made-by 0x032D.",
      +      "type": "boolean"
      +    },
      +    "deterministic": {
      +      "type": "boolean"
      +    },
      +    "epochTimestamps": {
      +      "description": "Every entry carries the DOS epoch, or the canonicalDate given.",
      +      "type": "boolean"
      +    },
      +    "noDataDescriptors": {
      +      "type": "boolean"
      +    },
      +    "offenderCount": {
      +      "minimum": 0,
      +      "type": "integer"
      +    },
      +    "offenders": {
      +      "description": "Every broken rule, entry by entry, in central-directory order (at most 200 rows).",
      +      "items": {
      +        "additionalProperties": false,
      +        "properties": {
      +          "concern": {
      +            "enum": [
      +              "timestamp",
      +              "order",
      +              "utf8-flag",
      +              "extra-field",
      +              "version-made-by",
      +              "data-descriptor"
      +            ],
      +            "type": "string"
      +          },
      +          "name": {
      +            "type": "string"
      +          }
      +        },
      +        "type": "object"
      +      },
      +      "type": "array"
      +    },
      +    "offendersTruncated": {
      +      "type": "boolean"
      +    },
      +    "pinnedDate": {
      +      "description": "The canonicalDate the timestamps were compared with (ISO-8601, UTC).",
      +      "type": "string"
      +    },
      +    "utf8Flags": {
      +      "type": "boolean"
      +    }
      +  },
      +  "type": "object"
      +}
    • changedOutput schema / properties / diagnosticCounts / description
      Previous value: -"Number of diagnostics received per code (counts every occurrence, including de-duplicated ones)."New value: +"Occurrences per code, duplicates included."
    • changedOutput schema / properties / diagnostics / description
      Previous value: -"Non-fatal conformance concerns the engine raised while parsing or writing (de-duplicated by code + entry, at most 200). Empty for a clean archive. Codes: ZIP_PREPENDED_DATA, ZIP_MULTIPLE_EOCD, ZIP_NAME_MISMATCH, ZIP_UNICODE_PATH_CONFLICT, ZIP_INVALID_UTF8_NAME, ZIP_DUPLICATE_NAME, ZIP_EXTRA_FIELD_MALFORMED, ZIP_ZIP64_EXTRA_IGNORED, ZIP_TIMESTAMP_NOT_PINNED, ZIP_NONDETERMINISTIC_CODEC, ZIP_DEAD_BYTES_RATIO."New value: +"Non-fatal engine concerns (de-duplicated by code + entry, ≤ 200; codes in describe_engine.diagnosticCodes). Empty for a clean archive."
    • changedOutput schema / properties / diagnosticsTruncated / description
      Previous value: -"Present (true) when more than 200 distinct diagnostics were dropped from `diagnostics`."New value: +"true when rows beyond 200 were dropped."
  2. First observedv1.0.0

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/idempotent annotations: it discloses the default eager validation behavior, that hostile shapes (overlapping entries, entries past EOF, Zip64 spoofing) are refused with their ZIP_* code rather than summarized, that strict turns the first diagnostic into an error, and the access/limits cost tradeoffs. It also clarifies what is deliberately out of scope (central-vs-local divergence → verify_zip).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with the core purpose, but the body is one long compressed block with arrow glyphs and parenthetical asides that is dense to parse. Nearly every clause carries information, but the packing hurts scannability for an agent deciding whether to call it.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 12-parameter tool with nested objects and an output schema, the description covers behavior, failure modes, CI-gate output shape, and cost knobs. Missing pieces are minor: it does not distinguish this tool from list_zip_entries/read_zip_entry, and does not describe the eager-vs-lazy cost threshold concretely (the schema covers access details).

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3, but the description adds real semantic linkage: check/assert produce checks[] + checksPassed (CI-gate semantics), verbosity:'summary' + fields shrink the payload, zipBase64/zipPath are mutually exclusive with zipPath saving re-sends, and eager-by-default maps to validate. It does not add much beyond the schema for access, limits, or canonicalDate, which the schema already explains.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource (read-only archive report) plus exactly what it returns: counts, Zip64/encryption/symlink flags, date range, a determinism verdict, and engine diagnostics. It explicitly differentiates from siblings by noting that method/CRC/size divergence between central and local headers is caught by verify_zip and on read, not here.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear usage contexts: one-call report, CI gate via check/assert, and token-frugal variants via verbosity:'summary' / fields:[…]. It names verify_zip as the alternative for header-divergence validation, but does not systematically cover when to prefer list_zip_entries, read_zip_entry, or scan_zip_forward.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.