@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.
- package/README.md +23 -0
- package/bin/server.js +206 -0
- 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
|
+
}
|