fraim-framework 2.0.36 → 2.0.38
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/bin/fraim.js +5 -52
- package/dist/registry/scripts/build-scripts-generator.js +205 -0
- package/dist/registry/scripts/fraim-config.js +61 -0
- package/dist/registry/scripts/generic-issues-api.js +100 -0
- package/dist/registry/scripts/openapi-generator.js +664 -0
- package/dist/registry/scripts/performance/profile-server.js +390 -0
- package/dist/scripts/build-stub-registry.js +108 -0
- package/dist/src/cli/commands/doctor.js +5 -5
- package/dist/src/cli/commands/init-project.js +74 -0
- package/dist/src/cli/commands/setup.js +176 -0
- package/dist/src/cli/commands/sync.js +33 -19
- package/dist/src/cli/commands/test-mcp.js +135 -0
- package/dist/src/cli/fraim.js +6 -0
- package/dist/src/cli/setup/auto-mcp-setup.js +367 -0
- package/dist/src/cli/setup/ide-detector.js +163 -0
- package/dist/src/cli/setup/mcp-config-generator.js +115 -0
- package/dist/src/cli/setup/token-validator.js +49 -0
- package/dist/test-utils.js +96 -0
- package/dist/tests/debug-tools.js +2 -2
- package/dist/tests/esm-compat.js +11 -0
- package/dist/tests/shared-server-utils.js +57 -0
- package/dist/tests/test-chalk-esm-issue.js +159 -0
- package/dist/tests/test-chalk-real-world.js +265 -0
- package/dist/tests/test-chalk-regression.js +2 -18
- package/dist/tests/test-chalk-resolution-issue.js +304 -0
- package/dist/tests/test-client-scripts-validation.js +27 -5
- package/dist/tests/test-complete-setup-flow.js +110 -0
- package/dist/tests/test-fraim-install-chalk-issue.js +254 -0
- package/dist/tests/test-ide-detector.js +46 -0
- package/dist/tests/test-improved-setup.js +121 -0
- package/dist/tests/test-mcp-config-generator.js +70 -0
- package/dist/tests/test-mcp-connection.js +58 -117
- package/dist/tests/test-mcp-issue-integration.js +2 -2
- package/dist/tests/test-mcp-lifecycle-methods.js +34 -100
- package/dist/tests/test-mcp-shared-server.js +308 -0
- package/dist/tests/test-npm-resolution-diagnostic.js +140 -0
- package/dist/tests/test-package-size.js +101 -0
- package/dist/tests/test-prep-issue.js +34 -1
- package/dist/tests/test-script-location-independence.js +39 -62
- package/dist/tests/test-server-utils.js +32 -0
- package/dist/tests/test-session-rehydration.js +2 -2
- package/dist/tests/test-setup-integration.js +98 -0
- package/dist/tests/test-standalone.js +2 -2
- package/dist/tests/test-stub-registry.js +136 -0
- package/dist/tests/test-sync-stubs.js +143 -0
- package/dist/tests/test-telemetry.js +2 -2
- package/dist/tests/test-token-validator.js +30 -0
- package/dist/tests/test-user-journey.js +2 -1
- package/package.json +7 -9
- package/registry/agent-guardrails.md +62 -62
- package/registry/scripts/code-quality-check.sh +559 -559
- package/registry/scripts/detect-tautological-tests.sh +38 -38
- package/registry/scripts/prep-issue.sh +61 -30
- package/registry/scripts/validate-openapi-limits.ts +366 -366
- package/registry/scripts/validate-test-coverage.ts +280 -280
- package/registry/scripts/verify-pr-comments.sh +70 -70
- package/registry/stubs/workflows/bootstrap/create-architecture.md +11 -0
- package/registry/stubs/workflows/bootstrap/detect-broken-windows.md +11 -0
- package/registry/stubs/workflows/bootstrap/evaluate-code-quality.md +11 -0
- package/registry/stubs/workflows/bootstrap/verify-test-coverage.md +11 -0
- package/registry/stubs/workflows/business-development/create-business-plan.md +11 -0
- package/registry/stubs/workflows/business-development/ideate-business-opportunity.md +11 -0
- package/registry/stubs/workflows/business-development/price-product.md +18 -0
- package/registry/stubs/workflows/convert-to-pdf.md +11 -0
- package/registry/stubs/workflows/customer-development/insight-analysis.md +11 -0
- package/registry/stubs/workflows/customer-development/insight-triage.md +11 -0
- package/registry/stubs/workflows/customer-development/interview-preparation.md +11 -0
- package/registry/stubs/workflows/customer-development/linkedin-outreach.md +11 -0
- package/registry/stubs/workflows/customer-development/strategic-brainstorming.md +11 -0
- package/registry/stubs/workflows/customer-development/thank-customers.md +11 -0
- package/registry/stubs/workflows/customer-development/weekly-newsletter.md +11 -0
- package/registry/stubs/workflows/deploy/cloud-deployment.md +11 -0
- package/registry/stubs/workflows/improve-fraim/contribute.md +11 -0
- package/registry/stubs/workflows/improve-fraim/file-issue.md +11 -0
- package/registry/stubs/workflows/marketing/content-creation.md +11 -0
- package/registry/stubs/workflows/marketing/hbr-article.md +11 -0
- package/registry/stubs/workflows/marketing/launch-checklist.md +11 -0
- package/registry/stubs/workflows/marketing/marketing-strategy.md +11 -0
- package/registry/stubs/workflows/marketing/storytelling.md +11 -0
- package/registry/stubs/workflows/performance/analyze-performance.md +11 -0
- package/registry/stubs/workflows/product-building/design.md +11 -0
- package/registry/stubs/workflows/product-building/implement.md +12 -0
- package/registry/stubs/workflows/product-building/iterate-on-pr-comments.md +11 -0
- package/registry/stubs/workflows/product-building/prep-issue.md +11 -0
- package/registry/stubs/workflows/product-building/prototype.md +11 -0
- package/registry/stubs/workflows/product-building/resolve.md +11 -0
- package/registry/stubs/workflows/product-building/retrospect.md +11 -0
- package/registry/stubs/workflows/product-building/spec.md +11 -0
- package/registry/stubs/workflows/product-building/test.md +11 -0
- package/registry/stubs/workflows/quality-assurance/browser-validation.md +11 -0
- package/registry/stubs/workflows/quality-assurance/iterative-improvement-cycle.md +11 -0
- package/registry/stubs/workflows/replicate/replicate-discovery.md +11 -0
- package/registry/stubs/workflows/replicate/replicate-to-issues.md +11 -0
- package/registry/stubs/workflows/reviewer/review-implementation-vs-design-spec.md +11 -0
- package/registry/stubs/workflows/reviewer/review-implementation-vs-feature-spec.md +11 -0
- package/registry/stubs/workflows/startup-credits/aws-activate-application.md +11 -0
- package/registry/stubs/workflows/startup-credits/google-cloud-application.md +11 -0
- package/registry/stubs/workflows/startup-credits/microsoft-azure-application.md +11 -0
- package/.github/workflows/ci.yml +0 -65
- package/.github/workflows/deploy-fraim.yml +0 -87
- package/.github/workflows/phase-change.yml +0 -251
- package/.github/workflows/status-change.yml +0 -68
- package/.github/workflows/sync-on-pr-review.yml +0 -66
- package/examples/simple-webapp/TESTING.md +0 -62
- package/examples/simple-webapp/example-test.ts +0 -186
- package/registry/github/workflows/ci.yml +0 -51
- package/registry/github/workflows/phase-change.yml +0 -251
- package/registry/github/workflows/status-change.yml +0 -68
- package/registry/github/workflows/sync-on-pr-review.yml +0 -66
- package/registry/mcp-template.jsonc +0 -29
- package/registry/rules/agent-success-criteria.md +0 -52
- package/registry/rules/agent-testing-guidelines.md +0 -502
- package/registry/rules/architecture.md +0 -52
- package/registry/rules/communication.md +0 -122
- package/registry/rules/continuous-learning.md +0 -55
- package/registry/rules/debugging-multitenancy-issues.md +0 -85
- package/registry/rules/ephemeral-execution.md +0 -57
- package/registry/rules/git-safe-commands.md +0 -34
- package/registry/rules/hitl-ppe-record-analysis.md +0 -302
- package/registry/rules/integrity-and-test-ethics.md +0 -275
- package/registry/rules/local-development.md +0 -254
- package/registry/rules/merge-requirements.md +0 -231
- package/registry/rules/simplicity.md +0 -118
- package/registry/rules/software-development-lifecycle.md +0 -105
- package/registry/rules/spike-first-development.md +0 -205
- package/registry/rules/successful-debugging-patterns.md +0 -491
- package/registry/rules/telemetry.md +0 -67
- package/registry/templates/bootstrap/ARCHITECTURE-TEMPLATE.md +0 -53
- package/registry/templates/bootstrap/CODE-QUALITY-REPORT-TEMPLATE.md +0 -37
- package/registry/templates/bootstrap/TEST-COVERAGE-REPORT-TEMPLATE.md +0 -35
- package/registry/templates/business-development/IDEATION-REPORT-TEMPLATE.md +0 -29
- package/registry/templates/business-development/PRICING-STRATEGY-TEMPLATE.md +0 -126
- package/registry/templates/customer-development/customer-interview-template.md +0 -99
- package/registry/templates/customer-development/follow-up-email-templates.md +0 -132
- package/registry/templates/customer-development/insight-analysis-template.md +0 -74
- package/registry/templates/customer-development/strategic-recommendations-template.md +0 -53
- package/registry/templates/customer-development/thank-you-email-template.html +0 -124
- package/registry/templates/customer-development/thank-you-note-template.md +0 -16
- package/registry/templates/customer-development/triage-log-template.md +0 -278
- package/registry/templates/customer-development/weekly-newsletter-template.html +0 -204
- package/registry/templates/evidence/Design-Evidence.md +0 -30
- package/registry/templates/evidence/Implementation-BugEvidence.md +0 -86
- package/registry/templates/evidence/Implementation-FeatureEvidence.md +0 -121
- package/registry/templates/evidence/Spec-Evidence.md +0 -19
- package/registry/templates/help/HelpNeeded.md +0 -14
- package/registry/templates/marketing/HBR-ARTICLE-TEMPLATE.md +0 -66
- package/registry/templates/replicate/implementation-checklist.md +0 -39
- package/registry/templates/replicate/use-cases-template.md +0 -88
- package/registry/templates/retrospective/RETROSPECTIVE-TEMPLATE.md +0 -55
- package/registry/templates/specs/BUGSPEC-TEMPLATE.md +0 -37
- package/registry/templates/specs/FEATURESPEC-TEMPLATE.md +0 -29
- package/registry/templates/specs/TECHSPEC-TEMPLATE.md +0 -39
- package/registry/workflows/bootstrap/create-architecture.md +0 -38
- package/registry/workflows/bootstrap/evaluate-code-quality.md +0 -36
- package/registry/workflows/bootstrap/verify-test-coverage.md +0 -37
- package/registry/workflows/business-development/create-business-plan.md +0 -737
- package/registry/workflows/business-development/ideate-business-opportunity.md +0 -55
- package/registry/workflows/business-development/price-product.md +0 -325
- package/registry/workflows/convert-to-pdf.md +0 -235
- package/registry/workflows/customer-development/insight-analysis.md +0 -156
- package/registry/workflows/customer-development/insight-triage.md +0 -933
- package/registry/workflows/customer-development/interview-preparation.md +0 -421
- package/registry/workflows/customer-development/linkedin-outreach.md +0 -593
- package/registry/workflows/customer-development/strategic-brainstorming.md +0 -146
- package/registry/workflows/customer-development/thank-customers.md +0 -203
- package/registry/workflows/customer-development/weekly-newsletter.md +0 -366
- package/registry/workflows/deploy/cloud-deployment.md +0 -310
- package/registry/workflows/improve-fraim/contribute.md +0 -32
- package/registry/workflows/improve-fraim/file-issue.md +0 -32
- package/registry/workflows/marketing/content-creation.md +0 -37
- package/registry/workflows/marketing/hbr-article.md +0 -73
- package/registry/workflows/marketing/launch-checklist.md +0 -37
- package/registry/workflows/marketing/marketing-strategy.md +0 -45
- package/registry/workflows/performance/analyze-performance.md +0 -65
- package/registry/workflows/product-building/design.md +0 -130
- package/registry/workflows/product-building/implement.md +0 -315
- package/registry/workflows/product-building/iterate-on-pr-comments.md +0 -70
- package/registry/workflows/product-building/prep-issue.md +0 -43
- package/registry/workflows/product-building/prototype.md +0 -60
- package/registry/workflows/product-building/resolve.md +0 -164
- package/registry/workflows/product-building/retrospect.md +0 -86
- package/registry/workflows/product-building/spec.md +0 -117
- package/registry/workflows/product-building/test.md +0 -120
- package/registry/workflows/quality-assurance/browser-validation.md +0 -221
- package/registry/workflows/quality-assurance/iterative-improvement-cycle.md +0 -562
- package/registry/workflows/replicate/replicate-discovery.md +0 -336
- package/registry/workflows/replicate/replicate-to-issues.md +0 -319
- package/registry/workflows/reviewer/review-implementation-vs-design-spec.md +0 -632
- package/registry/workflows/reviewer/review-implementation-vs-feature-spec.md +0 -669
- package/registry/workflows/startup-credits/aws-activate-application.md +0 -535
- package/registry/workflows/startup-credits/google-cloud-application.md +0 -647
- package/registry/workflows/startup-credits/microsoft-azure-application.md +0 -538
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.autoConfigureMCP = exports.validateSetupResults = exports.promptForGitHubToken = exports.promptForIDESelection = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
10
|
+
const prompts_1 = __importDefault(require("prompts"));
|
|
11
|
+
const ide_detector_1 = require("./ide-detector");
|
|
12
|
+
const mcp_config_generator_1 = require("./mcp-config-generator");
|
|
13
|
+
const token_validator_1 = require("./token-validator");
|
|
14
|
+
const promptForIDESelection = async (detectedIDEs) => {
|
|
15
|
+
console.log(chalk_1.default.green(`✅ Found ${detectedIDEs.length} IDEs that can be configured with FRAIM:\n`));
|
|
16
|
+
detectedIDEs.forEach((ide, index) => {
|
|
17
|
+
const configExists = fs_1.default.existsSync((0, ide_detector_1.expandPath)(ide.configPath));
|
|
18
|
+
const statusIcon = configExists ? '📝' : '📄';
|
|
19
|
+
const statusText = configExists ? 'has config' : 'new config';
|
|
20
|
+
console.log(chalk_1.default.white(` ${index + 1}. ${ide.name} ${statusIcon} (${statusText})`));
|
|
21
|
+
console.log(chalk_1.default.gray(` Config: ${ide.configPath}`));
|
|
22
|
+
});
|
|
23
|
+
console.log(chalk_1.default.blue('\nFRAIM will add these MCP servers to selected IDEs:'));
|
|
24
|
+
console.log(chalk_1.default.gray(' • fraim (required for FRAIM workflows)'));
|
|
25
|
+
console.log(chalk_1.default.gray(' • git (version control integration)'));
|
|
26
|
+
console.log(chalk_1.default.gray(' • github (GitHub API access)'));
|
|
27
|
+
console.log(chalk_1.default.gray(' • playwright (browser automation)'));
|
|
28
|
+
console.log(chalk_1.default.yellow('\n💡 Existing MCP servers will be preserved - only missing servers will be added.'));
|
|
29
|
+
const response = await (0, prompts_1.default)({
|
|
30
|
+
type: 'text',
|
|
31
|
+
name: 'selection',
|
|
32
|
+
message: 'Configure FRAIM for which IDEs? (Enter \'all\' or numbers like \'1,3\')',
|
|
33
|
+
initial: 'all',
|
|
34
|
+
validate: (value) => {
|
|
35
|
+
if (value.toLowerCase() === 'all')
|
|
36
|
+
return true;
|
|
37
|
+
if (value.toLowerCase() === 'none' || value.toLowerCase() === 'skip')
|
|
38
|
+
return true;
|
|
39
|
+
const numbers = value.split(',').map(n => parseInt(n.trim()));
|
|
40
|
+
const valid = numbers.every(n => n >= 1 && n <= detectedIDEs.length && !isNaN(n));
|
|
41
|
+
return valid || 'Please enter "all", "none", or valid numbers (e.g., "1,3")';
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
if (response.selection.toLowerCase() === 'all') {
|
|
45
|
+
return detectedIDEs;
|
|
46
|
+
}
|
|
47
|
+
if (response.selection.toLowerCase() === 'none' || response.selection.toLowerCase() === 'skip') {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
const selectedIndices = response.selection.split(',').map((n) => parseInt(n.trim()) - 1);
|
|
51
|
+
return selectedIndices.map((i) => detectedIDEs[i]).filter((ide) => ide !== undefined);
|
|
52
|
+
};
|
|
53
|
+
exports.promptForIDESelection = promptForIDESelection;
|
|
54
|
+
const promptForGitHubToken = async () => {
|
|
55
|
+
console.log(chalk_1.default.blue('\n🔧 GitHub Integration Setup'));
|
|
56
|
+
console.log('FRAIM requires a GitHub Personal Access Token to function properly.\n');
|
|
57
|
+
console.log(chalk_1.default.yellow('🔑 Why GitHub token is required:'));
|
|
58
|
+
console.log(chalk_1.default.gray(' • Create and manage GitHub issues'));
|
|
59
|
+
console.log(chalk_1.default.gray(' • Access repository information'));
|
|
60
|
+
console.log(chalk_1.default.gray(' • Perform git operations through MCP'));
|
|
61
|
+
console.log(chalk_1.default.gray(' • Enable full development workflow automation\n'));
|
|
62
|
+
const hasToken = await (0, prompts_1.default)({
|
|
63
|
+
type: 'confirm',
|
|
64
|
+
name: 'hasToken',
|
|
65
|
+
message: 'Do you have a GitHub Personal Access Token?',
|
|
66
|
+
initial: false
|
|
67
|
+
});
|
|
68
|
+
if (!hasToken.hasToken) {
|
|
69
|
+
console.log(chalk_1.default.yellow('\n📝 To create a GitHub Personal Access Token:'));
|
|
70
|
+
console.log(chalk_1.default.gray(' 1. Go to https://github.com/settings/tokens'));
|
|
71
|
+
console.log(chalk_1.default.gray(' 2. Click "Generate new token (classic)"'));
|
|
72
|
+
console.log(chalk_1.default.gray(' 3. Select these scopes:'));
|
|
73
|
+
console.log(chalk_1.default.gray(' • repo (Full control of private repositories)'));
|
|
74
|
+
console.log(chalk_1.default.gray(' • read:org (Read org and team membership)'));
|
|
75
|
+
console.log(chalk_1.default.gray(' • read:user (Read user profile data)'));
|
|
76
|
+
console.log(chalk_1.default.gray(' 4. Set expiration (recommend 90 days or no expiration)'));
|
|
77
|
+
console.log(chalk_1.default.gray(' 5. Click "Generate token" and copy it immediately'));
|
|
78
|
+
console.log(chalk_1.default.yellow(' ⚠️ You won\'t be able to see the token again!\n'));
|
|
79
|
+
const openBrowser = await (0, prompts_1.default)({
|
|
80
|
+
type: 'confirm',
|
|
81
|
+
name: 'open',
|
|
82
|
+
message: 'Open GitHub token creation page in browser?',
|
|
83
|
+
initial: true
|
|
84
|
+
});
|
|
85
|
+
if (openBrowser.open) {
|
|
86
|
+
const { spawn } = require('child_process');
|
|
87
|
+
const url = 'https://github.com/settings/tokens';
|
|
88
|
+
try {
|
|
89
|
+
// Cross-platform browser opening
|
|
90
|
+
const command = process.platform === 'win32' ? 'start' :
|
|
91
|
+
process.platform === 'darwin' ? 'open' : 'xdg-open';
|
|
92
|
+
spawn(command, [url], { detached: true, stdio: 'ignore' });
|
|
93
|
+
console.log(chalk_1.default.green(' 🌐 Opened GitHub in your browser'));
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
console.log(chalk_1.default.yellow(` ⚠️ Could not open browser. Please visit: ${url}`));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
let token = null;
|
|
101
|
+
let attempts = 0;
|
|
102
|
+
const maxAttempts = 3;
|
|
103
|
+
while (!token && attempts < maxAttempts) {
|
|
104
|
+
const tokenResponse = await (0, prompts_1.default)({
|
|
105
|
+
type: 'password',
|
|
106
|
+
name: 'token',
|
|
107
|
+
message: attempts === 0
|
|
108
|
+
? 'Enter your GitHub token (required)'
|
|
109
|
+
: `Enter your GitHub token (attempt ${attempts + 1}/${maxAttempts})`,
|
|
110
|
+
validate: (value) => {
|
|
111
|
+
if (!value)
|
|
112
|
+
return 'GitHub token is required for FRAIM to function';
|
|
113
|
+
if ((0, token_validator_1.isValidTokenFormat)(value, 'github'))
|
|
114
|
+
return true;
|
|
115
|
+
return 'Please enter a valid GitHub token (starts with ghp_ or github_pat_)';
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
if (!tokenResponse.token) {
|
|
119
|
+
console.log(chalk_1.default.red('\n❌ GitHub token is required for FRAIM to function properly.\n'));
|
|
120
|
+
console.log('FRAIM requires both keys to provide value:');
|
|
121
|
+
console.log(chalk_1.default.gray(' • FRAIM key: Access to workflows and AI management features'));
|
|
122
|
+
console.log(chalk_1.default.gray(' • GitHub token: Essential for git operations, issue management, and repository access\n'));
|
|
123
|
+
console.log('Without GitHub integration, FRAIM workflows cannot:');
|
|
124
|
+
console.log(chalk_1.default.gray(' • Create or manage GitHub issues'));
|
|
125
|
+
console.log(chalk_1.default.gray(' • Access repository information'));
|
|
126
|
+
console.log(chalk_1.default.gray(' • Perform git operations through MCP'));
|
|
127
|
+
console.log(chalk_1.default.gray(' • Provide full development workflow automation\n'));
|
|
128
|
+
const retry = await (0, prompts_1.default)({
|
|
129
|
+
type: 'confirm',
|
|
130
|
+
name: 'retry',
|
|
131
|
+
message: 'Would you like to try entering the GitHub token again?',
|
|
132
|
+
initial: true
|
|
133
|
+
});
|
|
134
|
+
if (!retry.retry) {
|
|
135
|
+
console.log(chalk_1.default.red('Setup cancelled. Run \'fraim setup --key=<fraim-key>\' again when you have both tokens.'));
|
|
136
|
+
process.exit(1);
|
|
137
|
+
}
|
|
138
|
+
attempts++;
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
console.log(chalk_1.default.blue(' 🔍 Validating GitHub token...'));
|
|
142
|
+
// Validate token
|
|
143
|
+
const isValid = await (0, token_validator_1.validateGitHubToken)(tokenResponse.token);
|
|
144
|
+
if (isValid) {
|
|
145
|
+
console.log(chalk_1.default.green(' ✅ GitHub token validated successfully!\n'));
|
|
146
|
+
return tokenResponse.token;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
console.log(chalk_1.default.red(' ❌ Invalid GitHub token or network error'));
|
|
150
|
+
console.log(chalk_1.default.yellow(' 💡 Make sure the token has the required scopes and hasn\'t expired\n'));
|
|
151
|
+
attempts++;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
console.log(chalk_1.default.red('\n❌ Maximum attempts reached. Setup cancelled.'));
|
|
155
|
+
console.log(chalk_1.default.gray('Please ensure you have a valid GitHub token and try again.'));
|
|
156
|
+
console.log(chalk_1.default.blue('💡 Run "fraim setup --key=<fraim-key> --github-token=<github-token>" to skip prompts.'));
|
|
157
|
+
process.exit(1);
|
|
158
|
+
};
|
|
159
|
+
exports.promptForGitHubToken = promptForGitHubToken;
|
|
160
|
+
const backupConfig = (configPath) => {
|
|
161
|
+
if (fs_1.default.existsSync(configPath)) {
|
|
162
|
+
const backupPath = `${configPath}.fraim-backup-${Date.now()}`;
|
|
163
|
+
fs_1.default.copyFileSync(configPath, backupPath);
|
|
164
|
+
console.log(chalk_1.default.gray(` 📁 Backup created: ${backupPath}`));
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const testMCPConnection = async (ide) => {
|
|
168
|
+
// This is a placeholder for future MCP connection testing
|
|
169
|
+
// For now, we'll just check if the config file was created successfully
|
|
170
|
+
const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
|
|
171
|
+
return fs_1.default.existsSync(configPath);
|
|
172
|
+
};
|
|
173
|
+
const validateSetupResults = async (configuredIDEs) => {
|
|
174
|
+
if (configuredIDEs.length === 0)
|
|
175
|
+
return;
|
|
176
|
+
console.log(chalk_1.default.blue('\n🔍 Validating setup results...'));
|
|
177
|
+
const validationResults = await Promise.all(configuredIDEs.map(async (ide) => {
|
|
178
|
+
const isValid = await testMCPConnection(ide);
|
|
179
|
+
return { ide: ide.name, valid: isValid };
|
|
180
|
+
}));
|
|
181
|
+
const validIDEs = validationResults.filter(r => r.valid);
|
|
182
|
+
const invalidIDEs = validationResults.filter(r => !r.valid);
|
|
183
|
+
if (validIDEs.length > 0) {
|
|
184
|
+
console.log(chalk_1.default.green(`✅ ${validIDEs.length} IDEs configured successfully:`));
|
|
185
|
+
validIDEs.forEach(({ ide }) => {
|
|
186
|
+
console.log(chalk_1.default.green(` • ${ide}`));
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (invalidIDEs.length > 0) {
|
|
190
|
+
console.log(chalk_1.default.red(`❌ ${invalidIDEs.length} IDEs may have configuration issues:`));
|
|
191
|
+
invalidIDEs.forEach(({ ide }) => {
|
|
192
|
+
console.log(chalk_1.default.red(` • ${ide}`));
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
exports.validateSetupResults = validateSetupResults;
|
|
197
|
+
const configureIDEMCP = async (ide, fraimKey, githubToken) => {
|
|
198
|
+
const configPath = (0, ide_detector_1.expandPath)(ide.configPath);
|
|
199
|
+
console.log(chalk_1.default.blue(`🔧 Configuring ${ide.name}...`));
|
|
200
|
+
// Create backup
|
|
201
|
+
backupConfig(configPath);
|
|
202
|
+
// Ensure directory exists
|
|
203
|
+
const configDir = path_1.default.dirname(configPath);
|
|
204
|
+
if (!fs_1.default.existsSync(configDir)) {
|
|
205
|
+
fs_1.default.mkdirSync(configDir, { recursive: true });
|
|
206
|
+
console.log(chalk_1.default.gray(` 📁 Created directory: ${configDir}`));
|
|
207
|
+
}
|
|
208
|
+
let existingConfig = {};
|
|
209
|
+
let existingMCPServers = {};
|
|
210
|
+
if (fs_1.default.existsSync(configPath) && ide.configFormat === 'json') {
|
|
211
|
+
try {
|
|
212
|
+
existingConfig = JSON.parse(fs_1.default.readFileSync(configPath, 'utf8'));
|
|
213
|
+
existingMCPServers = existingConfig.mcpServers || {};
|
|
214
|
+
console.log(chalk_1.default.gray(` 📋 Found existing config with ${Object.keys(existingMCPServers).length} MCP servers`));
|
|
215
|
+
}
|
|
216
|
+
catch (e) {
|
|
217
|
+
console.log(chalk_1.default.yellow(` ⚠️ Could not parse existing ${ide.name} config, creating new one`));
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
if (ide.configFormat === 'toml') {
|
|
221
|
+
// For TOML (Codex), we need to handle differently
|
|
222
|
+
let existingTomlContent = '';
|
|
223
|
+
if (fs_1.default.existsSync(configPath)) {
|
|
224
|
+
existingTomlContent = fs_1.default.readFileSync(configPath, 'utf8');
|
|
225
|
+
console.log(chalk_1.default.gray(` 📋 Found existing TOML config`));
|
|
226
|
+
}
|
|
227
|
+
const newTomlContent = (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, githubToken);
|
|
228
|
+
// For TOML, we'll append new servers if they don't exist
|
|
229
|
+
let finalContent = existingTomlContent;
|
|
230
|
+
const serversToAdd = ['fraim', 'git', 'github', 'playwright'];
|
|
231
|
+
const addedServers = [];
|
|
232
|
+
for (const server of serversToAdd) {
|
|
233
|
+
if (!existingTomlContent.includes(`[mcp_servers.${server}]`)) {
|
|
234
|
+
// Extract this server's config from the new content
|
|
235
|
+
const serverRegex = new RegExp(`\\[mcp_servers\\.${server}\\][\\s\\S]*?(?=\\[mcp_servers\\.|$)`, 'g');
|
|
236
|
+
const serverMatch = newTomlContent.match(serverRegex);
|
|
237
|
+
if (serverMatch) {
|
|
238
|
+
finalContent += '\n' + serverMatch[0].trim() + '\n';
|
|
239
|
+
addedServers.push(server);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
console.log(chalk_1.default.gray(` ⏭️ Skipped ${server} (already exists)`));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
fs_1.default.writeFileSync(configPath, finalContent);
|
|
247
|
+
addedServers.forEach(server => {
|
|
248
|
+
console.log(chalk_1.default.green(` ✅ Added ${server} MCP server`));
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
// For JSON configs - intelligent merging
|
|
253
|
+
const newConfig = (0, mcp_config_generator_1.generateMCPConfig)(ide.configType, fraimKey, githubToken);
|
|
254
|
+
const newMCPServers = newConfig.mcpServers || {};
|
|
255
|
+
// Merge MCP servers intelligently
|
|
256
|
+
const mergedMCPServers = { ...existingMCPServers };
|
|
257
|
+
const addedServers = [];
|
|
258
|
+
const skippedServers = [];
|
|
259
|
+
for (const [serverName, serverConfig] of Object.entries(newMCPServers)) {
|
|
260
|
+
if (!existingMCPServers[serverName]) {
|
|
261
|
+
mergedMCPServers[serverName] = serverConfig;
|
|
262
|
+
addedServers.push(serverName);
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
skippedServers.push(serverName);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
// Merge with existing config
|
|
269
|
+
const mergedConfig = {
|
|
270
|
+
...existingConfig,
|
|
271
|
+
...newConfig,
|
|
272
|
+
mcpServers: mergedMCPServers
|
|
273
|
+
};
|
|
274
|
+
// Write updated config
|
|
275
|
+
fs_1.default.writeFileSync(configPath, JSON.stringify(mergedConfig, null, 2));
|
|
276
|
+
addedServers.forEach(server => {
|
|
277
|
+
console.log(chalk_1.default.green(` ✅ Added ${server} MCP server`));
|
|
278
|
+
});
|
|
279
|
+
skippedServers.forEach(server => {
|
|
280
|
+
console.log(chalk_1.default.gray(` ⏭️ Skipped ${server} (already exists)`));
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
console.log(chalk_1.default.green(`✅ Updated ${configPath}`));
|
|
284
|
+
};
|
|
285
|
+
const autoConfigureMCP = async (fraimKey, githubToken, selectedIDEs) => {
|
|
286
|
+
const detectedIDEs = (0, ide_detector_1.detectInstalledIDEs)();
|
|
287
|
+
if (detectedIDEs.length === 0) {
|
|
288
|
+
console.log(chalk_1.default.yellow('⚠️ No supported IDEs detected.'));
|
|
289
|
+
console.log(chalk_1.default.gray('Supported IDEs: Claude Desktop, Antigravity, Kiro, Cursor, VSCode, Codex, Windsurf'));
|
|
290
|
+
console.log(chalk_1.default.blue('\n💡 You can install an IDE and run setup again later.'));
|
|
291
|
+
console.log(chalk_1.default.gray(' Or continue with manual MCP configuration.'));
|
|
292
|
+
const continueAnyway = await (0, prompts_1.default)({
|
|
293
|
+
type: 'confirm',
|
|
294
|
+
name: 'continue',
|
|
295
|
+
message: 'Continue setup without IDE configuration?',
|
|
296
|
+
initial: true
|
|
297
|
+
});
|
|
298
|
+
if (!continueAnyway.continue) {
|
|
299
|
+
console.log(chalk_1.default.red('Setup cancelled. Install an IDE and run setup again.'));
|
|
300
|
+
process.exit(1);
|
|
301
|
+
}
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
let idesToConfigure;
|
|
305
|
+
if (selectedIDEs && selectedIDEs.length > 0) {
|
|
306
|
+
// Use command line specified IDEs
|
|
307
|
+
idesToConfigure = detectedIDEs.filter(ide => selectedIDEs.some(selected => ide.name.toLowerCase().includes(selected.toLowerCase())));
|
|
308
|
+
if (idesToConfigure.length === 0) {
|
|
309
|
+
console.log(chalk_1.default.yellow(`⚠️ No IDEs found matching: ${selectedIDEs.join(', ')}`));
|
|
310
|
+
console.log(chalk_1.default.gray('Available IDEs:'));
|
|
311
|
+
detectedIDEs.forEach(ide => console.log(chalk_1.default.gray(` • ${ide.name}`)));
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
// Interactive selection
|
|
317
|
+
idesToConfigure = await (0, exports.promptForIDESelection)(detectedIDEs);
|
|
318
|
+
}
|
|
319
|
+
if (idesToConfigure.length === 0) {
|
|
320
|
+
console.log(chalk_1.default.yellow('⚠️ No IDEs selected for configuration.'));
|
|
321
|
+
console.log(chalk_1.default.blue('💡 You can run "fraim setup" again later to configure IDEs.'));
|
|
322
|
+
return;
|
|
323
|
+
}
|
|
324
|
+
console.log(chalk_1.default.blue(`\n🚀 Configuring ${idesToConfigure.length} IDEs...`));
|
|
325
|
+
const results = {
|
|
326
|
+
successful: [],
|
|
327
|
+
failed: []
|
|
328
|
+
};
|
|
329
|
+
for (const ide of idesToConfigure) {
|
|
330
|
+
try {
|
|
331
|
+
await configureIDEMCP(ide, fraimKey, githubToken);
|
|
332
|
+
results.successful.push(ide.name);
|
|
333
|
+
}
|
|
334
|
+
catch (error) {
|
|
335
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
336
|
+
results.failed.push({ ide: ide.name, error: errorMessage });
|
|
337
|
+
console.log(chalk_1.default.red(`❌ Failed to configure ${ide.name}: ${errorMessage}`));
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Summary
|
|
341
|
+
console.log(chalk_1.default.green(`\n🎉 Setup Summary:`));
|
|
342
|
+
console.log(chalk_1.default.green(` ✅ Successfully configured: ${results.successful.length} IDEs`));
|
|
343
|
+
if (results.successful.length > 0) {
|
|
344
|
+
results.successful.forEach(ide => {
|
|
345
|
+
console.log(chalk_1.default.green(` • ${ide}`));
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
if (results.failed.length > 0) {
|
|
349
|
+
console.log(chalk_1.default.red(` ❌ Failed to configure: ${results.failed.length} IDEs`));
|
|
350
|
+
results.failed.forEach(({ ide, error }) => {
|
|
351
|
+
console.log(chalk_1.default.red(` • ${ide}: ${error}`));
|
|
352
|
+
});
|
|
353
|
+
console.log(chalk_1.default.yellow('\n💡 You can try running setup again or configure these IDEs manually.'));
|
|
354
|
+
}
|
|
355
|
+
if (results.successful.length > 0) {
|
|
356
|
+
console.log(chalk_1.default.blue('\n🔄 Please restart your configured IDEs to load the new MCP servers.'));
|
|
357
|
+
// Validate setup results
|
|
358
|
+
const successfulIDEs = idesToConfigure.filter(ide => results.successful.includes(ide.name));
|
|
359
|
+
await (0, exports.validateSetupResults)(successfulIDEs);
|
|
360
|
+
console.log(chalk_1.default.blue('\n🎯 Next steps:'));
|
|
361
|
+
console.log(chalk_1.default.cyan(' 1. Restart your configured IDEs'));
|
|
362
|
+
console.log(chalk_1.default.cyan(' 2. Go to any project directory'));
|
|
363
|
+
console.log(chalk_1.default.cyan(' 3. Run: fraim init-project'));
|
|
364
|
+
console.log(chalk_1.default.cyan(' 4. Ask your AI agent: "list fraim workflows"'));
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
exports.autoConfigureMCP = autoConfigureMCP;
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.expandPath = exports.findIDEByName = exports.getAllSupportedIDEs = exports.detectInstalledIDEs = exports.IDE_CONFIGS = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const os_1 = __importDefault(require("os"));
|
|
10
|
+
const expandPath = (filePath) => {
|
|
11
|
+
if (filePath.startsWith('~/')) {
|
|
12
|
+
return path_1.default.join(os_1.default.homedir(), filePath.slice(2));
|
|
13
|
+
}
|
|
14
|
+
return filePath;
|
|
15
|
+
};
|
|
16
|
+
exports.expandPath = expandPath;
|
|
17
|
+
const checkMultiplePaths = (paths) => {
|
|
18
|
+
return paths.some(p => fs_1.default.existsSync(expandPath(p)));
|
|
19
|
+
};
|
|
20
|
+
const detectClaude = () => {
|
|
21
|
+
const paths = [
|
|
22
|
+
'~/.claude',
|
|
23
|
+
'~/Library/Application Support/Claude',
|
|
24
|
+
'~/AppData/Roaming/Claude'
|
|
25
|
+
];
|
|
26
|
+
return checkMultiplePaths(paths);
|
|
27
|
+
};
|
|
28
|
+
const detectVSCode = () => {
|
|
29
|
+
const paths = [
|
|
30
|
+
'~/.vscode',
|
|
31
|
+
'~/Library/Application Support/Code',
|
|
32
|
+
'~/AppData/Roaming/Code',
|
|
33
|
+
'~/.config/Code'
|
|
34
|
+
];
|
|
35
|
+
return checkMultiplePaths(paths);
|
|
36
|
+
};
|
|
37
|
+
const detectCursor = () => {
|
|
38
|
+
const paths = [
|
|
39
|
+
'~/.cursor',
|
|
40
|
+
'~/Library/Application Support/Cursor',
|
|
41
|
+
'~/AppData/Roaming/Cursor',
|
|
42
|
+
'~/.config/Cursor'
|
|
43
|
+
];
|
|
44
|
+
return checkMultiplePaths(paths);
|
|
45
|
+
};
|
|
46
|
+
const detectWindsurf = () => {
|
|
47
|
+
const paths = [
|
|
48
|
+
'~/.codeium/windsurf',
|
|
49
|
+
'~/Library/Application Support/Windsurf',
|
|
50
|
+
'~/AppData/Roaming/Windsurf',
|
|
51
|
+
'~/.config/windsurf'
|
|
52
|
+
];
|
|
53
|
+
return checkMultiplePaths(paths);
|
|
54
|
+
};
|
|
55
|
+
exports.IDE_CONFIGS = [
|
|
56
|
+
{
|
|
57
|
+
name: 'Claude Desktop',
|
|
58
|
+
configPath: '~/.claude/settings.json',
|
|
59
|
+
configFormat: 'json',
|
|
60
|
+
configType: 'standard',
|
|
61
|
+
detectMethod: detectClaude,
|
|
62
|
+
alternativePaths: [
|
|
63
|
+
'~/Library/Application Support/Claude/settings.json',
|
|
64
|
+
'~/AppData/Roaming/Claude/settings.json'
|
|
65
|
+
],
|
|
66
|
+
description: 'Anthropic Claude Desktop application'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'Antigravity',
|
|
70
|
+
configPath: '~/.gemini/antigravity/mcp_config.json',
|
|
71
|
+
configFormat: 'json',
|
|
72
|
+
configType: 'standard',
|
|
73
|
+
detectMethod: () => fs_1.default.existsSync(expandPath('~/.gemini/antigravity')),
|
|
74
|
+
description: 'Google Gemini Antigravity IDE'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
name: 'Kiro',
|
|
78
|
+
configPath: '~/.kiro/settings/mcp.json',
|
|
79
|
+
configFormat: 'json',
|
|
80
|
+
configType: 'kiro',
|
|
81
|
+
detectMethod: () => fs_1.default.existsSync(expandPath('~/.kiro')),
|
|
82
|
+
description: 'Kiro AI-powered IDE'
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
name: 'Cursor',
|
|
86
|
+
configPath: '~/.cursor/mcp.json',
|
|
87
|
+
configFormat: 'json',
|
|
88
|
+
configType: 'kiro',
|
|
89
|
+
detectMethod: detectCursor,
|
|
90
|
+
alternativePaths: [
|
|
91
|
+
'~/Library/Application Support/Cursor/mcp.json',
|
|
92
|
+
'~/AppData/Roaming/Cursor/mcp.json',
|
|
93
|
+
'~/.config/Cursor/mcp.json'
|
|
94
|
+
],
|
|
95
|
+
description: 'Cursor AI code editor'
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
name: 'VSCode',
|
|
99
|
+
configPath: '~/.vscode/settings/mcp.json',
|
|
100
|
+
configFormat: 'json',
|
|
101
|
+
configType: 'kiro',
|
|
102
|
+
detectMethod: detectVSCode,
|
|
103
|
+
alternativePaths: [
|
|
104
|
+
'~/Library/Application Support/Code/User/settings/mcp.json',
|
|
105
|
+
'~/AppData/Roaming/Code/User/settings/mcp.json',
|
|
106
|
+
'~/.config/Code/User/settings/mcp.json'
|
|
107
|
+
],
|
|
108
|
+
description: 'Visual Studio Code'
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: 'Codex',
|
|
112
|
+
configPath: '~/.codex/config.toml',
|
|
113
|
+
configFormat: 'toml',
|
|
114
|
+
configType: 'codex',
|
|
115
|
+
detectMethod: () => fs_1.default.existsSync(expandPath('~/.codex')),
|
|
116
|
+
description: 'Codex AI development environment'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
name: 'Windsurf',
|
|
120
|
+
configPath: '~/.codeium/windsurf/mcp_config.json',
|
|
121
|
+
configFormat: 'json',
|
|
122
|
+
configType: 'windsurf',
|
|
123
|
+
detectMethod: detectWindsurf,
|
|
124
|
+
alternativePaths: [
|
|
125
|
+
'~/Library/Application Support/Windsurf/mcp_config.json',
|
|
126
|
+
'~/AppData/Roaming/Windsurf/mcp_config.json',
|
|
127
|
+
'~/.config/windsurf/mcp_config.json'
|
|
128
|
+
],
|
|
129
|
+
description: 'Codeium Windsurf IDE'
|
|
130
|
+
}
|
|
131
|
+
];
|
|
132
|
+
const findBestConfigPath = (ide) => {
|
|
133
|
+
// First try the default path
|
|
134
|
+
if (fs_1.default.existsSync(expandPath(ide.configPath))) {
|
|
135
|
+
return ide.configPath;
|
|
136
|
+
}
|
|
137
|
+
// Then try alternative paths
|
|
138
|
+
if (ide.alternativePaths) {
|
|
139
|
+
for (const altPath of ide.alternativePaths) {
|
|
140
|
+
if (fs_1.default.existsSync(expandPath(altPath))) {
|
|
141
|
+
return altPath;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Return default path if nothing found (will be created)
|
|
146
|
+
return ide.configPath;
|
|
147
|
+
};
|
|
148
|
+
const detectInstalledIDEs = () => {
|
|
149
|
+
return exports.IDE_CONFIGS.filter(ide => ide.detectMethod()).map(ide => ({
|
|
150
|
+
...ide,
|
|
151
|
+
configPath: findBestConfigPath(ide)
|
|
152
|
+
}));
|
|
153
|
+
};
|
|
154
|
+
exports.detectInstalledIDEs = detectInstalledIDEs;
|
|
155
|
+
const getAllSupportedIDEs = () => {
|
|
156
|
+
return exports.IDE_CONFIGS;
|
|
157
|
+
};
|
|
158
|
+
exports.getAllSupportedIDEs = getAllSupportedIDEs;
|
|
159
|
+
const findIDEByName = (name) => {
|
|
160
|
+
return exports.IDE_CONFIGS.find(ide => ide.name.toLowerCase().includes(name.toLowerCase()) ||
|
|
161
|
+
name.toLowerCase().includes(ide.name.toLowerCase()));
|
|
162
|
+
};
|
|
163
|
+
exports.findIDEByName = findIDEByName;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateMCPConfig = exports.generateWindsurfMCPServers = exports.generateCodexMCPServers = exports.generateKiroMCPServers = exports.generateStandardMCPServers = void 0;
|
|
4
|
+
const generateStandardMCPServers = (fraimKey, githubToken) => ({
|
|
5
|
+
mcpServers: {
|
|
6
|
+
git: {
|
|
7
|
+
command: "npx",
|
|
8
|
+
args: ["-y", "@cyanheads/git-mcp-server"]
|
|
9
|
+
},
|
|
10
|
+
github: {
|
|
11
|
+
serverUrl: "https://api.githubcopilot.com/mcp/",
|
|
12
|
+
headers: {
|
|
13
|
+
Authorization: `Bearer ${githubToken}`
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
playwright: {
|
|
17
|
+
command: "npx",
|
|
18
|
+
args: ["-y", "@playwright/mcp"]
|
|
19
|
+
},
|
|
20
|
+
fraim: {
|
|
21
|
+
serverUrl: "https://fraim.wellnessatwork.me",
|
|
22
|
+
headers: {
|
|
23
|
+
"x-api-key": fraimKey
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
exports.generateStandardMCPServers = generateStandardMCPServers;
|
|
29
|
+
const generateKiroMCPServers = (fraimKey, githubToken) => ({
|
|
30
|
+
mcpServers: {
|
|
31
|
+
git: {
|
|
32
|
+
command: "npx",
|
|
33
|
+
args: ["-y", "@cyanheads/git-mcp-server"]
|
|
34
|
+
},
|
|
35
|
+
github: {
|
|
36
|
+
url: "https://api.githubcopilot.com/mcp/",
|
|
37
|
+
headers: {
|
|
38
|
+
Authorization: `Bearer ${githubToken}`
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
playwright: {
|
|
42
|
+
command: "npx",
|
|
43
|
+
args: ["-y", "@playwright/mcp"]
|
|
44
|
+
},
|
|
45
|
+
fraim: {
|
|
46
|
+
url: "https://fraim.wellnessatwork.me",
|
|
47
|
+
headers: {
|
|
48
|
+
"x-api-key": fraimKey
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
exports.generateKiroMCPServers = generateKiroMCPServers;
|
|
54
|
+
const generateCodexMCPServers = (fraimKey, githubToken) => `
|
|
55
|
+
[mcp_servers.git]
|
|
56
|
+
command = "npx"
|
|
57
|
+
args = ["-y", "@cyanheads/git-mcp-server"]
|
|
58
|
+
|
|
59
|
+
[mcp_servers.github]
|
|
60
|
+
url = "https://api.githubcopilot.com/mcp/"
|
|
61
|
+
bearer_token_env_var = "GIT_TOKEN"
|
|
62
|
+
|
|
63
|
+
[mcp_servers.playwright]
|
|
64
|
+
command = "npx"
|
|
65
|
+
args = ["-y", "@playwright/mcp"]
|
|
66
|
+
|
|
67
|
+
[mcp_servers.fraim]
|
|
68
|
+
url = "https://fraim.wellnessatwork.me/"
|
|
69
|
+
|
|
70
|
+
[mcp_servers.fraim.headers]
|
|
71
|
+
x-api-key = "${fraimKey}"
|
|
72
|
+
`;
|
|
73
|
+
exports.generateCodexMCPServers = generateCodexMCPServers;
|
|
74
|
+
const generateWindsurfMCPServers = (fraimKey, githubToken) => ({
|
|
75
|
+
mcpServers: {
|
|
76
|
+
git: {
|
|
77
|
+
command: "npx",
|
|
78
|
+
args: ["-y", "@cyanheads/git-mcp-server"]
|
|
79
|
+
},
|
|
80
|
+
github: {
|
|
81
|
+
command: "npx",
|
|
82
|
+
args: ["-y", "@modelcontextprotocol/server-fetch", "https://api.githubcopilot.com/mcp/"],
|
|
83
|
+
env: {
|
|
84
|
+
GITHUB_TOKEN: githubToken
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
playwright: {
|
|
88
|
+
command: "npx",
|
|
89
|
+
args: ["-y", "@playwright/mcp"]
|
|
90
|
+
},
|
|
91
|
+
fraim: {
|
|
92
|
+
command: "npx",
|
|
93
|
+
args: ["-y", "@modelcontextprotocol/server-fetch", "https://fraim.wellnessatwork.me"],
|
|
94
|
+
env: {
|
|
95
|
+
FRAIM_API_KEY: fraimKey
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
exports.generateWindsurfMCPServers = generateWindsurfMCPServers;
|
|
101
|
+
const generateMCPConfig = (configType, fraimKey, githubToken) => {
|
|
102
|
+
switch (configType) {
|
|
103
|
+
case 'standard':
|
|
104
|
+
return (0, exports.generateStandardMCPServers)(fraimKey, githubToken);
|
|
105
|
+
case 'kiro':
|
|
106
|
+
return (0, exports.generateKiroMCPServers)(fraimKey, githubToken);
|
|
107
|
+
case 'codex':
|
|
108
|
+
return (0, exports.generateCodexMCPServers)(fraimKey, githubToken);
|
|
109
|
+
case 'windsurf':
|
|
110
|
+
return (0, exports.generateWindsurfMCPServers)(fraimKey, githubToken);
|
|
111
|
+
default:
|
|
112
|
+
throw new Error(`Unsupported config type: ${configType}`);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
exports.generateMCPConfig = generateMCPConfig;
|