MCPcopy Create free account
hub / github.com/modelcontextprotocol/mcpb / validateIcon

Function validateIcon

src/node/validate.ts:39–109  ·  view source on GitHub ↗

* Validate icon field in manifest * @param iconPath - The icon path from manifest.json * @param baseDir - The base directory containing the manifest * @returns Validation result with errors and warnings

(
  iconPath: string,
  baseDir: string,
)

Source from the content-addressed store, hash-verified

37 * @returns Validation result with errors and warnings
38 */
39function validateIcon(
40 iconPath: string,
41 baseDir: string,
42): { valid: boolean; errors: string[]; warnings: string[] } {
43 const errors: string[] = [];
44 const warnings: string[] = [];
45
46 const isRemoteUrl =
47 iconPath.startsWith("http://") || iconPath.startsWith("https://");
48 const hasVariableSubstitution = iconPath.includes("${__dirname}");
49 const isAbsolutePath = isAbsolute(iconPath);
50
51 // Warn about remote URLs (best practice: use local files)
52 if (isRemoteUrl) {
53 warnings.push(
54 "Icon path uses a remote URL. " +
55 'Best practice for local MCP servers: Use local files like "icon": "icon.png" for maximum compatibility. ' +
56 "Claude Desktop currently only supports local icon files in bundles.",
57 );
58 }
59
60 // Check for ${__dirname} variable (error - doesn't work)
61 if (hasVariableSubstitution) {
62 errors.push(
63 "Icon path should not use ${__dirname} variable substitution. " +
64 'Use a simple relative path like "icon.png" instead of "${__dirname}/icon.png".',
65 );
66 }
67
68 // Check for absolute path (error - not portable)
69 if (isAbsolutePath) {
70 errors.push(
71 "Icon path must be relative to the bundle root, not an absolute path. " +
72 `Found: "${iconPath}"`,
73 );
74 }
75
76 // Only proceed with file checks if the path looks like a local file
77 if (!isRemoteUrl && !isAbsolutePath && !hasVariableSubstitution) {
78 // Check file existence
79 const fullIconPath = join(baseDir, iconPath);
80 if (!existsSync(fullIconPath)) {
81 errors.push(`Icon file not found at path: ${iconPath}`);
82 } else {
83 try {
84 // Check PNG format
85 const buffer = readFileSync(fullIconPath);
86 if (!isPNG(buffer)) {
87 errors.push(
88 `Icon file must be PNG format. The file at "${iconPath}" does not appear to be a valid PNG file.`,
89 );
90 } else {
91 // File exists and is a valid PNG - add recommendation
92 warnings.push(
93 "Icon validation passed. Recommended size is 512×512 pixels for best display in Claude Desktop.",
94 );
95 }
96 } catch (error) {

Callers 1

validateManifestFunction · 0.85

Calls 1

isPNGFunction · 0.85

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…