Files
affaan-m--everything-claude…/scripts/mcp-inventory.js
T
wehub-resource-sync d48cda4081
CI / Test (ubuntu-latest, Node 18.x, bun) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, npm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, pnpm) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 18.x, yarn) (push) Failing after 15m1s
CI / Test (ubuntu-latest, Node 20.x, bun) (push) Failing after 17m13s
CI / Test (ubuntu-latest, Node 20.x, npm) (push) Failing after 18m42s
CI / Test (ubuntu-latest, Node 20.x, pnpm) (push) Failing after 15m0s
CI / Test (ubuntu-latest, Node 20.x, yarn) (push) Failing after 49m44s
CI / Test (ubuntu-latest, Node 22.x, bun) (push) Failing after 51m55s
CI / Test (ubuntu-latest, Node 22.x, pnpm) (push) Failing after 21m57s
CI / Test (ubuntu-latest, Node 22.x, npm) (push) Failing after 37m39s
CI / Test (ubuntu-latest, Node 22.x, yarn) (push) Failing after 34m7s
CI / Validate Components (push) Failing after 37m15s
CI / Python Tests (push) Failing after 10m1s
CI / Security Scan (push) Failing after 10m1s
CI / Lint (push) Failing after 17m12s
CI / Coverage (push) Failing after 20m19s
CI / Test (macos-latest, Node 18.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 18.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 20.x, yarn) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, bun) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (macos-latest, Node 22.x, yarn) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, npm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, pnpm) (push) Has been cancelled
CI / Test (windows-latest, Node 22.x, yarn) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 11:55:55 +08:00

107 lines
3.0 KiB
JavaScript
Executable File

#!/usr/bin/env node
'use strict';
const { collectMcpInventory } = require('./lib/mcp-inventory/collect');
function parseArgs(argv = process.argv) {
const args = argv.slice(2);
const options = { json: false, fragmentedOnly: false, help: false };
for (const arg of args) {
if (arg === '--json') {
options.json = true;
} else if (arg === '--fragmented' || arg === '--fragmented-only') {
options.fragmentedOnly = true;
} else if (arg === '--help' || arg === '-h') {
options.help = true;
}
}
return options;
}
function usage() {
return [
'Usage: mcp-inventory [options]',
'',
'Read MCP server configs across every installed harness (Claude Code,',
'Codex, OpenCode), normalize them to ecc.mcp.v1, and report which servers',
'are configured in more than one harness. Secrets are never printed; only',
'env key names are shown.',
'',
'Options:',
' --json Print the full ecc.mcp.v1 inventory as JSON',
' --fragmented Only show servers configured in 2+ harnesses',
' -h, --help Show this help'
].join('\n');
}
function formatHumanReport(inventory, options = {}) {
const lines = [];
const { aggregates, servers, fragmentation } = inventory;
lines.push('MCP Inventory (ecc.mcp.v1)');
lines.push(
` ${aggregates.serverCount} servers across ${aggregates.harnessCount} harnesses, `
+ `${aggregates.duplicateServerCount} configured in 2+ harnesses `
+ `(${aggregates.inconsistentServerCount} inconsistent), `
+ `${aggregates.serversWithSecrets} carry secrets`
);
lines.push('');
if (fragmentation.length > 0) {
lines.push('Fragmented servers (configure-once candidates):');
for (const item of fragmentation) {
const flag = item.consistent ? 'consistent' : 'DRIFT';
lines.push(` ${item.name} x${item.harnessCount} [${item.harnesses.join(', ')}] ${flag}`);
}
lines.push('');
} else {
lines.push('No servers are configured in more than one harness.');
lines.push('');
}
if (!options.fragmentedOnly) {
lines.push('All servers:');
for (const server of servers) {
const transport = server.transport === 'stdio'
? `stdio:${[server.command, ...server.args].filter(Boolean).join(' ')}`
: `${server.transport}:${server.url || ''}`;
const secretFlag = server.hasSecrets ? ' (secrets)' : '';
const disabledFlag = server.enabled ? '' : ' (disabled)';
lines.push(` ${server.name} -> ${transport}${secretFlag}${disabledFlag}`);
}
}
return lines.join('\n');
}
function main(argv = process.argv) {
const options = parseArgs(argv);
if (options.help) {
console.log(usage());
return;
}
const inventory = collectMcpInventory();
if (options.json) {
console.log(JSON.stringify(inventory, null, 2));
return;
}
console.log(formatHumanReport(inventory, options));
}
if (require.main === module) {
main();
}
module.exports = {
parseArgs,
usage,
formatHumanReport,
main
};