@viberaven/mcp 1.0.6 → 1.1.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/README.md +67 -32
- package/bin/server.js +530 -292
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,45 +10,80 @@ This package exposes VibeRaven CLI actions as MCP tools for Codex, Claude Code,
|
|
|
10
10
|
|
|
11
11
|
The MCP server wraps the stable CLI package: `npx -y viberaven`.
|
|
12
12
|
|
|
13
|
-
## Run
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
npx -y @viberaven/mcp
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
npx -y viberaven
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
## Tools
|
|
26
|
-
|
|
27
|
-
- `viberaven_check_readiness` -> `npx -y viberaven --agent-mode`
|
|
28
|
-
- `viberaven_verify` -> `npx -y viberaven --verify`
|
|
29
|
-
- `viberaven_audit` -> `npx -y viberaven audit --vercel-supabase`
|
|
30
|
-
- `viberaven_init_rules` -> `npx -y viberaven init`
|
|
31
|
-
- `viberaven_clean_plan` -> `npx -y viberaven clean --plan`
|
|
32
|
-
- `viberaven_strict_gate` -> `npx -y viberaven --agent-mode --strict --json`
|
|
33
|
-
- `viberaven_gate_result` -> `npx -y viberaven --agent-mode --json`
|
|
34
|
-
- `viberaven_context_map` -> `npx -y viberaven --condense`
|
|
13
|
+
## Run
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx -y @viberaven/mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
MCP config:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{ "viberaven": { "command": "npx", "args": ["-y", "@viberaven/mcp"] } }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Tools
|
|
26
|
+
|
|
27
|
+
- `viberaven_check_readiness` -> `npx -y viberaven --agent-mode`
|
|
28
|
+
- `viberaven_verify` -> `npx -y viberaven --verify`
|
|
29
|
+
- `viberaven_audit` -> `npx -y viberaven audit --vercel-supabase`
|
|
30
|
+
- `viberaven_init_rules` -> `npx -y viberaven init`
|
|
31
|
+
- `viberaven_clean_plan` -> `npx -y viberaven clean --plan`
|
|
32
|
+
- `viberaven_strict_gate` -> `npx -y viberaven --agent-mode --strict --json`
|
|
33
|
+
- `viberaven_gate_result` -> `npx -y viberaven --agent-mode --json`
|
|
34
|
+
- `viberaven_context_map` -> `npx -y viberaven --condense`
|
|
35
|
+
- `viberaven_prp_current` -> read `.viberaven/prp.json`
|
|
36
|
+
- `viberaven_prp_findings` -> list PRP findings
|
|
37
|
+
- `viberaven_prp_next_action` -> return the first PRP next action
|
|
38
|
+
- `viberaven_verify_url` -> URL-specific verification fallback; currently unsupported and not live URL proof
|
|
39
|
+
- `viberaven_mark_manual_evidence` -> append manual PRP evidence; manual evidence is not live provider proof
|
|
35
40
|
- `viberaven_heal_plan` -> `npx -y viberaven --heal --plan`
|
|
36
41
|
- `viberaven_heal_prompt` -> `npx -y viberaven --heal --prompt`
|
|
37
42
|
- `viberaven_heal_apply` -> `npx -y viberaven --heal --apply`
|
|
38
|
-
- `viberaven_validate_npm_package` ->
|
|
39
|
-
|
|
40
|
-
`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`.
|
|
43
|
+
- `viberaven_validate_npm_package` -> check npm package names before install
|
|
44
|
+
|
|
45
|
+
`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`.
|
|
41
46
|
|
|
42
47
|
After one fix, call `viberaven_verify`. Before deploy or CI pass, call `viberaven_strict_gate` or run:
|
|
43
48
|
|
|
44
49
|
```bash
|
|
45
|
-
npx -y viberaven --strict
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
50
|
+
npx -y viberaven --strict
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## VibeRaven Production Protocol
|
|
54
|
+
|
|
55
|
+
VibeRaven 1.1.0 introduces the Production Protocol for AI-built apps.
|
|
56
|
+
|
|
57
|
+
Run the canonical agent command:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx -y viberaven --agent-mode
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Then have the AI coding agent read:
|
|
64
|
+
|
|
65
|
+
- `.viberaven/prp.json`
|
|
66
|
+
- `.viberaven/mission-map.md`
|
|
67
|
+
- `.viberaven/context-map.json`
|
|
68
|
+
|
|
69
|
+
The agent should fix `nextActions` in order and must not claim production-ready while `decision.status` is `blocked`.
|
|
70
|
+
|
|
71
|
+
## Production Protocol Resources
|
|
72
|
+
|
|
73
|
+
The MCP server exposes VibeRaven Production Protocol artifacts directly:
|
|
74
|
+
|
|
75
|
+
- `prp://current`
|
|
76
|
+
- `prp://findings`
|
|
77
|
+
- `prp://next-actions`
|
|
78
|
+
- `prp://mission-map`
|
|
79
|
+
- `prp://context-map`
|
|
80
|
+
|
|
81
|
+
Use `viberaven_check_readiness` to generate the artifacts, then use `viberaven_prp_current`, `viberaven_prp_findings`, or `viberaven_prp_next_action` so agents can act without scraping terminal prose.
|
|
82
|
+
|
|
83
|
+
## Machine Artifact Contract
|
|
84
|
+
|
|
85
|
+
```text
|
|
86
|
+
docs/contracts/artifacts.md
|
|
52
87
|
https://viberaven.dev/schemas/gate-result.schema.json
|
|
53
88
|
https://viberaven.dev/schemas/context-map.schema.json
|
|
54
89
|
https://viberaven.dev/schemas/gap.schema.json
|
package/bin/server.js
CHANGED
|
@@ -1,383 +1,621 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
const { spawn } = require('node:child_process');
|
|
3
|
+
const { readFile, writeFile } = require('node:fs/promises');
|
|
4
|
+
const { join } = require('node:path');
|
|
3
5
|
let spawnChild = spawn;
|
|
4
|
-
|
|
5
|
-
const SERVER_INFO = { name: 'viberaven-mcp', version: '1.0
|
|
6
|
+
|
|
7
|
+
const SERVER_INFO = { name: 'viberaven-mcp', version: '1.1.0' };
|
|
6
8
|
const CLI_PACKAGE = '@viberaven/cli';
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
const PRP_MISSING_MESSAGE = '.viberaven/prp.json not found. Run npx -y viberaven --agent-mode first.';
|
|
10
|
+
const PRP_INVALID_JSON_MESSAGE = '.viberaven/prp.json is invalid JSON. Re-run npx -y viberaven --agent-mode.';
|
|
11
|
+
|
|
12
|
+
const cwdSchema = {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
cwd: { type: 'string', description: 'Project root. Defaults to the MCP server working directory.' }
|
|
16
|
+
},
|
|
17
|
+
additionalProperties: false
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const healSchema = {
|
|
21
|
+
type: 'object',
|
|
22
|
+
properties: {
|
|
23
|
+
cwd: { type: 'string' },
|
|
24
|
+
target: { type: 'string' },
|
|
25
|
+
gap: { type: 'string' },
|
|
26
|
+
yes: { type: 'boolean' }
|
|
27
|
+
},
|
|
13
28
|
additionalProperties: false
|
|
14
29
|
};
|
|
15
30
|
|
|
16
|
-
const
|
|
31
|
+
const manualEvidenceSchema = {
|
|
17
32
|
type: 'object',
|
|
18
33
|
properties: {
|
|
19
34
|
cwd: { type: 'string' },
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
id: { type: 'string' },
|
|
36
|
+
summary: { type: 'string' },
|
|
37
|
+
source: { type: 'string' }
|
|
23
38
|
},
|
|
39
|
+
required: ['id', 'summary'],
|
|
24
40
|
additionalProperties: false
|
|
25
41
|
};
|
|
26
42
|
|
|
27
|
-
const
|
|
28
|
-
{
|
|
29
|
-
name: 'viberaven_check_readiness',
|
|
30
|
-
description: 'Run the VibeRaven agent-mode production-readiness check and write .viberaven artifacts.',
|
|
31
|
-
inputSchema: cwdSchema
|
|
32
|
-
},
|
|
43
|
+
const RESOURCES = [
|
|
33
44
|
{
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
}
|
|
45
|
+
uri: 'prp://current',
|
|
46
|
+
name: 'Current VibeRaven Production Protocol',
|
|
47
|
+
mimeType: 'application/json'
|
|
49
48
|
},
|
|
50
49
|
{
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
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
|
-
}
|
|
50
|
+
uri: 'prp://findings',
|
|
51
|
+
name: 'VibeRaven PRP Findings',
|
|
52
|
+
mimeType: 'application/json'
|
|
62
53
|
},
|
|
63
54
|
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
55
|
+
uri: 'prp://next-actions',
|
|
56
|
+
name: 'VibeRaven PRP Next Actions',
|
|
57
|
+
mimeType: 'application/json'
|
|
67
58
|
},
|
|
68
59
|
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
60
|
+
uri: 'prp://mission-map',
|
|
61
|
+
name: 'VibeRaven Mission Map',
|
|
62
|
+
mimeType: 'text/markdown'
|
|
72
63
|
},
|
|
73
64
|
{
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
65
|
+
uri: 'prp://context-map',
|
|
66
|
+
name: 'VibeRaven Context Map',
|
|
67
|
+
mimeType: 'application/json'
|
|
68
|
+
}
|
|
69
|
+
];
|
|
70
|
+
|
|
71
|
+
const TOOLS = [
|
|
72
|
+
{
|
|
73
|
+
name: 'viberaven_check_readiness',
|
|
74
|
+
description: 'Run the VibeRaven agent-mode production-readiness check and write .viberaven artifacts.',
|
|
75
|
+
inputSchema: cwdSchema
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'viberaven_verify',
|
|
79
|
+
description: 'Rescan and refresh VibeRaven production-readiness artifacts after a fix.',
|
|
80
|
+
inputSchema: cwdSchema
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: 'viberaven_audit',
|
|
84
|
+
description: 'Run local Vercel/Supabase production checks for RLS, service-role boundaries, and Vercel pooler usage.',
|
|
85
|
+
inputSchema: {
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
cwd: { type: 'string', description: 'Project root. Defaults to current working directory.' },
|
|
89
|
+
json: { type: 'boolean', description: 'Return JSON output.' }
|
|
90
|
+
},
|
|
91
|
+
additionalProperties: false
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'viberaven_init_rules',
|
|
96
|
+
description: 'Install bounded VibeRaven rules into native AI instruction files.',
|
|
97
|
+
inputSchema: {
|
|
98
|
+
type: 'object',
|
|
99
|
+
properties: {
|
|
100
|
+
cwd: { type: 'string', description: 'Project root. Defaults to current working directory.' },
|
|
101
|
+
agents: { type: 'string', description: 'Comma-separated agent targets, or all.' },
|
|
102
|
+
dryRun: { type: 'boolean', description: 'Preview changes without writing files.' }
|
|
103
|
+
},
|
|
104
|
+
additionalProperties: false
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: 'viberaven_clean_plan',
|
|
109
|
+
description: 'Write a non-destructive context cleanup plan for generated artifacts and logs.',
|
|
110
|
+
inputSchema: cwdSchema
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'viberaven_strict_gate',
|
|
114
|
+
description: 'Run VibeRaven agent-mode strict gate and return the machine verdict.',
|
|
115
|
+
inputSchema: cwdSchema
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: 'viberaven_gate_result',
|
|
119
|
+
description: 'Run VibeRaven agent-mode JSON output and return gate-result.json content.',
|
|
120
|
+
inputSchema: cwdSchema
|
|
121
|
+
},
|
|
78
122
|
{
|
|
79
123
|
name: 'viberaven_context_map',
|
|
80
124
|
description: 'Refresh .viberaven/context-map.json from the last scan.',
|
|
81
125
|
inputSchema: cwdSchema
|
|
82
126
|
},
|
|
83
127
|
{
|
|
84
|
-
name: '
|
|
85
|
-
description: '
|
|
86
|
-
inputSchema:
|
|
128
|
+
name: 'viberaven_prp_current',
|
|
129
|
+
description: 'Read .viberaven/prp.json, the VibeRaven Production Protocol truth object.',
|
|
130
|
+
inputSchema: cwdSchema
|
|
87
131
|
},
|
|
88
132
|
{
|
|
89
|
-
name: '
|
|
90
|
-
description: '
|
|
91
|
-
inputSchema:
|
|
133
|
+
name: 'viberaven_prp_findings',
|
|
134
|
+
description: 'List PRP findings from .viberaven/prp.json.',
|
|
135
|
+
inputSchema: cwdSchema
|
|
92
136
|
},
|
|
93
137
|
{
|
|
94
|
-
name: '
|
|
95
|
-
description: '
|
|
96
|
-
inputSchema:
|
|
138
|
+
name: 'viberaven_prp_next_action',
|
|
139
|
+
description: 'Return the first PRP next action from .viberaven/prp.json.',
|
|
140
|
+
inputSchema: cwdSchema
|
|
97
141
|
},
|
|
98
142
|
{
|
|
99
|
-
name: '
|
|
143
|
+
name: 'viberaven_verify_url',
|
|
100
144
|
description:
|
|
101
|
-
'
|
|
145
|
+
'Run VibeRaven verify for the current workspace. URL-specific verification is reported when supported by the CLI.',
|
|
102
146
|
inputSchema: {
|
|
103
147
|
type: 'object',
|
|
104
148
|
properties: {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
type: 'array',
|
|
108
|
-
items: { type: 'string' },
|
|
109
|
-
description: 'Multiple npm package names to validate in one call.'
|
|
110
|
-
}
|
|
149
|
+
cwd: { type: 'string' },
|
|
150
|
+
url: { type: 'string' }
|
|
111
151
|
},
|
|
112
152
|
additionalProperties: false
|
|
113
153
|
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: 'viberaven_mark_manual_evidence',
|
|
157
|
+
description: 'Append manual evidence to PRP. Manual evidence is not live provider proof.',
|
|
158
|
+
inputSchema: manualEvidenceSchema
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: 'viberaven_heal_plan',
|
|
162
|
+
description: 'Write a non-destructive VibeRaven heal plan for a target file or gap.',
|
|
163
|
+
inputSchema: healSchema
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: 'viberaven_heal_prompt',
|
|
167
|
+
description: 'Write an agent-ready VibeRaven heal prompt for a target file or gap.',
|
|
168
|
+
inputSchema: healSchema
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
name: 'viberaven_heal_apply',
|
|
172
|
+
description: 'Apply a guarded VibeRaven repo-code heal recipe when supported.',
|
|
173
|
+
inputSchema: healSchema
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
name: 'viberaven_validate_npm_package',
|
|
177
|
+
description:
|
|
178
|
+
'Check whether an npm package name exists and looks safe before install. Always run viberaven --agent-mode after adding dependencies.',
|
|
179
|
+
inputSchema: {
|
|
180
|
+
type: 'object',
|
|
181
|
+
properties: {
|
|
182
|
+
packageName: { type: 'string', description: 'Single npm package name to validate.' },
|
|
183
|
+
packageNames: {
|
|
184
|
+
type: 'array',
|
|
185
|
+
items: { type: 'string' },
|
|
186
|
+
description: 'Multiple npm package names to validate in one call.'
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
additionalProperties: false
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
];
|
|
193
|
+
|
|
194
|
+
let buffer = Buffer.alloc(0);
|
|
195
|
+
|
|
196
|
+
function main() {
|
|
197
|
+
if (process.argv.includes('--help') || process.argv.includes('-h')) {
|
|
198
|
+
console.log(`${SERVER_INFO.name} ${SERVER_INFO.version}`);
|
|
199
|
+
console.log(`MCP stdio server wrapping npx -y ${CLI_PACKAGE}.`);
|
|
200
|
+
process.exit(0);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
process.stdin.on('data', (chunk) => {
|
|
204
|
+
buffer = Buffer.concat([buffer, chunk]);
|
|
205
|
+
drainMessages();
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function drainMessages() {
|
|
210
|
+
while (true) {
|
|
211
|
+
const headerEnd = buffer.indexOf('\r\n\r\n');
|
|
212
|
+
if (headerEnd === -1) return;
|
|
213
|
+
|
|
214
|
+
const header = buffer.slice(0, headerEnd).toString('utf8');
|
|
215
|
+
const match = header.match(/content-length:\s*(\d+)/i);
|
|
216
|
+
if (!match) {
|
|
217
|
+
buffer = buffer.slice(headerEnd + 4);
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const length = Number(match[1]);
|
|
222
|
+
const messageStart = headerEnd + 4;
|
|
223
|
+
const messageEnd = messageStart + length;
|
|
224
|
+
if (buffer.length < messageEnd) return;
|
|
225
|
+
|
|
226
|
+
const raw = buffer.slice(messageStart, messageEnd).toString('utf8');
|
|
227
|
+
buffer = buffer.slice(messageEnd);
|
|
228
|
+
void handleRawMessage(raw);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async function handleRawMessage(raw) {
|
|
233
|
+
let message;
|
|
234
|
+
try {
|
|
235
|
+
message = JSON.parse(raw);
|
|
236
|
+
} catch {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
if (!message || typeof message.method !== 'string') return;
|
|
241
|
+
if (message.id === undefined || message.id === null) return;
|
|
242
|
+
|
|
243
|
+
try {
|
|
244
|
+
const result = await handleRequest(message.method, message.params || {});
|
|
245
|
+
send({ jsonrpc: '2.0', id: message.id, result });
|
|
246
|
+
} catch (error) {
|
|
247
|
+
send({
|
|
248
|
+
jsonrpc: '2.0',
|
|
249
|
+
id: message.id,
|
|
250
|
+
error: {
|
|
251
|
+
code: -32000,
|
|
252
|
+
message: error instanceof Error ? error.message : String(error)
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
async function handleRequest(method, params) {
|
|
259
|
+
if (method === 'initialize') {
|
|
260
|
+
return {
|
|
184
261
|
protocolVersion: params.protocolVersion || '2024-11-05',
|
|
185
|
-
capabilities: { tools: {} },
|
|
262
|
+
capabilities: { tools: {}, resources: {} },
|
|
186
263
|
serverInfo: SERVER_INFO
|
|
187
264
|
};
|
|
188
265
|
}
|
|
266
|
+
|
|
267
|
+
if (method === 'tools/list') {
|
|
268
|
+
return { tools: TOOLS };
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
if (method === 'tools/call') {
|
|
272
|
+
const name = params.name;
|
|
273
|
+
const args = params.arguments || {};
|
|
274
|
+
const text = await callTool(name, args);
|
|
275
|
+
const parsed = parseJsonObjectFromToolText(text);
|
|
276
|
+
return {
|
|
277
|
+
content: [{ type: 'text', text }],
|
|
278
|
+
...(parsed ? { structuredContent: parsed } : {})
|
|
279
|
+
};
|
|
280
|
+
}
|
|
189
281
|
|
|
190
|
-
if (method === '
|
|
191
|
-
return {
|
|
282
|
+
if (method === 'resources/list') {
|
|
283
|
+
return { resources: RESOURCES };
|
|
192
284
|
}
|
|
193
285
|
|
|
194
|
-
if (method === '
|
|
195
|
-
const
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
const parsed = parseJsonObjectFromToolText(text);
|
|
199
|
-
return {
|
|
200
|
-
content: [{ type: 'text', text }],
|
|
201
|
-
...(parsed ? { structuredContent: parsed } : {})
|
|
202
|
-
};
|
|
286
|
+
if (method === 'resources/read') {
|
|
287
|
+
const uri = params.uri;
|
|
288
|
+
const text = await readResourceText(uri, params.cwd);
|
|
289
|
+
return { contents: [{ uri, text }] };
|
|
203
290
|
}
|
|
204
291
|
|
|
205
292
|
throw new Error(`Unsupported MCP method: ${method}`);
|
|
206
293
|
}
|
|
207
294
|
|
|
208
295
|
async function callTool(name, args) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
function buildToolArgs(name, args) {
|
|
213
|
-
if (name === 'viberaven_check_readiness') {
|
|
214
|
-
return ['--agent-mode'];
|
|
215
|
-
}
|
|
216
|
-
if (name === 'viberaven_verify') {
|
|
217
|
-
return ['--verify'];
|
|
218
|
-
}
|
|
219
|
-
if (name === 'viberaven_audit') {
|
|
220
|
-
return ['audit', '--vercel-supabase', ...(args.json ? ['--json'] : [])];
|
|
221
|
-
}
|
|
222
|
-
if (name === 'viberaven_init_rules') {
|
|
223
|
-
const cliArgs = ['init'];
|
|
224
|
-
if (args.agents) cliArgs.push('--agents', safeStringArg(args.agents, 'agents'));
|
|
225
|
-
if (args.dryRun) cliArgs.push('--dry-run');
|
|
226
|
-
return cliArgs;
|
|
227
|
-
}
|
|
228
|
-
if (name === 'viberaven_clean_plan') {
|
|
229
|
-
return ['clean', '--plan'];
|
|
230
|
-
}
|
|
231
|
-
if (name === 'viberaven_strict_gate') {
|
|
232
|
-
return ['--agent-mode', '--strict', '--json'];
|
|
296
|
+
if (name === 'viberaven_prp_current') {
|
|
297
|
+
return readPrpText(args && args.cwd);
|
|
233
298
|
}
|
|
234
|
-
if (name === '
|
|
235
|
-
return
|
|
299
|
+
if (name === 'viberaven_prp_findings') {
|
|
300
|
+
return readPrpFindingsText(args && args.cwd);
|
|
236
301
|
}
|
|
237
|
-
if (name === '
|
|
238
|
-
return
|
|
302
|
+
if (name === 'viberaven_prp_next_action') {
|
|
303
|
+
return readPrpNextActionText(args && args.cwd);
|
|
239
304
|
}
|
|
240
|
-
if (name === '
|
|
241
|
-
return
|
|
305
|
+
if (name === 'viberaven_verify_url' && Object.prototype.hasOwnProperty.call(args || {}, 'url')) {
|
|
306
|
+
return JSON.stringify(
|
|
307
|
+
{
|
|
308
|
+
ok: false,
|
|
309
|
+
unsupported: 'url-verification',
|
|
310
|
+
message: 'URL-specific verification is not supported yet; run viberaven_verify for workspace verification.',
|
|
311
|
+
fallbackTool: 'viberaven_verify'
|
|
312
|
+
},
|
|
313
|
+
null,
|
|
314
|
+
2
|
|
315
|
+
);
|
|
242
316
|
}
|
|
243
|
-
if (name === '
|
|
244
|
-
return
|
|
317
|
+
if (name === 'viberaven_mark_manual_evidence') {
|
|
318
|
+
return markManualEvidence(args || {});
|
|
245
319
|
}
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
320
|
+
return runVibeRaven(['-y', CLI_PACKAGE, ...buildToolArgs(name, args || {})], args && args.cwd);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
function buildToolArgs(name, args) {
|
|
324
|
+
if (name === 'viberaven_check_readiness') {
|
|
325
|
+
return ['--agent-mode'];
|
|
326
|
+
}
|
|
327
|
+
if (name === 'viberaven_verify') {
|
|
328
|
+
return ['--verify'];
|
|
250
329
|
}
|
|
251
|
-
if (name === '
|
|
252
|
-
|
|
253
|
-
if (args.packageName) {
|
|
254
|
-
names.push(safeStringArg(args.packageName, 'packageName'));
|
|
255
|
-
}
|
|
256
|
-
if (Array.isArray(args.packageNames)) {
|
|
257
|
-
for (const entry of args.packageNames) {
|
|
258
|
-
names.push(safeStringArg(entry, 'packageName'));
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
if (names.length === 0) {
|
|
262
|
-
throw new Error('packageName or packageNames is required');
|
|
263
|
-
}
|
|
264
|
-
return ['validate-npm-package', '--json', ...names];
|
|
330
|
+
if (name === 'viberaven_verify_url') {
|
|
331
|
+
return ['--verify'];
|
|
265
332
|
}
|
|
266
|
-
|
|
333
|
+
if (name === 'viberaven_audit') {
|
|
334
|
+
return ['audit', '--vercel-supabase', ...(args.json ? ['--json'] : [])];
|
|
335
|
+
}
|
|
336
|
+
if (name === 'viberaven_init_rules') {
|
|
337
|
+
const cliArgs = ['init'];
|
|
338
|
+
if (args.agents) cliArgs.push('--agents', safeStringArg(args.agents, 'agents'));
|
|
339
|
+
if (args.dryRun) cliArgs.push('--dry-run');
|
|
340
|
+
return cliArgs;
|
|
341
|
+
}
|
|
342
|
+
if (name === 'viberaven_clean_plan') {
|
|
343
|
+
return ['clean', '--plan'];
|
|
344
|
+
}
|
|
345
|
+
if (name === 'viberaven_strict_gate') {
|
|
346
|
+
return ['--agent-mode', '--strict', '--json'];
|
|
347
|
+
}
|
|
348
|
+
if (name === 'viberaven_gate_result') {
|
|
349
|
+
return ['--agent-mode', '--json'];
|
|
350
|
+
}
|
|
351
|
+
if (name === 'viberaven_context_map') {
|
|
352
|
+
return ['--condense'];
|
|
353
|
+
}
|
|
354
|
+
if (name === 'viberaven_heal_plan') {
|
|
355
|
+
return buildHealArgs(['--heal', '--plan'], args);
|
|
356
|
+
}
|
|
357
|
+
if (name === 'viberaven_heal_prompt') {
|
|
358
|
+
return buildHealArgs(['--heal', '--prompt'], args);
|
|
359
|
+
}
|
|
360
|
+
if (name === 'viberaven_heal_apply') {
|
|
361
|
+
const cliArgs = buildHealArgs(['--heal', '--apply'], args);
|
|
362
|
+
if (args.yes === true) cliArgs.push('--yes');
|
|
363
|
+
return cliArgs;
|
|
364
|
+
}
|
|
365
|
+
if (name === 'viberaven_validate_npm_package') {
|
|
366
|
+
const names = [];
|
|
367
|
+
if (args.packageName) {
|
|
368
|
+
names.push(safeStringArg(args.packageName, 'packageName'));
|
|
369
|
+
}
|
|
370
|
+
if (Array.isArray(args.packageNames)) {
|
|
371
|
+
for (const entry of args.packageNames) {
|
|
372
|
+
names.push(safeStringArg(entry, 'packageName'));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (names.length === 0) {
|
|
376
|
+
throw new Error('packageName or packageNames is required');
|
|
377
|
+
}
|
|
378
|
+
return ['validate-npm-package', '--json', ...names];
|
|
379
|
+
}
|
|
380
|
+
throw new Error(`Unknown VibeRaven tool: ${name}`);
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
function buildHealArgs(prefix, args) {
|
|
384
|
+
const cliArgs = [...prefix];
|
|
385
|
+
if (args.target) cliArgs.push('--target', safeStringArg(args.target, 'target'));
|
|
386
|
+
if (args.gap) cliArgs.push('--gap', safeStringArg(args.gap, 'gap'));
|
|
387
|
+
return cliArgs;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function safeStringArg(value, label) {
|
|
391
|
+
if (typeof value !== 'string') {
|
|
392
|
+
throw new Error(`Invalid ${label}: expected string`);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (!value.trim()) {
|
|
396
|
+
throw new Error(`Invalid ${label}: expected non-empty string`);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
if (/[&|<>^%!"\r\n]/.test(value)) {
|
|
400
|
+
throw new Error(`Unsafe characters in ${label}`);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
return value;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
function resolveCwd(cwd) {
|
|
407
|
+
if (cwd === undefined || cwd === null) {
|
|
408
|
+
return process.cwd();
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if (typeof cwd !== 'string') {
|
|
412
|
+
throw new Error('Invalid cwd: expected string');
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if (!cwd.trim()) {
|
|
416
|
+
throw new Error('Invalid cwd: expected non-empty string');
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return cwd;
|
|
267
420
|
}
|
|
268
421
|
|
|
269
|
-
function
|
|
270
|
-
|
|
271
|
-
if (args.target) cliArgs.push('--target', safeStringArg(args.target, 'target'));
|
|
272
|
-
if (args.gap) cliArgs.push('--gap', safeStringArg(args.gap, 'gap'));
|
|
273
|
-
return cliArgs;
|
|
422
|
+
function prpPath(cwd) {
|
|
423
|
+
return join(resolveCwd(cwd), '.viberaven', 'prp.json');
|
|
274
424
|
}
|
|
275
425
|
|
|
276
|
-
function
|
|
277
|
-
|
|
278
|
-
|
|
426
|
+
async function readPrpText(cwd) {
|
|
427
|
+
try {
|
|
428
|
+
return await readFile(prpPath(cwd), 'utf8');
|
|
429
|
+
} catch (error) {
|
|
430
|
+
if (error && error.code === 'ENOENT') {
|
|
431
|
+
return `ERROR: ${PRP_MISSING_MESSAGE}`;
|
|
432
|
+
}
|
|
433
|
+
throw error;
|
|
279
434
|
}
|
|
435
|
+
}
|
|
280
436
|
|
|
281
|
-
|
|
282
|
-
|
|
437
|
+
async function readExistingPrpJson(cwd) {
|
|
438
|
+
let text;
|
|
439
|
+
try {
|
|
440
|
+
text = await readFile(prpPath(cwd), 'utf8');
|
|
441
|
+
} catch (error) {
|
|
442
|
+
if (error && error.code === 'ENOENT') {
|
|
443
|
+
throw new Error(PRP_MISSING_MESSAGE);
|
|
444
|
+
}
|
|
445
|
+
throw error;
|
|
283
446
|
}
|
|
284
447
|
|
|
285
|
-
|
|
286
|
-
|
|
448
|
+
try {
|
|
449
|
+
return JSON.parse(text);
|
|
450
|
+
} catch {
|
|
451
|
+
throw new Error(PRP_INVALID_JSON_MESSAGE);
|
|
287
452
|
}
|
|
288
|
-
|
|
289
|
-
return value;
|
|
290
453
|
}
|
|
291
454
|
|
|
292
|
-
function
|
|
293
|
-
|
|
294
|
-
|
|
455
|
+
async function readPrpFindingsText(cwd) {
|
|
456
|
+
try {
|
|
457
|
+
const prp = await readExistingPrpJson(cwd);
|
|
458
|
+
return JSON.stringify({ findings: prp.findings || [] }, null, 2);
|
|
459
|
+
} catch (error) {
|
|
460
|
+
return JSON.stringify({ error: errorMessage(error), findings: [] }, null, 2);
|
|
295
461
|
}
|
|
462
|
+
}
|
|
296
463
|
|
|
297
|
-
|
|
298
|
-
|
|
464
|
+
async function readPrpNextActionText(cwd) {
|
|
465
|
+
try {
|
|
466
|
+
const prp = await readExistingPrpJson(cwd);
|
|
467
|
+
return JSON.stringify({ nextAction: (prp.nextActions || [])[0] || null }, null, 2);
|
|
468
|
+
} catch (error) {
|
|
469
|
+
return JSON.stringify({ error: errorMessage(error), nextAction: null }, null, 2);
|
|
299
470
|
}
|
|
471
|
+
}
|
|
300
472
|
|
|
301
|
-
|
|
302
|
-
|
|
473
|
+
async function readPrpNextActionsText(cwd) {
|
|
474
|
+
try {
|
|
475
|
+
const prp = await readExistingPrpJson(cwd);
|
|
476
|
+
return JSON.stringify({ nextActions: prp.nextActions || [] }, null, 2);
|
|
477
|
+
} catch (error) {
|
|
478
|
+
return JSON.stringify({ error: errorMessage(error), nextActions: [] }, null, 2);
|
|
303
479
|
}
|
|
304
|
-
|
|
305
|
-
return cwd;
|
|
306
480
|
}
|
|
307
481
|
|
|
308
|
-
function
|
|
309
|
-
if (
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
};
|
|
482
|
+
async function markManualEvidence(args) {
|
|
483
|
+
if (typeof args.id !== 'string' || !args.id.trim()) {
|
|
484
|
+
throw new Error('Invalid id: expected non-empty string');
|
|
485
|
+
}
|
|
486
|
+
if (typeof args.summary !== 'string' || !args.summary.trim()) {
|
|
487
|
+
throw new Error('Invalid summary: expected non-empty string');
|
|
315
488
|
}
|
|
316
489
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return new Promise((resolve) => {
|
|
326
|
-
const built = buildNpxCommand(args);
|
|
327
|
-
const child = spawnChild(built.command, built.args, {
|
|
328
|
-
cwd: resolveCwd(cwd),
|
|
329
|
-
env: process.env,
|
|
330
|
-
shell: built.options.shell,
|
|
331
|
-
stdio: ['ignore', 'pipe', 'pipe']
|
|
332
|
-
});
|
|
333
|
-
let stdout = '';
|
|
334
|
-
let stderr = '';
|
|
335
|
-
child.stdout.on('data', (chunk) => {
|
|
336
|
-
stdout += chunk.toString();
|
|
337
|
-
});
|
|
338
|
-
child.stderr.on('data', (chunk) => {
|
|
339
|
-
stderr += chunk.toString();
|
|
340
|
-
});
|
|
341
|
-
child.on('error', (error) => {
|
|
342
|
-
resolve(`ERROR: ${error.message}`);
|
|
343
|
-
});
|
|
344
|
-
child.on('close', (code) => {
|
|
345
|
-
const combined = `${stdout}${stderr}`.trim();
|
|
346
|
-
resolve(`exit ${code ?? 1}${combined ? `\n${combined}` : ''}`);
|
|
347
|
-
});
|
|
490
|
+
const prp = await readExistingPrpJson(args.cwd);
|
|
491
|
+
const evidence = Array.isArray(prp.evidence) ? prp.evidence : [];
|
|
492
|
+
evidence.push({
|
|
493
|
+
id: args.id,
|
|
494
|
+
kind: 'manual',
|
|
495
|
+
status: 'present',
|
|
496
|
+
source: typeof args.source === 'string' && args.source.trim() ? args.source : 'manual',
|
|
497
|
+
summary: `${args.summary} Manual confirmation is not live provider proof.`
|
|
348
498
|
});
|
|
499
|
+
prp.evidence = evidence;
|
|
500
|
+
await writeFile(prpPath(args.cwd), `${JSON.stringify(prp, null, 2)}\n`);
|
|
501
|
+
return JSON.stringify({ ok: true, evidenceId: args.id, kind: 'manual' }, null, 2);
|
|
349
502
|
}
|
|
350
503
|
|
|
351
|
-
function
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
try {
|
|
355
|
-
return JSON.parse(text.slice(jsonStart));
|
|
356
|
-
} catch {
|
|
357
|
-
return undefined;
|
|
504
|
+
async function readResourceText(uri, cwd) {
|
|
505
|
+
if (typeof uri !== 'string') {
|
|
506
|
+
throw new Error('Invalid resource uri: expected string');
|
|
358
507
|
}
|
|
359
|
-
}
|
|
360
508
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
509
|
+
if (uri === 'prp://current') {
|
|
510
|
+
return readPrpText(cwd);
|
|
511
|
+
}
|
|
512
|
+
if (uri === 'prp://findings') {
|
|
513
|
+
return readPrpFindingsText(cwd);
|
|
514
|
+
}
|
|
515
|
+
if (uri === 'prp://next-actions') {
|
|
516
|
+
return readPrpNextActionsText(cwd);
|
|
517
|
+
}
|
|
518
|
+
if (uri === 'prp://mission-map') {
|
|
519
|
+
try {
|
|
520
|
+
return await readFile(join(resolveCwd(cwd), '.viberaven', 'mission-map.md'), 'utf8');
|
|
521
|
+
} catch (error) {
|
|
522
|
+
if (error && error.code === 'ENOENT') {
|
|
523
|
+
return 'ERROR: .viberaven/mission-map.md not found. Run npx -y viberaven --agent-mode first.';
|
|
524
|
+
}
|
|
525
|
+
throw error;
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
if (uri === 'prp://context-map') {
|
|
529
|
+
try {
|
|
530
|
+
return await readFile(join(resolveCwd(cwd), '.viberaven', 'context-map.json'), 'utf8');
|
|
531
|
+
} catch (error) {
|
|
532
|
+
if (error && error.code === 'ENOENT') {
|
|
533
|
+
return 'ERROR: .viberaven/context-map.json not found. Run npx -y viberaven --agent-mode first.';
|
|
534
|
+
}
|
|
535
|
+
throw error;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
throw new Error(`Unknown resource uri: ${uri}`);
|
|
364
540
|
}
|
|
365
541
|
|
|
366
|
-
|
|
367
|
-
|
|
542
|
+
function errorMessage(error) {
|
|
543
|
+
return error instanceof Error ? error.message : String(error);
|
|
368
544
|
}
|
|
369
545
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
};
|
|
546
|
+
function buildNpxCommand(args) {
|
|
547
|
+
if (process.platform === 'win32') {
|
|
548
|
+
return {
|
|
549
|
+
command: 'cmd.exe',
|
|
550
|
+
args: ['/d', '/s', '/c', 'npx', ...args],
|
|
551
|
+
options: { shell: false }
|
|
552
|
+
};
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return {
|
|
556
|
+
command: 'npx',
|
|
557
|
+
args,
|
|
558
|
+
options: { shell: false }
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function runVibeRaven(args, cwd) {
|
|
563
|
+
return new Promise((resolve) => {
|
|
564
|
+
const built = buildNpxCommand(args);
|
|
565
|
+
const child = spawnChild(built.command, built.args, {
|
|
566
|
+
cwd: resolveCwd(cwd),
|
|
567
|
+
env: process.env,
|
|
568
|
+
shell: built.options.shell,
|
|
569
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
570
|
+
});
|
|
571
|
+
let stdout = '';
|
|
572
|
+
let stderr = '';
|
|
573
|
+
child.stdout.on('data', (chunk) => {
|
|
574
|
+
stdout += chunk.toString();
|
|
575
|
+
});
|
|
576
|
+
child.stderr.on('data', (chunk) => {
|
|
577
|
+
stderr += chunk.toString();
|
|
578
|
+
});
|
|
579
|
+
child.on('error', (error) => {
|
|
580
|
+
resolve(`ERROR: ${error.message}`);
|
|
581
|
+
});
|
|
582
|
+
child.on('close', (code) => {
|
|
583
|
+
const combined = `${stdout}${stderr}`.trim();
|
|
584
|
+
resolve(`exit ${code ?? 1}${combined ? `\n${combined}` : ''}`);
|
|
585
|
+
});
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
function parseJsonObjectFromToolText(text) {
|
|
590
|
+
const jsonStart = text.indexOf('{');
|
|
591
|
+
if (jsonStart === -1) return undefined;
|
|
592
|
+
try {
|
|
593
|
+
return JSON.parse(text.slice(jsonStart));
|
|
594
|
+
} catch {
|
|
595
|
+
return undefined;
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
function send(message) {
|
|
600
|
+
const body = JSON.stringify(message);
|
|
601
|
+
process.stdout.write(`Content-Length: ${Buffer.byteLength(body, 'utf8')}\r\n\r\n${body}`);
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
if (require.main === module) {
|
|
605
|
+
main();
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
module.exports = {
|
|
609
|
+
TOOLS,
|
|
610
|
+
buildNpxCommand,
|
|
611
|
+
callTool,
|
|
612
|
+
handleRequest,
|
|
613
|
+
parseJsonObjectFromToolText,
|
|
614
|
+
safeStringArg,
|
|
615
|
+
__setSpawnForTest(spawnForTest) {
|
|
616
|
+
spawnChild = spawnForTest;
|
|
617
|
+
},
|
|
618
|
+
__resetSpawnForTest() {
|
|
619
|
+
spawnChild = spawn;
|
|
620
|
+
}
|
|
621
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@viberaven/mcp",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "MCP server for VibeRaven production-readiness: check_readiness, verify, heal, audit, and strict gate tools for Cursor, Claude Code, and Codex.",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "VibeRaven",
|