@saiteja1123/mcp-server 1.1.5 → 1.1.6
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/package.json +1 -1
- package/src/cli.js +141 -83
- package/src/mcp-config.mjs +161 -0
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -18,7 +18,6 @@
|
|
|
18
18
|
|
|
19
19
|
import fs from 'fs/promises';
|
|
20
20
|
import path from 'path';
|
|
21
|
-
import os from 'os';
|
|
22
21
|
import { createRequire } from 'module';
|
|
23
22
|
import { fileURLToPath } from 'url';
|
|
24
23
|
import {
|
|
@@ -30,6 +29,16 @@ import {
|
|
|
30
29
|
isRuntimeCompatibleLock,
|
|
31
30
|
} from './lock.mjs';
|
|
32
31
|
import { pingBackend, requestServerBind, verifyInstallBinding } from './api-scan.mjs';
|
|
32
|
+
import {
|
|
33
|
+
DEFAULT_API_BASE,
|
|
34
|
+
NPM_PACKAGE_NAME,
|
|
35
|
+
buildLegacyEnv,
|
|
36
|
+
buildUniversalEnv,
|
|
37
|
+
formatIdeConfigBlocks,
|
|
38
|
+
IDE_CONFIG_TARGETS,
|
|
39
|
+
isUniversalMode,
|
|
40
|
+
publishedServerCmd,
|
|
41
|
+
} from './mcp-config.mjs';
|
|
33
42
|
import {
|
|
34
43
|
DeepScanRuntime,
|
|
35
44
|
LocalDeepScanStore,
|
|
@@ -41,8 +50,7 @@ import {
|
|
|
41
50
|
|
|
42
51
|
const require = createRequire(import.meta.url);
|
|
43
52
|
const mcpPkg = require('../package.json');
|
|
44
|
-
const
|
|
45
|
-
const DEFAULT_API_BASE = 'https://vibesecur.onrender.com';
|
|
53
|
+
const NPM_PACKAGE = NPM_PACKAGE_NAME;
|
|
46
54
|
|
|
47
55
|
const serverPath = fileURLToPath(new URL('./server.js', import.meta.url));
|
|
48
56
|
|
|
@@ -85,17 +93,25 @@ function allowLocalFallback() {
|
|
|
85
93
|
function serverCmd() {
|
|
86
94
|
const normalizedPath = serverPath.replace(/\\/g, '/');
|
|
87
95
|
if (normalizedPath.includes('/node_modules/')) {
|
|
88
|
-
return
|
|
96
|
+
return publishedServerCmd();
|
|
89
97
|
}
|
|
90
98
|
return { command: 'node', args: [serverPath] };
|
|
91
99
|
}
|
|
92
100
|
|
|
93
101
|
function buildEnv(folder, token, apiBase) {
|
|
94
|
-
return
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
102
|
+
return buildLegacyEnv(folder, token, apiBase);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function printIdeBlocks(sc, env, options = {}) {
|
|
106
|
+
for (const block of formatIdeConfigBlocks(sc, env, options)) {
|
|
107
|
+
if (block.title === 'Mode') {
|
|
108
|
+
console.log(`${DIM}${block.body}${RESET}\n`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
console.log(`${BOLD}-- ${block.title} --${RESET}`);
|
|
112
|
+
console.log(block.body);
|
|
113
|
+
console.log();
|
|
114
|
+
}
|
|
99
115
|
}
|
|
100
116
|
|
|
101
117
|
function printLocalDiagnosticNotice(folder) {
|
|
@@ -137,20 +153,30 @@ async function createServerIssuedLock({ folder, account, authToken, apiBase, act
|
|
|
137
153
|
return { ok: false, remote };
|
|
138
154
|
}
|
|
139
155
|
|
|
140
|
-
function
|
|
141
|
-
|
|
142
|
-
|
|
156
|
+
function printIdeBlocksLegacy(sc, env) {
|
|
157
|
+
printIdeBlocks(sc, env, { universal: false });
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function runUniversalSetup({ apiBase, authToken, folder, write }) {
|
|
161
|
+
const sc = serverCmd();
|
|
162
|
+
const env = buildUniversalEnv(apiBase, authToken);
|
|
143
163
|
|
|
144
|
-
console.log(
|
|
145
|
-
console.log(
|
|
164
|
+
console.log(ok('Universal account MCP config (works in Cursor, Windsurf, VS Code, Claude Desktop, Continue)'));
|
|
165
|
+
console.log(dim('No per-folder bind required. Use projectUpsert in the IDE before scanning a new codebase.\n'));
|
|
146
166
|
|
|
147
|
-
console.log(
|
|
148
|
-
|
|
167
|
+
console.log(`${BOLD}Next:${RESET} paste ONE block below into your IDE MCP settings, then reload the IDE.\n`);
|
|
168
|
+
printIdeBlocks(sc, env, { universal: true });
|
|
149
169
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
170
|
+
if (write) {
|
|
171
|
+
const w = String(write).toLowerCase();
|
|
172
|
+
const allowed = ['cursor', 'vscode', 'windsurf', 'claude', 'all'];
|
|
173
|
+
if (!allowed.includes(w)) {
|
|
174
|
+
console.log(err(`Invalid --write=${write}. Use: ${allowed.join(' | ')}`));
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
await writeIdeConfig(w, sc, env, folder);
|
|
178
|
+
console.log(dim('Reload your IDE so it picks up the new MCP config.'));
|
|
179
|
+
}
|
|
154
180
|
}
|
|
155
181
|
|
|
156
182
|
async function mergeJsonFile(filePath, merger) {
|
|
@@ -166,40 +192,34 @@ async function mergeJsonFile(filePath, merger) {
|
|
|
166
192
|
await fs.writeFile(filePath, JSON.stringify(next, null, 2), 'utf8');
|
|
167
193
|
}
|
|
168
194
|
|
|
169
|
-
async function writeIdeConfig(which, sc, env) {
|
|
170
|
-
const
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
if (which === 'vscode' || which === 'all') {
|
|
184
|
-
const folder = env.VIBESECUR_BOUND_ROOT;
|
|
185
|
-
const file = path.join(folder, '.vscode', 'mcp.json');
|
|
186
|
-
await mergeJsonFile(file, (data) => {
|
|
195
|
+
async function writeIdeConfig(which, sc, env, folder = process.cwd()) {
|
|
196
|
+
const writeOne = async (id) => {
|
|
197
|
+
const target = IDE_CONFIG_TARGETS[id];
|
|
198
|
+
if (!target) return false;
|
|
199
|
+
if (target.needsFolder && !folder) {
|
|
200
|
+
console.log(err(`Skipping ${id}: pass a project folder for .vscode/mcp.json`));
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
const filePath = target.needsFolder ? target.path(folder) : target.path();
|
|
204
|
+
const built = target.build(sc, env);
|
|
205
|
+
const entry = built[target.mergeKey][target.entryKey];
|
|
206
|
+
await mergeJsonFile(filePath, (data) => {
|
|
187
207
|
const out = { ...data };
|
|
188
|
-
out.
|
|
208
|
+
out[target.mergeKey] = { ...(out[target.mergeKey] || {}), [target.entryKey]: entry };
|
|
189
209
|
return out;
|
|
190
210
|
});
|
|
191
|
-
console.log(ok(`Wrote
|
|
192
|
-
|
|
211
|
+
console.log(ok(`Wrote ${target.label}: ${filePath}`));
|
|
212
|
+
return true;
|
|
213
|
+
};
|
|
193
214
|
|
|
194
|
-
if (which === '
|
|
195
|
-
|
|
196
|
-
await
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
});
|
|
201
|
-
console.log(ok(`Wrote Windsurf MCP config: ${file}`));
|
|
215
|
+
if (which === 'all') {
|
|
216
|
+
await writeOne('cursor');
|
|
217
|
+
await writeOne('windsurf');
|
|
218
|
+
await writeOne('claude');
|
|
219
|
+
await writeOne('vscode');
|
|
220
|
+
return;
|
|
202
221
|
}
|
|
222
|
+
await writeOne(which);
|
|
203
223
|
}
|
|
204
224
|
|
|
205
225
|
function createDeepScanRuntime(folder) {
|
|
@@ -544,24 +564,38 @@ async function cmdStatus() {
|
|
|
544
564
|
|
|
545
565
|
async function cmdConfig() {
|
|
546
566
|
const folder = path.resolve(arg || process.cwd());
|
|
547
|
-
const lock = await readLock(folder);
|
|
548
|
-
const token = lock?.installToken || 'YOUR_INSTALL_TOKEN';
|
|
549
567
|
const apiBase = (flags['api-base'] || process.env.VIBESECUR_API_BASE || DEFAULT_API_BASE).trim();
|
|
568
|
+
const authToken = flags['auth-token'] || process.env.VIBESECUR_AUTH_TOKEN || '';
|
|
550
569
|
|
|
551
570
|
console.log(`\n${h('Vibesecur MCP - IDE Config Snippets')}`);
|
|
571
|
+
|
|
572
|
+
if (isUniversalMode(flags, authToken)) {
|
|
573
|
+
if (!authToken) {
|
|
574
|
+
console.log(err('Universal config requires VIBESECUR_AUTH_TOKEN or --auth-token=<jwt>'));
|
|
575
|
+
process.exit(1);
|
|
576
|
+
}
|
|
577
|
+
console.log(`Mode: ${BOLD}universal (account-wide)${RESET}`);
|
|
578
|
+
console.log(`API: ${apiBase}\n`);
|
|
579
|
+
const sc = serverCmd();
|
|
580
|
+
printIdeBlocks(sc, buildUniversalEnv(apiBase, authToken), { universal: true });
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
console.log(`Mode: ${BOLD}legacy (single folder)${RESET}`);
|
|
552
585
|
console.log(`Folder: ${folder}`);
|
|
553
|
-
|
|
586
|
+
const lock = await readLock(folder);
|
|
587
|
+
const token = lock?.installToken || 'YOUR_INSTALL_TOKEN';
|
|
588
|
+
if (!lock) console.log(err(`No lock found. Run: vibesecur-mcp init ${folder} --mode=legacy`));
|
|
554
589
|
else if (!isRuntimeCompatibleLock(lock)) {
|
|
555
590
|
console.log(err('Existing lock is local diagnostic-only and will not start the MCP runtime.'));
|
|
556
|
-
console.log(`Run: VIBESECUR_AUTH_TOKEN=<jwt> vibesecur-mcp
|
|
591
|
+
console.log(`Run: VIBESECUR_AUTH_TOKEN=<jwt> vibesecur-mcp init --mode=universal`);
|
|
557
592
|
console.log();
|
|
558
593
|
return;
|
|
559
594
|
}
|
|
560
595
|
console.log();
|
|
561
596
|
|
|
562
|
-
const env = buildEnv(folder, token, apiBase);
|
|
563
597
|
const sc = serverCmd();
|
|
564
|
-
printIdeBlocks(sc,
|
|
598
|
+
printIdeBlocks(sc, buildEnv(folder, token, apiBase), { universal: false });
|
|
565
599
|
}
|
|
566
600
|
|
|
567
601
|
async function cmdInit() {
|
|
@@ -570,13 +604,23 @@ async function cmdInit() {
|
|
|
570
604
|
const account = process.env.VIBESECUR_ACCOUNT || 'anonymous';
|
|
571
605
|
const skipBind = flags['skip-bind'] === true || flags['skip-bind'] === 'true';
|
|
572
606
|
const canFallbackLocal = allowLocalFallback();
|
|
607
|
+
const authToken = flags['auth-token'] || process.env.VIBESECUR_AUTH_TOKEN || '';
|
|
608
|
+
const write = flags.write;
|
|
573
609
|
|
|
574
610
|
console.log(`\n${h('Vibesecur MCP - Init')}`);
|
|
575
611
|
console.log(`Project folder: ${folder}`);
|
|
576
612
|
console.log(`API base: ${apiBase}`);
|
|
577
|
-
console.log(`Package: ${NPM_PACKAGE_NAME}\n`);
|
|
613
|
+
console.log(`Package: ${NPM_PACKAGE_NAME}@${mcpPkg.version}\n`);
|
|
578
614
|
|
|
579
|
-
|
|
615
|
+
if (isUniversalMode(flags, authToken)) {
|
|
616
|
+
if (!authToken) {
|
|
617
|
+
console.log(err('Universal init requires VIBESECUR_AUTH_TOKEN or --auth-token=<jwt> from the dashboard login.'));
|
|
618
|
+
console.log(dim('Example: npx -y @saiteja1123/mcp-server init --auth-token=<jwt> --write=all'));
|
|
619
|
+
process.exit(1);
|
|
620
|
+
}
|
|
621
|
+
await runUniversalSetup({ apiBase, authToken, folder, write });
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
580
624
|
|
|
581
625
|
let lock = await readLock(folder);
|
|
582
626
|
if (lock && !isRuntimeCompatibleLock(lock) && !skipBind) {
|
|
@@ -615,16 +659,15 @@ async function cmdInit() {
|
|
|
615
659
|
const sc = serverCmd();
|
|
616
660
|
|
|
617
661
|
console.log(`\n${BOLD}Next:${RESET} paste ONE block below into your IDE MCP settings, then reload the IDE.\n`);
|
|
618
|
-
printIdeBlocks(sc, env);
|
|
662
|
+
printIdeBlocks(sc, env, { universal: false });
|
|
619
663
|
|
|
620
|
-
const write = flags.write;
|
|
621
664
|
if (write) {
|
|
622
665
|
const w = String(write).toLowerCase();
|
|
623
|
-
if (!['cursor', 'vscode', 'windsurf', 'all'].includes(w)) {
|
|
624
|
-
console.log(err(`Invalid --write=${write}. Use: cursor | vscode | windsurf | all`));
|
|
666
|
+
if (!['cursor', 'vscode', 'windsurf', 'claude', 'all'].includes(w)) {
|
|
667
|
+
console.log(err(`Invalid --write=${write}. Use: cursor | vscode | windsurf | claude | all`));
|
|
625
668
|
process.exit(1);
|
|
626
669
|
}
|
|
627
|
-
await writeIdeConfig(w, sc, env);
|
|
670
|
+
await writeIdeConfig(w, sc, env, folder);
|
|
628
671
|
console.log(dim('Reload your IDE so it picks up the new MCP config.'));
|
|
629
672
|
}
|
|
630
673
|
}
|
|
@@ -632,28 +675,42 @@ async function cmdInit() {
|
|
|
632
675
|
async function cmdDoctor() {
|
|
633
676
|
const folder = path.resolve(arg || process.cwd());
|
|
634
677
|
const apiBase = (flags['api-base'] || process.env.VIBESECUR_API_BASE || DEFAULT_API_BASE).trim();
|
|
678
|
+
const authToken = flags['auth-token'] || process.env.VIBESECUR_AUTH_TOKEN || '';
|
|
679
|
+
const universal = isUniversalMode(flags, authToken);
|
|
635
680
|
|
|
636
681
|
console.log(`\n${h('Vibesecur MCP - Doctor')}`);
|
|
637
682
|
console.log(`Folder: ${folder}`);
|
|
638
|
-
console.log(`API base: ${apiBase}
|
|
683
|
+
console.log(`API base: ${apiBase}`);
|
|
684
|
+
console.log(`Mode: ${universal ? 'universal (account-wide)' : 'legacy (single folder)'}\n`);
|
|
639
685
|
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
686
|
+
if (universal) {
|
|
687
|
+
if (authToken) {
|
|
688
|
+
console.log(ok('VIBESECUR_AUTH_TOKEN present (universal mode ready)'));
|
|
689
|
+
} else {
|
|
690
|
+
console.log(err('VIBESECUR_AUTH_TOKEN missing — set it in IDE MCP env or pass --auth-token=<jwt>'));
|
|
691
|
+
}
|
|
692
|
+
console.log(dim('Per-project locks are optional in universal mode. Use projectUpsert before scanning a codebase.\n'));
|
|
643
693
|
} else {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
694
|
+
const lock = await readLock(folder);
|
|
695
|
+
if (!lock) {
|
|
696
|
+
console.log(err('No lock file. Run: vibesecur-mcp init --auth-token=<jwt> for universal mode'));
|
|
697
|
+
} else {
|
|
698
|
+
console.log(ok('Lock file present'));
|
|
699
|
+
const diag = await diagnosticLock(folder);
|
|
700
|
+
console.log(diag.healthy ? ok('Lock diagnostic: healthy') : err('Lock diagnostic: issues'));
|
|
701
|
+
console.log(diag.runtimeCompatible ? ok('Runtime binding: server-issued') : err('Runtime binding: not server-issued'));
|
|
702
|
+
if (diag.issues?.length) diag.issues.forEach((i) => console.log(` - ${i}`));
|
|
703
|
+
}
|
|
649
704
|
}
|
|
650
705
|
|
|
651
706
|
const tokenEnv = process.env.VIBESECUR_INSTALL_TOKEN;
|
|
652
707
|
const rootEnv = process.env.VIBESECUR_BOUND_ROOT;
|
|
653
|
-
|
|
654
|
-
console.log(
|
|
655
|
-
console.log(`
|
|
656
|
-
console.log(`
|
|
708
|
+
const authEnv = process.env.VIBESECUR_AUTH_TOKEN;
|
|
709
|
+
console.log(`\n${BOLD}Shell env (IDE injects these when MCP runs):${RESET}`);
|
|
710
|
+
console.log(` VIBESECUR_AUTH_TOKEN: ${authEnv ? dim('set') : dim('not set in this shell')}`);
|
|
711
|
+
console.log(` VIBESECUR_INSTALL_TOKEN: ${tokenEnv ? dim('set') : dim('not set (OK in universal mode)')}`);
|
|
712
|
+
console.log(` VIBESECUR_BOUND_ROOT: ${rootEnv ? dim('set') : dim('not set (OK in universal mode)')}`);
|
|
713
|
+
console.log(` VIBESECUR_API_BASE: ${process.env.VIBESECUR_API_BASE ? dim(process.env.VIBESECUR_API_BASE) : dim(`${DEFAULT_API_BASE} (default)`)}`);
|
|
657
714
|
|
|
658
715
|
const ping = await pingBackend(apiBase);
|
|
659
716
|
if (ping.skipped) {
|
|
@@ -669,18 +726,19 @@ async function cmdDoctor() {
|
|
|
669
726
|
}
|
|
670
727
|
|
|
671
728
|
console.log(`\n${BOLD}CLI:${RESET} ${NPM_PACKAGE_NAME}@${mcpPkg.version}`);
|
|
672
|
-
console.log(dim('
|
|
729
|
+
console.log(dim('Universal setup: npx -y @saiteja1123/mcp-server init --auth-token=<jwt> --write=all --api-base=URL'));
|
|
730
|
+
console.log(dim('If IDE still fails: reload IDE after pasting config, then run projectUpsert for your codebase.\n'));
|
|
673
731
|
}
|
|
674
732
|
|
|
675
733
|
function usage() {
|
|
676
734
|
console.log(`\n${h('Vibesecur MCP')}`);
|
|
677
|
-
console.log(` ${dim('Quick start:')}
|
|
678
|
-
console.log(' init [folder]
|
|
679
|
-
console.log(' doctor [folder] check
|
|
680
|
-
console.log(' bind <folder>
|
|
681
|
-
console.log(' rebind <folder> rotate
|
|
682
|
-
console.log(' status [folder] lock health');
|
|
683
|
-
console.log(' config [folder] print snippets
|
|
735
|
+
console.log(` ${dim('Quick start (universal):')} VIBESECUR_AUTH_TOKEN=<jwt> npx -y ${NPM_PACKAGE_NAME} init --write=all`);
|
|
736
|
+
console.log(' init [folder] print IDE configs [--auth-token=JWT] [--api-base=URL] [--mode=universal|legacy] [--write=cursor|vscode|windsurf|claude|all]');
|
|
737
|
+
console.log(' doctor [folder] check env + backend [--auth-token=JWT] [--api-base=URL] [--mode=universal]');
|
|
738
|
+
console.log(' bind <folder> legacy single-folder bind [--auth-token=JWT]');
|
|
739
|
+
console.log(' rebind <folder> rotate legacy folder token');
|
|
740
|
+
console.log(' status [folder] lock health (legacy mode)');
|
|
741
|
+
console.log(' config [folder] print IDE snippets [--auth-token=JWT] [--mode=universal]');
|
|
684
742
|
console.log(' deep-scan-start [folder] create and run local Deep Scan Project Map, deterministic scan, metadata-only test plan, Ralph tasks, and rerun comparison [--demo=true] [--human-approval=true] [--previous-run-id=<runId>] [--previous-scan-uri=<uri> --previous-scan-hash=<sha256>]');
|
|
685
743
|
console.log(' deep-scan-status <runId> [folder] inspect local Deep Scan status');
|
|
686
744
|
console.log(' deep-scan-approve <runId> [folder] record approval metadata');
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import os from 'os';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { createRequire } from 'module';
|
|
4
|
+
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const mcpPkg = require('../package.json');
|
|
7
|
+
|
|
8
|
+
export const NPM_PACKAGE_NAME = mcpPkg.name || '@saiteja1123/mcp-server';
|
|
9
|
+
export const DEFAULT_API_BASE = 'https://vibesecur.onrender.com';
|
|
10
|
+
export const PUBLISHED_SERVER_ARGS = ['-y', `${NPM_PACKAGE_NAME}@${mcpPkg.version}`, 'start'];
|
|
11
|
+
|
|
12
|
+
/** Stdio MCP launch via pinned npm package (works in every IDE). */
|
|
13
|
+
export function publishedServerCmd() {
|
|
14
|
+
return { command: 'npx', args: [...PUBLISHED_SERVER_ARGS] };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Legacy single-folder install env. */
|
|
18
|
+
export function buildLegacyEnv(folder, installToken, apiBase) {
|
|
19
|
+
return {
|
|
20
|
+
VIBESECUR_INSTALL_TOKEN: installToken,
|
|
21
|
+
VIBESECUR_BOUND_ROOT: folder,
|
|
22
|
+
VIBESECUR_API_BASE: apiBase || DEFAULT_API_BASE,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Account-wide universal install env — one config for all projects/IDEs. */
|
|
27
|
+
export function buildUniversalEnv(apiBase, authToken = '<paste-auth-token-from-dashboard>') {
|
|
28
|
+
const env = {
|
|
29
|
+
VIBESECUR_API_BASE: apiBase || DEFAULT_API_BASE,
|
|
30
|
+
VIBESECUR_AUTH_TOKEN: authToken,
|
|
31
|
+
};
|
|
32
|
+
return env;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isUniversalMode(flags = {}, authToken = '') {
|
|
36
|
+
const mode = String(flags.mode || flags['config-mode'] || '').toLowerCase();
|
|
37
|
+
if (mode === 'legacy' || mode === 'folder') return false;
|
|
38
|
+
if (mode === 'universal' || mode === 'account') return true;
|
|
39
|
+
return !!authToken;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function buildMcpServerEntry(sc, env) {
|
|
43
|
+
return { command: sc.command, args: sc.args, env };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function buildCursorConfig(sc, env) {
|
|
47
|
+
return { mcpServers: { vibesecur: buildMcpServerEntry(sc, env) } };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function buildWindsurfConfig(sc, env) {
|
|
51
|
+
return { mcpServers: { vibesecur: buildMcpServerEntry(sc, env) } };
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function buildClaudeDesktopConfig(sc, env) {
|
|
55
|
+
return { mcpServers: { vibesecur: buildMcpServerEntry(sc, env) } };
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function buildVsCodeMcpConfig(sc, env) {
|
|
59
|
+
return {
|
|
60
|
+
servers: {
|
|
61
|
+
vibesecur: { type: 'stdio', command: sc.command, args: sc.args, env },
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function buildContinueMcpConfig(sc, env) {
|
|
67
|
+
return {
|
|
68
|
+
experimental: {
|
|
69
|
+
modelContextProtocolServers: [
|
|
70
|
+
{
|
|
71
|
+
name: 'vibesecur',
|
|
72
|
+
transport: {
|
|
73
|
+
type: 'stdio',
|
|
74
|
+
command: sc.command,
|
|
75
|
+
args: sc.args,
|
|
76
|
+
env,
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const IDE_CONFIG_TARGETS = {
|
|
85
|
+
cursor: {
|
|
86
|
+
label: 'Cursor (~/.cursor/mcp.json)',
|
|
87
|
+
path: () => path.join(os.homedir(), '.cursor', 'mcp.json'),
|
|
88
|
+
build: buildCursorConfig,
|
|
89
|
+
mergeKey: 'mcpServers',
|
|
90
|
+
entryKey: 'vibesecur',
|
|
91
|
+
},
|
|
92
|
+
windsurf: {
|
|
93
|
+
label: 'Windsurf (~/.codeium/windsurf/mcp_config.json)',
|
|
94
|
+
path: () => path.join(os.homedir(), '.codeium', 'windsurf', 'mcp_config.json'),
|
|
95
|
+
build: buildWindsurfConfig,
|
|
96
|
+
mergeKey: 'mcpServers',
|
|
97
|
+
entryKey: 'vibesecur',
|
|
98
|
+
},
|
|
99
|
+
claude: {
|
|
100
|
+
label: 'Claude Desktop (%APPDATA%/Claude/claude_desktop_config.json)',
|
|
101
|
+
path: () => path.join(
|
|
102
|
+
process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming'),
|
|
103
|
+
'Claude',
|
|
104
|
+
'claude_desktop_config.json',
|
|
105
|
+
),
|
|
106
|
+
build: buildClaudeDesktopConfig,
|
|
107
|
+
mergeKey: 'mcpServers',
|
|
108
|
+
entryKey: 'vibesecur',
|
|
109
|
+
},
|
|
110
|
+
vscode: {
|
|
111
|
+
label: 'VS Code (project .vscode/mcp.json)',
|
|
112
|
+
path: (folder) => path.join(folder, '.vscode', 'mcp.json'),
|
|
113
|
+
build: buildVsCodeMcpConfig,
|
|
114
|
+
mergeKey: 'servers',
|
|
115
|
+
entryKey: 'vibesecur',
|
|
116
|
+
needsFolder: true,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export function formatIdeConfigBlocks(sc, env, { universal = false } = {}) {
|
|
121
|
+
const lines = [];
|
|
122
|
+
const note = universal
|
|
123
|
+
? 'Universal account config — works across projects. Use projectUpsert before scanning a new codebase.'
|
|
124
|
+
: 'Single-folder legacy config — bound to one project root.';
|
|
125
|
+
|
|
126
|
+
lines.push({ title: 'Mode', body: note });
|
|
127
|
+
|
|
128
|
+
for (const [id, target] of Object.entries(IDE_CONFIG_TARGETS)) {
|
|
129
|
+
if (id === 'vscode') {
|
|
130
|
+
lines.push({
|
|
131
|
+
id,
|
|
132
|
+
title: target.label,
|
|
133
|
+
body: JSON.stringify(target.build(sc, env), null, 2),
|
|
134
|
+
});
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
lines.push({
|
|
138
|
+
id,
|
|
139
|
+
title: target.label,
|
|
140
|
+
body: JSON.stringify(target.build(sc, env), null, 2),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
lines.push({
|
|
145
|
+
id: 'continue',
|
|
146
|
+
title: 'Continue.dev (~/.continue/config.json fragment)',
|
|
147
|
+
body: JSON.stringify(buildContinueMcpConfig(sc, env), null, 2),
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
lines.push({
|
|
151
|
+
id: 'generic',
|
|
152
|
+
title: 'Generic stdio MCP client',
|
|
153
|
+
body: [
|
|
154
|
+
`command: ${sc.command}`,
|
|
155
|
+
`args: ${sc.args.join(' ')}`,
|
|
156
|
+
...Object.entries(env).map(([k, v]) => `${k}=${v}`),
|
|
157
|
+
].join('\n'),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
return lines;
|
|
161
|
+
}
|