{"record":{"id":"3d21b95d0153daa2","repo":"CherryHQ/cherry-studio","slug":"invalid-manifest-missing-server-mcp-config-comman","errorCode":null,"errorMessage":"Invalid manifest: missing server.mcp_config.command","messagePattern":"Invalid manifest: missing server\\.mcp_config\\.command","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/mcp/McpPackageService.ts","lineNumber":562,"sourceCode":"        if (!parsedManifest.dxt_version) {\n          throw new Error('Invalid manifest: missing dxt_version')\n        }\n        manifest = { ...parsedManifest, dxt_version: parsedManifest.dxt_version }\n      }\n      if (!manifest.name) {\n        throw new Error('Invalid manifest: missing name')\n      }\n      if (!manifest.version) {\n        throw new Error('Invalid manifest: missing version')\n      }\n      if (!manifest.server) {\n        throw new Error('Invalid manifest: missing server configuration')\n      }\n      if (!manifest.server.mcp_config) {\n        throw new Error('Invalid manifest: missing server.mcp_config')\n      }\n      if (!manifest.server.mcp_config.command) {\n        throw new Error('Invalid manifest: missing server.mcp_config.command')\n      }\n      if (!Array.isArray(manifest.server.mcp_config.args)) {\n        throw new Error('Invalid manifest: server.mcp_config.args must be an array')\n      }\n\n      // Use server name as the final extract directory for automatic version management\n      const serverDirName = `server-${manifest.name}`\n      const finalExtractDir = ensurePathWithin(this.mcpDir, path.join(this.mcpDir, serverDirName))\n\n      // Stage the new package first, then swap directories so a failed install\n      // does not destroy the last working version.\n      await this.replacePackageDirectory(tempExtractDir, finalExtractDir, serverDirName)\n      logger.debug(`${packageLabel} server extracted to: ${finalExtractDir}`)\n\n      // Clean up the uploaded package file if it's in temp directory\n      if (filePath.startsWith(this.tempDir)) {\n        fs.unlinkSync(filePath)\n      }","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/mcp/McpPackageService.ts#L544-L580","documentation":"Thrown during MCP package (.dxt or .mcpb) installation when the extracted manifest.json lacks a `server.mcp_config.command` string. The command field tells the runtime which executable to launch (e.g. 'npx', 'uvx', 'node'). This is part of a sequential validation chain that checks name → version → server → mcp_config → command → args.","triggerScenarios":"Calling the package upload/processing method (processUploadedPackage) with an archive whose manifest.json has `server.mcp_config` defined but no `command` key, or `command` is an empty string/falsy value.","commonSituations":"Hand-authoring a manifest.json and forgetting the command field; using a wrong key name like 'cmd' or 'binary'; manifest follows an outdated or non-standard DXT/MCPB spec version; the package was generated by a tool that omits command.","solutions":["Open the package archive and inspect manifest.json — confirm `server.mcp_config.command` exists and is a non-empty string","If authoring the package, add the command: \"server\": { \"mcp_config\": { \"command\": \"npx\", \"args\": [] } }","Verify the manifest version field (manifest_version for .mcpb, dxt_version for .dxt) matches the spec the validator expects","Re-package the archive with the corrected manifest.json at the root level"],"exampleFix":"// before (manifest.json)\n{\n  \"name\": \"my-server\",\n  \"version\": \"1.0.0\",\n  \"server\": {\n    \"mcp_config\": {\n      \"args\": [\"-y\", \"@my/mcp-server\"]\n    }\n  }\n}\n\n// after\n{\n  \"name\": \"my-server\",\n  \"version\": \"1.0.0\",\n  \"server\": {\n    \"mcp_config\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@my/mcp-server\"]\n    }\n  }\n}","handlingStrategy":"validation","validationCode":"// Validate manifest before passing to the package processor\nfunction validateManifest(manifest: unknown): asserts manifest is McpPackageManifest {\n  const m = manifest as Record<string, any>\n  if (!m?.server?.mcp_config?.command) {\n    throw new Error('Manifest must include server.mcp_config.command')\n  }\n}","typeGuard":"function hasValidCommand(manifest: unknown): manifest is McpPackageManifest {\n  return typeof (manifest as any)?.server?.mcp_config?.command === 'string'\n    && (manifest as any).server.mcp_config.command.length > 0\n}","tryCatchPattern":"try {\n  await mcpPackageService.processUploadedPackage(filePath)\n} catch (e) {\n  if (e instanceof Error && e.message.includes('missing server.mcp_config.command')) {\n    // Show user: package manifest is incomplete, cannot install\n  }\n  throw e\n}","preventionTips":["Use a JSON schema validator (e.g. Zod or ajv) on manifest.json before submission","Provide a manifest template or generator tool to package authors","Document the required manifest structure in your packaging guide"],"tags":["mcp","manifest-validation","package-install","configuration"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}