@viberaven/mcp 0.1.0-beta.1 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +43 -7
  2. package/bin/server.js +214 -69
  3. package/package.json +5 -3
package/README.md CHANGED
@@ -4,20 +4,56 @@ Thin MCP wrapper for VibeRaven.
4
4
 
5
5
  This package exposes VibeRaven CLI actions as MCP tools for Codex, Claude Code, Cursor, and other agent runtimes. It does not contain VibeRaven backend logic and does not bypass VibeRaven login or scan quotas.
6
6
 
7
+ The MCP server wraps the stable CLI package: `npx -y viberaven`.
8
+
7
9
  ## Run
8
10
 
9
11
  ```bash
10
- npx -y @viberaven/mcp@beta
12
+ npx -y @viberaven/mcp
13
+ ```
14
+
15
+ You can also start the MCP server from the main CLI package:
16
+
17
+ ```bash
18
+ npx -y viberaven mcp
11
19
  ```
12
20
 
13
21
  ## Tools
14
22
 
15
- - `viberaven_scan` -> `npx -y @viberaven/cli@beta scan`
16
- - `viberaven_status` -> `npx -y @viberaven/cli@beta status`
17
- - `viberaven_next` -> `npx -y @viberaven/cli@beta next --json`
18
- - `viberaven_prompt` -> `npx -y @viberaven/cli@beta prompt`
19
- - `viberaven_login` -> `npx -y @viberaven/cli@beta login`
23
+ - `viberaven_check_readiness` -> `npx -y viberaven --agent-mode`
24
+ - `viberaven_verify` -> `npx -y viberaven --verify`
25
+ - `viberaven_audit` -> `npx -y viberaven audit --vercel-supabase`
26
+ - `viberaven_init_rules` -> `npx -y viberaven init`
27
+ - `viberaven_clean_plan` -> `npx -y viberaven clean --plan`
28
+ - `viberaven_strict_gate` -> `npx -y viberaven --agent-mode --strict --json`
29
+ - `viberaven_gate_result` -> `npx -y viberaven --agent-mode --json`
30
+ - `viberaven_context_map` -> `npx -y viberaven --condense`
31
+ - `viberaven_heal_plan` -> `npx -y viberaven --heal --plan`
32
+ - `viberaven_heal_prompt` -> `npx -y viberaven --heal --prompt`
33
+ - `viberaven_heal_apply` -> `npx -y viberaven --heal --apply`
34
+
35
+ `viberaven_check_readiness` is the canonical entrypoint. It runs VibeRaven as the Agent Context + Production Gate and writes `.viberaven/agent-tasklist.md`, `.viberaven/gate-result.json`, and `.viberaven/context-map.json`.
36
+
37
+ After one fix, call `viberaven_verify`. Before deploy or CI pass, call `viberaven_strict_gate` or run:
38
+
39
+ ```bash
40
+ npx -y viberaven --strict
41
+ ```
42
+
43
+ ## Machine Artifact Contract
44
+
45
+ ```text
46
+ docs/contracts/artifacts.md
47
+ https://viberaven.dev/schemas/gate-result.schema.json
48
+ https://viberaven.dev/schemas/context-map.schema.json
49
+ https://viberaven.dev/schemas/gap.schema.json
50
+ https://viberaven.dev/schemas/heal-result.schema.json
51
+ ```
52
+
53
+ ## Login
54
+
55
+ If VibeRaven prints `LOGIN_URL_READY`, open that exact URL for the user, keep the MCP call alive, and do not ask for passwords, tokens, cookies, or other secrets.
20
56
 
21
57
  ## Security
22
58
 
23
- The MCP package is public integration glue only. The CLI still calls the managed VibeRaven API after user login. Free and Pro quota rules still apply.
59
+ The MCP package is public integration glue only. It returns CLI stdout/stderr and structured JSON content when available. It does not mutate provider dashboards and does not bypass VibeRaven login, managed API checks, or quota enforcement. Do not claim provider dashboard checks are fixed by repo-code edits.
package/bin/server.js CHANGED
@@ -1,84 +1,116 @@
1
1
  #!/usr/bin/env node
2
2
  const { spawn } = require('node:child_process');
3
+ let spawnChild = spawn;
3
4
 
4
- const SERVER_INFO = { name: 'viberaven-mcp', version: '0.1.0-beta.1' };
5
+ const SERVER_INFO = { name: 'viberaven-mcp', version: '1.0.0' };
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
+ };
5
26
 
