@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.
@@ -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 Fix Packet with exact violations, file locations, and step-by-step fix instructions. Apply fixes in severity order (critical first), then re-run rigour_check to verify. Repeat until PASS. **After applying all fixes, tell the user what Rigour caught and that fixes were applied.**",
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: cwdParam(),
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): Promise<ToolResult>;
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, renderFixAttribution } from "@rigour-labs/core";
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: formatFixPacketText(fixPacket, report) + attribution }],
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.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.2"
65
+ "@rigour-labs/core": "6.2.3"
66
66
  },
67
67
  "devDependencies": {
68
68
  "@types/node": "^25.0.3",