@viberaven/mcp 0.1.0-beta.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 +23 -0
  2. package/bin/server.js +206 -0
  3. package/package.json +42 -0
package/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # @viberaven/mcp
2
+
3
+ Thin MCP wrapper for VibeRaven.
4
+
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
+
7
+ ## Run
8
+
9
+ ```bash
10
+ npx -y @viberaven/mcp@beta
11
+ ```
12
+
13
+ ## Tools
14
+
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`
20
+
21
+ ## Security
22
+
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.
package/bin/server.js ADDED
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env node
2
+ const { spawn } = require('node:child_process');
3
+
4
+ const SERVER_INFO = { name: 'viberaven-mcp', version: '0.1.0-beta.1' };
5
+
6
+ const TOOLS = [
7
+ {
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
+ }
19
+ },
20
+ {
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
+ }
31
+ },
32
+ {
33
+ name: 'viberaven_next',
34
+ description: 'Return the next VibeRaven production action from the last scan.',
35
+ inputSchema: {
36
+ type: 'object',
37
+ properties: {
38
+ cwd: { type: 'string', description: 'Project root. Defaults to the MCP server working directory.' }
39
+ },
40
+ additionalProperties: false
41
+ }
42
+ },
43
+ {
44
+ name: 'viberaven_prompt',
45
+ description: 'Return the focused VibeRaven fix prompt for the top or selected gap.',
46
+ inputSchema: {
47
+ type: 'object',
48
+ 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.' }
53
+ },
54
+ additionalProperties: false
55
+ }
56
+ },
57
+ {
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
+ }
67
+ }
68
+ ];
69
+
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
+ let buffer = Buffer.alloc(0);
77
+
78
+ process.stdin.on('data', (chunk) => {
79
+ buffer = Buffer.concat([buffer, chunk]);
80
+ drainMessages();
81
+ });
82
+
83
+ function drainMessages() {
84
+ while (true) {
85
+ const headerEnd = buffer.indexOf('\r\n\r\n');
86
+ if (headerEnd === -1) return;
87
+
88
+ const header = buffer.slice(0, headerEnd).toString('utf8');
89
+ const match = header.match(/content-length:\s*(\d+)/i);
90
+ if (!match) {
91
+ buffer = buffer.slice(headerEnd + 4);
92
+ continue;
93
+ }
94
+
95
+ const length = Number(match[1]);
96
+ const messageStart = headerEnd + 4;
97
+ const messageEnd = messageStart + length;
98
+ if (buffer.length < messageEnd) return;
99
+
100
+ const raw = buffer.slice(messageStart, messageEnd).toString('utf8');
101
+ buffer = buffer.slice(messageEnd);
102
+ void handleRawMessage(raw);
103
+ }
104
+ }
105
+
106
+ async function handleRawMessage(raw) {
107
+ let message;
108
+ try {
109
+ message = JSON.parse(raw);
110
+ } catch {
111
+ return;
112
+ }
113
+
114
+ if (!message || typeof message.method !== 'string') return;
115
+ if (message.id === undefined || message.id === null) return;
116
+
117
+ try {
118
+ const result = await handleRequest(message.method, message.params || {});
119
+ send({ jsonrpc: '2.0', id: message.id, result });
120
+ } catch (error) {
121
+ send({
122
+ jsonrpc: '2.0',
123
+ id: message.id,
124
+ error: {
125
+ code: -32000,
126
+ message: error instanceof Error ? error.message : String(error)
127
+ }
128
+ });
129
+ }
130
+ }
131
+
132
+ async function handleRequest(method, params) {
133
+ if (method === 'initialize') {
134
+ return {
135
+ protocolVersion: params.protocolVersion || '2024-11-05',
136
+ capabilities: { tools: {} },
137
+ serverInfo: SERVER_INFO
138
+ };
139
+ }
140
+
141
+ if (method === 'tools/list') {
142
+ return { tools: TOOLS };
143
+ }
144
+
145
+ if (method === 'tools/call') {
146
+ const name = params.name;
147
+ const args = params.arguments || {};
148
+ const text = await callTool(name, args);
149
+ return { content: [{ type: 'text', text }] };
150
+ }
151
+
152
+ throw new Error(`Unsupported MCP method: ${method}`);
153
+ }
154
+
155
+ async function callTool(name, args) {
156
+ if (name === 'viberaven_scan') {
157
+ return runVibeRaven(['scan', ...(args.open ? ['--open'] : []), ...(args.path ? [String(args.path)] : [])], args.cwd);
158
+ }
159
+ if (name === 'viberaven_status') {
160
+ return runVibeRaven(['status', ...(args.json ? ['--json'] : [])], args.cwd);
161
+ }
162
+ if (name === 'viberaven_next') {
163
+ return runVibeRaven(['next', '--json'], args.cwd);
164
+ }
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);
171
+ }
172
+ if (name === 'viberaven_login') {
173
+ return runVibeRaven(['login'], args.cwd);
174
+ }
175
+ throw new Error(`Unknown VibeRaven tool: ${name}`);
176
+ }
177
+
178
+ function runVibeRaven(args, cwd) {
179
+ return new Promise((resolve) => {
180
+ const child = spawn('npx', ['-y', '@viberaven/cli@beta', ...args], {
181
+ cwd: typeof cwd === 'string' && cwd.trim() ? cwd : process.cwd(),
182
+ env: process.env,
183
+ shell: process.platform === 'win32'
184
+ });
185
+ let stdout = '';
186
+ let stderr = '';
187
+ child.stdout.on('data', (chunk) => {
188
+ stdout += chunk.toString();
189
+ });
190
+ child.stderr.on('data', (chunk) => {
191
+ stderr += chunk.toString();
192
+ });
193
+ child.on('error', (error) => {
194
+ resolve(`ERROR: ${error.message}`);
195
+ });
196
+ child.on('close', (code) => {
197
+ const combined = `${stdout}${stderr}`.trim();
198
+ resolve(`exit ${code ?? 1}\n${combined}`);
199
+ });
200
+ });
201
+ }
202
+
203
+ function send(message) {
204
+ const body = JSON.stringify(message);
205
+ process.stdout.write(`Content-Length: ${Buffer.byteLength(body, 'utf8')}\r\n\r\n${body}`);
206
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@viberaven/mcp",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Thin MCP wrapper around the VibeRaven CLI for agent launch-readiness workflows.",
5
+ "license": "UNLICENSED",
6
+ "author": "VibeRaven",
7
+ "homepage": "https://viberaven.dev/mcp.md",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/ohad6k/VibeRaven.git",
11
+ "directory": "packages/mcp"
12
+ },
13
+ "bugs": {
14
+ "url": "https://github.com/ohad6k/VibeRaven/issues"
15
+ },
16
+ "keywords": [
17
+ "viberaven",
18
+ "mcp",
19
+ "claude-code",
20
+ "codex",
21
+ "cursor",
22
+ "launch-readiness",
23
+ "production"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public",
27
+ "tag": "beta"
28
+ },
29
+ "bin": {
30
+ "viberaven-mcp": "bin/server.js"
31
+ },
32
+ "files": [
33
+ "bin",
34
+ "README.md"
35
+ ],
36
+ "engines": {
37
+ "node": ">=20"
38
+ },
39
+ "scripts": {
40
+ "smoke": "node scripts/smoke.mjs"
41
+ }
42
+ }