6
27
  const TOOLS = [
7
28
  {
8
- name: 'viberaven_scan',
9
- description: 'Run VibeRaven launch-readiness scan in a project. Opens VibeRaven login when required.',
10
- inputSchema: {
11
- type: 'object',
12
- properties: {
13
- cwd: { type: 'string', description: 'Project root to scan. Defaults to the MCP server working directory.' },
14
- path: { type: 'string', description: 'Optional path argument passed to viberaven scan.' },
15
- open: { type: 'boolean', description: 'Open the generated report after scan.' }
16
- },
17
- additionalProperties: false
18
- }
29
+ name: 'viberaven_check_readiness',
30
+ description: 'Run the VibeRaven agent-mode production-readiness check and write .viberaven artifacts.',
31
+ inputSchema: cwdSchema
19
32
  },
20
33
  {
21
- name: 'viberaven_status',
22
- description: 'Show VibeRaven account, quota, and last scan status.',
23
- inputSchema: {
24
- type: 'object',
25
- properties: {
26
- cwd: { type: 'string', description: 'Project root. Defaults to the MCP server working directory.' },
27
- json: { type: 'boolean', description: 'Return machine-readable status JSON.' }
28
- },
29
- additionalProperties: false
30
- }
34
+ name: 'viberaven_verify',
35
+ description: 'Rescan and refresh VibeRaven production-readiness artifacts after a fix.',
36
+ inputSchema: cwdSchema
31
37
  },
32
38
  {
33
- name: 'viberaven_next',
34
- description: 'Return the next VibeRaven production action from the last scan.',
39
+ name: 'viberaven_audit',
40
+ description: 'Run local Vercel/Supabase production checks for RLS, service-role boundaries, and Vercel pooler usage.',
35
41
  inputSchema: {
36
42
  type: 'object',
37
43
  properties: {
38
- cwd: { type: 'string', description: 'Project root. Defaults to the MCP server working directory.' }
44
+ cwd: { type: 'string', description: 'Project root. Defaults to current working directory.' },
45
+ json: { type: 'boolean', description: 'Return JSON output.' }
39
46
  },
40
47
  additionalProperties: false
41
48
  }
42
49
  },
43
50
  {
44
- name: 'viberaven_prompt',
45
- description: 'Return the focused VibeRaven fix prompt for the top or selected gap.',
51
+ name: 'viberaven_init_rules',
52
+ description: 'Install bounded VibeRaven rules into native AI instruction files.',
46
53
  inputSchema: {
47
54
  type: 'object',
48
55
  properties: {
49
- cwd: { type: 'string', description: 'Project root. Defaults to the MCP server working directory.' },
50
- gap: { type: 'string', description: 'Optional gap id.' },
51
- area: { type: 'string', description: 'Optional production area.' },
52
- provider: { type: 'string', description: 'Optional provider key.' }
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.' }
53
59
  },
54
60
  additionalProperties: false
55
61
  }
56
62
  },
57
63
  {
58
- name: 'viberaven_login',
59
- description: 'Start VibeRaven browser sign-in and save local CLI credentials after approval.',
60
- inputSchema: {
61
- type: 'object',
62
- properties: {
63
- cwd: { type: 'string', description: 'Working directory. Defaults to the MCP server working directory.' }
64
- },
65
- additionalProperties: false
66
- }
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_heal_plan',
85
+ description: 'Write a non-destructive VibeRaven heal plan for a target file or gap.',
86
+ inputSchema: healSchema
87
+ },
88
+ {
89
+ name: 'viberaven_heal_prompt',
90
+ description: 'Write an agent-ready VibeRaven heal prompt for a target file or gap.',
91
+ inputSchema: healSchema
92
+ },
93
+ {
94
+ name: 'viberaven_heal_apply',
95
+ description: 'Apply a guarded VibeRaven repo-code heal recipe when supported.',
96
+ inputSchema: healSchema
67
97
  }
68
98
  ];
69
99
 
70
- if (process.argv.includes('--help') || process.argv.includes('-h')) {
71
- console.log(`${SERVER_INFO.name} ${SERVER_INFO.version}`);
72
- console.log('MCP stdio server wrapping npx -y @viberaven/cli@beta.');
73
- process.exit(0);
74
- }
75
-
76
100
  let buffer = Buffer.alloc(0);
77
101
 
78
- process.stdin.on('data', (chunk) => {
79
- buffer = Buffer.concat([buffer, chunk]);
80
- drainMessages();
81
- });
102
+ function main() {
103
+ if (process.argv.includes('--help') || process.argv.includes('-h')) {
104
+ console.log(`${SERVER_INFO.name} ${SERVER_INFO.version}`);
105
+ console.log(`MCP stdio server wrapping npx -y ${CLI_PACKAGE}.`);
106
+ process.exit(0);
107
+ }
108
+
109
+ process.stdin.on('data', (chunk) => {
110
+ buffer = Buffer.concat([buffer, chunk]);
111
+ drainMessages();
112
+ });
113
+ }
82
114
 
