@viberaven/mcp 1.1.7 → 1.2.0

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/server.js DELETED
@@ -1,407 +0,0 @@
1
- #!/usr/bin/env node
2
- const { spawn } = require('node:child_process');
3
- let spawnChild = spawn;
4
-
5
- const SERVER_INFO = { name: 'viberaven-mcp', version: '1.1.7' };
6
- const CLI_PACKAGE = '@viberaven/cli';
7
-
8
- const cwdSchema = {
9
- type: 'object',
10
- properties: {
11
- cwd: { type: 'string', description: 'Project root. Defaults to the MCP server working directory.' }
12
- },
13
- additionalProperties: false
14
- };
15
-
16
- const healSchema = {
17
- type: 'object',
18
- properties: {
19
- cwd: { type: 'string' },
20
- target: { type: 'string' },
21
- gap: { type: 'string' },
22
- yes: { type: 'boolean' }
23
- },
24
- additionalProperties: false
25
- };
26
-
27
- const TOOLS = [
28
- {
29
- name: 'viberaven_check_readiness',
30
- description: 'Run the VibeRaven agent-mode production-readiness check and write .viberaven artifacts.',
31
- inputSchema: cwdSchema
32
- },
33
- {
34
- name: 'viberaven_verify',
35
- description: 'Rescan and refresh VibeRaven production-readiness artifacts after a fix.',
36
- inputSchema: cwdSchema
37
- },
38
- {
39
- name: 'viberaven_audit',
40
- description: 'Run local Vercel/Supabase production checks for RLS, service-role boundaries, and Vercel pooler usage.',
41
- inputSchema: {
42
- type: 'object',
43
- properties: {
44
- cwd: { type: 'string', description: 'Project root. Defaults to current working directory.' },
45
- json: { type: 'boolean', description: 'Return JSON output.' }
46
- },
47
- additionalProperties: false
48
- }
49
- },
50
- {
51
- name: 'viberaven_init_rules',
52
- description: 'Install bounded VibeRaven rules into native AI instruction files.',
53
- inputSchema: {
54
- type: 'object',
55
- properties: {
56
- cwd: { type: 'string', description: 'Project root. Defaults to current working directory.' },
57
- agents: { type: 'string', description: 'Comma-separated agent targets, or all.' },
58
- dryRun: { type: 'boolean', description: 'Preview changes without writing files.' }
59
- },
60
- additionalProperties: false
61
- }
62
- },
63
- {
64
- name: 'viberaven_clean_plan',
65
- description: 'Write a non-destructive context cleanup plan for generated artifacts and logs.',
66
- inputSchema: cwdSchema
67
- },
68
- {
69
- name: 'viberaven_strict_gate',
70
- description: 'Run VibeRaven agent-mode strict gate and return the machine verdict.',
71
- inputSchema: cwdSchema
72
- },
73
- {
74
- name: 'viberaven_gate_result',
75
- description: 'Run VibeRaven agent-mode JSON output and return gate-result.json content.',
76
- inputSchema: cwdSchema
77
- },
78
- {
79
- name: 'viberaven_context_map',
80
- description: 'Refresh .viberaven/context-map.json from the last scan.',
81
- inputSchema: cwdSchema
82
- },
83
- {
84
- name: 'viberaven_actions',
85
- description: 'Read the current VibeRaven chat-native action surface from .viberaven/actions.json.',
86
- inputSchema: cwdSchema
87
- },
88
- {
89
- name: 'viberaven_verify_action',
90
- description: 'Verify or explain the lifecycle state for a stable VibeRaven action ID.',
91
- inputSchema: {
92
- type: 'object',
93
- properties: {
94
- cwd: { type: 'string' },
95
- actionId: { type: 'string' }
96
- },
97
- required: ['actionId'],
98
- additionalProperties: false
99
- }
100
- },
101
- {
102
- name: 'viberaven_heal_plan',
103
- description: 'Write a non-destructive VibeRaven heal plan for a target file or gap.',
104
- inputSchema: healSchema
105
- },
106
- {
107
- name: 'viberaven_heal_prompt',
108
- description: 'Write an agent-ready VibeRaven heal prompt for a target file or gap.',
109
- inputSchema: healSchema
110
- },
111
- {
112
- name: 'viberaven_heal_apply',
113
- description: 'Apply a guarded VibeRaven repo-code heal recipe when supported.',
114
- inputSchema: healSchema
115
- },
116
- {
117
- name: 'viberaven_validate_npm_package',
118
- description:
119
- 'Check whether an npm package name exists and looks safe before install. Always run viberaven --agent-mode after adding dependencies.',
120
- inputSchema: {
121
- type: 'object',
122
- properties: {
123
- packageName: { type: 'string', description: 'Single npm package name to validate.' },
124
- packageNames: {
125
- type: 'array',
126
- items: { type: 'string' },
127
- description: 'Multiple npm package names to validate in one call.'
128
- }
129
- },
130
- additionalProperties: false
131
- }
132
- }
133
- ];
134
-
135
- let buffer = Buffer.alloc(0);
136
-
137
- function main() {
138
- if (process.argv.includes('--help') || process.argv.includes('-h')) {
139
- console.log(`${SERVER_INFO.name} ${SERVER_INFO.version}`);
140
- console.log(`MCP stdio server wrapping npx -y ${CLI_PACKAGE}.`);
141
- process.exit(0);
142
- }
143
-
144
- process.stdin.on('data', (chunk) => {
145
- buffer = Buffer.concat([buffer, chunk]);
146
- drainMessages();
147
- });
148
- }
149
-
150
- function drainMessages() {
151
- while (true) {
152
- const headerEnd = buffer.indexOf('\r\n\r\n');
153
- if (headerEnd === -1) return;
154
-
155
- const header = buffer.slice(0, headerEnd).toString('utf8');
156
- const match = header.match(/content-length:\s*(\d+)/i);
157
- if (!match) {
158
- buffer = buffer.slice(headerEnd + 4);
159
- continue;
160
- }
161
-
162
- const length = Number(match[1]);
163
- const messageStart = headerEnd + 4;
164
- const messageEnd = messageStart + length;
165
- if (buffer.length < messageEnd) return;
166
-
167
- const raw = buffer.slice(messageStart, messageEnd).toString('utf8');
168
- buffer = buffer.slice(messageEnd);
169
- void handleRawMessage(raw);
170
- }
171
- }
172
-
173
- async function handleRawMessage(raw) {
174
- let message;
175
- try {
176
- message = JSON.parse(raw);
177
- } catch {
178
- return;
179
- }
180
-
181
- if (!message || typeof message.method !== 'string') return;
182
- if (message.id === undefined || message.id === null) return;
183
-
184
- try {
185
- const result = await handleRequest(message.method, message.params || {});
186
- send({ jsonrpc: '2.0', id: message.id, result });
187
- } catch (error) {
188
- send({
189
- jsonrpc: '2.0',
190
- id: message.id,
191
- error: {
192
- code: -32000,
193
- message: error instanceof Error ? error.message : String(error)
194
- }
195
- });
196
- }
197
- }
198
-
199
- async function handleRequest(method, params) {
200
- if (method === 'initialize') {
201
- return {
202
- protocolVersion: params.protocolVersion || '2024-11-05',
203
- capabilities: { tools: {} },
204
- serverInfo: SERVER_INFO
205
- };
206
- }
207
-
208
- if (method === 'tools/list') {
209
- return { tools: TOOLS };
210
- }
211
-
212
- if (method === 'tools/call') {
213
- const name = params.name;
214
- const args = params.arguments || {};
215
- const text = await callTool(name, args);
216
- const parsed = parseJsonObjectFromToolText(text);
217
- return {
218
- content: [{ type: 'text', text }],
219
- ...(parsed ? { structuredContent: parsed } : {})
220
- };
221
- }
222
-
223
- throw new Error(`Unsupported MCP method: ${method}`);
224
- }
225
-
226
- async function callTool(name, args) {
227
- return runVibeRaven(['-y', CLI_PACKAGE, ...buildToolArgs(name, args || {})], args && args.cwd);
228
- }
229
-
230
- function buildToolArgs(name, args) {
231
- if (name === 'viberaven_check_readiness') {
232
- return ['--agent-mode'];
233
- }
234
- if (name === 'viberaven_verify') {
235
- return ['--verify'];
236
- }
237
- if (name === 'viberaven_audit') {
238
- return ['audit', '--vercel-supabase', ...(args.json ? ['--json'] : [])];
239
- }
240
- if (name === 'viberaven_init_rules') {
241
- const cliArgs = ['init'];
242
- if (args.agents) cliArgs.push('--agents', safeStringArg(args.agents, 'agents'));
243
- if (args.dryRun) cliArgs.push('--dry-run');
244
- return cliArgs;
245
- }
246
- if (name === 'viberaven_clean_plan') {
247
- return ['clean', '--plan'];
248
- }
249
- if (name === 'viberaven_strict_gate') {
250
- return ['--agent-mode', '--strict', '--json'];
251
- }
252
- if (name === 'viberaven_gate_result') {
253
- return ['--agent-mode', '--json'];
254
- }
255
- if (name === 'viberaven_context_map') {
256
- return ['--condense'];
257
- }
258
- if (name === 'viberaven_actions') {
259
- return ['actions'];
260
- }
261
- if (name === 'viberaven_verify_action') {
262
- return ['--verify', '--action', safeStringArg(args.actionId, 'actionId')];
263
- }
264
- if (name === 'viberaven_heal_plan') {
265
- return buildHealArgs(['--heal', '--plan'], args);
266
- }
267
- if (name === 'viberaven_heal_prompt') {
268
- return buildHealArgs(['--heal', '--prompt'], args);
269
- }
270
- if (name === 'viberaven_heal_apply') {
271
- const cliArgs = buildHealArgs(['--heal', '--apply'], args);
272
- if (args.yes === true) cliArgs.push('--yes');
273
- return cliArgs;
274
- }
275
- if (name === 'viberaven_validate_npm_package') {
276
- const names = [];
277
- if (args.packageName) {
278
- names.push(safeStringArg(args.packageName, 'packageName'));
279
- }
280
- if (Array.isArray(args.packageNames)) {
281
- for (const entry of args.packageNames) {
282
- names.push(safeStringArg(entry, 'packageName'));
283
- }
284
- }
285
- if (names.length === 0) {
286
- throw new Error('packageName or packageNames is required');
287
- }
288
- return ['validate-npm-package', '--json', ...names];
289
- }
290
- throw new Error(`Unknown VibeRaven tool: ${name}`);
291
- }
292
-
293
- function buildHealArgs(prefix, args) {
294
- const cliArgs = [...prefix];
295
- if (args.target) cliArgs.push('--target', safeStringArg(args.target, 'target'));
296
- if (args.gap) cliArgs.push('--gap', safeStringArg(args.gap, 'gap'));
297
- return cliArgs;
298
- }
299
-
300
- function safeStringArg(value, label) {
301
- if (typeof value !== 'string') {
302
- throw new Error(`Invalid ${label}: expected string`);
303
- }
304
-
305
- if (!value.trim()) {
306
- throw new Error(`Invalid ${label}: expected non-empty string`);
307
- }
308
-
309
- if (/[&|<>^%!"\r\n]/.test(value)) {
310
- throw new Error(`Unsafe characters in ${label}`);
311
- }
312
-
313
- return value;
314
- }
315
-
316
- function resolveCwd(cwd) {
317
- if (cwd === undefined || cwd === null) {
318
- return process.cwd();
319
- }
320
-
321
- if (typeof cwd !== 'string') {
322
- throw new Error('Invalid cwd: expected string');
323
- }
324
-
325
- if (!cwd.trim()) {
326
- throw new Error('Invalid cwd: expected non-empty string');
327
- }
328
-
329
- return cwd;
330
- }
331
-
332
- function buildNpxCommand(args) {
333
- if (process.platform === 'win32') {
334
- return {
335
- command: 'cmd.exe',
336
- args: ['/d', '/s', '/c', 'npx', ...args],
337
- options: { shell: false }
338
- };
339
- }
340
-
341
- return {
342
- command: 'npx',
343
- args,
344
- options: { shell: false }
345
- };
346
- }
347
-
348
- function runVibeRaven(args, cwd) {
349
- return new Promise((resolve) => {
350
- const built = buildNpxCommand(args);
351
- const child = spawnChild(built.command, built.args, {
352
- cwd: resolveCwd(cwd),
353
- env: process.env,
354
- shell: built.options.shell,
355
- stdio: ['ignore', 'pipe', 'pipe']
356
- });
357
- let stdout = '';
358
- let stderr = '';
359
- child.stdout.on('data', (chunk) => {
360
- stdout += chunk.toString();
361
- });
362
- child.stderr.on('data', (chunk) => {
363
- stderr += chunk.toString();
364
- });
365
- child.on('error', (error) => {
366
- resolve(`ERROR: ${error.message}`);
367
- });
368
- child.on('close', (code) => {
369
- const combined = `${stdout}${stderr}`.trim();
370
- resolve(`exit ${code ?? 1}${combined ? `\n${combined}` : ''}`);
371
- });
372
- });
373
- }
374
-
375
- function parseJsonObjectFromToolText(text) {
376
- const jsonStart = text.indexOf('{');
377
- if (jsonStart === -1) return undefined;
378
- try {
379
- return JSON.parse(text.slice(jsonStart));
380
- } catch {
381
- return undefined;
382
- }
383
- }
384
-
385
- function send(message) {
386
- const body = JSON.stringify(message);
387
- process.stdout.write(`Content-Length: ${Buffer.byteLength(body, 'utf8')}\r\n\r\n${body}`);
388
- }
389
-
390
- if (require.main === module) {
391
- main();
392
- }
393
-
394
- module.exports = {
395
- TOOLS,
396
- buildNpxCommand,
397
- callTool,
398
- handleRequest,
399
- parseJsonObjectFromToolText,
400
- safeStringArg,
401
- __setSpawnForTest(spawnForTest) {
402
- spawnChild = spawnForTest;
403
- },
404
- __resetSpawnForTest() {
405
- spawnChild = spawn;
406
- }
407
- };
@@ -1,175 +0,0 @@
1
- #!/usr/bin/env node
2
- const { spawn } = require('node:child_process');
3
- const readline = require('node:readline');
4
-
5
- const serverInfo = {
6
- name: 'viberaven-mcp',
7
- version: '0.1.0-beta.0',
8
- };
9
-
10
- const tools = [
11
- {
12
- name: 'viberaven_scan',
13
- description: 'Scan an AI-built app for launch-readiness gaps and write .viberaven artifacts.',
14
- inputSchema: {
15
- type: 'object',
16
- properties: {
17
- cwd: { type: 'string', description: 'Workspace directory to scan. Defaults to the MCP process cwd.' },
18
- json: { type: 'boolean', description: 'Return CLI JSON output when supported.' },
19
- },
20
- },
21
- },
22
- {
23
- name: 'viberaven_next',
24
- description: 'Return the next recommended launch-readiness action from the last scan.',
25
- inputSchema: {
26
- type: 'object',
27
- properties: {
28
- cwd: { type: 'string', description: 'Workspace directory. Defaults to the MCP process cwd.' },
29
- },
30
- },
31
- },
32
- {
33
- name: 'viberaven_prompt',
34
- description: 'Return a copy-ready coding-agent prompt for a launch gap.',
35
- inputSchema: {
36
- type: 'object',
37
- properties: {
38
- cwd: { type: 'string', description: 'Workspace directory. Defaults to the MCP process cwd.' },
39
- gap: { type: 'string', description: 'Gap id from .viberaven/last-scan.json or viberaven_next.' },
40
- area: { type: 'string', description: 'Optional production area such as auth, database, payments, deployment.' },
41
- provider: { type: 'string', description: 'Optional provider such as clerk, supabase, stripe, vercel.' },
42
- },
43
- },
44
- },
45
- {
46
- name: 'viberaven_status',
47
- description: 'Return VibeRaven account and scan quota status.',
48
- inputSchema: {
49
- type: 'object',
50
- properties: {
51
- cwd: { type: 'string', description: 'Workspace directory. Defaults to the MCP process cwd.' },
52
- },
53
- },
54
- },
55
- {
56
- name: 'viberaven_report',
57
- description: 'Rebuild .viberaven/report.html from the last scan without consuming scan quota.',
58
- inputSchema: {
59
- type: 'object',
60
- properties: {
61
- cwd: { type: 'string', description: 'Workspace directory. Defaults to the MCP process cwd.' },
62
- },
63
- },
64
- },
65
- ];
66
-
67
- function write(message) {
68
- process.stdout.write(`${JSON.stringify(message)}\n`);
69
- }
70
-
71
- function runCli(args, cwd) {
72
- return new Promise((resolve) => {
73
- const child = spawn('npx', ['-y', '@viberaven/cli@beta', ...args], {
74
- cwd: cwd || process.cwd(),
75
- shell: process.platform === 'win32',
76
- env: process.env,
77
- });
78
- let stdout = '';
79
- let stderr = '';
80
- child.stdout.on('data', (chunk) => {
81
- stdout += chunk.toString();
82
- });
83
- child.stderr.on('data', (chunk) => {
84
- stderr += chunk.toString();
85
- });
86
- child.on('close', (code) => {
87
- resolve({ code, stdout, stderr });
88
- });
89
- });
90
- }
91
-
92
- function textResult(text, isError = false) {
93
- return {
94
- content: [{ type: 'text', text: text || '(no output)' }],
95
- isError,
96
- };
97
- }
98
-
99
- async function callTool(name, input = {}) {
100
- const cwd = typeof input.cwd === 'string' && input.cwd.trim() ? input.cwd : undefined;
101
- if (name === 'viberaven_scan') {
102
- const args = ['scan'];
103
- if (input.json) args.push('--json');
104
- const result = await runCli(args, cwd);
105
- return textResult(`${result.stdout}${result.stderr ? `\n${result.stderr}` : ''}`.trim(), result.code !== 0);
106
- }
107
- if (name === 'viberaven_next') {
108
- const result = await runCli(['next', '--json'], cwd);
109
- return textResult(`${result.stdout}${result.stderr ? `\n${result.stderr}` : ''}`.trim(), result.code !== 0);
110
- }
111
- if (name === 'viberaven_prompt') {
112
- const args = ['prompt', '--no-copy'];
113
- if (input.gap) args.push('--gap', String(input.gap));
114
- if (input.area) args.push('--area', String(input.area));
115
- if (input.provider) args.push('--provider', String(input.provider));
116
- const result = await runCli(args, cwd);
117
- return textResult(`${result.stdout}${result.stderr ? `\n${result.stderr}` : ''}`.trim(), result.code !== 0);
118
- }
119
- if (name === 'viberaven_status') {
120
- const result = await runCli(['status', '--json'], cwd);
121
- return textResult(`${result.stdout}${result.stderr ? `\n${result.stderr}` : ''}`.trim(), result.code !== 0);
122
- }
123
- if (name === 'viberaven_report') {
124
- const result = await runCli(['report'], cwd);
125
- return textResult(`${result.stdout}${result.stderr ? `\n${result.stderr}` : ''}`.trim(), result.code !== 0);
126
- }
127
- return textResult(`Unknown VibeRaven MCP tool: ${name}`, true);
128
- }
129
-
130
- const rl = readline.createInterface({ input: process.stdin });
131
-
132
- rl.on('line', async (line) => {
133
- if (!line.trim()) return;
134
- let request;
135
- try {
136
- request = JSON.parse(line);
137
- } catch {
138
- return;
139
- }
140
-
141
- if (request.method === 'initialize') {
142
- write({
143
- jsonrpc: '2.0',
144
- id: request.id,
145
- result: {
146
- protocolVersion: '2024-11-05',
147
- capabilities: { tools: {} },
148
- serverInfo,
149
- },
150
- });
151
- return;
152
- }
153
-
154
- if (request.method === 'notifications/initialized') {
155
- return;
156
- }
157
-
158
- if (request.method === 'tools/list') {
159
- write({ jsonrpc: '2.0', id: request.id, result: { tools } });
160
- return;
161
- }
162
-
163
- if (request.method === 'tools/call') {
164
- const params = request.params || {};
165
- const result = await callTool(params.name, params.arguments || {});
166
- write({ jsonrpc: '2.0', id: request.id, result });
167
- return;
168
- }
169
-
170
- write({
171
- jsonrpc: '2.0',
172
- id: request.id,
173
- error: { code: -32601, message: `Method not found: ${request.method}` },
174
- });
175
- });