diff --git a/scripts/build-hooks.js b/scripts/build-hooks.js index 2df00280..a5f934bb 100644 --- a/scripts/build-hooks.js +++ b/scripts/build-hooks.js @@ -389,11 +389,18 @@ async function buildHooks() { if (claudeMemMarketplaceEntry?.source?.path !== './plugin') { throw new Error('.agents/plugins/marketplace.json must point claude-mem source.path at ./plugin so Codex loads the bundled plugin root'); } + const rootMcp = JSON.parse(fs.readFileSync('.mcp.json', 'utf-8')); const bundledMcp = JSON.parse(fs.readFileSync('plugin/.mcp.json', 'utf-8')); + if (JSON.stringify(rootMcp.mcpServers?.['mcp-search']) !== JSON.stringify(bundledMcp.mcpServers?.['mcp-search'])) { + throw new Error('.mcp.json and plugin/.mcp.json mcp-search launchers must stay in sync'); + } const mcpSearchCommand = bundledMcp.mcpServers?.['mcp-search']?.args?.join(' ') ?? ''; if (!mcpSearchCommand.includes('.codex/plugins/cache/claude-mem-local/claude-mem')) { throw new Error('plugin/.mcp.json mcp-search launcher must include Codex cache fallback for hosts that do not inject PLUGIN_ROOT'); } + if (!mcpSearchCommand.includes('.claude/plugins/cache/thedotmack/claude-mem')) { + throw new Error('plugin/.mcp.json mcp-search launcher must include Claude cache fallback for hosts that do not inject PLUGIN_ROOT'); + } console.log('āœ“ All required distribution files present'); console.log('\nāœ… All build targets compiled successfully!'); diff --git a/tests/infrastructure/plugin-distribution.test.ts b/tests/infrastructure/plugin-distribution.test.ts index dd415d83..c59dd2b6 100644 --- a/tests/infrastructure/plugin-distribution.test.ts +++ b/tests/infrastructure/plugin-distribution.test.ts @@ -70,6 +70,13 @@ describe('Plugin Distribution - Codex Marketplace', () => { expect(command).toContain('.claude/plugins/cache/thedotmack/claude-mem'); expect(command).toContain('claude-mem MCP server not found'); }); + + it('keeps root and bundled MCP launchers in sync', () => { + const rootMcp = JSON.parse(readFileSync(path.join(projectRoot, '.mcp.json'), 'utf-8')); + const bundledMcp = JSON.parse(readFileSync(path.join(projectRoot, 'plugin/.mcp.json'), 'utf-8')); + + expect(rootMcp.mcpServers['mcp-search']).toEqual(bundledMcp.mcpServers['mcp-search']); + }); }); describe('Plugin Distribution - hooks.json Integrity', () => {