Skip to content

Conversation

@bryan-anthropic
Copy link
Contributor

Icon Validation for MCPB Validate Command

Summary

Adds comprehensive icon validation to the mcpb validate command to catch common configuration issues and provide helpful guidance for developers creating MCPB bundles.

Problem

While investigating why bundle icons weren't displaying in Claude Desktop, we discovered several common configuration issues:

  • Remote URLs: Developers using https:// URLs for icons (works in spec, but Claude Desktop currently only supports local files)
  • Variable substitution: Using ${__dirname} in icon paths (doesn't work as expected)
  • Absolute paths: Breaking cross-platform compatibility
  • Wrong file formats: Non-PNG files causing display failures

This resulted in bundles being published with non-functional icons, degrading user experience.

Solution

Enhanced the mcpb validate command to perform comprehensive icon validation before bundling, catching issues early and providing helpful guidance.

Validation Approach

Non-blocking warnings for best practices:

  • Remote URLs (warns developers that local files are recommended for maximum compatibility)

Blocking errors for truly broken configurations:

  • Variable substitution (${__dirname}) - doesn't work
  • Absolute paths - not portable
  • Missing icon files - won't work
  • Non-PNG formats - may not display correctly

Validation Checks

  1. ⚠️ Remote URL warning - Warns about https:// or http:// icon paths with guidance to use local files
  2. No variable substitution - Rejects ${__dirname} in icon field (doesn't work)
  3. Relative paths only - Rejects absolute paths (not portable)
  4. File existence - Verifies icon file is present
  5. PNG format - Validates PNG file signature via magic bytes
  6. ℹ️ Size recommendation - Recommends optimal 512×512 size for valid icons

Example Output

Valid local PNG:

✓ Manifest schema validation passes!

Icon validation warnings:
  - Icon validation passed. Recommended size is 512×512 pixels for best display in Claude Desktop.

Remote URL (warns but doesn't block):

✓ Manifest schema validation passes!

Icon validation warnings:
  - 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.

Invalid configuration (blocks):

ERROR: Icon validation failed:
  - Icon path should not use ${__dirname} variable substitution. Use a simple relative path like "icon.png" instead of "${__dirname}/icon.png".

Changes

Core Implementation

  • File: src/node/validate.ts
  • Added isPNG() helper for PNG signature validation
  • Added validateIcon() function with error/warning separation
  • Integrated into validateManifest() workflow

Test Coverage

  • New file: test/icon-validation.test.ts (9 test cases)
  • Updated: test/cli.test.ts (integration tests)
  • Result: All 109 tests pass ✅

Documentation

  • Updated examples/hello-world-node/manifest.json to v0.3

Testing

Automated Tests

yarn test
# ✅ Test Suites: 7 passed, 7 total
# ✅ Tests: 109 passed, 109 total

Test Coverage Includes

  • Valid local PNG icons (root and subdirectories)
  • Remote URLs (warns, doesn't block)
  • ${__dirname} usage (blocks with error)
  • Absolute paths (blocks with error)
  • Missing icon files (blocks with error)
  • Non-PNG file formats (blocks with error)
  • Manifests without icons (no validation needed)

Benefits

  1. Educational, Not Blocking - Warns developers about best practices without preventing valid configurations
  2. Early Error Detection - Catches truly broken configurations during development
  3. Better Developer Experience - Clear, actionable guidance for both warnings and errors
  4. Improved Quality - Helps developers create better bundles
  5. Future-Proof - Non-blocking warnings accommodate MCPB's evolution beyond Claude Desktop-only use cases
  6. No Breaking Changes - Icon field remains optional; validation only provides helpful feedback

Design Philosophy

This implementation balances two important goals:

  1. Flexibility for MCPB's future: MCPB is evolving beyond Claude Desktop-only use cases, so validation uses warnings (not errors) for configurations that are valid per spec but may not work in Claude Desktop
  2. Helpful guidance for developers: Clear messaging about what works best for local MCP servers in Claude Desktop

Real-World Impact

Based on investigating actual icon display issues in production bundles, this validation helps developers avoid common pitfalls while maintaining flexibility for future MCPB evolution.

Implementation Details

PNG Validation

Uses magic byte checking (industry standard):

function isPNG(buffer: Buffer): boolean {
  // PNG signature: 89 50 4E 47 0D 0A 1A 0A
  return buffer[0] === 0x89 && buffer[1] === 0x50 && ...;
}

Error vs Warning Logic

function validateIcon(iconPath: string, baseDir: string): {
  valid: boolean;     // false only for blocking errors
  errors: string[];   // Truly broken configurations
  warnings: string[]; // Best practice guidance
}

Note on Spec and Implementation

The MANIFEST.md specification documents that the icon field can be "either relative in the package or a https:// url." However, Claude Desktop currently only supports local files in mcpb bundles - remote URLs don't display.

This validation provides warnings (not errors) for remote URLs to:

  • Help developers understand current Claude Desktop behavior
  • Maintain flexibility as MCPB evolves to support other platforms
  • Avoid blocking valid configurations per spec

Checklist

  • Tests pass locally (yarn test)
  • Code follows project style (TypeScript, ESLint)
  • Commit message follows conventional commits format
  • Documentation updated (example manifests)
  • No breaking changes
  • Backward compatible (icon validation is additive)

Generated with Claude Code

Co-Authored-By: Claude noreply@anthropic.com

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.
@joan-anthropic
Copy link
Contributor

@bthompson-sys thanks so much! this looks good - could you fix the lint errors when you get a sec? https://github.com/anthropics/mcpb/actions/runs/18881116986/job/54027390353?pr=136

- 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 modelcontextprotocol#136
All 6 errors and 27 warnings resolved
bryan-anthropic pushed a commit to bryan-anthropic/mcpb that referenced this pull request Oct 30, 2025
- 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 modelcontextprotocol#136
All 6 errors and 27 warnings resolved
@bryan-anthropic
Copy link
Contributor Author

@joan-anthropic Thanks for the review! I've addressed all the linting errors identified in the CI run.

joan-anthropic
joan-anthropic previously approved these changes Oct 30, 2025
bryan-anthropic pushed a commit to bryan-anthropic/mcpb that referenced this pull request Oct 30, 2025
- 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 modelcontextprotocol#136
All 6 errors and 27 warnings resolved
bryan-anthropic pushed a commit to bryan-anthropic/mcpb that referenced this pull request Oct 30, 2025
- 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 modelcontextprotocol#136
All 6 errors and 27 warnings resolved
bryan-anthropic added a commit to bryan-anthropic/mcpb that referenced this pull request Oct 30, 2025
- 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 modelcontextprotocol#136
All 6 errors and 27 warnings resolved
@bryan-anthropic bryan-anthropic force-pushed the feat/icon-validation branch 2 times, most recently from e444da0 to 55e3c3c Compare October 30, 2025 17:35
@joan-anthropic joan-anthropic merged commit ba74af5 into modelcontextprotocol:main Oct 30, 2025
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.

2 participants