Skip to content

feat: enhanced structural validation for validate command#209

Open
bryan-anthropic wants to merge 2 commits intomainfrom
feat/enhanced-validate
Open

feat: enhanced structural validation for validate command#209
bryan-anthropic wants to merge 2 commits intomainfrom
feat/enhanced-validate

Conversation

@bryan-anthropic
Copy link
Copy Markdown
Collaborator

@bryan-anthropic bryan-anthropic commented Mar 15, 2026

Summary

  • Adds three pre-pack structural validators to mcpb validate that catch common runtime failures early:
    • Entry point: verifies file exists, extension matches server type, binary has executable bit
    • Command variables: scans mcp_config for unrecognized ${...} patterns (e.g. ${BUNDLE_ROOT} which silently fails at runtime)
    • Sensitive files: warns about credentials.json, *.pem, *.key, .ssh/ etc. that would be bundled
  • Errors fail validation; warnings print but pass
  • validateManifest() accepts optional { projectDir } to support external manifest paths
  • NEW: mcpb pack enforces executable permissions on binary entry points — when server.type === "binary", pack ensures the entry_point file has execute bits (|0o111) in the ZIP external_attr, preventing EACCES failures when Claude Desktop extracts Windows-built binary MCPBs

Binary permission context

Claude Desktop's MCPB extraction preserves ZIP-stored permissions without post-processing. Windows-built ZIPs store 644 (no execute bit) because Windows has no Unix permission concept. This causes Permission denied when CD tries to spawn binary entry points. The validate check catches this at dev time; the pack fix ensures correct permissions in the produced artifact.

Closes #57

Test plan

  • yarn build — clean
  • yarn lint — clean
  • yarn test — 230 pass (218 existing + 12 new)
  • E2E: validate catches ${BUNDLE_ROOT} → fix to ${__dirname} → pack → MCP initialize succeeds
  • E2E: missing entry_point → exits 1; binary not executable → exits 1
  • E2E: credentials.json in subdir → warning (exits 0)
  • E2E: binary entry point with mode 700 → pack produces 711 (adds group+other execute)
  • E2E: non-binary (node) entry point → permissions unchanged

🤖 Generated with Claude Code

Add three pre-pack validators to catch common runtime failures early:

- validateEntryPoint: checks file exists, extension matches server type,
  binary has executable bit (Unix)
- validateCommandVariables: scans mcp_config for unrecognized ${...}
  variables against the runtime allowlist
- validateSensitiveFiles: warns about credentials.json, *.pem, *.key,
  .ssh/, etc. that would be bundled

validateManifest() now accepts optional { projectDir } to separate the
manifest directory from the source file directory.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@tobinsouth
Copy link
Copy Markdown
Collaborator

@claude can you review this

Copy link
Copy Markdown
Collaborator Author

@bryan-anthropic bryan-anthropic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review by Claude Code

Looks good — three practical pre-pack validators that catch real issues early (missing entry points, invalid variables, sensitive file leaks).

A few observations:

  1. Clean API design — the ValidationResult interface and the manifestDir vs projectDir separation are well thought out. Pack passing projectDir to handle external manifests is a nice touch.

  2. Sensitive files as warnings-only — correct call. A .pem could be a legitimate TLS cert; erroring would be too opinionated.

  3. Test coverage — 11 new integration tests covering all three validators, plus existing fixtures updated for entry_point checks. Solid.

Minor nit: the silent catch {} in validateSensitiveFiles could mask unexpected errors from getAllFilesWithCount, but the comment explains the rationale (pack will fail with a clearer error downstream). Fine as-is.

When server.type is "binary", mcpb pack now ensures the entry_point
file has execute bits (|0o111) in the ZIP external_attr, regardless
of the source filesystem permissions. This prevents EACCES failures
when Claude Desktop extracts Windows-built binary MCPBs (which store
644 because Windows has no Unix execute bit).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@tobinsouth tobinsouth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both commits look good. The three validators (entry point, command variables, sensitive files) catch real runtime failures early, and the error-vs-warning split is correct — sensitive files as warnings-only is the right call since .pem can be legitimate. The second commit's mode | 0o111 on binary entry points is clean and the test confirms non-entry files keep original perms (0o700 → 0o711, config.json stays 0o644). pack.ts hunks don't overlap with #208's. CI green including the second commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Provide a Validation/Debug Tool for Verifying DXT File

2 participants