@rigour-labs/mcp 6.2.2 → 6.2.3
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/dist/advertised-tools.d.ts +35 -0
- package/dist/index.js +1 -1
- package/dist/tools/definitions.d.ts +35 -0
- package/dist/tools/definitions.js +6 -2
- package/dist/tools/fix-packet-format.d.ts +4 -0
- package/dist/tools/fix-packet-format.js +64 -0
- package/dist/tools/quality-handlers.d.ts +4 -1
- package/dist/tools/quality-handlers.js +10 -91
- package/package.json +2 -2
|
@@ -75,6 +75,37 @@ export declare function getAdvertisedToolDefinitions(): ({
|
|
|
75
75
|
idempotentHint: boolean;
|
|
76
76
|
openWorldHint: boolean;
|
|
77
77
|
};
|
|
78
|
+
} | {
|
|
79
|
+
name: string;
|
|
80
|
+
description: string;
|
|
81
|
+
inputSchema: {
|
|
82
|
+
type: string;
|
|
83
|
+
properties: {
|
|
84
|
+
offset: {
|
|
85
|
+
type: string;
|
|
86
|
+
minimum: number;
|
|
87
|
+
description: string;
|
|
88
|
+
};
|
|
89
|
+
limit: {
|
|
90
|
+
type: string;
|
|
91
|
+
minimum: number;
|
|
92
|
+
maximum: number;
|
|
93
|
+
description: string;
|
|
94
|
+
};
|
|
95
|
+
cwd: {
|
|
96
|
+
type: "string";
|
|
97
|
+
description: string;
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
required: string[];
|
|
101
|
+
};
|
|
102
|
+
annotations: {
|
|
103
|
+
title: string;
|
|
104
|
+
readOnlyHint: boolean;
|
|
105
|
+
destructiveHint: boolean;
|
|
106
|
+
idempotentHint: boolean;
|
|
107
|
+
openWorldHint: boolean;
|
|
108
|
+
};
|
|
78
109
|
} | {
|
|
79
110
|
name: string;
|
|
80
111
|
description: string;
|
|
@@ -545,6 +576,8 @@ export declare function getAdvertisedToolDefinitions(): ({
|
|
|
545
576
|
limit: {
|
|
546
577
|
type: string;
|
|
547
578
|
description: string;
|
|
579
|
+
minimum?: undefined;
|
|
580
|
+
maximum?: undefined;
|
|
548
581
|
};
|
|
549
582
|
cwd: {
|
|
550
583
|
type: "string";
|
|
@@ -696,6 +729,8 @@ export declare function getAdvertisedToolDefinitions(): ({
|
|
|
696
729
|
limit: {
|
|
697
730
|
type: string;
|
|
698
731
|
description: string;
|
|
732
|
+
minimum?: undefined;
|
|
733
|
+
maximum?: undefined;
|
|
699
734
|
};
|
|
700
735
|
taskId: {
|
|
701
736
|
type: string;
|
package/dist/index.js
CHANGED
|
@@ -128,7 +128,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
128
128
|
result = await handleStatus(runner, cwd);
|
|
129
129
|
break;
|
|
130
130
|
case "rigour_get_fix_packet":
|
|
131
|
-
result = await handleGetFixPacket(runner, cwd, config);
|
|
131
|
+
result = await handleGetFixPacket(runner, cwd, config, args);
|
|
132
132
|
break;
|
|
133
133
|
case "rigour_list_gates":
|
|
134
134
|
result = handleListGates(config);
|
|
@@ -87,6 +87,37 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
87
87
|
idempotentHint: boolean;
|
|
88
88
|
openWorldHint: boolean;
|
|
89
89
|
};
|
|
90
|
+
} | {
|
|
91
|
+
name: string;
|
|
92
|
+
description: string;
|
|
93
|
+
inputSchema: {
|
|
94
|
+
type: string;
|
|
95
|
+
properties: {
|
|
96
|
+
offset: {
|
|
97
|
+
type: string;
|
|
98
|
+
minimum: number;
|
|
99
|
+
description: string;
|
|
100
|
+
};
|
|
101
|
+
limit: {
|
|
102
|
+
type: string;
|
|
103
|
+
minimum: number;
|
|
104
|
+
maximum: number;
|
|
105
|
+
description: string;
|
|
106
|
+
};
|
|
107
|
+
cwd: {
|
|
108
|
+
type: "string";
|
|
109
|
+
description: string;
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
required: string[];
|
|
113
|
+
};
|
|
114
|
+
annotations: {
|
|
115
|
+
title: string;
|
|
116
|
+
readOnlyHint: boolean;
|
|
117
|
+
destructiveHint: boolean;
|
|
118
|
+
idempotentHint: boolean;
|
|
119
|
+
openWorldHint: boolean;
|
|
120
|
+
};
|
|
90
121
|
} | {
|
|
91
122
|
name: string;
|
|
92
123
|
description: string;
|
|
@@ -557,6 +588,8 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
557
588
|
limit: {
|
|
558
589
|
type: string;
|
|
559
590
|
description: string;
|
|
591
|
+
minimum?: undefined;
|
|
592
|
+
maximum?: undefined;
|
|
560
593
|
};
|
|
561
594
|
cwd: {
|
|
562
595
|
type: "string";
|
|
@@ -708,6 +741,8 @@ export declare const TOOL_DEFINITIONS: ({
|
|
|
708
741
|
limit: {
|
|
709
742
|
type: string;
|
|
710
743
|
description: string;
|
|
744
|
+
minimum?: undefined;
|
|
745
|
+
maximum?: undefined;
|
|
711
746
|
};
|
|
712
747
|
taskId: {
|
|
713
748
|
type: string;
|
|
@@ -84,10 +84,14 @@ export const TOOL_DEFINITIONS = [
|
|
|
84
84
|
},
|
|
85
85
|
{
|
|
86
86
|
name: "rigour_get_fix_packet",
|
|
87
|
-
description: "Call this after rigour_check returns FAIL. Returns a prioritized
|
|
87
|
+
description: "Call this after rigour_check returns FAIL. Returns a bounded, prioritized page of violations with file locations and fix instructions. Use next_offset from the response to read further pages, then re-run rigour_check. Report only fixes that were actually verified.",
|
|
88
88
|
inputSchema: {
|
|
89
89
|
type: "object",
|
|
90
|
-
properties:
|
|
90
|
+
properties: {
|
|
91
|
+
...cwdParam(),
|
|
92
|
+
offset: { type: "integer", minimum: 0, description: "Zero-based violation offset. Start at 0, then use the next offset in the response." },
|
|
93
|
+
limit: { type: "integer", minimum: 1, maximum: 10, description: "Violations per page (default 5, maximum 10)." },
|
|
94
|
+
},
|
|
91
95
|
required: ["cwd"],
|
|
92
96
|
},
|
|
93
97
|
annotations: {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { FixPacketV2, Report } from '@rigour-labs/core';
|
|
2
|
+
export declare const DEFAULT_FIX_PACKET_PAGE_SIZE = 5;
|
|
3
|
+
export declare const MAX_FIX_PACKET_PAGE_SIZE = 10;
|
|
4
|
+
export declare function formatFixPacketPage(packet: FixPacketV2, report: Report, offset: number, limit: number): string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
export const DEFAULT_FIX_PACKET_PAGE_SIZE = 5;
|
|
2
|
+
export const MAX_FIX_PACKET_PAGE_SIZE = 10;
|
|
3
|
+
const MAX_ITEM_CHARS = 1_600;
|
|
4
|
+
function clip(value, max) {
|
|
5
|
+
const text = String(value ?? '');
|
|
6
|
+
return text.length <= max ? text : `${text.slice(0, max - 16)}... [truncated]`;
|
|
7
|
+
}
|
|
8
|
+
function formatViolation(violation, index, total) {
|
|
9
|
+
const lines = [
|
|
10
|
+
`━━━ FIX ${index + 1}/${total}: [${violation.severity.toUpperCase()}] ${clip(violation.title, 180)} ━━━`,
|
|
11
|
+
`GATE: ${clip(violation.id, 100)}`,
|
|
12
|
+
`PROBLEM: ${clip(violation.details, 600)}`,
|
|
13
|
+
];
|
|
14
|
+
const locations = violation.locations ?? [];
|
|
15
|
+
if (locations.length > 0) {
|
|
16
|
+
const shown = locations.slice(0, 5).map(loc => `${clip(loc.file, 160)}${loc.line ? `:${loc.line}` : ''}${loc.endLine && loc.endLine !== loc.line ? `-${loc.endLine}` : ''}`);
|
|
17
|
+
lines.push(`WHERE: ${shown.join(', ')}${locations.length > 5 ? ` (+${locations.length - 5} more locations)` : ''}`);
|
|
18
|
+
}
|
|
19
|
+
else if (violation.files?.length) {
|
|
20
|
+
lines.push(`FILES: ${violation.files.slice(0, 5).map(file => clip(file, 160)).join(', ')}`);
|
|
21
|
+
}
|
|
22
|
+
if (violation.instructions?.length) {
|
|
23
|
+
lines.push('FIX:');
|
|
24
|
+
for (const [step, instruction] of violation.instructions.slice(0, 3).entries()) {
|
|
25
|
+
lines.push(` ${step + 1}. ${clip(instruction, 260)}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
else if (violation.hint) {
|
|
29
|
+
lines.push(`HINT: ${clip(violation.hint, 300)}`);
|
|
30
|
+
}
|
|
31
|
+
return clip(lines.join('\n'), MAX_ITEM_CHARS);
|
|
32
|
+
}
|
|
33
|
+
export function formatFixPacketPage(packet, report, offset, limit) {
|
|
34
|
+
const total = packet.violations.length;
|
|
35
|
+
const start = Math.min(offset, total);
|
|
36
|
+
const end = Math.min(start + limit, total);
|
|
37
|
+
const lines = [
|
|
38
|
+
'ENGINEERING REFINEMENT REQUIRED',
|
|
39
|
+
`Score: ${report.stats.score ?? 'unknown'}/100 | Violations: ${total}`,
|
|
40
|
+
`Failed gates: ${clip(packet.failed_gates.join(', '), 900)}`,
|
|
41
|
+
`Page: ${start}-${end} of ${total}`,
|
|
42
|
+
`next_offset: ${end < total ? end : 'none'}`,
|
|
43
|
+
'',
|
|
44
|
+
];
|
|
45
|
+
for (let index = start; index < end; index++) {
|
|
46
|
+
lines.push(formatViolation(packet.violations[index], index, total), '');
|
|
47
|
+
}
|
|
48
|
+
if (packet.verification?.commands?.length) {
|
|
49
|
+
lines.push('VERIFICATION:');
|
|
50
|
+
for (const command of packet.verification.commands.slice(0, 5)) {
|
|
51
|
+
lines.push(` $ ${clip(command.cmd, 180)} — ${clip(command.purpose, 120)}`);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (packet.constraints?.do_not_touch?.length) {
|
|
55
|
+
lines.push(`DO NOT TOUCH: ${clip(packet.constraints.do_not_touch.join(', '), 600)}`);
|
|
56
|
+
}
|
|
57
|
+
if (packet.constraints?.allowed_scope?.length) {
|
|
58
|
+
lines.push(`Allowed scope: ${packet.constraints.allowed_scope.length} file(s); see individual locations above.`);
|
|
59
|
+
}
|
|
60
|
+
lines.push(end < total
|
|
61
|
+
? `More violations remain. Call rigour_get_fix_packet with offset=${end} and limit=${limit}.`
|
|
62
|
+
: 'End of Fix Packet. Re-run rigour_check after repairs; report PASS only after verification.');
|
|
63
|
+
return lines.join('\n');
|
|
64
|
+
}
|
|
@@ -29,7 +29,10 @@ export interface CheckArgs {
|
|
|
29
29
|
export declare function handleCheck(runner: GateRunner, cwd: string, args?: CheckArgs): Promise<ToolResult>;
|
|
30
30
|
export declare function handleExplain(runner: GateRunner, cwd: string): Promise<ToolResult>;
|
|
31
31
|
export declare function handleStatus(runner: GateRunner, cwd: string): Promise<ToolResult>;
|
|
32
|
-
export declare function handleGetFixPacket(runner: GateRunner, cwd: string, config: Config
|
|
32
|
+
export declare function handleGetFixPacket(runner: GateRunner, cwd: string, config: Config, args?: {
|
|
33
|
+
offset?: number;
|
|
34
|
+
limit?: number;
|
|
35
|
+
}): Promise<ToolResult>;
|
|
33
36
|
export declare function handleListGates(config: Config): ToolResult;
|
|
34
37
|
export declare function handleGetConfig(config: Config): ToolResult;
|
|
35
38
|
export {};
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
*
|
|
7
7
|
* @since v2.17.0 — extracted from monolithic index.ts
|
|
8
8
|
*/
|
|
9
|
-
import { renderMcpHeadline
|
|
9
|
+
import { renderMcpHeadline } from "@rigour-labs/core";
|
|
10
10
|
import { notifyProgress } from '../utils/notifications.js';
|
|
11
|
+
import { DEFAULT_FIX_PACKET_PAGE_SIZE, MAX_FIX_PACKET_PAGE_SIZE, formatFixPacketPage } from './fix-packet-format.js';
|
|
11
12
|
function resolveDeepExecution(args) {
|
|
12
13
|
const requestedProvider = (args.provider || '').toLowerCase();
|
|
13
14
|
const isForcedLocal = requestedProvider === 'local';
|
|
@@ -124,7 +125,13 @@ export async function handleStatus(runner, cwd) {
|
|
|
124
125
|
}],
|
|
125
126
|
};
|
|
126
127
|
}
|
|
127
|
-
export async function handleGetFixPacket(runner, cwd, config) {
|
|
128
|
+
export async function handleGetFixPacket(runner, cwd, config, args = {}) {
|
|
129
|
+
const offset = args.offset ?? 0;
|
|
130
|
+
const limit = args.limit ?? DEFAULT_FIX_PACKET_PAGE_SIZE;
|
|
131
|
+
if (!Number.isInteger(offset) || offset < 0 || !Number.isInteger(limit)
|
|
132
|
+
|| limit < 1 || limit > MAX_FIX_PACKET_PAGE_SIZE) {
|
|
133
|
+
return { isError: true, content: [{ type: 'text', text: 'offset must be a nonnegative integer and limit must be an integer from 1 to 10.' }] };
|
|
134
|
+
}
|
|
128
135
|
const report = await runner.run(cwd);
|
|
129
136
|
if (report.status === "PASS") {
|
|
130
137
|
const passScore = report.stats.score !== undefined ? ` Score: ${report.stats.score}/100.` : '';
|
|
@@ -136,98 +143,10 @@ export async function handleGetFixPacket(runner, cwd, config) {
|
|
|
136
143
|
const { FixPacketService } = await import("@rigour-labs/core");
|
|
137
144
|
const fixPacketService = new FixPacketService();
|
|
138
145
|
const fixPacket = fixPacketService.generate(report, config);
|
|
139
|
-
// Find worst violation for attribution
|
|
140
|
-
const worst = report.failures.find(f => f.severity === 'critical')
|
|
141
|
-
|| report.failures.find(f => f.severity === 'high')
|
|
142
|
-
|| report.failures[0];
|
|
143
|
-
const worstLabel = worst ? worst.title : 'quality violations';
|
|
144
|
-
const attribution = renderFixAttribution(report.failures.length, worstLabel);
|
|
145
146
|
return {
|
|
146
|
-
content: [{ type: "text", text:
|
|
147
|
+
content: [{ type: "text", text: formatFixPacketPage(fixPacket, report, offset, limit) }],
|
|
147
148
|
};
|
|
148
149
|
}
|
|
149
|
-
/**
|
|
150
|
-
* Formats a FixPacketV2 into a structured, agent-readable text block.
|
|
151
|
-
* Every violation includes: who failed, which files, what rule, where (line numbers),
|
|
152
|
-
* and what commands must pass after fixing.
|
|
153
|
-
*/
|
|
154
|
-
function formatFixPacketText(fixPacket, report) {
|
|
155
|
-
const lines = [];
|
|
156
|
-
// Header
|
|
157
|
-
let scoreHeader = formatScoreText(report.stats).trim();
|
|
158
|
-
lines.push('ENGINEERING REFINEMENT REQUIRED');
|
|
159
|
-
if (scoreHeader)
|
|
160
|
-
lines.push(scoreHeader);
|
|
161
|
-
lines.push(`Violations: ${report.failures.length} | Failed gates: ${fixPacket.failed_gates.join(', ')}`);
|
|
162
|
-
lines.push('');
|
|
163
|
-
// Violations
|
|
164
|
-
fixPacket.violations.forEach((v, i) => {
|
|
165
|
-
const sevTag = `[${(v.severity || 'medium').toUpperCase()}]`;
|
|
166
|
-
const catTag = v.category ? ` (${v.category})` : '';
|
|
167
|
-
lines.push(`━━━ FIX ${i + 1}/${fixPacket.violations.length}: ${sevTag}${catTag} ${v.title} ━━━`);
|
|
168
|
-
lines.push(`GATE: ${v.id}`);
|
|
169
|
-
lines.push(`PROBLEM: ${v.details}`);
|
|
170
|
-
// Locations with line numbers (precise targeting)
|
|
171
|
-
if (v.locations && v.locations.length > 0) {
|
|
172
|
-
const locStrs = v.locations.map((loc) => {
|
|
173
|
-
let s = loc.file;
|
|
174
|
-
if (loc.line)
|
|
175
|
-
s += `:${loc.line}`;
|
|
176
|
-
if (loc.endLine && loc.endLine !== loc.line)
|
|
177
|
-
s += `-${loc.endLine}`;
|
|
178
|
-
return s;
|
|
179
|
-
});
|
|
180
|
-
lines.push(`WHERE: ${locStrs.join(', ')}`);
|
|
181
|
-
}
|
|
182
|
-
else if (v.files && v.files.length > 0) {
|
|
183
|
-
lines.push(`FILES: ${v.files.join(', ')}`);
|
|
184
|
-
}
|
|
185
|
-
// Metrics (thresholds vs actuals)
|
|
186
|
-
if (v.metrics && Object.keys(v.metrics).length > 0) {
|
|
187
|
-
const metricStrs = Object.entries(v.metrics).map(([k, val]) => `${k}=${val}`);
|
|
188
|
-
lines.push(`METRICS: ${metricStrs.join(', ')}`);
|
|
189
|
-
}
|
|
190
|
-
// Instructions
|
|
191
|
-
if (v.instructions && v.instructions.length > 0) {
|
|
192
|
-
lines.push(`FIX:`);
|
|
193
|
-
v.instructions.forEach((inst, j) => {
|
|
194
|
-
lines.push(` ${j + 1}. ${inst}`);
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
else if (v.hint) {
|
|
198
|
-
lines.push(`HINT: ${v.hint}`);
|
|
199
|
-
}
|
|
200
|
-
lines.push('');
|
|
201
|
-
});
|
|
202
|
-
// Verification commands
|
|
203
|
-
if (fixPacket.verification?.commands?.length > 0) {
|
|
204
|
-
lines.push('━━━ VERIFICATION (run these after fixing) ━━━');
|
|
205
|
-
fixPacket.verification.commands.forEach((c) => {
|
|
206
|
-
lines.push(` $ ${c.cmd} — ${c.purpose}`);
|
|
207
|
-
});
|
|
208
|
-
lines.push('');
|
|
209
|
-
}
|
|
210
|
-
// Constraints
|
|
211
|
-
const c = fixPacket.constraints;
|
|
212
|
-
if (c) {
|
|
213
|
-
const constraintParts = [];
|
|
214
|
-
if (c.allowed_scope?.length > 0)
|
|
215
|
-
constraintParts.push(`ALLOWED SCOPE: ${c.allowed_scope.join(', ')}`);
|
|
216
|
-
if (c.do_not_touch?.length > 0)
|
|
217
|
-
constraintParts.push(`DO NOT TOUCH: ${c.do_not_touch.join(', ')}`);
|
|
218
|
-
if (c.max_files_changed)
|
|
219
|
-
constraintParts.push(`MAX FILES CHANGED: ${c.max_files_changed}`);
|
|
220
|
-
if (c.no_new_deps)
|
|
221
|
-
constraintParts.push('NO NEW DEPENDENCIES');
|
|
222
|
-
if (c.paradigm)
|
|
223
|
-
constraintParts.push(`PARADIGM: ${c.paradigm}`);
|
|
224
|
-
if (constraintParts.length > 0) {
|
|
225
|
-
lines.push('━━━ CONSTRAINTS ━━━');
|
|
226
|
-
constraintParts.forEach(p => lines.push(` ${p}`));
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
return lines.join('\n');
|
|
230
|
-
}
|
|
231
150
|
export function handleListGates(config) {
|
|
232
151
|
return {
|
|
233
152
|
content: [{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rigour-labs/mcp",
|
|
3
|
-
"version": "6.2.
|
|
3
|
+
"version": "6.2.3",
|
|
4
4
|
"description": "MCP server + live dashboard for AI code governance — OWASP LLM Top 10 (10/10), real-time MCP App UI, 25+ security patterns, Bayesian learning Brain, hallucinated import detection, multi-agent governance. Works with Claude, Cursor, VS Code, ChatGPT, Goose, Windsurf. Industry presets for HIPAA, SOC2, FedRAMP.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://rigour.run",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"execa": "^8.0.1",
|
|
63
63
|
"fs-extra": "^11.4.0",
|
|
64
64
|
"yaml": "^2.8.2",
|
|
65
|
-
"@rigour-labs/core": "6.2.
|
|
65
|
+
"@rigour-labs/core": "6.2.3"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
68
|
"@types/node": "^25.0.3",
|