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>
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>
Allow specifying an external manifest file path with `mcpb pack --manifest <path>`.
The manifest resolves relative to CWD, is validated, injected into the bundle,
and errors immediately if the specified file is not found.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove duplicate node:path import in test/icon-validation.test.ts
- Replace 4 instances of 'any' type with 'unknown' in error handlers
- Auto-format code with prettier (27 formatting fixes)
Addresses review feedback from PR #136
All 6 errors and 27 warnings resolved
Implements icon validation to catch common issues that prevent icons from
displaying in Claude Desktop. Uses a non-blocking warning approach for
remote URLs to maintain flexibility for MCPB's evolving multi-platform
ecosystem.
## Changes
### Core Implementation (src/node/validate.ts)
- Add `isPNG()` helper to validate PNG file signatures via magic bytes
- Add `validateIcon()` function with comprehensive checks:
- **Warn** about remote URLs (non-blocking, best practice guidance)
- **Reject** ${__dirname} variable usage in icon field (doesn't work)
- **Reject** absolute paths (not portable)
- Verify icon file exists at specified path
- Verify icon file is valid PNG format
- Recommend 512×512 size for Claude Desktop
- Integrate icon validation into `validateManifest()` after schema validation
### Test Coverage
- Update `test/icon-validation.test.ts` - Remote URL test now expects warning
- Update `test/cli.test.ts` - Integration test updated for warnings
- All 109 tests passing
### Documentation Updates
- Update examples/hello-world-node/manifest.json to v0.3
## Validation Behavior
**Remote URLs (WARNING - non-blocking):**
```
Icon path uses a remote URL. Best practice for local MCP servers:
Use local files like "icon": "icon.png" for maximum compatibility.
Claude Desktop currently only supports local icon files in bundles.
```
**Result:** Validation passes, developer is informed
**Other Issues (ERROR - blocking):**
- ${__dirname} usage: Rejects (doesn't work)
- Absolute paths: Rejects (not portable)
- Missing files: Rejects (broken reference)
- Non-PNG files: Rejects (wrong format)
## Rationale
**Non-Blocking Approach:**
- Doesn't prevent valid bundles from being created
- Educates developers about best practices
- Maintains flexibility as MCPB evolves beyond Claude Desktop
- Future-proof if remote URL support is added
**Still Protective:**
- Blocks truly broken configurations (missing files, wrong formats)
- Provides actionable error messages for fixable issues
Based on real-world findings from investigating icon display issues in
Claude Desktop with production MCPB bundles.
- Rename CURRENT_MANIFEST_VERSION to LATEST_MANIFEST_VERSION
- Rename CURRENT_MANIFEST_SCHEMA to LATEST_MANIFEST_SCHEMA
- Rename CURRENT_MANIFEST_SCHEMA_LOOSE to LATEST_MANIFEST_SCHEMA_LOOSE
- Update all references throughout codebase and tests
Add validation to ensure the manifest_version matches the current expected
version (0.2) during the mcpb pack command. This prevents users from
packing extensions with outdated or incorrect manifest versions.
Changes:
- Add CURRENT_MANIFEST_VERSION constant to centralize version management
- Validate manifest version in pack command before creating bundle
- Update init command to use version constant
- Update tests to use version constant
- Fix prettier formatting issues
- Replace manifest_version with $schema field pointing to official schema URL
- Support backward compatibility with legacy dxt_version field
- Update all examples and tests to use new $schema field
- Mark dxt_version as deprecated but still functional
- Require either $schema or dxt_version (at least one must be present)
- Parse ZIP central directory to extract Unix file permissions
- Restore executable permissions using chmodSync after unpacking files
- Skip permission restoration on Windows (Unix-only feature)
- Add comprehensive test to verify executable and regular file permissions are preserved
- Fix test setup to use npm instead of yarn for consistent build process
Fixes issue where executable files lose their execute permissions after being packed and unpacked, which is critical for extensions containing binary executables or shell scripts.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-authored-by: Claude <noreply@anthropic.com>