( source: string, pluginPath: string, pluginId: string, onProgress?: ProgressCallback, providedUserConfig?: UserConfigValues, forceConfigDialog?: boolean, )
| 706 | * @returns Success with MCP config, or needs-config status with schema |
| 707 | */ |
| 708 | export async function loadMcpbFile( |
| 709 | source: string, |
| 710 | pluginPath: string, |
| 711 | pluginId: string, |
| 712 | onProgress?: ProgressCallback, |
| 713 | providedUserConfig?: UserConfigValues, |
| 714 | forceConfigDialog?: boolean, |
| 715 | ): Promise<McpbLoadResult | McpbNeedsConfigResult> { |
| 716 | const fs = getFsImplementation() |
| 717 | const cacheDir = getMcpbCacheDir(pluginPath) |
| 718 | await fs.mkdir(cacheDir) |
| 719 | |
| 720 | logForDebugging(`Loading MCPB from source: ${source}`) |
| 721 | |
| 722 | // Check cache first |
| 723 | const metadata = await loadCacheMetadata(cacheDir, source) |
| 724 | if (metadata && !(await checkMcpbChanged(source, pluginPath))) { |
| 725 | logForDebugging( |
| 726 | `Using cached MCPB from ${metadata.extractedPath} (hash: ${metadata.contentHash})`, |
| 727 | ) |
| 728 | |
| 729 | // Load manifest from cache |
| 730 | const manifestPath = join(metadata.extractedPath, 'manifest.json') |
| 731 | let manifestContent: string |
| 732 | try { |
| 733 | manifestContent = await fs.readFile(manifestPath, { encoding: 'utf-8' }) |
| 734 | } catch (error) { |
| 735 | if (isENOENT(error)) { |
| 736 | const err = new Error(`Cached manifest not found: ${manifestPath}`) |
| 737 | logError(err) |
| 738 | throw err |
| 739 | } |
| 740 | throw error |
| 741 | } |
| 742 | |
| 743 | const manifestData = new TextEncoder().encode(manifestContent) |
| 744 | const manifest = await parseAndValidateManifestFromBytes(manifestData) |
| 745 | |
| 746 | // Check for user_config requirement |
| 747 | if (manifest.user_config && Object.keys(manifest.user_config).length > 0) { |
| 748 | // Server name from DXT manifest |
| 749 | const serverName = manifest.name |
| 750 | |
| 751 | // Try to load existing config from settings.json or use provided config |
| 752 | const savedConfig = loadMcpServerUserConfig(pluginId, serverName) |
| 753 | const userConfig = providedUserConfig || savedConfig || {} |
| 754 | |
| 755 | // Validate we have all required fields |
| 756 | const validation = validateUserConfig(userConfig, manifest.user_config) |
| 757 | |
| 758 | // Return needs-config if: forced (reconfiguration) OR validation failed |
| 759 | if (forceConfigDialog || !validation.valid) { |
| 760 | return { |
| 761 | status: 'needs-config', |
| 762 | manifest, |
| 763 | extractedPath: metadata.extractedPath, |
| 764 | contentHash: metadata.contentHash, |
| 765 | configSchema: manifest.user_config, |
no test coverage detected