83
115
  function drainMessages() {
84
116
  while (true) {
@@ -146,41 +178,125 @@ async function handleRequest(method, params) {
146
178
  const name = params.name;
147
179
  const args = params.arguments || {};
148
180
  const text = await callTool(name, args);
149
- return { content: [{ type: 'text', text }] };
181
+ const parsed = parseJsonObjectFromToolText(text);
182
+ return {
183
+ content: [{ type: 'text', text }],
184
+ ...(parsed ? { structuredContent: parsed } : {})
185
+ };
150
186
  }
151
187
 
152
188
  throw new Error(`Unsupported MCP method: ${method}`);
153
189
  }
154
190
 
155
191
  async function callTool(name, args) {
156
- if (name === 'viberaven_scan') {
157
- return runVibeRaven(['scan', ...(args.open ? ['--open'] : []), ...(args.path ? [String(args.path)] : [])], args.cwd);
192
+ return runVibeRaven(['-y', CLI_PACKAGE, ...buildToolArgs(name, args || {})], args && args.cwd);
193
+ }
194
+
195
+ function buildToolArgs(name, args) {
196
+ if (name === 'viberaven_check_readiness') {
197
+ return ['--agent-mode'];
198
+ }
199
+ if (name === 'viberaven_verify') {
200
+ return ['--verify'];
201
+ }
202
+ if (name === 'viberaven_audit') {
203
+ return ['audit', '--vercel-supabase', ...(args.json ? ['--json'] : [])];
204
+ }
205
+ if (name === 'viberaven_init_rules') {
206
+ const cliArgs = ['init'];
207
+ if (args.agents) cliArgs.push('--agents', safeStringArg(args.agents, 'agents'));
208
+ if (args.dryRun) cliArgs.push('--dry-run');
209
+ return cliArgs;
210
+ }
211
+ if (name === 'viberaven_clean_plan') {
212
+ return ['clean', '--plan'];
158
213
  }
159
- if (name === 'viberaven_status') {
160
- return runVibeRaven(['status', ...(args.json ? ['--json'] : [])], args.cwd);
214
+ if (name === 'viberaven_strict_gate') {
215
+ return ['--agent-mode', '--strict', '--json'];
161
216
  }
162
- if (name === 'viberaven_next') {
163
- return runVibeRaven(['next', '--json'], args.cwd);
217
+ if (name === 'viberaven_gate_result') {
218
+ return ['--agent-mode', '--json'];
164
219
  }
165
- if (name === 'viberaven_prompt') {
166
- const cliArgs = ['prompt'];
167
- if (args.gap) cliArgs.push('--gap', String(args.gap));
168
- if (args.area) cliArgs.push('--area', String(args.area));
169
- if (args.provider) cliArgs.push('--provider', String(args.provider));
170
- return runVibeRaven(cliArgs, args.cwd);
220
+ if (name === 'viberaven_context_map') {
221
+ return ['--condense'];
171
222
  }
172
- if (name === 'viberaven_login') {
173
- return runVibeRaven(['login'], args.cwd);
223
+ if (name === 'viberaven_heal_plan') {
224
+ return buildHealArgs(['--heal', '--plan'], args);
225
+ }
226
+ if (name === 'viberaven_heal_prompt') {
227
+ return buildHealArgs(['--heal', '--prompt'], args);
228
+ }
229
+ if (name === 'viberaven_heal_apply') {
230
+ const cliArgs = buildHealArgs(['--heal', '--apply'], args);
231
+ if (args.yes === true) cliArgs.push('--yes');
232
+ return cliArgs;
174
233
  }
175
234
  throw new Error(`Unknown VibeRaven tool: ${name}`);
176
235
  }
177
236
 
237
+ function buildHealArgs(prefix, args) {
238
+ const cliArgs = [...prefix];
239
+ if (args.target) cliArgs.push('--target', safeStringArg(args.target, 'target'));
240
+ if (args.gap) cliArgs.push('--gap', safeStringArg(args.gap, 'gap'));
241
+ return cliArgs;
242
+ }
243
+
244
+ function safeStringArg(value, label) {
245
+ if (typeof value !== 'string') {
246
+ throw new Error(`Invalid ${label}: expected string`);
247
+ }
248
+
249
+ if (!value.trim()) {
250
+ throw new Error(`Invalid ${label}: expected non-empty string`);
251
+ }
252
+
253
+ if (/[&|<>^%!"\r\n]/.test(value)) {
254
+ throw new Error(`Unsafe characters in ${label}`);
255
+ }
256
+
257
+ return value;
258
+ }
259
+
260
+ function resolveCwd(cwd) {
261
+ if (cwd === undefined || cwd === null) {
262
+ return process.cwd();
263
+ }
264
+
265
+ if (typeof cwd !== 'string') {
266
+ throw new Error('Invalid cwd: expected string');
267
+ }
268
+
269
+ if (!cwd.trim()) {
270
+ throw new Error('Invalid cwd: expected non-empty string');
271
+ }
272
+
273
+ return cwd;
274
+ }
275
+
276
+ function buildNpxCommand(args) {
277
+ if (process.platform === 'win32') {
278
+ return {
279
+ command: 'cmd.exe',
280
+ args: ['/d', '/s', '/c', 'npx', ...args],
281
+ options: { shell: false }
282
+ };
283
+ }
284
+
285
+ return {
286
+ command: 'npx',
287
+ args,
288
+ options: { shell: false }
289
+ };
290
+ }
291
+
178
292
  function runVibeRaven(args, cwd) {
179
293
  return new Promise((resolve) => {
180
- const child = spawn('npx', ['-y', '@viberaven/cli@beta', ...args], {
181
- cwd: typeof cwd === 'string' && cwd.trim() ? cwd : process.cwd(),
294
+ const built = buildNpxCommand(args);
295
+ const child = spawnChild(built.command, built.args, {
296
+ cwd: resolveCwd(cwd),
182
297
  env: process.env,
183
- shell: process.platform === 'win32'
298
+ shell: built.options.shell,
299
+ stdio: ['ignore', 'pipe', 'pipe']
184
300
  });
185
301
  let stdout = '';
186
302
  let stderr = '';
@@ -195,12 +311,41 @@ function runVibeRaven(args, cwd) {
195
311
  });
196
312
  child.on('close', (code) => {
197
313
  const combined = `${stdout}${stderr}`.trim();
198
- resolve(`exit ${code ?? 1}\n${combined}`);
314
+ resolve(`exit ${code ?? 1}${combined ? `\n${combined}` : ''}`);
199
315
  });
200
316
  });
201
317
  }
202
318
 
319
+ function parseJsonObjectFromToolText(text) {
320
+ const jsonStart = text.indexOf('{');
321
+ if (jsonStart === -1) return undefined;
322
+ try {
323
+ return JSON.parse(text.slice(jsonStart));
324
+ } catch {
325
+ return undefined;
326
+ }
327
+ }
328
+
203
329
  function send(message) {
204
330
  const body = JSON.stringify(message);
205
331
  process.stdout.write(`Content-Length: ${Buffer.byteLength(body, 'utf8')}\r\n\r\n${body}`);
206
332
  }
333
+
334
+ if (require.main === module) {
335
+ main();
336
+ }
337
+
338
+ module.exports = {
339
+ TOOLS,
340
+ buildNpxCommand,
341
+ callTool,
342
+ handleRequest,
343
+ parseJsonObjectFromToolText,
344
+ safeStringArg,
345
+ __setSpawnForTest(spawnForTest) {
346
+ spawnChild = spawnForTest;
347
+ },
348
+ __resetSpawnForTest() {
349
+ spawnChild = spawn;
350
+ }
351
+ };
package/package.json CHANGED
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "name": "@viberaven/mcp",
3
- "version": "0.1.0-beta.1",
3
+ "version": "1.0.1",
4
4
  "description": "Thin MCP wrapper around the VibeRaven CLI for agent launch-readiness workflows.",
5
5
  "license": "UNLICENSED",
6
6
  "author": "VibeRaven",
7
+ "mcpName": "io.github.ohad6k/viberaven",
7
8
  "homepage": "https://viberaven.dev/mcp.md",
8
9
  "repository": {
9
10
  "type": "git",
@@ -24,7 +25,7 @@
24
25
  ],
25
26
  "publishConfig": {
26
27
  "access": "public",
27
- "tag": "beta"
28
+ "tag": "latest"
28
29
  },
29
30
  "bin": {
30
31
  "viberaven-mcp": "bin/server.js"
@@ -37,6 +38,7 @@
37
38
  "node": ">=20"
38
39
  },
39
40
  "scripts": {
40
- "smoke": "node scripts/smoke.mjs"
41
+ "smoke": "node scripts/smoke.mjs",
42
+ "test": "vitest run"
41
43
  }
42
44
  }