@musashishao/agent-kit 1.2.2
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/.agent/agents/backend-specialist.md +263 -0
- package/.agent/agents/database-architect.md +226 -0
- package/.agent/agents/debugger.md +225 -0
- package/.agent/agents/devops-engineer.md +242 -0
- package/.agent/agents/documentation-writer.md +104 -0
- package/.agent/agents/explorer-agent.md +73 -0
- package/.agent/agents/frontend-specialist.md +556 -0
- package/.agent/agents/game-developer.md +162 -0
- package/.agent/agents/mobile-developer.md +377 -0
- package/.agent/agents/orchestrator.md +416 -0
- package/.agent/agents/penetration-tester.md +188 -0
- package/.agent/agents/performance-optimizer.md +187 -0
- package/.agent/agents/project-planner.md +403 -0
- package/.agent/agents/security-auditor.md +170 -0
- package/.agent/agents/seo-specialist.md +111 -0
- package/.agent/agents/test-engineer.md +158 -0
- package/.agent/mcp/README.md +69 -0
- package/.agent/mcp/config/mcp-config.json +62 -0
- package/.agent/mcp/config/registry.json +54 -0
- package/.agent/mcp/servers/agent-kit-core/package.json +28 -0
- package/.agent/mcp/servers/agent-kit-core/src/index.ts +455 -0
- package/.agent/mcp/servers/agent-kit-core/tsconfig.json +16 -0
- package/.agent/mcp/servers/agent-kit-fs/package.json +25 -0
- package/.agent/mcp/servers/agent-kit-fs/src/index.ts +399 -0
- package/.agent/mcp/servers/agent-kit-fs/tsconfig.json +16 -0
- package/.agent/mcp/servers/agent-kit-git/package.json +24 -0
- package/.agent/mcp/servers/agent-kit-git/src/index.ts +283 -0
- package/.agent/mcp/servers/agent-kit-git/tsconfig.json +16 -0
- package/.agent/mcp/templates/README.md +49 -0
- package/.agent/mcp/templates/api/README.md.template +45 -0
- package/.agent/mcp/templates/api/src/index.ts.template +185 -0
- package/.agent/mcp/templates/base-package.json.template +27 -0
- package/.agent/mcp/templates/base-tsconfig.json +21 -0
- package/.agent/mcp/templates/custom/src/index.ts.template +133 -0
- package/.agent/mcp/templates/database/src/index.ts.template +273 -0
- package/.agent/mcp/templates/web-scraper/src/index.ts.template +239 -0
- package/.agent/rules/CODEX.md +250 -0
- package/.agent/rules/GEMINI.md +251 -0
- package/.agent/skills/api-patterns/SKILL.md +81 -0
- package/.agent/skills/api-patterns/api-style.md +42 -0
- package/.agent/skills/api-patterns/auth.md +24 -0
- package/.agent/skills/api-patterns/documentation.md +26 -0
- package/.agent/skills/api-patterns/graphql.md +41 -0
- package/.agent/skills/api-patterns/rate-limiting.md +31 -0
- package/.agent/skills/api-patterns/response.md +37 -0
- package/.agent/skills/api-patterns/rest.md +40 -0
- package/.agent/skills/api-patterns/scripts/api_validator.py +211 -0
- package/.agent/skills/api-patterns/security-testing.md +122 -0
- package/.agent/skills/api-patterns/trpc.md +41 -0
- package/.agent/skills/api-patterns/versioning.md +22 -0
- package/.agent/skills/app-builder/SKILL.md +75 -0
- package/.agent/skills/app-builder/agent-coordination.md +71 -0
- package/.agent/skills/app-builder/feature-building.md +53 -0
- package/.agent/skills/app-builder/project-detection.md +34 -0
- package/.agent/skills/app-builder/scaffolding.md +118 -0
- package/.agent/skills/app-builder/tech-stack.md +40 -0
- package/.agent/skills/app-builder/templates/SKILL.md +39 -0
- package/.agent/skills/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/.agent/skills/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/.agent/skills/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/.agent/skills/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/.agent/skills/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
- package/.agent/skills/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
- package/.agent/skills/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
- package/.agent/skills/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
- package/.agent/skills/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/.agent/skills/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
- package/.agent/skills/architecture/SKILL.md +55 -0
- package/.agent/skills/architecture/context-discovery.md +43 -0
- package/.agent/skills/architecture/examples.md +94 -0
- package/.agent/skills/architecture/pattern-selection.md +68 -0
- package/.agent/skills/architecture/patterns-reference.md +50 -0
- package/.agent/skills/architecture/trade-off-analysis.md +77 -0
- package/.agent/skills/bash-linux/SKILL.md +199 -0
- package/.agent/skills/behavioral-modes/SKILL.md +242 -0
- package/.agent/skills/brainstorming/SKILL.md +163 -0
- package/.agent/skills/brainstorming/dynamic-questioning.md +350 -0
- package/.agent/skills/clean-code/SKILL.md +201 -0
- package/.agent/skills/code-review-checklist/SKILL.md +109 -0
- package/.agent/skills/context-engineering/SKILL.md +74 -0
- package/.agent/skills/context-engineering/examples/advanced_code_request.md +73 -0
- package/.agent/skills/context-engineering/scripts/quality_validator.py +294 -0
- package/.agent/skills/context-engineering/scripts/repo_mapper.py +27 -0
- package/.agent/skills/context-engineering/scripts/skill_checker.py +194 -0
- package/.agent/skills/context-engineering/scripts/token_counter.py +65 -0
- package/.agent/skills/context-engineering/strategies/context-caching.md +50 -0
- package/.agent/skills/context-engineering/strategies/few-shot-examples.md +56 -0
- package/.agent/skills/context-engineering/strategies/skeleton-code.md +59 -0
- package/.agent/skills/context-engineering/strategies/xml-framing.md +57 -0
- package/.agent/skills/database-design/SKILL.md +52 -0
- package/.agent/skills/database-design/database-selection.md +43 -0
- package/.agent/skills/database-design/indexing.md +39 -0
- package/.agent/skills/database-design/migrations.md +48 -0
- package/.agent/skills/database-design/optimization.md +36 -0
- package/.agent/skills/database-design/orm-selection.md +30 -0
- package/.agent/skills/database-design/schema-design.md +56 -0
- package/.agent/skills/database-design/scripts/schema_validator.py +172 -0
- package/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/.agent/skills/doc.md +177 -0
- package/.agent/skills/docker-expert/SKILL.md +409 -0
- package/.agent/skills/documentation-templates/SKILL.md +194 -0
- package/.agent/skills/frontend-design/SKILL.md +396 -0
- package/.agent/skills/frontend-design/animation-guide.md +331 -0
- package/.agent/skills/frontend-design/color-system.md +311 -0
- package/.agent/skills/frontend-design/decision-trees.md +418 -0
- package/.agent/skills/frontend-design/motion-graphics.md +306 -0
- package/.agent/skills/frontend-design/scripts/accessibility_checker.py +183 -0
- package/.agent/skills/frontend-design/scripts/ux_audit.py +722 -0
- package/.agent/skills/frontend-design/typography-system.md +345 -0
- package/.agent/skills/frontend-design/ux-psychology.md +541 -0
- package/.agent/skills/frontend-design/visual-effects.md +383 -0
- package/.agent/skills/game-development/2d-games/SKILL.md +119 -0
- package/.agent/skills/game-development/3d-games/SKILL.md +135 -0
- package/.agent/skills/game-development/SKILL.md +167 -0
- package/.agent/skills/game-development/game-art/SKILL.md +185 -0
- package/.agent/skills/game-development/game-audio/SKILL.md +190 -0
- package/.agent/skills/game-development/game-design/SKILL.md +129 -0
- package/.agent/skills/game-development/mobile-games/SKILL.md +108 -0
- package/.agent/skills/game-development/multiplayer/SKILL.md +132 -0
- package/.agent/skills/game-development/pc-games/SKILL.md +144 -0
- package/.agent/skills/game-development/vr-ar/SKILL.md +123 -0
- package/.agent/skills/game-development/web-games/SKILL.md +150 -0
- package/.agent/skills/geo-fundamentals/SKILL.md +156 -0
- package/.agent/skills/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/.agent/skills/i18n-localization/SKILL.md +154 -0
- package/.agent/skills/i18n-localization/scripts/i18n_checker.py +241 -0
- package/.agent/skills/lint-and-validate/SKILL.md +45 -0
- package/.agent/skills/lint-and-validate/scripts/lint_runner.py +172 -0
- package/.agent/skills/lint-and-validate/scripts/type_coverage.py +173 -0
- package/.agent/skills/mcp-builder/SKILL.md +662 -0
- package/.agent/skills/mcp-builder/python-template.md +522 -0
- package/.agent/skills/mcp-builder/tool-patterns.md +642 -0
- package/.agent/skills/mcp-builder/typescript-template.md +361 -0
- package/.agent/skills/mobile-design/SKILL.md +394 -0
- package/.agent/skills/mobile-design/decision-trees.md +516 -0
- package/.agent/skills/mobile-design/mobile-backend.md +491 -0
- package/.agent/skills/mobile-design/mobile-color-system.md +420 -0
- package/.agent/skills/mobile-design/mobile-debugging.md +122 -0
- package/.agent/skills/mobile-design/mobile-design-thinking.md +357 -0
- package/.agent/skills/mobile-design/mobile-navigation.md +458 -0
- package/.agent/skills/mobile-design/mobile-performance.md +767 -0
- package/.agent/skills/mobile-design/mobile-testing.md +356 -0
- package/.agent/skills/mobile-design/mobile-typography.md +433 -0
- package/.agent/skills/mobile-design/platform-android.md +666 -0
- package/.agent/skills/mobile-design/platform-ios.md +561 -0
- package/.agent/skills/mobile-design/scripts/mobile_audit.py +670 -0
- package/.agent/skills/mobile-design/touch-psychology.md +537 -0
- package/.agent/skills/nestjs-expert/SKILL.md +552 -0
- package/.agent/skills/nextjs-best-practices/SKILL.md +203 -0
- package/.agent/skills/nodejs-best-practices/SKILL.md +333 -0
- package/.agent/skills/parallel-agents/SKILL.md +175 -0
- package/.agent/skills/performance-profiling/SKILL.md +143 -0
- package/.agent/skills/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/.agent/skills/plan-writing/SKILL.md +152 -0
- package/.agent/skills/powershell-windows/SKILL.md +167 -0
- package/.agent/skills/prisma-expert/SKILL.md +355 -0
- package/.agent/skills/problem-solving/SKILL.md +556 -0
- package/.agent/skills/problem-solving/collision-zone-thinking.md +285 -0
- package/.agent/skills/problem-solving/inversion-exercise.md +205 -0
- package/.agent/skills/problem-solving/meta-pattern-recognition.md +313 -0
- package/.agent/skills/problem-solving/scale-game.md +300 -0
- package/.agent/skills/problem-solving/simplification-cascades.md +321 -0
- package/.agent/skills/problem-solving/when-stuck.md +146 -0
- package/.agent/skills/python-patterns/SKILL.md +441 -0
- package/.agent/skills/react-patterns/SKILL.md +198 -0
- package/.agent/skills/red-team-tactics/SKILL.md +199 -0
- package/.agent/skills/seo-fundamentals/SKILL.md +129 -0
- package/.agent/skills/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/.agent/skills/server-management/SKILL.md +161 -0
- package/.agent/skills/systematic-debugging/SKILL.md +109 -0
- package/.agent/skills/tailwind-patterns/SKILL.md +269 -0
- package/.agent/skills/tdd-workflow/SKILL.md +149 -0
- package/.agent/skills/testing-patterns/SKILL.md +178 -0
- package/.agent/skills/testing-patterns/scripts/test_runner.py +219 -0
- package/.agent/skills/typescript-expert/SKILL.md +429 -0
- package/.agent/skills/typescript-expert/references/tsconfig-strict.json +92 -0
- package/.agent/skills/typescript-expert/references/typescript-cheatsheet.md +383 -0
- package/.agent/skills/typescript-expert/references/utility-types.ts +335 -0
- package/.agent/skills/typescript-expert/scripts/ts_diagnostic.py +203 -0
- package/.agent/skills/ui-ux-pro-max/SKILL.md +351 -0
- package/.agent/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.agent/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/icons.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.agent/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.agent/skills/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.agent/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.agent/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.agent/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.agent/skills/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/.agent/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.agent/skills/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/.agent/skills/ui-ux-pro-max/scripts/core.py +257 -0
- package/.agent/skills/ui-ux-pro-max/scripts/design_system.py +487 -0
- package/.agent/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/.agent/skills/vulnerability-scanner/SKILL.md +276 -0
- package/.agent/skills/vulnerability-scanner/checklists.md +121 -0
- package/.agent/skills/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/.agent/skills/webapp-testing/SKILL.md +187 -0
- package/.agent/skills/webapp-testing/scripts/playwright_runner.py +173 -0
- package/.agent/templates/AGENTS.backend.md +230 -0
- package/.agent/templates/AGENTS.md +121 -0
- package/.agent/templates/AGENTS.mobile.md +183 -0
- package/.agent/templates/AGENTS.web.md +192 -0
- package/.agent/workflows/brainstorm.md +113 -0
- package/.agent/workflows/context.md +47 -0
- package/.agent/workflows/create.md +59 -0
- package/.agent/workflows/debug.md +103 -0
- package/.agent/workflows/deploy.md +176 -0
- package/.agent/workflows/enhance.md +63 -0
- package/.agent/workflows/orchestrate.md +237 -0
- package/.agent/workflows/plan.md +89 -0
- package/.agent/workflows/preview.md +80 -0
- package/.agent/workflows/quality.md +89 -0
- package/.agent/workflows/status.md +86 -0
- package/.agent/workflows/test.md +144 -0
- package/.agent/workflows/ui-ux-pro-max.md +250 -0
- package/LICENSE +21 -0
- package/README.md +317 -0
- package/bin/cli.js +1267 -0
- package/index.js +1 -0
- package/package.json +50 -0
package/bin/cli.js
ADDED
|
@@ -0,0 +1,1267 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const VERSION = require('../package.json').version;
|
|
9
|
+
const PACKAGE_NAME = '@musashishao/agent-kit';
|
|
10
|
+
|
|
11
|
+
// Colors for terminal
|
|
12
|
+
const colors = {
|
|
13
|
+
reset: '\x1b[0m',
|
|
14
|
+
bright: '\x1b[1m',
|
|
15
|
+
green: '\x1b[32m',
|
|
16
|
+
yellow: '\x1b[33m',
|
|
17
|
+
blue: '\x1b[34m',
|
|
18
|
+
magenta: '\x1b[35m',
|
|
19
|
+
cyan: '\x1b[36m',
|
|
20
|
+
red: '\x1b[31m'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const log = {
|
|
24
|
+
info: (msg) => console.log(`${colors.blue}ℹ${colors.reset} ${msg}`),
|
|
25
|
+
success: (msg) => console.log(`${colors.green}✔${colors.reset} ${msg}`),
|
|
26
|
+
warn: (msg) => console.log(`${colors.yellow}⚠${colors.reset} ${msg}`),
|
|
27
|
+
error: (msg) => console.log(`${colors.red}✖${colors.reset} ${msg}`),
|
|
28
|
+
title: (msg) => console.log(`\n${colors.bright}${colors.magenta}${msg}${colors.reset}\n`)
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
function showHelp() {
|
|
32
|
+
console.log(`
|
|
33
|
+
${colors.bright}${colors.cyan}🚀 Musa Agent Kit${colors.reset} v${VERSION}
|
|
34
|
+
|
|
35
|
+
${colors.bright}Usage:${colors.reset}
|
|
36
|
+
npx ${PACKAGE_NAME} <command> [options]
|
|
37
|
+
|
|
38
|
+
${colors.bright}Commands:${colors.reset}
|
|
39
|
+
${colors.cyan}init${colors.reset} Install .agent folder into current project
|
|
40
|
+
${colors.cyan}setup-codex${colors.reset} Sync workflows with Codex CLI slash commands
|
|
41
|
+
${colors.cyan}codex${colors.reset} Generate AGENTS.md for Codex CLI (use --template)
|
|
42
|
+
${colors.cyan}mcp${colors.reset} MCP server management (setup, list, build)
|
|
43
|
+
${colors.cyan}agents${colors.reset} List all available agents
|
|
44
|
+
${colors.cyan}skills${colors.reset} List all available skills
|
|
45
|
+
${colors.cyan}workflows${colors.reset} List all available workflows
|
|
46
|
+
${colors.cyan}doctor${colors.reset} Check configuration and diagnose issues
|
|
47
|
+
${colors.cyan}update${colors.reset} Update .agent folder to latest version
|
|
48
|
+
${colors.cyan}status${colors.reset} Check installation status
|
|
49
|
+
|
|
50
|
+
${colors.bright}MCP Subcommands:${colors.reset}
|
|
51
|
+
${colors.cyan}mcp setup${colors.reset} Configure MCP servers for Claude/Cursor
|
|
52
|
+
${colors.cyan}mcp list${colors.reset} List available MCP servers
|
|
53
|
+
${colors.cyan}mcp build${colors.reset} Build MCP servers
|
|
54
|
+
|
|
55
|
+
${colors.bright}Options:${colors.reset}
|
|
56
|
+
--force Overwrite existing files
|
|
57
|
+
--path <dir> Install in specific directory
|
|
58
|
+
--prefix <str> Custom prefix for slash commands (default: kit-)
|
|
59
|
+
--template <type> Template type: web, mobile, backend (for codex command)
|
|
60
|
+
--client <name> MCP client: claude, cursor (for mcp setup)
|
|
61
|
+
--quiet Suppress output
|
|
62
|
+
--help Show this help message
|
|
63
|
+
--version Show version
|
|
64
|
+
|
|
65
|
+
${colors.bright}Examples:${colors.reset}
|
|
66
|
+
npx ${PACKAGE_NAME} init
|
|
67
|
+
npx ${PACKAGE_NAME} mcp setup --client claude
|
|
68
|
+
npx ${PACKAGE_NAME} codex --template web
|
|
69
|
+
npx ${PACKAGE_NAME} doctor
|
|
70
|
+
|
|
71
|
+
${colors.yellow}# To ensure you have the latest version from NPM:${colors.reset}
|
|
72
|
+
npx ${PACKAGE_NAME}@latest update
|
|
73
|
+
`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
function showVersion() {
|
|
78
|
+
console.log(`${PACKAGE_NAME} v${VERSION}`);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function copyFolderRecursive(src, dest) {
|
|
82
|
+
if (!fs.existsSync(dest)) {
|
|
83
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
87
|
+
|
|
88
|
+
for (const entry of entries) {
|
|
89
|
+
const srcPath = path.join(src, entry.name);
|
|
90
|
+
const destPath = path.join(dest, entry.name);
|
|
91
|
+
|
|
92
|
+
if (entry.isDirectory()) {
|
|
93
|
+
copyFolderRecursive(srcPath, destPath);
|
|
94
|
+
} else {
|
|
95
|
+
fs.copyFileSync(srcPath, destPath);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function countItems(dir) {
|
|
101
|
+
let count = { files: 0, dirs: 0 };
|
|
102
|
+
|
|
103
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
104
|
+
for (const entry of entries) {
|
|
105
|
+
if (entry.isDirectory()) {
|
|
106
|
+
count.dirs++;
|
|
107
|
+
const subCount = countItems(path.join(dir, entry.name));
|
|
108
|
+
count.files += subCount.files;
|
|
109
|
+
count.dirs += subCount.dirs;
|
|
110
|
+
} else {
|
|
111
|
+
count.files++;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return count;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function initCommand(options) {
|
|
119
|
+
const targetDir = options.path || process.cwd();
|
|
120
|
+
const agentDir = path.join(targetDir, '.agent');
|
|
121
|
+
const quiet = options.quiet;
|
|
122
|
+
|
|
123
|
+
if (!quiet) {
|
|
124
|
+
log.title('🚀 Musa Agent Kit - Installing...');
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Check if .agent exists
|
|
128
|
+
if (fs.existsSync(agentDir)) {
|
|
129
|
+
if (!options.force) {
|
|
130
|
+
log.warn('.agent folder already exists!');
|
|
131
|
+
log.info('Use --force to overwrite');
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
if (!quiet) log.info('Removing existing .agent folder...');
|
|
135
|
+
fs.rmSync(agentDir, { recursive: true, force: true });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Find source .agent folder
|
|
139
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
140
|
+
const sourceAgent = path.join(packageRoot, '.agent');
|
|
141
|
+
|
|
142
|
+
if (!fs.existsSync(sourceAgent)) {
|
|
143
|
+
log.error('Source .agent folder not found in package!');
|
|
144
|
+
process.exit(1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Copy
|
|
148
|
+
if (!quiet) log.info('Copying .agent folder...');
|
|
149
|
+
copyFolderRecursive(sourceAgent, agentDir);
|
|
150
|
+
|
|
151
|
+
// Summary
|
|
152
|
+
const counts = countItems(agentDir);
|
|
153
|
+
|
|
154
|
+
if (!quiet) {
|
|
155
|
+
log.success('Installation complete!');
|
|
156
|
+
console.log(`
|
|
157
|
+
${colors.bright}📦 Installed:${colors.reset}
|
|
158
|
+
${colors.cyan}${counts.dirs}${colors.reset} folders
|
|
159
|
+
${colors.cyan}${counts.files}${colors.reset} files
|
|
160
|
+
|
|
161
|
+
${colors.bright}📁 Location:${colors.reset} ${agentDir}
|
|
162
|
+
|
|
163
|
+
${colors.bright}🎯 Quick Start:${colors.reset}
|
|
164
|
+
1. Open your project in Cursor/VS Code
|
|
165
|
+
2. Use slash commands: /brainstorm, /create, /debug
|
|
166
|
+
3. Mention agents: "Use security-auditor to review auth"
|
|
167
|
+
|
|
168
|
+
${colors.bright}📚 Documentation:${colors.reset}
|
|
169
|
+
See .agent/ARCHITECTURE.md for full guide
|
|
170
|
+
`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function setupCodexCommand(options) {
|
|
175
|
+
const codexPromptDir = path.join(os.homedir(), '.codex', 'prompts');
|
|
176
|
+
const agentDir = path.join(process.cwd(), '.agent');
|
|
177
|
+
const workflowDir = path.join(agentDir, 'workflows');
|
|
178
|
+
const prefix = options.prefix || 'kit-';
|
|
179
|
+
|
|
180
|
+
log.title('🔗 Musa Agent Kit - Syncing with Codex CLI');
|
|
181
|
+
|
|
182
|
+
if (!fs.existsSync(agentDir)) {
|
|
183
|
+
log.error('.agent folder not found. Please run "init" first.');
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
if (!fs.existsSync(codexPromptDir)) {
|
|
188
|
+
log.info('Creating Codex prompt directory...');
|
|
189
|
+
fs.mkdirSync(codexPromptDir, { recursive: true });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const workflows = fs.readdirSync(workflowDir).filter(f => f.endsWith('.md'));
|
|
193
|
+
|
|
194
|
+
log.info(`Found ${workflows.length} workflows. Linking to ${codexPromptDir}...`);
|
|
195
|
+
|
|
196
|
+
let successCount = 0;
|
|
197
|
+
for (const wf of workflows) {
|
|
198
|
+
const src = path.join(workflowDir, wf);
|
|
199
|
+
const destName = `${prefix}${wf}`;
|
|
200
|
+
const dest = path.join(codexPromptDir, destName);
|
|
201
|
+
|
|
202
|
+
try {
|
|
203
|
+
if (fs.existsSync(dest)) {
|
|
204
|
+
if (options.force) {
|
|
205
|
+
fs.unlinkSync(dest);
|
|
206
|
+
} else {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Use absolute path for symlink
|
|
212
|
+
fs.symlinkSync(src, dest, 'file');
|
|
213
|
+
successCount++;
|
|
214
|
+
} catch (err) {
|
|
215
|
+
// If symlink fails (e.g. on Windows without admin), copy instead
|
|
216
|
+
try {
|
|
217
|
+
fs.copyFileSync(src, dest);
|
|
218
|
+
successCount++;
|
|
219
|
+
} catch (copyErr) {
|
|
220
|
+
log.error(`Failed to sync ${wf}: ${copyErr.message}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
log.success(`Successfully synced ${successCount} slash commands to Codex CLI!`);
|
|
226
|
+
log.info(`You can now use: /${prefix}${workflows[0].replace('.md', '')} in Codex CLI.`);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function statusCommand() {
|
|
230
|
+
const agentDir = path.join(process.cwd(), '.agent');
|
|
231
|
+
|
|
232
|
+
log.title('📊 Musa Agent Kit - Status');
|
|
233
|
+
|
|
234
|
+
if (!fs.existsSync(agentDir)) {
|
|
235
|
+
log.warn('.agent folder not found');
|
|
236
|
+
log.info(`Run: npx ${PACKAGE_NAME} init`);
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const counts = countItems(agentDir);
|
|
241
|
+
log.success('.agent folder found');
|
|
242
|
+
console.log(`
|
|
243
|
+
${colors.bright}📦 Contents:${colors.reset}
|
|
244
|
+
${colors.cyan}${counts.dirs}${colors.reset} folders
|
|
245
|
+
${colors.cyan}${counts.files}${colors.reset} files
|
|
246
|
+
|
|
247
|
+
${colors.bright}📁 Components:${colors.reset}`);
|
|
248
|
+
|
|
249
|
+
const components = ['agents', 'skills', 'workflows', 'rules'];
|
|
250
|
+
for (const comp of components) {
|
|
251
|
+
const compDir = path.join(agentDir, comp);
|
|
252
|
+
if (fs.existsSync(compDir)) {
|
|
253
|
+
const items = fs.readdirSync(compDir);
|
|
254
|
+
console.log(` ${colors.green}✔${colors.reset} ${comp}: ${items.length} items`);
|
|
255
|
+
} else {
|
|
256
|
+
console.log(` ${colors.yellow}○${colors.reset} ${comp}: not found`);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function updateCommand(options) {
|
|
262
|
+
log.title('🔄 Musa Agent Kit - Updating...');
|
|
263
|
+
|
|
264
|
+
// Re-run init with force
|
|
265
|
+
initCommand({ ...options, force: true });
|
|
266
|
+
|
|
267
|
+
log.success('Update complete!');
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// ============ NEW COMMANDS ============
|
|
271
|
+
|
|
272
|
+
function codexCommand(options) {
|
|
273
|
+
const targetDir = options.path || process.cwd();
|
|
274
|
+
const template = options.template || 'default';
|
|
275
|
+
|
|
276
|
+
log.title('📝 Musa Agent Kit - Generating AGENTS.md for Codex CLI');
|
|
277
|
+
|
|
278
|
+
const packageRoot = path.resolve(__dirname, '..');
|
|
279
|
+
const templatesDir = path.join(packageRoot, '.agent', 'templates');
|
|
280
|
+
|
|
281
|
+
// Determine template file
|
|
282
|
+
let templateFile;
|
|
283
|
+
switch (template) {
|
|
284
|
+
case 'web':
|
|
285
|
+
templateFile = 'AGENTS.web.md';
|
|
286
|
+
break;
|
|
287
|
+
case 'mobile':
|
|
288
|
+
templateFile = 'AGENTS.mobile.md';
|
|
289
|
+
break;
|
|
290
|
+
case 'backend':
|
|
291
|
+
templateFile = 'AGENTS.backend.md';
|
|
292
|
+
break;
|
|
293
|
+
default:
|
|
294
|
+
templateFile = 'AGENTS.md';
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const templatePath = path.join(templatesDir, templateFile);
|
|
298
|
+
const destPath = path.join(targetDir, 'AGENTS.md');
|
|
299
|
+
|
|
300
|
+
if (!fs.existsSync(templatePath)) {
|
|
301
|
+
log.error(`Template not found: ${templateFile}`);
|
|
302
|
+
log.info('Available templates: default, web, mobile, backend');
|
|
303
|
+
process.exit(1);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (fs.existsSync(destPath) && !options.force) {
|
|
307
|
+
log.warn('AGENTS.md already exists!');
|
|
308
|
+
log.info('Use --force to overwrite');
|
|
309
|
+
process.exit(1);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
fs.copyFileSync(templatePath, destPath);
|
|
313
|
+
|
|
314
|
+
log.success(`AGENTS.md created with "${template}" template!`);
|
|
315
|
+
log.info('Edit the file to customize for your project.');
|
|
316
|
+
console.log(`
|
|
317
|
+
${colors.bright}📄 File created:${colors.reset} ${destPath}
|
|
318
|
+
|
|
319
|
+
${colors.bright}🎯 Next steps:${colors.reset}
|
|
320
|
+
1. Edit AGENTS.md with your project details
|
|
321
|
+
2. Replace [PROJECT_NAME] placeholders
|
|
322
|
+
3. Update tech stack section
|
|
323
|
+
4. Codex CLI will now use this config!
|
|
324
|
+
`);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
function agentsCommand() {
|
|
328
|
+
const agentDir = path.join(process.cwd(), '.agent', 'agents');
|
|
329
|
+
|
|
330
|
+
log.title('🤖 Available Agents');
|
|
331
|
+
|
|
332
|
+
if (!fs.existsSync(agentDir)) {
|
|
333
|
+
log.warn('.agent/agents folder not found. Run "init" first.');
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const agents = fs.readdirSync(agentDir).filter(f => f.endsWith('.md'));
|
|
338
|
+
|
|
339
|
+
console.log(`${colors.bright}Found ${agents.length} agents:${colors.reset}\n`);
|
|
340
|
+
|
|
341
|
+
for (const agent of agents) {
|
|
342
|
+
const name = agent.replace('.md', '');
|
|
343
|
+
const content = fs.readFileSync(path.join(agentDir, agent), 'utf-8');
|
|
344
|
+
|
|
345
|
+
// Extract description from frontmatter
|
|
346
|
+
const descMatch = content.match(/description:\s*(.+)/);
|
|
347
|
+
const desc = descMatch ? descMatch[1].substring(0, 60) + '...' : 'No description';
|
|
348
|
+
|
|
349
|
+
console.log(` ${colors.cyan}@${name}${colors.reset}`);
|
|
350
|
+
console.log(` ${colors.yellow}${desc}${colors.reset}\n`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function skillsCommand() {
|
|
355
|
+
const skillsDir = path.join(process.cwd(), '.agent', 'skills');
|
|
356
|
+
|
|
357
|
+
log.title('🧠 Available Skills');
|
|
358
|
+
|
|
359
|
+
if (!fs.existsSync(skillsDir)) {
|
|
360
|
+
log.warn('.agent/skills folder not found. Run "init" first.');
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
const skills = fs.readdirSync(skillsDir, { withFileTypes: true })
|
|
365
|
+
.filter(d => d.isDirectory());
|
|
366
|
+
|
|
367
|
+
console.log(`${colors.bright}Found ${skills.length} skills:${colors.reset}\n`);
|
|
368
|
+
|
|
369
|
+
const categories = {
|
|
370
|
+
frontend: [],
|
|
371
|
+
backend: [],
|
|
372
|
+
security: [],
|
|
373
|
+
design: [],
|
|
374
|
+
debug: [],
|
|
375
|
+
other: []
|
|
376
|
+
};
|
|
377
|
+
|
|
378
|
+
for (const skill of skills) {
|
|
379
|
+
const skillPath = path.join(skillsDir, skill.name, 'SKILL.md');
|
|
380
|
+
if (fs.existsSync(skillPath)) {
|
|
381
|
+
const content = fs.readFileSync(skillPath, 'utf-8');
|
|
382
|
+
const descMatch = content.match(/description:\s*(.+)/);
|
|
383
|
+
const desc = descMatch ? descMatch[1].substring(0, 50) : '';
|
|
384
|
+
|
|
385
|
+
// Categorize
|
|
386
|
+
if (['react', 'next', 'tailwind', 'frontend'].some(k => skill.name.includes(k))) {
|
|
387
|
+
categories.frontend.push({ name: skill.name, desc });
|
|
388
|
+
} else if (['api', 'node', 'prisma', 'database', 'backend'].some(k => skill.name.includes(k))) {
|
|
389
|
+
categories.backend.push({ name: skill.name, desc });
|
|
390
|
+
} else if (['security', 'vulnerability', 'red-team'].some(k => skill.name.includes(k))) {
|
|
391
|
+
categories.security.push({ name: skill.name, desc });
|
|
392
|
+
} else if (['ui', 'design', 'mobile'].some(k => skill.name.includes(k))) {
|
|
393
|
+
categories.design.push({ name: skill.name, desc });
|
|
394
|
+
} else if (['debug', 'problem'].some(k => skill.name.includes(k))) {
|
|
395
|
+
categories.debug.push({ name: skill.name, desc });
|
|
396
|
+
} else {
|
|
397
|
+
categories.other.push({ name: skill.name, desc });
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
for (const [category, items] of Object.entries(categories)) {
|
|
403
|
+
if (items.length > 0) {
|
|
404
|
+
console.log(`${colors.bright}${category.toUpperCase()}${colors.reset} (${items.length})`);
|
|
405
|
+
for (const item of items) {
|
|
406
|
+
console.log(` ${colors.cyan}${item.name}${colors.reset}`);
|
|
407
|
+
}
|
|
408
|
+
console.log('');
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
function workflowsCommand() {
|
|
414
|
+
const workflowsDir = path.join(process.cwd(), '.agent', 'workflows');
|
|
415
|
+
|
|
416
|
+
log.title('⚡ Available Workflows (Slash Commands)');
|
|
417
|
+
|
|
418
|
+
if (!fs.existsSync(workflowsDir)) {
|
|
419
|
+
log.warn('.agent/workflows folder not found. Run "init" first.');
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const workflows = fs.readdirSync(workflowsDir).filter(f => f.endsWith('.md'));
|
|
424
|
+
|
|
425
|
+
console.log(`${colors.bright}Found ${workflows.length} workflows:${colors.reset}\n`);
|
|
426
|
+
|
|
427
|
+
for (const wf of workflows) {
|
|
428
|
+
const name = wf.replace('.md', '');
|
|
429
|
+
const content = fs.readFileSync(path.join(workflowsDir, wf), 'utf-8');
|
|
430
|
+
|
|
431
|
+
const descMatch = content.match(/description:\s*(.+)/);
|
|
432
|
+
const desc = descMatch ? descMatch[1] : 'No description';
|
|
433
|
+
|
|
434
|
+
console.log(` ${colors.green}/${name}${colors.reset}`);
|
|
435
|
+
console.log(` ${desc}\n`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
function doctorCommand() {
|
|
440
|
+
log.title('🩺 Agent Kit - Health Check');
|
|
441
|
+
|
|
442
|
+
const cwd = process.cwd();
|
|
443
|
+
const checks = [];
|
|
444
|
+
|
|
445
|
+
// Check 1: .agent folder
|
|
446
|
+
const agentDir = path.join(cwd, '.agent');
|
|
447
|
+
if (fs.existsSync(agentDir)) {
|
|
448
|
+
checks.push({ name: '.agent folder', status: '✅', message: 'Found' });
|
|
449
|
+
} else {
|
|
450
|
+
checks.push({ name: '.agent folder', status: '❌', message: 'Not found - run "init"' });
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
// Check 2: AGENTS.md
|
|
454
|
+
const agentsMd = path.join(cwd, 'AGENTS.md');
|
|
455
|
+
if (fs.existsSync(agentsMd)) {
|
|
456
|
+
checks.push({ name: 'AGENTS.md', status: '✅', message: 'Found (Codex CLI ready)' });
|
|
457
|
+
} else {
|
|
458
|
+
checks.push({ name: 'AGENTS.md', status: '⚠️', message: 'Not found - run "codex"' });
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Check 3: .codex folder
|
|
462
|
+
const codexDir = path.join(cwd, '.codex');
|
|
463
|
+
if (fs.existsSync(codexDir)) {
|
|
464
|
+
checks.push({ name: '.codex folder', status: '✅', message: 'Found' });
|
|
465
|
+
} else {
|
|
466
|
+
checks.push({ name: '.codex folder', status: '⚠️', message: 'Optional - not found' });
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
// Check 4: Agents count
|
|
470
|
+
if (fs.existsSync(path.join(agentDir, 'agents'))) {
|
|
471
|
+
const count = fs.readdirSync(path.join(agentDir, 'agents')).length;
|
|
472
|
+
checks.push({ name: 'Agents', status: '✅', message: `${count} available` });
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Check 5: Skills count
|
|
476
|
+
if (fs.existsSync(path.join(agentDir, 'skills'))) {
|
|
477
|
+
const count = fs.readdirSync(path.join(agentDir, 'skills')).length;
|
|
478
|
+
checks.push({ name: 'Skills', status: '✅', message: `${count} available` });
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Check 6: Workflows count
|
|
482
|
+
if (fs.existsSync(path.join(agentDir, 'workflows'))) {
|
|
483
|
+
const count = fs.readdirSync(path.join(agentDir, 'workflows')).length;
|
|
484
|
+
checks.push({ name: 'Workflows', status: '✅', message: `${count} available` });
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Check 7: Codex CLI global prompts
|
|
488
|
+
const codexPromptDir = path.join(os.homedir(), '.codex', 'prompts');
|
|
489
|
+
if (fs.existsSync(codexPromptDir)) {
|
|
490
|
+
const prompts = fs.readdirSync(codexPromptDir).filter(f => f.startsWith('kit-'));
|
|
491
|
+
if (prompts.length > 0) {
|
|
492
|
+
checks.push({ name: 'Codex slash commands', status: '✅', message: `${prompts.length} synced` });
|
|
493
|
+
} else {
|
|
494
|
+
checks.push({ name: 'Codex slash commands', status: '⚠️', message: 'Not synced - run "setup-codex"' });
|
|
495
|
+
}
|
|
496
|
+
} else {
|
|
497
|
+
checks.push({ name: 'Codex prompts dir', status: '⚠️', message: 'Not found' });
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Display results
|
|
501
|
+
console.log(`${colors.bright}Diagnostic Results:${colors.reset}\n`);
|
|
502
|
+
|
|
503
|
+
for (const check of checks) {
|
|
504
|
+
console.log(` ${check.status} ${colors.cyan}${check.name}${colors.reset}: ${check.message}`);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
const hasErrors = checks.some(c => c.status === '❌');
|
|
508
|
+
const hasWarnings = checks.some(c => c.status === '⚠️');
|
|
509
|
+
|
|
510
|
+
console.log('');
|
|
511
|
+
if (hasErrors) {
|
|
512
|
+
log.error('Some critical checks failed. Run suggested commands to fix.');
|
|
513
|
+
} else if (hasWarnings) {
|
|
514
|
+
log.warn('Some optional configurations missing. Consider running suggested commands.');
|
|
515
|
+
} else {
|
|
516
|
+
log.success('All checks passed! Agent Kit is ready.');
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// ============================================================================
|
|
521
|
+
// MCP Command
|
|
522
|
+
// ============================================================================
|
|
523
|
+
|
|
524
|
+
function mcpCommand(subArgs, options) {
|
|
525
|
+
const subCommand = subArgs[0];
|
|
526
|
+
const agentDir = path.join(process.cwd(), '.agent');
|
|
527
|
+
const mcpDir = path.join(agentDir, 'mcp');
|
|
528
|
+
const serversDir = path.join(mcpDir, 'servers');
|
|
529
|
+
|
|
530
|
+
if (!fs.existsSync(agentDir)) {
|
|
531
|
+
log.error('.agent folder not found. Run: npx @musashishao/agent-kit init');
|
|
532
|
+
process.exit(1);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
switch (subCommand) {
|
|
536
|
+
case 'setup':
|
|
537
|
+
mcpSetup(options);
|
|
538
|
+
break;
|
|
539
|
+
case 'list':
|
|
540
|
+
mcpList();
|
|
541
|
+
break;
|
|
542
|
+
case 'build':
|
|
543
|
+
mcpBuild();
|
|
544
|
+
break;
|
|
545
|
+
case 'status':
|
|
546
|
+
mcpStatus();
|
|
547
|
+
break;
|
|
548
|
+
case 'create':
|
|
549
|
+
mcpCreate(subArgs.slice(1), options);
|
|
550
|
+
break;
|
|
551
|
+
case 'templates':
|
|
552
|
+
mcpTemplates();
|
|
553
|
+
break;
|
|
554
|
+
case 'search':
|
|
555
|
+
mcpSearch(subArgs.slice(1));
|
|
556
|
+
break;
|
|
557
|
+
case 'install':
|
|
558
|
+
mcpInstall(subArgs.slice(1), options);
|
|
559
|
+
break;
|
|
560
|
+
case 'featured':
|
|
561
|
+
mcpFeatured();
|
|
562
|
+
break;
|
|
563
|
+
default:
|
|
564
|
+
console.log(`
|
|
565
|
+
${colors.bright}${colors.cyan}🔌 Agent Kit MCP${colors.reset}
|
|
566
|
+
|
|
567
|
+
${colors.bright}Subcommands:${colors.reset}
|
|
568
|
+
${colors.cyan}mcp setup${colors.reset} Configure MCP servers for your AI client
|
|
569
|
+
${colors.cyan}mcp list${colors.reset} List available MCP servers
|
|
570
|
+
${colors.cyan}mcp build${colors.reset} Build all MCP servers
|
|
571
|
+
${colors.cyan}mcp status${colors.reset} Check MCP server status
|
|
572
|
+
${colors.cyan}mcp create${colors.reset} Create new MCP server from template
|
|
573
|
+
${colors.cyan}mcp templates${colors.reset} List available templates
|
|
574
|
+
${colors.cyan}mcp search${colors.reset} Search MCP servers on npm
|
|
575
|
+
${colors.cyan}mcp install${colors.reset} Install MCP server from npm
|
|
576
|
+
${colors.cyan}mcp featured${colors.reset} Show featured MCP servers
|
|
577
|
+
|
|
578
|
+
${colors.bright}Options:${colors.reset}
|
|
579
|
+
--client <name> AI client: claude, cursor (for setup)
|
|
580
|
+
--type <template> Template type: api, database, web-scraper, custom
|
|
581
|
+
--force Overwrite existing
|
|
582
|
+
|
|
583
|
+
${colors.bright}Examples:${colors.reset}
|
|
584
|
+
npx @musashishao/agent-kit mcp setup --client claude
|
|
585
|
+
npx @musashishao/agent-kit mcp create my-api --type api
|
|
586
|
+
npx @musashishao/agent-kit mcp search github
|
|
587
|
+
npx @musashishao/agent-kit mcp install @anthropic/mcp-server-github
|
|
588
|
+
npx @musashishao/agent-kit mcp featured
|
|
589
|
+
`);
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
function mcpSetup(options) {
|
|
594
|
+
log.title('🔌 MCP Server Setup');
|
|
595
|
+
|
|
596
|
+
const agentDir = path.join(process.cwd(), '.agent');
|
|
597
|
+
const mcpDir = path.join(agentDir, 'mcp');
|
|
598
|
+
const serversDir = path.join(mcpDir, 'servers');
|
|
599
|
+
|
|
600
|
+
if (!fs.existsSync(serversDir)) {
|
|
601
|
+
log.error('MCP servers not found. Make sure Agent Kit is up to date.');
|
|
602
|
+
process.exit(1);
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
const clientIndex = process.argv.indexOf('--client');
|
|
606
|
+
const client = clientIndex !== -1 ? process.argv[clientIndex + 1] : 'claude';
|
|
607
|
+
|
|
608
|
+
const servers = fs.readdirSync(serversDir).filter(f =>
|
|
609
|
+
fs.statSync(path.join(serversDir, f)).isDirectory()
|
|
610
|
+
);
|
|
611
|
+
|
|
612
|
+
log.info(`Found ${servers.length} MCP servers`);
|
|
613
|
+
|
|
614
|
+
// Generate config based on client
|
|
615
|
+
const projectRoot = process.cwd();
|
|
616
|
+
|
|
617
|
+
if (client === 'claude') {
|
|
618
|
+
const claudeConfigPath = path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
619
|
+
|
|
620
|
+
let existingConfig = {};
|
|
621
|
+
if (fs.existsSync(claudeConfigPath)) {
|
|
622
|
+
try {
|
|
623
|
+
existingConfig = JSON.parse(fs.readFileSync(claudeConfigPath, 'utf-8'));
|
|
624
|
+
} catch {
|
|
625
|
+
existingConfig = {};
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
if (!existingConfig.mcpServers) {
|
|
630
|
+
existingConfig.mcpServers = {};
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// Add each server
|
|
634
|
+
for (const server of servers) {
|
|
635
|
+
const serverPath = path.join(serversDir, server, 'dist', 'index.js');
|
|
636
|
+
existingConfig.mcpServers[server] = {
|
|
637
|
+
command: 'node',
|
|
638
|
+
args: [serverPath],
|
|
639
|
+
cwd: projectRoot
|
|
640
|
+
};
|
|
641
|
+
log.success(`Added ${server} to Claude config`);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// Write config
|
|
645
|
+
const configDir = path.dirname(claudeConfigPath);
|
|
646
|
+
if (!fs.existsSync(configDir)) {
|
|
647
|
+
fs.mkdirSync(configDir, { recursive: true });
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
fs.writeFileSync(claudeConfigPath, JSON.stringify(existingConfig, null, 2));
|
|
651
|
+
log.success(`Claude Desktop config updated: ${claudeConfigPath}`);
|
|
652
|
+
|
|
653
|
+
console.log(`
|
|
654
|
+
${colors.yellow}⚠️ Important:${colors.reset}
|
|
655
|
+
1. Build MCP servers first: ${colors.cyan}npx @musashishao/agent-kit mcp build${colors.reset}
|
|
656
|
+
2. Restart Claude Desktop to apply changes
|
|
657
|
+
`);
|
|
658
|
+
|
|
659
|
+
} else if (client === 'cursor') {
|
|
660
|
+
const cursorDir = path.join(projectRoot, '.cursor');
|
|
661
|
+
const cursorConfigPath = path.join(cursorDir, 'mcp.json');
|
|
662
|
+
|
|
663
|
+
if (!fs.existsSync(cursorDir)) {
|
|
664
|
+
fs.mkdirSync(cursorDir, { recursive: true });
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
const config = { mcpServers: {} };
|
|
668
|
+
|
|
669
|
+
for (const server of servers) {
|
|
670
|
+
const serverPath = path.join(serversDir, server, 'dist', 'index.js');
|
|
671
|
+
config.mcpServers[server] = {
|
|
672
|
+
command: 'node',
|
|
673
|
+
args: [serverPath]
|
|
674
|
+
};
|
|
675
|
+
log.success(`Added ${server}`);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
fs.writeFileSync(cursorConfigPath, JSON.stringify(config, null, 2));
|
|
679
|
+
log.success(`Cursor config created: ${cursorConfigPath}`);
|
|
680
|
+
|
|
681
|
+
} else {
|
|
682
|
+
log.error(`Unknown client: ${client}. Use 'claude' or 'cursor'`);
|
|
683
|
+
process.exit(1);
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
function mcpList() {
|
|
688
|
+
log.title('🔌 Available MCP Servers');
|
|
689
|
+
|
|
690
|
+
const serversDir = path.join(process.cwd(), '.agent', 'mcp', 'servers');
|
|
691
|
+
|
|
692
|
+
if (!fs.existsSync(serversDir)) {
|
|
693
|
+
log.warn('No MCP servers found');
|
|
694
|
+
return;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
const servers = fs.readdirSync(serversDir).filter(f =>
|
|
698
|
+
fs.statSync(path.join(serversDir, f)).isDirectory()
|
|
699
|
+
);
|
|
700
|
+
|
|
701
|
+
console.log(`Found ${servers.length} servers:\n`);
|
|
702
|
+
|
|
703
|
+
for (const server of servers) {
|
|
704
|
+
const packagePath = path.join(serversDir, server, 'package.json');
|
|
705
|
+
let description = 'No description';
|
|
706
|
+
|
|
707
|
+
if (fs.existsSync(packagePath)) {
|
|
708
|
+
try {
|
|
709
|
+
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf-8'));
|
|
710
|
+
description = pkg.description || description;
|
|
711
|
+
} catch {}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const distExists = fs.existsSync(path.join(serversDir, server, 'dist'));
|
|
715
|
+
const status = distExists ? `${colors.green}✓ Built${colors.reset}` : `${colors.yellow}○ Not built${colors.reset}`;
|
|
716
|
+
|
|
717
|
+
console.log(` ${colors.cyan}${server}${colors.reset} ${status}`);
|
|
718
|
+
console.log(` ${description}\n`);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
function mcpBuild() {
|
|
723
|
+
log.title('🔨 Building MCP Servers');
|
|
724
|
+
|
|
725
|
+
const serversDir = path.join(process.cwd(), '.agent', 'mcp', 'servers');
|
|
726
|
+
|
|
727
|
+
if (!fs.existsSync(serversDir)) {
|
|
728
|
+
log.error('No MCP servers found');
|
|
729
|
+
process.exit(1);
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
const servers = fs.readdirSync(serversDir).filter(f =>
|
|
733
|
+
fs.statSync(path.join(serversDir, f)).isDirectory()
|
|
734
|
+
);
|
|
735
|
+
|
|
736
|
+
let successCount = 0;
|
|
737
|
+
|
|
738
|
+
for (const server of servers) {
|
|
739
|
+
const serverPath = path.join(serversDir, server);
|
|
740
|
+
const packagePath = path.join(serverPath, 'package.json');
|
|
741
|
+
|
|
742
|
+
if (!fs.existsSync(packagePath)) {
|
|
743
|
+
log.warn(`Skipping ${server}: no package.json`);
|
|
744
|
+
continue;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
log.info(`Building ${server}...`);
|
|
748
|
+
|
|
749
|
+
try {
|
|
750
|
+
// Install dependencies
|
|
751
|
+
execSync('npm install', {
|
|
752
|
+
cwd: serverPath,
|
|
753
|
+
stdio: 'pipe',
|
|
754
|
+
timeout: 120000
|
|
755
|
+
});
|
|
756
|
+
|
|
757
|
+
// Build
|
|
758
|
+
execSync('npm run build', {
|
|
759
|
+
cwd: serverPath,
|
|
760
|
+
stdio: 'pipe',
|
|
761
|
+
timeout: 60000
|
|
762
|
+
});
|
|
763
|
+
|
|
764
|
+
log.success(`Built ${server}`);
|
|
765
|
+
successCount++;
|
|
766
|
+
} catch (error) {
|
|
767
|
+
log.error(`Failed to build ${server}: ${error.message}`);
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
console.log('');
|
|
772
|
+
if (successCount === servers.length) {
|
|
773
|
+
log.success(`All ${successCount} servers built successfully!`);
|
|
774
|
+
console.log(`\n${colors.bright}Next:${colors.reset} Run ${colors.cyan}npx @musashishao/agent-kit mcp setup --client claude${colors.reset}`);
|
|
775
|
+
} else {
|
|
776
|
+
log.warn(`Built ${successCount}/${servers.length} servers`);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
function mcpStatus() {
|
|
781
|
+
log.title('🔌 MCP Status');
|
|
782
|
+
|
|
783
|
+
const serversDir = path.join(process.cwd(), '.agent', 'mcp', 'servers');
|
|
784
|
+
|
|
785
|
+
if (!fs.existsSync(serversDir)) {
|
|
786
|
+
log.warn('MCP not configured');
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
const servers = fs.readdirSync(serversDir).filter(f =>
|
|
791
|
+
fs.statSync(path.join(serversDir, f)).isDirectory()
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
console.log(`\n${colors.bright}Servers:${colors.reset}`);
|
|
795
|
+
for (const server of servers) {
|
|
796
|
+
const distExists = fs.existsSync(path.join(serversDir, server, 'dist'));
|
|
797
|
+
const status = distExists ? `${colors.green}✓${colors.reset}` : `${colors.red}✗${colors.reset}`;
|
|
798
|
+
console.log(` ${status} ${server}`);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
// Check Claude config
|
|
802
|
+
const claudeConfigPath = path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
|
|
803
|
+
const claudeConfigured = fs.existsSync(claudeConfigPath);
|
|
804
|
+
|
|
805
|
+
// Check Cursor config
|
|
806
|
+
const cursorConfigPath = path.join(process.cwd(), '.cursor', 'mcp.json');
|
|
807
|
+
const cursorConfigured = fs.existsSync(cursorConfigPath);
|
|
808
|
+
|
|
809
|
+
console.log(`\n${colors.bright}Clients:${colors.reset}`);
|
|
810
|
+
console.log(` ${claudeConfigured ? `${colors.green}✓${colors.reset}` : `${colors.yellow}○${colors.reset}`} Claude Desktop`);
|
|
811
|
+
console.log(` ${cursorConfigured ? `${colors.green}✓${colors.reset}` : `${colors.yellow}○${colors.reset}`} Cursor`);
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
// ============================================================================
|
|
815
|
+
// MCP Create Command
|
|
816
|
+
// ============================================================================
|
|
817
|
+
|
|
818
|
+
function mcpCreate(createArgs, options) {
|
|
819
|
+
const serverName = createArgs[0];
|
|
820
|
+
|
|
821
|
+
if (!serverName) {
|
|
822
|
+
log.error('Please provide a server name: mcp create <name> --type <template>');
|
|
823
|
+
process.exit(1);
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Get template type
|
|
827
|
+
const typeIndex = process.argv.indexOf('--type');
|
|
828
|
+
const templateType = typeIndex !== -1 ? process.argv[typeIndex + 1] : 'custom';
|
|
829
|
+
|
|
830
|
+
const validTemplates = ['api', 'database', 'web-scraper', 'custom'];
|
|
831
|
+
if (!validTemplates.includes(templateType)) {
|
|
832
|
+
log.error(`Invalid template type: ${templateType}`);
|
|
833
|
+
log.info(`Valid types: ${validTemplates.join(', ')}`);
|
|
834
|
+
process.exit(1);
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
log.title(`🔌 Creating MCP Server: ${serverName}`);
|
|
838
|
+
log.info(`Template: ${templateType}`);
|
|
839
|
+
|
|
840
|
+
const agentDir = path.join(process.cwd(), '.agent');
|
|
841
|
+
const mcpDir = path.join(agentDir, 'mcp');
|
|
842
|
+
const templatesDir = path.join(mcpDir, 'templates');
|
|
843
|
+
const serversDir = path.join(mcpDir, 'servers');
|
|
844
|
+
const targetDir = path.join(serversDir, serverName);
|
|
845
|
+
|
|
846
|
+
// Check if server already exists
|
|
847
|
+
if (fs.existsSync(targetDir)) {
|
|
848
|
+
if (!options.force) {
|
|
849
|
+
log.error(`Server '${serverName}' already exists. Use --force to overwrite.`);
|
|
850
|
+
process.exit(1);
|
|
851
|
+
}
|
|
852
|
+
fs.rmSync(targetDir, { recursive: true, force: true });
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
// Create target directory
|
|
856
|
+
fs.mkdirSync(path.join(targetDir, 'src'), { recursive: true });
|
|
857
|
+
|
|
858
|
+
// Copy and process template files
|
|
859
|
+
const templateDir = path.join(templatesDir, templateType);
|
|
860
|
+
const basePackage = path.join(templatesDir, 'base-package.json.template');
|
|
861
|
+
const baseTsconfig = path.join(templatesDir, 'base-tsconfig.json');
|
|
862
|
+
|
|
863
|
+
// Process package.json
|
|
864
|
+
if (fs.existsSync(basePackage)) {
|
|
865
|
+
let packageContent = fs.readFileSync(basePackage, 'utf-8');
|
|
866
|
+
packageContent = packageContent
|
|
867
|
+
.replace(/\{\{SERVER_NAME\}\}/g, serverName)
|
|
868
|
+
.replace(/\{\{DESCRIPTION\}\}/g, `${templateType} integration`);
|
|
869
|
+
|
|
870
|
+
// Add extra dependencies based on template
|
|
871
|
+
const pkg = JSON.parse(packageContent);
|
|
872
|
+
if (templateType === 'database') {
|
|
873
|
+
pkg.dependencies['better-sqlite3'] = '^11.0.0';
|
|
874
|
+
pkg.devDependencies['@types/better-sqlite3'] = '^7.6.0';
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
fs.writeFileSync(path.join(targetDir, 'package.json'), JSON.stringify(pkg, null, 2));
|
|
878
|
+
log.success('Created package.json');
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// Copy tsconfig
|
|
882
|
+
if (fs.existsSync(baseTsconfig)) {
|
|
883
|
+
fs.copyFileSync(baseTsconfig, path.join(targetDir, 'tsconfig.json'));
|
|
884
|
+
log.success('Created tsconfig.json');
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// Process main template file
|
|
888
|
+
const templateSrc = path.join(templateDir, 'src', 'index.ts.template');
|
|
889
|
+
if (fs.existsSync(templateSrc)) {
|
|
890
|
+
let srcContent = fs.readFileSync(templateSrc, 'utf-8');
|
|
891
|
+
srcContent = srcContent.replace(/\{\{SERVER_NAME\}\}/g, serverName);
|
|
892
|
+
fs.writeFileSync(path.join(targetDir, 'src', 'index.ts'), srcContent);
|
|
893
|
+
log.success('Created src/index.ts');
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// Copy README if exists
|
|
897
|
+
const templateReadme = path.join(templateDir, 'README.md.template');
|
|
898
|
+
if (fs.existsSync(templateReadme)) {
|
|
899
|
+
let readmeContent = fs.readFileSync(templateReadme, 'utf-8');
|
|
900
|
+
readmeContent = readmeContent.replace(/\{\{SERVER_NAME\}\}/g, serverName);
|
|
901
|
+
fs.writeFileSync(path.join(targetDir, 'README.md'), readmeContent);
|
|
902
|
+
log.success('Created README.md');
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
console.log(`
|
|
906
|
+
${colors.bright}${colors.green}✔ MCP Server created successfully!${colors.reset}
|
|
907
|
+
|
|
908
|
+
${colors.bright}Location:${colors.reset} ${targetDir}
|
|
909
|
+
|
|
910
|
+
${colors.bright}Next steps:${colors.reset}
|
|
911
|
+
1. ${colors.cyan}cd ${targetDir}${colors.reset}
|
|
912
|
+
2. ${colors.cyan}npm install${colors.reset}
|
|
913
|
+
3. Edit ${colors.cyan}src/index.ts${colors.reset} to customize your server
|
|
914
|
+
4. ${colors.cyan}npm run build${colors.reset}
|
|
915
|
+
5. ${colors.cyan}npx @musashishao/agent-kit mcp setup --client claude${colors.reset}
|
|
916
|
+
`);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
function mcpTemplates() {
|
|
920
|
+
log.title('🔌 Available MCP Templates');
|
|
921
|
+
|
|
922
|
+
const templates = [
|
|
923
|
+
{
|
|
924
|
+
name: 'api',
|
|
925
|
+
description: 'REST API integration',
|
|
926
|
+
tools: ['api_get', 'api_post', 'api_list_endpoints'],
|
|
927
|
+
useCase: 'Connect to external REST APIs',
|
|
928
|
+
},
|
|
929
|
+
{
|
|
930
|
+
name: 'database',
|
|
931
|
+
description: 'SQLite database connector',
|
|
932
|
+
tools: ['db_query', 'db_schema', 'db_tables', 'db_describe'],
|
|
933
|
+
useCase: 'Query and analyze databases',
|
|
934
|
+
},
|
|
935
|
+
{
|
|
936
|
+
name: 'web-scraper',
|
|
937
|
+
description: 'Web page scraper',
|
|
938
|
+
tools: ['scrape_url', 'extract_links', 'extract_metadata'],
|
|
939
|
+
useCase: 'Extract data from websites',
|
|
940
|
+
},
|
|
941
|
+
{
|
|
942
|
+
name: 'custom',
|
|
943
|
+
description: 'Minimal template',
|
|
944
|
+
tools: ['hello', 'calculate'],
|
|
945
|
+
useCase: 'Build from scratch',
|
|
946
|
+
},
|
|
947
|
+
];
|
|
948
|
+
|
|
949
|
+
for (const t of templates) {
|
|
950
|
+
console.log(`
|
|
951
|
+
${colors.cyan}${colors.bright}${t.name}${colors.reset}
|
|
952
|
+
${t.description}
|
|
953
|
+
${colors.yellow}Tools:${colors.reset} ${t.tools.join(', ')}
|
|
954
|
+
${colors.yellow}Use case:${colors.reset} ${t.useCase}`);
|
|
955
|
+
}
|
|
956
|
+
|
|
957
|
+
console.log(`
|
|
958
|
+
|
|
959
|
+
${colors.bright}Usage:${colors.reset}
|
|
960
|
+
npx @musashishao/agent-kit mcp create <server-name> --type <template>
|
|
961
|
+
|
|
962
|
+
${colors.bright}Example:${colors.reset}
|
|
963
|
+
npx @musashishao/agent-kit mcp create github-api --type api
|
|
964
|
+
`);
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// ============================================================================
|
|
968
|
+
// MCP Registry Commands
|
|
969
|
+
// ============================================================================
|
|
970
|
+
|
|
971
|
+
async function mcpSearch(searchArgs) {
|
|
972
|
+
const query = searchArgs.join(' ');
|
|
973
|
+
|
|
974
|
+
if (!query) {
|
|
975
|
+
log.error('Please provide a search query: mcp search <query>');
|
|
976
|
+
process.exit(1);
|
|
977
|
+
}
|
|
978
|
+
|
|
979
|
+
log.title(`🔍 Searching MCP servers: "${query}"`);
|
|
980
|
+
|
|
981
|
+
try {
|
|
982
|
+
// Search npm registry
|
|
983
|
+
const https = require('https');
|
|
984
|
+
|
|
985
|
+
const searchUrl = `https://registry.npmjs.org/-/v1/search?text=mcp+${encodeURIComponent(query)}&size=15`;
|
|
986
|
+
|
|
987
|
+
const data = await new Promise((resolve, reject) => {
|
|
988
|
+
https.get(searchUrl, (res) => {
|
|
989
|
+
let body = '';
|
|
990
|
+
res.on('data', chunk => body += chunk);
|
|
991
|
+
res.on('end', () => {
|
|
992
|
+
try {
|
|
993
|
+
resolve(JSON.parse(body));
|
|
994
|
+
} catch (e) {
|
|
995
|
+
reject(new Error('Failed to parse response'));
|
|
996
|
+
}
|
|
997
|
+
});
|
|
998
|
+
}).on('error', reject);
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
if (!data.objects || data.objects.length === 0) {
|
|
1002
|
+
log.warn('No MCP servers found matching your query');
|
|
1003
|
+
return;
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
console.log(`\nFound ${data.objects.length} packages:\n`);
|
|
1007
|
+
|
|
1008
|
+
for (const pkg of data.objects) {
|
|
1009
|
+
const name = pkg.package.name;
|
|
1010
|
+
const desc = pkg.package.description || 'No description';
|
|
1011
|
+
const version = pkg.package.version;
|
|
1012
|
+
|
|
1013
|
+
console.log(` ${colors.cyan}${name}${colors.reset} ${colors.yellow}v${version}${colors.reset}`);
|
|
1014
|
+
console.log(` ${desc.slice(0, 80)}${desc.length > 80 ? '...' : ''}\n`);
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
console.log(`${colors.bright}Install with:${colors.reset}`);
|
|
1018
|
+
console.log(` npx @musashishao/agent-kit mcp install <package-name>\n`);
|
|
1019
|
+
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
log.error(`Search failed: ${error.message}`);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
async function mcpInstall(installArgs, options) {
|
|
1026
|
+
const packageName = installArgs[0];
|
|
1027
|
+
|
|
1028
|
+
if (!packageName) {
|
|
1029
|
+
log.error('Please provide a package name: mcp install <package>');
|
|
1030
|
+
process.exit(1);
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
log.title(`📦 Installing MCP Server: ${packageName}`);
|
|
1034
|
+
|
|
1035
|
+
const agentDir = path.join(process.cwd(), '.agent');
|
|
1036
|
+
const mcpDir = path.join(agentDir, 'mcp');
|
|
1037
|
+
const externalDir = path.join(mcpDir, 'external');
|
|
1038
|
+
|
|
1039
|
+
// Create external directory if needed
|
|
1040
|
+
if (!fs.existsSync(externalDir)) {
|
|
1041
|
+
fs.mkdirSync(externalDir, { recursive: true });
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
try {
|
|
1045
|
+
// Install package globally or in external dir
|
|
1046
|
+
log.info(`Installing ${packageName}...`);
|
|
1047
|
+
|
|
1048
|
+
execSync(`npm install ${packageName}`, {
|
|
1049
|
+
cwd: externalDir,
|
|
1050
|
+
stdio: 'pipe',
|
|
1051
|
+
timeout: 120000
|
|
1052
|
+
});
|
|
1053
|
+
|
|
1054
|
+
log.success(`Installed ${packageName}`);
|
|
1055
|
+
|
|
1056
|
+
// Try to find the package and get its binary
|
|
1057
|
+
const packagePath = path.join(externalDir, 'node_modules', packageName);
|
|
1058
|
+
let binPath = null;
|
|
1059
|
+
|
|
1060
|
+
if (fs.existsSync(path.join(packagePath, 'package.json'))) {
|
|
1061
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(packagePath, 'package.json'), 'utf-8'));
|
|
1062
|
+
|
|
1063
|
+
if (pkg.bin) {
|
|
1064
|
+
const binName = typeof pkg.bin === 'string' ? packageName : Object.keys(pkg.bin)[0];
|
|
1065
|
+
const binFile = typeof pkg.bin === 'string' ? pkg.bin : pkg.bin[binName];
|
|
1066
|
+
binPath = path.join(packagePath, binFile);
|
|
1067
|
+
} else if (pkg.main) {
|
|
1068
|
+
binPath = path.join(packagePath, pkg.main);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1072
|
+
// Save to installed registry
|
|
1073
|
+
const registryPath = path.join(mcpDir, 'config', 'registry.json');
|
|
1074
|
+
let registry = { installed: [] };
|
|
1075
|
+
|
|
1076
|
+
if (fs.existsSync(registryPath)) {
|
|
1077
|
+
try {
|
|
1078
|
+
registry = JSON.parse(fs.readFileSync(registryPath, 'utf-8'));
|
|
1079
|
+
} catch {}
|
|
1080
|
+
}
|
|
1081
|
+
|
|
1082
|
+
if (!registry.installed) registry.installed = [];
|
|
1083
|
+
|
|
1084
|
+
// Add to installed list
|
|
1085
|
+
const existing = registry.installed.findIndex(i => i.name === packageName);
|
|
1086
|
+
const installInfo = {
|
|
1087
|
+
name: packageName,
|
|
1088
|
+
path: binPath || packagePath,
|
|
1089
|
+
installedAt: new Date().toISOString()
|
|
1090
|
+
};
|
|
1091
|
+
|
|
1092
|
+
if (existing >= 0) {
|
|
1093
|
+
registry.installed[existing] = installInfo;
|
|
1094
|
+
} else {
|
|
1095
|
+
registry.installed.push(installInfo);
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
fs.writeFileSync(registryPath, JSON.stringify(registry, null, 2));
|
|
1099
|
+
|
|
1100
|
+
console.log(`
|
|
1101
|
+
${colors.bright}${colors.green}✔ Installation complete!${colors.reset}
|
|
1102
|
+
|
|
1103
|
+
${colors.bright}Package:${colors.reset} ${packageName}
|
|
1104
|
+
${colors.bright}Location:${colors.reset} ${externalDir}/node_modules/${packageName}
|
|
1105
|
+
|
|
1106
|
+
${colors.bright}Next steps:${colors.reset}
|
|
1107
|
+
1. Run ${colors.cyan}npx @musashishao/agent-kit mcp setup --client claude${colors.reset}
|
|
1108
|
+
2. Restart Claude Desktop
|
|
1109
|
+
`);
|
|
1110
|
+
|
|
1111
|
+
} catch (error) {
|
|
1112
|
+
log.error(`Installation failed: ${error.message}`);
|
|
1113
|
+
process.exit(1);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
|
|
1117
|
+
function mcpFeatured() {
|
|
1118
|
+
log.title('⭐ Featured MCP Servers');
|
|
1119
|
+
|
|
1120
|
+
const featured = [
|
|
1121
|
+
{
|
|
1122
|
+
name: '@anthropic/mcp-server-filesystem',
|
|
1123
|
+
description: 'Secure file system access for AI',
|
|
1124
|
+
category: 'File Systems',
|
|
1125
|
+
official: true
|
|
1126
|
+
},
|
|
1127
|
+
{
|
|
1128
|
+
name: '@anthropic/mcp-server-sqlite',
|
|
1129
|
+
description: 'SQLite database integration',
|
|
1130
|
+
category: 'Databases',
|
|
1131
|
+
official: true
|
|
1132
|
+
},
|
|
1133
|
+
{
|
|
1134
|
+
name: '@anthropic/mcp-server-github',
|
|
1135
|
+
description: 'GitHub API - repos, issues, PRs',
|
|
1136
|
+
category: 'Developer Tools',
|
|
1137
|
+
official: true
|
|
1138
|
+
},
|
|
1139
|
+
{
|
|
1140
|
+
name: '@anthropic/mcp-server-memory',
|
|
1141
|
+
description: 'Persistent memory/knowledge graph',
|
|
1142
|
+
category: 'Knowledge',
|
|
1143
|
+
official: true
|
|
1144
|
+
},
|
|
1145
|
+
{
|
|
1146
|
+
name: 'playwright-mcp',
|
|
1147
|
+
description: 'Browser automation with Playwright',
|
|
1148
|
+
category: 'Browser Automation',
|
|
1149
|
+
official: false
|
|
1150
|
+
},
|
|
1151
|
+
{
|
|
1152
|
+
name: 'mcp-server-fetch',
|
|
1153
|
+
description: 'HTTP requests and web fetching',
|
|
1154
|
+
category: 'Web',
|
|
1155
|
+
official: false
|
|
1156
|
+
},
|
|
1157
|
+
{
|
|
1158
|
+
name: '@anthropic/mcp-server-postgres',
|
|
1159
|
+
description: 'PostgreSQL database integration',
|
|
1160
|
+
category: 'Databases',
|
|
1161
|
+
official: true
|
|
1162
|
+
},
|
|
1163
|
+
{
|
|
1164
|
+
name: 'mcp-server-slack',
|
|
1165
|
+
description: 'Slack workspace integration',
|
|
1166
|
+
category: 'Communication',
|
|
1167
|
+
official: false
|
|
1168
|
+
}
|
|
1169
|
+
];
|
|
1170
|
+
|
|
1171
|
+
console.log('\n');
|
|
1172
|
+
|
|
1173
|
+
for (const server of featured) {
|
|
1174
|
+
const badge = server.official ? `${colors.green}[Official]${colors.reset}` : '';
|
|
1175
|
+
console.log(` ${colors.cyan}${colors.bright}${server.name}${colors.reset} ${badge}`);
|
|
1176
|
+
console.log(` ${server.description}`);
|
|
1177
|
+
console.log(` ${colors.yellow}Category:${colors.reset} ${server.category}\n`);
|
|
1178
|
+
}
|
|
1179
|
+
|
|
1180
|
+
console.log(`
|
|
1181
|
+
${colors.bright}Install with:${colors.reset}
|
|
1182
|
+
npx @musashishao/agent-kit mcp install <package-name>
|
|
1183
|
+
|
|
1184
|
+
${colors.bright}Example:${colors.reset}
|
|
1185
|
+
npx @musashishao/agent-kit mcp install @anthropic/mcp-server-github
|
|
1186
|
+
|
|
1187
|
+
${colors.bright}More servers:${colors.reset}
|
|
1188
|
+
https://github.com/punkpeye/awesome-mcp-servers
|
|
1189
|
+
`);
|
|
1190
|
+
}
|
|
1191
|
+
|
|
1192
|
+
// Parse arguments
|
|
1193
|
+
const args = process.argv.slice(2);
|
|
1194
|
+
const command = args[0];
|
|
1195
|
+
|
|
1196
|
+
const options = {
|
|
1197
|
+
force: args.includes('--force'),
|
|
1198
|
+
quiet: args.includes('--quiet'),
|
|
1199
|
+
path: null,
|
|
1200
|
+
prefix: null,
|
|
1201
|
+
template: null
|
|
1202
|
+
};
|
|
1203
|
+
|
|
1204
|
+
// Parse --path
|
|
1205
|
+
const pathIndex = args.indexOf('--path');
|
|
1206
|
+
if (pathIndex !== -1 && args[pathIndex + 1]) {
|
|
1207
|
+
options.path = path.resolve(args[pathIndex + 1]);
|
|
1208
|
+
}
|
|
1209
|
+
|
|
1210
|
+
// Parse --prefix
|
|
1211
|
+
const prefixIndex = args.indexOf('--prefix');
|
|
1212
|
+
if (prefixIndex !== -1 && args[prefixIndex + 1]) {
|
|
1213
|
+
options.prefix = args[prefixIndex + 1];
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
// Parse --template
|
|
1217
|
+
const templateIndex = args.indexOf('--template');
|
|
1218
|
+
if (templateIndex !== -1 && args[templateIndex + 1]) {
|
|
1219
|
+
options.template = args[templateIndex + 1];
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
// Execute command
|
|
1223
|
+
switch (command) {
|
|
1224
|
+
case 'init':
|
|
1225
|
+
initCommand(options);
|
|
1226
|
+
break;
|
|
1227
|
+
case 'setup-codex':
|
|
1228
|
+
setupCodexCommand(options);
|
|
1229
|
+
break;
|
|
1230
|
+
case 'codex':
|
|
1231
|
+
codexCommand(options);
|
|
1232
|
+
break;
|
|
1233
|
+
case 'mcp':
|
|
1234
|
+
mcpCommand(args.slice(1), options);
|
|
1235
|
+
break;
|
|
1236
|
+
case 'agents':
|
|
1237
|
+
agentsCommand();
|
|
1238
|
+
break;
|
|
1239
|
+
case 'skills':
|
|
1240
|
+
skillsCommand();
|
|
1241
|
+
break;
|
|
1242
|
+
case 'workflows':
|
|
1243
|
+
workflowsCommand();
|
|
1244
|
+
break;
|
|
1245
|
+
case 'doctor':
|
|
1246
|
+
doctorCommand();
|
|
1247
|
+
break;
|
|
1248
|
+
case 'update':
|
|
1249
|
+
updateCommand(options);
|
|
1250
|
+
break;
|
|
1251
|
+
case 'status':
|
|
1252
|
+
statusCommand();
|
|
1253
|
+
break;
|
|
1254
|
+
case '--version':
|
|
1255
|
+
case '-v':
|
|
1256
|
+
showVersion();
|
|
1257
|
+
break;
|
|
1258
|
+
case '--help':
|
|
1259
|
+
case '-h':
|
|
1260
|
+
case undefined:
|
|
1261
|
+
showHelp();
|
|
1262
|
+
break;
|
|
1263
|
+
default:
|
|
1264
|
+
log.error(`Unknown command: ${command}`);
|
|
1265
|
+
showHelp();
|
|
1266
|
+
process.exit(1);
|
|
1267
|
+
}
|