claude-autopm 1.12.3 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/test.yml +50 -0
- package/README.md +147 -1
- package/autopm/.claude/providers/azure/issue-show.js +1 -293
- package/bin/autopm.js +20 -0
- package/bin/commands/mcp.js +175 -0
- package/package.json +5 -5
- package/scripts/mcp-handler.js +1019 -1
package/scripts/mcp-handler.js
CHANGED
|
@@ -40,6 +40,10 @@ try {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
class MCPHandler {
|
|
43
|
+
// Regular expression patterns as class constants
|
|
44
|
+
static MCP_URI_REGEX = /mcp:\/\/([a-zA-Z0-9_-]+)/g;
|
|
45
|
+
static ENV_VAR_NAME_REGEX = /^[A-Z_][A-Z0-9_]*$/;
|
|
46
|
+
|
|
43
47
|
constructor() {
|
|
44
48
|
this.projectRoot = process.cwd();
|
|
45
49
|
this.frameworkRoot = path.join(__dirname, '..');
|
|
@@ -47,6 +51,9 @@ class MCPHandler {
|
|
|
47
51
|
this.configPath = path.join(this.projectRoot, '.claude', 'config.json');
|
|
48
52
|
this.mcpServersPath = path.join(this.projectRoot, '.claude', 'mcp-servers.json');
|
|
49
53
|
this.envPath = path.join(this.projectRoot, '.claude', '.env');
|
|
54
|
+
|
|
55
|
+
// Cache for environment status to reduce file I/O
|
|
56
|
+
this._envStatusCache = null;
|
|
50
57
|
}
|
|
51
58
|
|
|
52
59
|
/**
|
|
@@ -520,6 +527,958 @@ This server can be integrated with various agents and context pools.
|
|
|
520
527
|
// This would update MCP-REGISTRY.md
|
|
521
528
|
console.log(`📝 TODO: Remove ${name} from registry`);
|
|
522
529
|
}
|
|
530
|
+
|
|
531
|
+
// ==========================================
|
|
532
|
+
// EXTENDED FEATURES: Agent Analysis
|
|
533
|
+
// ==========================================
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* Calculate percentage with safe division
|
|
537
|
+
* @param {number} numerator
|
|
538
|
+
* @param {number} denominator
|
|
539
|
+
* @returns {string} Formatted percentage or 'N/A%'
|
|
540
|
+
* @private
|
|
541
|
+
*/
|
|
542
|
+
_calculatePercentage(numerator, denominator) {
|
|
543
|
+
if (denominator === 0) {
|
|
544
|
+
return 'N/A%';
|
|
545
|
+
}
|
|
546
|
+
return `${Math.round((numerator / denominator) * 100)}%`;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/**
|
|
550
|
+
* Analyze all agents to find MCP usage
|
|
551
|
+
* @returns {Object} Analysis result with agent-to-MCP mapping
|
|
552
|
+
*/
|
|
553
|
+
analyzeAgents() {
|
|
554
|
+
const agentsDir = this.agentsDir || path.join(this.frameworkRoot, 'autopm', '.claude', 'agents');
|
|
555
|
+
|
|
556
|
+
if (!fs.existsSync(agentsDir)) {
|
|
557
|
+
return {
|
|
558
|
+
totalAgents: 0,
|
|
559
|
+
agentsWithMCP: 0,
|
|
560
|
+
agentsWithoutMCP: 0,
|
|
561
|
+
mcpUsage: {}
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
const result = {
|
|
566
|
+
totalAgents: 0,
|
|
567
|
+
agentsWithMCP: 0,
|
|
568
|
+
agentsWithoutMCP: 0,
|
|
569
|
+
mcpUsage: {}
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
// Recursively scan agent files
|
|
573
|
+
const scanDir = (dir) => {
|
|
574
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
575
|
+
|
|
576
|
+
entries.forEach(entry => {
|
|
577
|
+
const fullPath = path.join(dir, entry.name);
|
|
578
|
+
|
|
579
|
+
if (entry.isDirectory()) {
|
|
580
|
+
scanDir(fullPath);
|
|
581
|
+
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
582
|
+
result.totalAgents++;
|
|
583
|
+
|
|
584
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
585
|
+
|
|
586
|
+
// Extract agent name from frontmatter
|
|
587
|
+
const nameMatch = content.match(/^---[\s\S]*?name:\s*([^\n]+)/m);
|
|
588
|
+
const agentName = nameMatch ? nameMatch[1].trim() : path.basename(entry.name, '.md');
|
|
589
|
+
|
|
590
|
+
// Extract MCP URIs (mcp://server-name/path)
|
|
591
|
+
const matches = [...content.matchAll(MCPHandler.MCP_URI_REGEX)];
|
|
592
|
+
|
|
593
|
+
if (matches.length > 0) {
|
|
594
|
+
result.agentsWithMCP++;
|
|
595
|
+
const servers = [...new Set(matches.map(m => m[1]))];
|
|
596
|
+
result.mcpUsage[agentName] = servers;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
});
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
scanDir(agentsDir);
|
|
603
|
+
result.agentsWithoutMCP = result.totalAgents - result.agentsWithMCP;
|
|
604
|
+
|
|
605
|
+
return result;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
/**
|
|
609
|
+
* Get MCP usage for specific agent
|
|
610
|
+
* @param {string} agentName - Name of the agent
|
|
611
|
+
* @returns {Object} Agent MCP configuration
|
|
612
|
+
*/
|
|
613
|
+
getAgentMCP(agentName) {
|
|
614
|
+
const agentsDir = this.agentsDir || path.join(this.frameworkRoot, 'autopm', '.claude', 'agents');
|
|
615
|
+
|
|
616
|
+
const result = {
|
|
617
|
+
agentName,
|
|
618
|
+
found: false,
|
|
619
|
+
mcpServers: [],
|
|
620
|
+
serverDetails: []
|
|
621
|
+
};
|
|
622
|
+
|
|
623
|
+
if (!fs.existsSync(agentsDir)) {
|
|
624
|
+
return result;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
// Find agent file
|
|
628
|
+
const findAgentFile = (dir) => {
|
|
629
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
630
|
+
|
|
631
|
+
for (const entry of entries) {
|
|
632
|
+
const fullPath = path.join(dir, entry.name);
|
|
633
|
+
|
|
634
|
+
if (entry.isDirectory()) {
|
|
635
|
+
const found = findAgentFile(fullPath);
|
|
636
|
+
if (found) return found;
|
|
637
|
+
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
638
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
639
|
+
const nameMatch = content.match(/^---[\s\S]*?name:\s*([^\n]+)/m);
|
|
640
|
+
const fileAgentName = nameMatch ? nameMatch[1].trim() : path.basename(entry.name, '.md');
|
|
641
|
+
|
|
642
|
+
if (fileAgentName === agentName) {
|
|
643
|
+
return { path: fullPath, content };
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
return null;
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
const agentFile = findAgentFile(agentsDir);
|
|
652
|
+
|
|
653
|
+
if (!agentFile) {
|
|
654
|
+
return result;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
result.found = true;
|
|
658
|
+
|
|
659
|
+
// Extract MCP URIs
|
|
660
|
+
const regex = MCPHandler.MCP_URI_REGEX;
|
|
661
|
+
const matches = [...agentFile.content.matchAll(regex)];
|
|
662
|
+
result.mcpServers = [...new Set(matches.map(m => m[1]))];
|
|
663
|
+
|
|
664
|
+
// Get server details
|
|
665
|
+
result.mcpServers.forEach(serverName => {
|
|
666
|
+
const server = this.getServer(serverName);
|
|
667
|
+
if (server) {
|
|
668
|
+
result.serverDetails.push({
|
|
669
|
+
name: serverName,
|
|
670
|
+
category: server.metadata.category,
|
|
671
|
+
description: server.metadata.description,
|
|
672
|
+
status: server.metadata.status
|
|
673
|
+
});
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
|
|
677
|
+
return result;
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Display all agents using MCP
|
|
682
|
+
* @param {Object} options - Display options
|
|
683
|
+
*/
|
|
684
|
+
mcpAgents(options = {}) {
|
|
685
|
+
console.log('🤖 Agents Using MCP\n');
|
|
686
|
+
|
|
687
|
+
const analysis = this.analyzeAgents();
|
|
688
|
+
|
|
689
|
+
if (analysis.agentsWithMCP === 0) {
|
|
690
|
+
console.log('ℹ️ No agents are currently using MCP servers\n');
|
|
691
|
+
return;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
if (options.groupBy === 'server') {
|
|
695
|
+
// Group by MCP server
|
|
696
|
+
const serverMap = {};
|
|
697
|
+
Object.entries(analysis.mcpUsage).forEach(([agent, servers]) => {
|
|
698
|
+
servers.forEach(server => {
|
|
699
|
+
if (!serverMap[server]) {
|
|
700
|
+
serverMap[server] = [];
|
|
701
|
+
}
|
|
702
|
+
serverMap[server].push(agent);
|
|
703
|
+
});
|
|
704
|
+
});
|
|
705
|
+
|
|
706
|
+
Object.entries(serverMap).forEach(([server, agents]) => {
|
|
707
|
+
console.log(`📡 ${server} (${agents.length} agents)`);
|
|
708
|
+
agents.forEach(agent => {
|
|
709
|
+
console.log(` └─ ${agent}`);
|
|
710
|
+
});
|
|
711
|
+
console.log();
|
|
712
|
+
});
|
|
713
|
+
} else {
|
|
714
|
+
// List agents with their servers
|
|
715
|
+
Object.entries(analysis.mcpUsage).forEach(([agent, servers]) => {
|
|
716
|
+
console.log(`✅ ${agent}`);
|
|
717
|
+
servers.forEach(server => {
|
|
718
|
+
console.log(` └─ ${server}`);
|
|
719
|
+
});
|
|
720
|
+
console.log();
|
|
721
|
+
});
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
console.log(`📊 Summary:`);
|
|
725
|
+
console.log(` Total agents: ${analysis.totalAgents}`);
|
|
726
|
+
console.log(` Using MCP: ${analysis.agentsWithMCP}`);
|
|
727
|
+
console.log(` Without MCP: ${analysis.agentsWithoutMCP}`);
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
/**
|
|
731
|
+
* Display MCP configuration for specific agent
|
|
732
|
+
* @param {string} agentName - Name of the agent
|
|
733
|
+
*/
|
|
734
|
+
mcpAgent(agentName) {
|
|
735
|
+
const config = this.loadConfig();
|
|
736
|
+
const activeServers = config.mcp?.activeServers || [];
|
|
737
|
+
|
|
738
|
+
const agentInfo = this.getAgentMCP(agentName);
|
|
739
|
+
|
|
740
|
+
if (!agentInfo.found) {
|
|
741
|
+
console.error(`❌ Agent '${agentName}' not found`);
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
console.log(`\n🤖 Agent: ${agentName}`);
|
|
746
|
+
console.log('='.repeat(50));
|
|
747
|
+
|
|
748
|
+
if (agentInfo.mcpServers.length === 0) {
|
|
749
|
+
console.log('\nℹ️ This agent does not use any MCP servers');
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
console.log(`\n📡 MCP Servers (${agentInfo.mcpServers.length}):\n`);
|
|
754
|
+
|
|
755
|
+
agentInfo.serverDetails.forEach(server => {
|
|
756
|
+
const isActive = activeServers.includes(server.name);
|
|
757
|
+
const status = isActive ? '✅ Active' : '⚪ Inactive';
|
|
758
|
+
|
|
759
|
+
console.log(`${status} ${server.name}`);
|
|
760
|
+
console.log(` Category: ${server.category || 'uncategorized'}`);
|
|
761
|
+
console.log(` Description: ${server.description || 'No description'}`);
|
|
762
|
+
|
|
763
|
+
// Show env vars if available
|
|
764
|
+
const serverDef = this.getServer(server.name);
|
|
765
|
+
if (serverDef && serverDef.metadata.env) {
|
|
766
|
+
console.log(` Environment Variables:`);
|
|
767
|
+
Object.keys(serverDef.metadata.env).forEach(envVar => {
|
|
768
|
+
console.log(` - ${envVar}`);
|
|
769
|
+
});
|
|
770
|
+
}
|
|
771
|
+
console.log();
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Display MCP usage statistics
|
|
777
|
+
*/
|
|
778
|
+
mcpUsage() {
|
|
779
|
+
console.log('📊 MCP Usage Statistics\n');
|
|
780
|
+
|
|
781
|
+
const analysis = this.analyzeAgents();
|
|
782
|
+
|
|
783
|
+
if (analysis.agentsWithMCP === 0) {
|
|
784
|
+
console.log('ℹ️ No MCP usage detected\n');
|
|
785
|
+
return;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
// Group by server
|
|
789
|
+
const serverUsage = {};
|
|
790
|
+
Object.entries(analysis.mcpUsage).forEach(([agent, servers]) => {
|
|
791
|
+
servers.forEach(server => {
|
|
792
|
+
if (!serverUsage[server]) {
|
|
793
|
+
serverUsage[server] = [];
|
|
794
|
+
}
|
|
795
|
+
serverUsage[server].push(agent);
|
|
796
|
+
});
|
|
797
|
+
});
|
|
798
|
+
|
|
799
|
+
// Sort by usage count
|
|
800
|
+
const sorted = Object.entries(serverUsage)
|
|
801
|
+
.sort((a, b) => b[1].length - a[1].length);
|
|
802
|
+
|
|
803
|
+
console.log('📡 MCP Servers by Usage:\n');
|
|
804
|
+
sorted.forEach(([server, agents]) => {
|
|
805
|
+
console.log(`${server}: ${agents.length} agents`);
|
|
806
|
+
agents.forEach(agent => {
|
|
807
|
+
console.log(` └─ ${agent}`);
|
|
808
|
+
});
|
|
809
|
+
console.log();
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
console.log('📈 Summary:');
|
|
813
|
+
console.log(` Total agents: ${analysis.totalAgents}`);
|
|
814
|
+
const percentage = this._calculatePercentage(analysis.agentsWithMCP, analysis.totalAgents);
|
|
815
|
+
console.log(` Using MCP: ${analysis.agentsWithMCP} (${percentage})`);
|
|
816
|
+
console.log(` MCP servers in use: ${sorted.length}`);
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// ==========================================
|
|
820
|
+
// EXTENDED FEATURES: Setup Wizard
|
|
821
|
+
// ==========================================
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Detect required environment variables from active servers
|
|
825
|
+
* @returns {Array} List of required env vars
|
|
826
|
+
*/
|
|
827
|
+
detectRequiredEnvVars() {
|
|
828
|
+
const config = this.loadConfig();
|
|
829
|
+
const activeServers = config.mcp?.activeServers || [];
|
|
830
|
+
const requiredVars = new Set();
|
|
831
|
+
|
|
832
|
+
activeServers.forEach(serverName => {
|
|
833
|
+
const server = this.getServer(serverName);
|
|
834
|
+
if (server && server.metadata.env) {
|
|
835
|
+
Object.keys(server.metadata.env).forEach(envVar => {
|
|
836
|
+
requiredVars.add(envVar);
|
|
837
|
+
});
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
|
|
841
|
+
return Array.from(requiredVars);
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
/**
|
|
845
|
+
* Check status of environment variables
|
|
846
|
+
* @param {boolean} useCache - Whether to use cached result (default: false)
|
|
847
|
+
* @returns {Object} Status of env vars (configured/missing)
|
|
848
|
+
*/
|
|
849
|
+
checkEnvVarsStatus(useCache = false) {
|
|
850
|
+
// Return cached result if available and requested
|
|
851
|
+
if (useCache && this._envStatusCache !== null) {
|
|
852
|
+
return this._envStatusCache;
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
const requiredVars = this.detectRequiredEnvVars();
|
|
856
|
+
const configured = [];
|
|
857
|
+
const missing = [];
|
|
858
|
+
|
|
859
|
+
// Check .env file
|
|
860
|
+
let envContent = '';
|
|
861
|
+
if (fs.existsSync(this.envPath)) {
|
|
862
|
+
envContent = fs.readFileSync(this.envPath, 'utf8');
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
requiredVars.forEach(varName => {
|
|
866
|
+
// Check if variable is in .env file
|
|
867
|
+
const regex = new RegExp(`^${varName}=.+`, 'm');
|
|
868
|
+
if (regex.test(envContent)) {
|
|
869
|
+
configured.push(varName);
|
|
870
|
+
} else {
|
|
871
|
+
missing.push(varName);
|
|
872
|
+
}
|
|
873
|
+
});
|
|
874
|
+
|
|
875
|
+
const result = { configured, missing };
|
|
876
|
+
|
|
877
|
+
// Cache the result if requested
|
|
878
|
+
if (useCache) {
|
|
879
|
+
this._envStatusCache = result;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
return result;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
/**
|
|
886
|
+
* Interactive setup wizard for API keys
|
|
887
|
+
* @param {Object} options - Options including readline interface
|
|
888
|
+
*/
|
|
889
|
+
async setupWizard(options = {}) {
|
|
890
|
+
console.log('🔧 MCP Configuration Setup');
|
|
891
|
+
console.log('='.repeat(50));
|
|
892
|
+
console.log();
|
|
893
|
+
|
|
894
|
+
const status = this.checkEnvVarsStatus();
|
|
895
|
+
|
|
896
|
+
if (status.missing.length === 0) {
|
|
897
|
+
console.log('✅ All required environment variables are configured!');
|
|
898
|
+
return;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
console.log(`⚠️ Missing environment variables: ${status.missing.length}\n`);
|
|
902
|
+
|
|
903
|
+
status.missing.forEach(varName => {
|
|
904
|
+
console.log(`❌ ${varName}`);
|
|
905
|
+
});
|
|
906
|
+
|
|
907
|
+
console.log('\n💡 Configure these in .claude/.env file');
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Save environment variables to .env file
|
|
912
|
+
* @param {Object} envVars - Key-value pairs of env vars
|
|
913
|
+
*/
|
|
914
|
+
saveEnvVars(envVars) {
|
|
915
|
+
this.ensureClaudeDir();
|
|
916
|
+
|
|
917
|
+
let existingContent = '';
|
|
918
|
+
if (fs.existsSync(this.envPath)) {
|
|
919
|
+
existingContent = fs.readFileSync(this.envPath, 'utf8');
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Parse existing vars
|
|
923
|
+
const existingVars = {};
|
|
924
|
+
existingContent.split('\n').forEach(line => {
|
|
925
|
+
const trimmedLine = line.trim();
|
|
926
|
+
if (!trimmedLine || trimmedLine.startsWith('#')) return; // skip empty/comment lines
|
|
927
|
+
const parts = trimmedLine.split('=', 2);
|
|
928
|
+
if (parts.length === 2) {
|
|
929
|
+
existingVars[parts[0]] = parts[1];
|
|
930
|
+
}
|
|
931
|
+
});
|
|
932
|
+
|
|
933
|
+
// Merge with new vars
|
|
934
|
+
Object.assign(existingVars, envVars);
|
|
935
|
+
|
|
936
|
+
// Write back
|
|
937
|
+
const newContent = Object.entries(existingVars)
|
|
938
|
+
.map(([key, value]) => `${key}=${value}`)
|
|
939
|
+
.join('\n') + '\n';
|
|
940
|
+
|
|
941
|
+
fs.writeFileSync(this.envPath, newContent);
|
|
942
|
+
|
|
943
|
+
// Invalidate cache after updating env vars
|
|
944
|
+
this._envStatusCache = null;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Validate environment variable format
|
|
949
|
+
* @param {string} name - Variable name
|
|
950
|
+
* @param {string} value - Variable value
|
|
951
|
+
* @returns {boolean} Whether the var is valid
|
|
952
|
+
*/
|
|
953
|
+
validateEnvVar(name, value) {
|
|
954
|
+
// Name should be uppercase with underscores
|
|
955
|
+
if (!MCPHandler.ENV_VAR_NAME_REGEX.test(name)) {
|
|
956
|
+
return false;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
// Value should not be empty
|
|
960
|
+
if (!value || value.trim() === '') {
|
|
961
|
+
return false;
|
|
962
|
+
}
|
|
963
|
+
|
|
964
|
+
return true;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// ==========================================
|
|
968
|
+
// EXTENDED FEATURES: Diagnostics
|
|
969
|
+
// ==========================================
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Extract unique environment variable names from missingEnvVars array
|
|
973
|
+
* @param {Array} missingEnvVars - Array of objects with server and variable properties
|
|
974
|
+
* @returns {Array<string>} Array of unique variable names
|
|
975
|
+
* @private
|
|
976
|
+
*/
|
|
977
|
+
_getUniqueEnvVars(missingEnvVars) {
|
|
978
|
+
return [...new Set(missingEnvVars.map(v => v.variable))];
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
/**
|
|
982
|
+
* Check if required MCP servers are properly configured
|
|
983
|
+
* @returns {Object} Configuration check result
|
|
984
|
+
*/
|
|
985
|
+
checkRequiredServers() {
|
|
986
|
+
const analysis = this.analyzeAgents();
|
|
987
|
+
const config = this.loadConfig();
|
|
988
|
+
const activeServers = config.mcp?.activeServers || [];
|
|
989
|
+
const envStatus = this.checkEnvVarsStatus();
|
|
990
|
+
|
|
991
|
+
const result = {
|
|
992
|
+
agentsUsingMCP: analysis.agentsWithMCP,
|
|
993
|
+
totalAgents: analysis.totalAgents,
|
|
994
|
+
serversInUse: new Set(),
|
|
995
|
+
missingServers: [],
|
|
996
|
+
disabledServers: [],
|
|
997
|
+
missingEnvVars: [],
|
|
998
|
+
warnings: [],
|
|
999
|
+
recommendations: []
|
|
1000
|
+
};
|
|
1001
|
+
|
|
1002
|
+
// Collect all MCP servers used by agents
|
|
1003
|
+
Object.values(analysis.mcpUsage).forEach(servers => {
|
|
1004
|
+
servers.forEach(server => result.serversInUse.add(server));
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
// Check each server
|
|
1008
|
+
result.serversInUse.forEach(serverName => {
|
|
1009
|
+
const server = this.getServer(serverName);
|
|
1010
|
+
|
|
1011
|
+
if (!server) {
|
|
1012
|
+
result.missingServers.push({
|
|
1013
|
+
name: serverName,
|
|
1014
|
+
reason: 'Server definition not found in registry'
|
|
1015
|
+
});
|
|
1016
|
+
result.warnings.push(`⚠️ MCP server '${serverName}' is used by agents but not defined in registry`);
|
|
1017
|
+
} else {
|
|
1018
|
+
// Check if server is enabled
|
|
1019
|
+
if (!activeServers.includes(serverName)) {
|
|
1020
|
+
result.disabledServers.push({
|
|
1021
|
+
name: serverName,
|
|
1022
|
+
category: server.metadata.category,
|
|
1023
|
+
description: server.metadata.description
|
|
1024
|
+
});
|
|
1025
|
+
result.warnings.push(`⚠️ MCP server '${serverName}' is used by agents but NOT enabled`);
|
|
1026
|
+
result.recommendations.push(` Run: autopm mcp enable ${serverName}`);
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// Check environment variables for this server
|
|
1030
|
+
if (server.metadata.env) {
|
|
1031
|
+
const serverEnvVars = Object.keys(server.metadata.env);
|
|
1032
|
+
serverEnvVars.forEach(envVar => {
|
|
1033
|
+
if (envStatus.missing.includes(envVar)) {
|
|
1034
|
+
result.missingEnvVars.push({
|
|
1035
|
+
server: serverName,
|
|
1036
|
+
variable: envVar
|
|
1037
|
+
});
|
|
1038
|
+
}
|
|
1039
|
+
});
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
|
|
1044
|
+
// Add recommendations for missing env vars
|
|
1045
|
+
if (result.missingEnvVars.length > 0) {
|
|
1046
|
+
const uniqueVars = this._getUniqueEnvVars(result.missingEnvVars);
|
|
1047
|
+
result.warnings.push(`⚠️ Missing ${uniqueVars.length} environment variable(s): ${uniqueVars.join(', ')}`);
|
|
1048
|
+
result.recommendations.push(` Configure in .claude/.env file`);
|
|
1049
|
+
result.recommendations.push(` Run: autopm mcp setup`);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
return result;
|
|
1053
|
+
}
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Display quick configuration check
|
|
1057
|
+
*/
|
|
1058
|
+
check() {
|
|
1059
|
+
console.log('🔍 MCP Configuration Check\n');
|
|
1060
|
+
|
|
1061
|
+
const checkResult = this.checkRequiredServers();
|
|
1062
|
+
|
|
1063
|
+
if (checkResult.agentsUsingMCP === 0) {
|
|
1064
|
+
console.log('ℹ️ No agents are using MCP servers\n');
|
|
1065
|
+
console.log('✅ Configuration OK - MCP not required\n');
|
|
1066
|
+
return;
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
console.log(`📊 Overview:`);
|
|
1070
|
+
console.log(` Agents using MCP: ${checkResult.agentsUsingMCP}/${checkResult.totalAgents}`);
|
|
1071
|
+
console.log(` MCP servers in use: ${checkResult.serversInUse.size}\n`);
|
|
1072
|
+
|
|
1073
|
+
// Check for issues
|
|
1074
|
+
const hasIssues = checkResult.missingServers.length > 0 ||
|
|
1075
|
+
checkResult.disabledServers.length > 0 ||
|
|
1076
|
+
checkResult.missingEnvVars.length > 0;
|
|
1077
|
+
|
|
1078
|
+
if (!hasIssues) {
|
|
1079
|
+
console.log('✅ All required MCP servers are properly configured!\n');
|
|
1080
|
+
return;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
// Show warnings
|
|
1084
|
+
if (checkResult.warnings.length > 0) {
|
|
1085
|
+
console.log('⚠️ Configuration Issues:\n');
|
|
1086
|
+
checkResult.warnings.forEach(warning => console.log(warning));
|
|
1087
|
+
console.log();
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
// Show disabled servers
|
|
1091
|
+
if (checkResult.disabledServers.length > 0) {
|
|
1092
|
+
console.log('🔴 Disabled Servers (used by agents):\n');
|
|
1093
|
+
checkResult.disabledServers.forEach(server => {
|
|
1094
|
+
console.log(` • ${server.name}`);
|
|
1095
|
+
console.log(` Category: ${server.category || 'uncategorized'}`);
|
|
1096
|
+
console.log(` Description: ${server.description || 'No description'}`);
|
|
1097
|
+
});
|
|
1098
|
+
console.log();
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// Show missing env vars details
|
|
1102
|
+
if (checkResult.missingEnvVars.length > 0) {
|
|
1103
|
+
console.log('🔑 Missing Environment Variables:\n');
|
|
1104
|
+
const byServer = Object.groupBy(checkResult.missingEnvVars, ({ server }) => server);
|
|
1105
|
+
Object.entries(byServer).forEach(([server, entries]) => {
|
|
1106
|
+
console.log(` ${server}:`);
|
|
1107
|
+
entries.forEach(({ variable }) => console.log(` - ${variable}`));
|
|
1108
|
+
});
|
|
1109
|
+
console.log();
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// Show recommendations
|
|
1113
|
+
if (checkResult.recommendations.length > 0) {
|
|
1114
|
+
console.log('💡 Recommendations:\n');
|
|
1115
|
+
checkResult.recommendations.forEach(rec => console.log(rec));
|
|
1116
|
+
console.log();
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
console.log('🔧 Quick Fix:');
|
|
1120
|
+
if (Array.isArray(checkResult.disabledServers) && checkResult.disabledServers.length > 0) {
|
|
1121
|
+
checkResult.disabledServers.forEach(server => {
|
|
1122
|
+
console.log(` autopm mcp enable ${server.name}`);
|
|
1123
|
+
});
|
|
1124
|
+
}
|
|
1125
|
+
if (checkResult.missingEnvVars.length > 0) {
|
|
1126
|
+
console.log(` autopm mcp setup`);
|
|
1127
|
+
}
|
|
1128
|
+
console.log(` autopm mcp sync`);
|
|
1129
|
+
console.log();
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
/**
|
|
1133
|
+
* Run comprehensive MCP diagnostics
|
|
1134
|
+
* @returns {Object} Diagnostic results
|
|
1135
|
+
*/
|
|
1136
|
+
diagnose() {
|
|
1137
|
+
console.log('🔍 Running MCP Diagnostics...\n');
|
|
1138
|
+
|
|
1139
|
+
const result = {
|
|
1140
|
+
status: 'healthy',
|
|
1141
|
+
checks: [],
|
|
1142
|
+
errors: [],
|
|
1143
|
+
warnings: []
|
|
1144
|
+
};
|
|
1145
|
+
|
|
1146
|
+
// Check 1: .claude directory
|
|
1147
|
+
const claudeDirCheck = {
|
|
1148
|
+
name: '.claude directory exists',
|
|
1149
|
+
passed: fs.existsSync(path.join(this.projectRoot, '.claude'))
|
|
1150
|
+
};
|
|
1151
|
+
result.checks.push(claudeDirCheck);
|
|
1152
|
+
|
|
1153
|
+
if (!claudeDirCheck.passed) {
|
|
1154
|
+
result.errors.push('.claude directory not found');
|
|
1155
|
+
result.status = 'error';
|
|
1156
|
+
}
|
|
1157
|
+
|
|
1158
|
+
// Check 2: config.json
|
|
1159
|
+
const configCheck = {
|
|
1160
|
+
name: 'config.json exists and is valid',
|
|
1161
|
+
passed: false
|
|
1162
|
+
};
|
|
1163
|
+
|
|
1164
|
+
if (fs.existsSync(this.configPath)) {
|
|
1165
|
+
try {
|
|
1166
|
+
JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
|
|
1167
|
+
configCheck.passed = true;
|
|
1168
|
+
} catch (e) {
|
|
1169
|
+
result.errors.push('config.json is invalid JSON');
|
|
1170
|
+
result.status = 'error';
|
|
1171
|
+
}
|
|
1172
|
+
} else {
|
|
1173
|
+
result.warnings.push('config.json not found');
|
|
1174
|
+
if (result.status === 'healthy') result.status = 'warning';
|
|
1175
|
+
}
|
|
1176
|
+
result.checks.push(configCheck);
|
|
1177
|
+
|
|
1178
|
+
// Check 3: Active servers exist
|
|
1179
|
+
const config = this.loadConfig();
|
|
1180
|
+
const activeServers = config.mcp?.activeServers || [];
|
|
1181
|
+
|
|
1182
|
+
activeServers.forEach(serverName => {
|
|
1183
|
+
const server = this.getServer(serverName);
|
|
1184
|
+
if (!server) {
|
|
1185
|
+
result.errors.push(`Active server '${serverName}' definition not found`);
|
|
1186
|
+
result.status = 'error';
|
|
1187
|
+
}
|
|
1188
|
+
});
|
|
1189
|
+
|
|
1190
|
+
// Check 4: Environment variables
|
|
1191
|
+
const envStatus = this.checkEnvVarsStatus();
|
|
1192
|
+
const envCheck = {
|
|
1193
|
+
name: 'environment variables configured',
|
|
1194
|
+
passed: envStatus.missing.length === 0
|
|
1195
|
+
};
|
|
1196
|
+
result.checks.push(envCheck);
|
|
1197
|
+
|
|
1198
|
+
if (envStatus.missing.length > 0) {
|
|
1199
|
+
envStatus.missing.forEach(varName => {
|
|
1200
|
+
result.warnings.push(`Environment variable ${varName} not configured`);
|
|
1201
|
+
});
|
|
1202
|
+
if (result.status === 'healthy') result.status = 'warning';
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// Check 5: mcp-servers.json
|
|
1206
|
+
if (fs.existsSync(this.mcpServersPath)) {
|
|
1207
|
+
try {
|
|
1208
|
+
JSON.parse(fs.readFileSync(this.mcpServersPath, 'utf8'));
|
|
1209
|
+
} catch (e) {
|
|
1210
|
+
result.errors.push('mcp-servers.json is invalid JSON');
|
|
1211
|
+
result.status = 'error';
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
// Check 6: Agents directory
|
|
1216
|
+
const agentsDir = this.agentsDir || path.join(this.frameworkRoot, 'autopm', '.claude', 'agents');
|
|
1217
|
+
const agentsDirCheck = {
|
|
1218
|
+
name: 'agents directory exists',
|
|
1219
|
+
passed: fs.existsSync(agentsDir)
|
|
1220
|
+
};
|
|
1221
|
+
result.checks.push(agentsDirCheck);
|
|
1222
|
+
|
|
1223
|
+
// Display results
|
|
1224
|
+
console.log('📋 Diagnostic Results:\n');
|
|
1225
|
+
result.checks.forEach(check => {
|
|
1226
|
+
const icon = check.passed ? '✅' : '❌';
|
|
1227
|
+
console.log(`${icon} ${check.name}`);
|
|
1228
|
+
});
|
|
1229
|
+
|
|
1230
|
+
if (result.errors.length > 0) {
|
|
1231
|
+
console.log('\n❌ Errors:');
|
|
1232
|
+
result.errors.forEach(err => console.log(` ${err}`));
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
if (result.warnings.length > 0) {
|
|
1236
|
+
console.log('\n⚠️ Warnings:');
|
|
1237
|
+
result.warnings.forEach(warn => console.log(` ${warn}`));
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// Check for missing/disabled MCP servers
|
|
1241
|
+
console.log('\n🔌 MCP Server Requirements:');
|
|
1242
|
+
const serverCheck = this.checkRequiredServers();
|
|
1243
|
+
|
|
1244
|
+
if (serverCheck.agentsUsingMCP === 0) {
|
|
1245
|
+
console.log(' ℹ️ No agents using MCP servers');
|
|
1246
|
+
} else {
|
|
1247
|
+
console.log(` Agents using MCP: ${serverCheck.agentsUsingMCP}/${serverCheck.totalAgents}`);
|
|
1248
|
+
console.log(` MCP servers in use: ${serverCheck.serversInUse.size}`);
|
|
1249
|
+
|
|
1250
|
+
if (serverCheck.disabledServers.length > 0) {
|
|
1251
|
+
console.log(` ⚠️ ${serverCheck.disabledServers.length} required server(s) are DISABLED`);
|
|
1252
|
+
result.warnings.push(`${serverCheck.disabledServers.length} MCP server(s) used by agents are not enabled`);
|
|
1253
|
+
if (result.status === 'healthy') result.status = 'warning';
|
|
1254
|
+
}
|
|
1255
|
+
|
|
1256
|
+
if (serverCheck.missingServers.length > 0) {
|
|
1257
|
+
console.log(` ❌ ${serverCheck.missingServers.length} server(s) not found in registry`);
|
|
1258
|
+
result.errors.push(`${serverCheck.missingServers.length} MCP server(s) referenced but not defined`);
|
|
1259
|
+
result.status = 'error';
|
|
1260
|
+
}
|
|
1261
|
+
|
|
1262
|
+
if (serverCheck.missingEnvVars.length > 0) {
|
|
1263
|
+
const uniqueVars = this._getUniqueEnvVars(serverCheck.missingEnvVars);
|
|
1264
|
+
console.log(` ⚠️ ${uniqueVars.length} environment variable(s) not configured`);
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
if (serverCheck.disabledServers.length === 0 &&
|
|
1268
|
+
serverCheck.missingServers.length === 0 &&
|
|
1269
|
+
serverCheck.missingEnvVars.length === 0) {
|
|
1270
|
+
console.log(' ✅ All required servers properly configured');
|
|
1271
|
+
} else {
|
|
1272
|
+
console.log('\n💡 Run "autopm mcp check" for detailed recommendations');
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
console.log(`\n🏥 Overall Health: ${result.status.toUpperCase()}`);
|
|
1277
|
+
|
|
1278
|
+
return result;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Test MCP server connection
|
|
1283
|
+
* @param {string} serverName - Name of server to test
|
|
1284
|
+
* @returns {Promise<Object>} Test results
|
|
1285
|
+
*/
|
|
1286
|
+
async testServer(serverName) {
|
|
1287
|
+
const result = {
|
|
1288
|
+
serverName,
|
|
1289
|
+
success: false,
|
|
1290
|
+
message: '',
|
|
1291
|
+
commandCheck: false
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
// Check if server exists
|
|
1295
|
+
const server = this.getServer(serverName);
|
|
1296
|
+
if (!server) {
|
|
1297
|
+
result.message = `Server '${serverName}' not found`;
|
|
1298
|
+
return result;
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
// Check required env vars
|
|
1302
|
+
if (server.metadata.env) {
|
|
1303
|
+
const envVars = Object.keys(server.metadata.env);
|
|
1304
|
+
const envStatus = this.checkEnvVarsStatus(true); // Use cache to reduce file I/O
|
|
1305
|
+
|
|
1306
|
+
const missingVars = envVars.filter(v => envStatus.missing.includes(v));
|
|
1307
|
+
if (missingVars.length > 0) {
|
|
1308
|
+
result.message = `Missing environment variables: ${missingVars.join(', ')}`;
|
|
1309
|
+
return result;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
|
|
1313
|
+
// Check command accessibility (basic check)
|
|
1314
|
+
result.commandCheck = true;
|
|
1315
|
+
result.success = true;
|
|
1316
|
+
result.message = 'Server configuration appears valid';
|
|
1317
|
+
|
|
1318
|
+
return result;
|
|
1319
|
+
}
|
|
1320
|
+
|
|
1321
|
+
// ==========================================
|
|
1322
|
+
// EXTENDED FEATURES: Visualization
|
|
1323
|
+
// ==========================================
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Generate agent-MCP dependency tree
|
|
1327
|
+
* @returns {Object} Tree structure with nodes and edges
|
|
1328
|
+
*/
|
|
1329
|
+
generateTree() {
|
|
1330
|
+
const analysis = this.analyzeAgents();
|
|
1331
|
+
const agentsDir = this.agentsDir || path.join(this.frameworkRoot, 'autopm', '.claude', 'agents');
|
|
1332
|
+
|
|
1333
|
+
const tree = {
|
|
1334
|
+
nodes: [],
|
|
1335
|
+
edges: []
|
|
1336
|
+
};
|
|
1337
|
+
|
|
1338
|
+
// Build category nodes
|
|
1339
|
+
const categories = {};
|
|
1340
|
+
|
|
1341
|
+
const scanDir = (dir, category = 'root') => {
|
|
1342
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
1343
|
+
|
|
1344
|
+
entries.forEach(entry => {
|
|
1345
|
+
const fullPath = path.join(dir, entry.name);
|
|
1346
|
+
|
|
1347
|
+
if (entry.isDirectory()) {
|
|
1348
|
+
if (!categories[entry.name]) {
|
|
1349
|
+
categories[entry.name] = true;
|
|
1350
|
+
tree.nodes.push({
|
|
1351
|
+
type: 'category',
|
|
1352
|
+
name: entry.name
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
scanDir(fullPath, entry.name);
|
|
1356
|
+
} else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
1357
|
+
const content = fs.readFileSync(fullPath, 'utf8');
|
|
1358
|
+
const nameMatch = content.match(/^---[\s\S]*?name:\s*([^\n]+)/m);
|
|
1359
|
+
const agentName = nameMatch ? nameMatch[1].trim() : path.basename(entry.name, '.md');
|
|
1360
|
+
|
|
1361
|
+
tree.nodes.push({
|
|
1362
|
+
type: 'agent',
|
|
1363
|
+
name: agentName,
|
|
1364
|
+
category
|
|
1365
|
+
});
|
|
1366
|
+
|
|
1367
|
+
// Create edges to MCP servers
|
|
1368
|
+
if (analysis.mcpUsage[agentName]) {
|
|
1369
|
+
analysis.mcpUsage[agentName].forEach(server => {
|
|
1370
|
+
tree.edges.push({
|
|
1371
|
+
from: agentName,
|
|
1372
|
+
to: server
|
|
1373
|
+
});
|
|
1374
|
+
});
|
|
1375
|
+
}
|
|
1376
|
+
}
|
|
1377
|
+
});
|
|
1378
|
+
};
|
|
1379
|
+
|
|
1380
|
+
if (fs.existsSync(agentsDir)) {
|
|
1381
|
+
scanDir(agentsDir);
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
return tree;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
/**
|
|
1388
|
+
* Display tree visualization
|
|
1389
|
+
*/
|
|
1390
|
+
showTree() {
|
|
1391
|
+
console.log('🌳 Agent → MCP Dependency Tree\n');
|
|
1392
|
+
|
|
1393
|
+
const tree = this.generateTree();
|
|
1394
|
+
const analysis = this.analyzeAgents();
|
|
1395
|
+
|
|
1396
|
+
// Group agents by category
|
|
1397
|
+
const categories = {};
|
|
1398
|
+
tree.nodes.filter(n => n.type === 'agent').forEach(agent => {
|
|
1399
|
+
const cat = agent.category || 'root';
|
|
1400
|
+
if (!categories[cat]) {
|
|
1401
|
+
categories[cat] = [];
|
|
1402
|
+
}
|
|
1403
|
+
categories[cat].push(agent.name);
|
|
1404
|
+
});
|
|
1405
|
+
|
|
1406
|
+
Object.entries(categories).forEach(([category, agents]) => {
|
|
1407
|
+
if (category !== 'root') {
|
|
1408
|
+
console.log(`📁 ${category}`);
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
agents.forEach((agent, index) => {
|
|
1412
|
+
const isLast = index === agents.length - 1;
|
|
1413
|
+
const prefix = isLast ? '└─' : '├─';
|
|
1414
|
+
|
|
1415
|
+
const mcpServers = analysis.mcpUsage[agent] || [];
|
|
1416
|
+
const status = mcpServers.length > 0 ? '✅' : '⚪';
|
|
1417
|
+
|
|
1418
|
+
console.log(`${prefix} ${agent} ${status}`);
|
|
1419
|
+
|
|
1420
|
+
if (mcpServers.length > 0) {
|
|
1421
|
+
mcpServers.forEach((server, sIndex) => {
|
|
1422
|
+
const sIsLast = sIndex === mcpServers.length - 1;
|
|
1423
|
+
const sPrefix = sIsLast ? ' └─' : ' ├─';
|
|
1424
|
+
console.log(`${sPrefix} ${server}`);
|
|
1425
|
+
});
|
|
1426
|
+
}
|
|
1427
|
+
});
|
|
1428
|
+
console.log();
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
/**
|
|
1433
|
+
* Show status of all MCP servers
|
|
1434
|
+
*/
|
|
1435
|
+
showStatus() {
|
|
1436
|
+
console.log('📊 MCP Servers Status\n');
|
|
1437
|
+
|
|
1438
|
+
const config = this.loadConfig();
|
|
1439
|
+
const activeServers = config.mcp?.activeServers || [];
|
|
1440
|
+
const allServers = this.getAllServers();
|
|
1441
|
+
const analysis = this.analyzeAgents();
|
|
1442
|
+
|
|
1443
|
+
// Count agent usage per server
|
|
1444
|
+
const serverAgentCount = {};
|
|
1445
|
+
Object.values(analysis.mcpUsage).forEach(servers => {
|
|
1446
|
+
servers.forEach(server => {
|
|
1447
|
+
serverAgentCount[server] = (serverAgentCount[server] || 0) + 1;
|
|
1448
|
+
});
|
|
1449
|
+
});
|
|
1450
|
+
|
|
1451
|
+
allServers.forEach(server => {
|
|
1452
|
+
const isEnabled = activeServers.includes(server.name);
|
|
1453
|
+
const status = isEnabled ? '✅' : '⚪';
|
|
1454
|
+
const agentCount = serverAgentCount[server.name] || 0;
|
|
1455
|
+
|
|
1456
|
+
console.log(`${status} ${server.name}`);
|
|
1457
|
+
console.log(` Category: ${server.metadata.category || 'uncategorized'}`);
|
|
1458
|
+
console.log(` Status: ${isEnabled ? 'Enabled' : 'Disabled'}`);
|
|
1459
|
+
console.log(` Used by: ${agentCount} agent${agentCount !== 1 ? 's' : ''}`);
|
|
1460
|
+
|
|
1461
|
+
// Show required env vars
|
|
1462
|
+
if (server.metadata.env) {
|
|
1463
|
+
const envVars = Object.keys(server.metadata.env);
|
|
1464
|
+
const envStatus = this.checkEnvVarsStatus();
|
|
1465
|
+
|
|
1466
|
+
console.log(` Environment:`);
|
|
1467
|
+
envVars.forEach(envVar => {
|
|
1468
|
+
const configured = envStatus.configured.includes(envVar);
|
|
1469
|
+
const varStatus = configured ? '✅' : '❌';
|
|
1470
|
+
console.log(` ${varStatus} ${envVar}`);
|
|
1471
|
+
});
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1474
|
+
console.log();
|
|
1475
|
+
});
|
|
1476
|
+
|
|
1477
|
+
console.log('📈 Summary:');
|
|
1478
|
+
console.log(` Total servers: ${allServers.length}`);
|
|
1479
|
+
console.log(` Enabled: ${activeServers.length}`);
|
|
1480
|
+
console.log(` Disabled: ${allServers.length - activeServers.length}`);
|
|
1481
|
+
}
|
|
523
1482
|
}
|
|
524
1483
|
|
|
525
1484
|
// CLI execution
|
|
@@ -553,9 +1512,55 @@ if (require.main === module) {
|
|
|
553
1512
|
case 'info':
|
|
554
1513
|
handler.info(args[0]);
|
|
555
1514
|
break;
|
|
1515
|
+
// Extended commands
|
|
1516
|
+
case 'agents':
|
|
1517
|
+
handler.mcpAgents(args.includes('--by-server') ? { groupBy: 'server' } : {});
|
|
1518
|
+
break;
|
|
1519
|
+
case 'agent':
|
|
1520
|
+
if (!args[0]) {
|
|
1521
|
+
console.error('❌ Please specify an agent name');
|
|
1522
|
+
process.exit(1);
|
|
1523
|
+
}
|
|
1524
|
+
handler.mcpAgent(args[0]);
|
|
1525
|
+
break;
|
|
1526
|
+
case 'usage':
|
|
1527
|
+
handler.mcpUsage();
|
|
1528
|
+
break;
|
|
1529
|
+
case 'setup':
|
|
1530
|
+
handler.setupWizard();
|
|
1531
|
+
break;
|
|
1532
|
+
case 'check':
|
|
1533
|
+
handler.check();
|
|
1534
|
+
break;
|
|
1535
|
+
case 'diagnose':
|
|
1536
|
+
handler.diagnose();
|
|
1537
|
+
break;
|
|
1538
|
+
case 'test':
|
|
1539
|
+
if (!args[0]) {
|
|
1540
|
+
console.error('❌ Please specify a server name');
|
|
1541
|
+
process.exit(1);
|
|
1542
|
+
}
|
|
1543
|
+
handler.testServer(args[0]).then(result => {
|
|
1544
|
+
if (result.success) {
|
|
1545
|
+
console.log(`✅ ${result.message}`);
|
|
1546
|
+
} else {
|
|
1547
|
+
console.error(`❌ ${result.message}`);
|
|
1548
|
+
process.exit(1);
|
|
1549
|
+
}
|
|
1550
|
+
}).catch(error => {
|
|
1551
|
+
console.error(`❌ Error testing server: ${error?.message || error}`);
|
|
1552
|
+
console.error(`❌ Error testing server: ${error?.message || error}`);
|
|
1553
|
+
});
|
|
1554
|
+
break;
|
|
1555
|
+
case 'tree':
|
|
1556
|
+
handler.showTree();
|
|
1557
|
+
break;
|
|
1558
|
+
case 'status':
|
|
1559
|
+
handler.showStatus();
|
|
1560
|
+
break;
|
|
556
1561
|
default:
|
|
557
1562
|
console.log('Usage: mcp-handler <command> [options]');
|
|
558
|
-
console.log('\
|
|
1563
|
+
console.log('\nBasic Commands:');
|
|
559
1564
|
console.log(' list List all available servers');
|
|
560
1565
|
console.log(' add Add a new server interactively');
|
|
561
1566
|
console.log(' remove <name> Remove a server');
|
|
@@ -564,6 +1569,19 @@ if (require.main === module) {
|
|
|
564
1569
|
console.log(' sync Sync configuration');
|
|
565
1570
|
console.log(' validate Validate all servers');
|
|
566
1571
|
console.log(' info <name> Show server details');
|
|
1572
|
+
console.log('\nAgent Analysis:');
|
|
1573
|
+
console.log(' agents List agents using MCP');
|
|
1574
|
+
console.log(' agents --by-server Group agents by MCP server');
|
|
1575
|
+
console.log(' agent <name> Show MCP config for specific agent');
|
|
1576
|
+
console.log(' usage Show MCP usage statistics');
|
|
1577
|
+
console.log('\nConfiguration:');
|
|
1578
|
+
console.log(' setup Interactive API key setup');
|
|
1579
|
+
console.log(' check Quick MCP configuration check');
|
|
1580
|
+
console.log(' diagnose Run MCP diagnostics');
|
|
1581
|
+
console.log(' test <server> Test MCP server connection');
|
|
1582
|
+
console.log('\nVisualization:');
|
|
1583
|
+
console.log(' tree Show agent-MCP dependency tree');
|
|
1584
|
+
console.log(' status Show MCP servers status');
|
|
567
1585
|
process.exit(1);
|
|
568
1586
|
}
|
|
569
1587
|
}
|