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.
108 lines
3.2 KiB
JSON
108 lines
3.2 KiB
JSON
{
|
|
"$schema": "../../dist/mcpb-manifest.schema.json",
|
|
"manifest_version": "0.3",
|
|
"name": "hello-world-node",
|
|
"display_name": "Hello World MCP Server (Reference Extension)",
|
|
"version": "0.1.0",
|
|
"description": "A reference MCP extension demonstrating best practices and all available features",
|
|
"long_description": "This is a reference implementation of a MCP Bundle (DXT). It demonstrates all available manifest features, user configuration options, and security best practices. Use this extension as a template when creating your own MCP servers. The extension includes examples of all user configuration types, proper request token verification, and comprehensive metadata fields.",
|
|
"author": {
|
|
"name": "Acme Inc",
|
|
"email": "support@acme.void",
|
|
"url": "https://www.acme.void"
|
|
},
|
|
"repository": {
|
|
"type": "git",
|
|
"url": "https://github.com/acme/my-repo"
|
|
},
|
|
"homepage": "https://docs.acme.void/my-repo/extensions",
|
|
"documentation": "https://docs.acme.void/my-repo/extensions/hello-world",
|
|
"support": "https://github.com/acme/my-repo/issues",
|
|
"icon": "icon.png",
|
|
"server": {
|
|
"type": "node",
|
|
"entry_point": "server/index.js",
|
|
"mcp_config": {
|
|
"command": "node",
|
|
"args": [
|
|
"${__dirname}/server/index.js",
|
|
"--verbose=${user_config.verbose_logging}",
|
|
"--max-results=${user_config.max_results}",
|
|
"--config=${user_config.config_file}",
|
|
"--workspace=${user_config.workspace_directory}"
|
|
],
|
|
"env": {
|
|
"API_KEY": "${user_config.api_key}",
|
|
"DEBUG": "${user_config.debug_mode}"
|
|
}
|
|
}
|
|
},
|
|
"tools": [
|
|
{
|
|
"name": "get_current_time",
|
|
"description": "Get the current computer time in various formats"
|
|
}
|
|
],
|
|
"keywords": [
|
|
"reference",
|
|
"example",
|
|
"hello-world",
|
|
"tutorial",
|
|
"mcp",
|
|
"time"
|
|
],
|
|
"license": "MIT",
|
|
"user_config": {
|
|
"api_key": {
|
|
"type": "string",
|
|
"title": "API Key",
|
|
"description": "Your API key for authentication (example of sensitive string)",
|
|
"sensitive": true,
|
|
"required": false
|
|
},
|
|
"verbose_logging": {
|
|
"type": "boolean",
|
|
"title": "Verbose Logging",
|
|
"description": "Enable detailed logging output",
|
|
"default": false,
|
|
"required": false
|
|
},
|
|
"max_results": {
|
|
"type": "number",
|
|
"title": "Maximum Results",
|
|
"description": "Maximum number of results to return",
|
|
"default": 10,
|
|
"min": 1,
|
|
"max": 100,
|
|
"required": false
|
|
},
|
|
"config_file": {
|
|
"type": "file",
|
|
"title": "Configuration File",
|
|
"description": "Path to a JSON configuration file",
|
|
"required": false
|
|
},
|
|
"workspace_directory": {
|
|
"type": "directory",
|
|
"title": "Workspace Directory",
|
|
"description": "Directory to use as workspace",
|
|
"default": "${HOME}/Documents",
|
|
"required": false
|
|
},
|
|
"debug_mode": {
|
|
"type": "string",
|
|
"title": "Debug Mode",
|
|
"description": "Set debug level (example of non-sensitive string)",
|
|
"default": "info",
|
|
"required": false
|
|
}
|
|
},
|
|
"compatibility": {
|
|
"claude_desktop": ">=0.10.0",
|
|
"platforms": ["darwin", "win32", "linux"],
|
|
"runtimes": {
|
|
"node": ">=16.0.0"
|
|
}
|
|
},
|
|
"privacy_policies": []
|
|
}
|