mcpb/examples/hello-world-node/manifest.json
Bryan Thompson ccf9470979
feat: add comprehensive icon validation to mcpb validate command
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.
2025-10-28 09:14:12 -05:00

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": []
}