@rigour-labs/mcp 6.6.0 → 6.6.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 CHANGED
@@ -132,6 +132,8 @@ No global install: npx fetches the server when your agent starts it. Keep a vers
132
132
 
133
133
  Only Rigour's core tools are listed by default; add `"RIGOUR_MCP_TOOLS": "governance,telemetry"` (or `"full"`) to `env` for the rest. Node.js 22 or later is required.
134
134
 
135
+ To keep a server apart from your other work (one per employer or client), add `"RIGOUR_USER_MEMORY": "off"`: it then never reads or writes the memories you keep for all your repositories.
136
+
135
137
  ---
136
138
 
137
139
  ## 📖 Documentation
package/dist/index.js CHANGED
@@ -15,7 +15,7 @@ import { CallToolRequestSchema, ListToolsRequestSchema, ListPromptsRequestSchema
15
15
  import { randomUUID } from "crypto";
16
16
  import { GateRunner, countUsage, flushDailyUsage } from "@rigour-labs/core";
17
17
  // Utils
18
- import { loadConfig, loadMcpSettings, logStudioEvent } from './utils/config.js';
18
+ import { loadConfig, loadMcpSettings, logStudioEvent, resolveCwd } from './utils/config.js';
19
19
  import { bindServer } from './utils/notifications.js';
20
20
  import { getMcpVersion } from './utils/package-version.js';
21
21
  import { buildMcpResultMeta, buildStudioImpact } from './utils/impact-receipt.js';
@@ -85,7 +85,7 @@ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
85
85
  // ─── Tool Dispatch ────────────────────────────────────────────────
86
86
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
87
87
  const { name, arguments: args } = request.params;
88
- const cwd = args?.cwd || process.cwd();
88
+ const cwd = resolveCwd(args);
89
89
  const requestId = randomUUID();
90
90
  try {
91
91
  await logStudioEvent(cwd, { type: "tool_call", requestId, tool: name, arguments: args });
@@ -369,7 +369,7 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => ({
369
369
  }));
370
370
  server.setRequestHandler(GetPromptRequestSchema, async (request) => {
371
371
  const { name, arguments: promptArgs } = request.params;
372
- const cwd = promptArgs?.cwd || process.env.RIGOUR_CWD || process.cwd();
372
+ const cwd = resolveCwd(promptArgs);
373
373
  const mcpSettings = await loadMcpSettings(cwd);
374
374
  const deepMode = mcpSettings.deep_default_mode;
375
375
  const prompt = PROMPT_DEFINITIONS.find((p) => p.name === name);
@@ -14,7 +14,7 @@
14
14
  * @since v2.17.0 — extracted from monolithic index.ts
15
15
  * @since v4.2.0 — DLP gate on memory persistence
16
16
  */
17
- import { loadMemory, saveMemory } from '../utils/config.js';
17
+ import { loadMemory, saveMemory, USER_MEMORY_OFF, userMemoryEnabled } from '../utils/config.js';
18
18
  import { scanInputForCredentials, formatDLPAlert, createDLPAuditEntry, loadTeamConfiguration, shareMemoryLesson, } from '@rigour-labs/core';
19
19
  import { loadPatternIndex, getDefaultIndexPath, } from '@rigour-labs/core/pattern-index';
20
20
  import { buildTelemetryMeta } from '../utils/context-telemetry.js';
@@ -95,6 +95,8 @@ export async function handleRemember(cwd, key, value, scope = 'repo') {
95
95
  }],
96
96
  };
97
97
  }
98
+ if (scope === 'user' && !userMemoryEnabled())
99
+ return { content: [{ type: "text", text: `MEMORY NOT STORED: ${USER_MEMORY_OFF}` }] };
98
100
  // ── DLP Gate: deep-scan key + value (including JSON interiors) ──
99
101
  const textToScan = deepScanValue(key, value);
100
102
  const dlpResult = scanInputForCredentials(textToScan);
@@ -148,6 +150,8 @@ async function shareWithTeam(cwd, key, value) {
148
150
  return '\nShared with your team as a candidate. Teammates\' agents receive it once someone shares it from Studio (How it learns).';
149
151
  }
150
152
  export async function handleForget(cwd, key, scope = 'repo') {
153
+ if (scope === 'user' && !userMemoryEnabled())
154
+ return { content: [{ type: "text", text: `NOTHING FORGOTTEN: ${USER_MEMORY_OFF}` }] };
151
155
  const store = await loadMemory(cwd, scope);
152
156
  if (!store.memories[key]) {
153
157
  return { content: [{ type: "text", text: `NO MEMORY FOUND for key "${key}" in ${scope} memory. Nothing to forget.` }] };
@@ -5,8 +5,17 @@
5
5
  * With no diff, the change is taken from git: uncommitted work (what the
6
6
  * agent just wrote, new files included), or the branch against `base`.
7
7
  */
8
- import { acknowledgeReview, buildReviewTask, diffFromGit, recordFixLessons, recordLessonsServed, recordReviewOutcome, reviewChange, toReviewFinding } from "@rigour-labs/core";
8
+ import { acknowledgeReview, buildQualityReceipt, buildReviewTask, receiptReport, diffFromGit, recordFixLessons, recordLessonsServed, recordReviewOutcome, reviewChange, toReviewFinding } from "@rigour-labs/core";
9
9
  import { notifyProgress } from '../utils/notifications.js';
10
+ /** What is known about each changed function before a model looks; never fails the review. */
11
+ function qualityReceipt(config, cwd, diff) {
12
+ try {
13
+ return { quality_receipt: receiptReport(buildQualityReceipt(cwd, diff, { policy: config.gates.deep?.router, lessonMode: config.gates.deep?.review_lessons })) };
14
+ }
15
+ catch {
16
+ return {};
17
+ }
18
+ }
10
19
  export async function handleReview(config, cwd, args) {
11
20
  notifyProgress("info", args.diff ? "Reviewing the provided diff..." : `Reviewing ${args.base ? `this branch against ${args.base}` : "uncommitted changes"}...`);
12
21
  try {
@@ -32,6 +41,7 @@ export async function handleReview(config, cwd, args) {
32
41
  excluded_outside_changed_lines: result.excludedOutsideChangedLines,
33
42
  unlocated_failures: result.unlocated,
34
43
  gate_errors: result.gateErrors,
44
+ ...qualityReceipt(config, cwd, diff),
35
45
  ...(task ? { review_task: { items: task.items, already_reviewed: task.alreadyReviewed, team_lessons: task.lessons, repo_rules: task.rules, instructions: task.instructions } } : {}),
36
46
  next_step: nextStep(result.findings.length, task?.items.length ?? 0),
37
47
  });
@@ -295,6 +295,15 @@ export interface MemoryStore {
295
295
  }
296
296
  /** The home whose .rigour/ holds user-scope memory: RIGOUR_HOME when set (tests, sandboxes), else the OS home. */
297
297
  export declare function userHome(): string;
298
+ /**
299
+ * False when RIGOUR_USER_MEMORY=off. A server kept apart from the user's other work (a private
300
+ * HOME per employer, a sandbox) then never reads or writes ~/.rigour/memory.json, even if it is
301
+ * started with the real home by mistake.
302
+ */
303
+ export declare function userMemoryEnabled(): boolean;
304
+ export declare const USER_MEMORY_OFF = "User memory is off on this server (RIGOUR_USER_MEMORY=off); use scope \"repo\".";
305
+ /** The repository a call works in: the call's own cwd, else RIGOUR_CWD, else where the server was started. */
306
+ export declare function resolveCwd(args: unknown): string;
298
307
  /** Where memories live: `repo` in this checkout's .rigour/, `user` in ~/.rigour/ for every repository. */
299
308
  export type LocalMemoryScope = 'repo' | 'user';
300
309
  export declare function getMemoryPath(cwd: string, scope?: LocalMemoryScope): Promise<string>;
@@ -38,12 +38,28 @@ function noteMissingConfig(cwd) {
38
38
  export function userHome() {
39
39
  return process.env.RIGOUR_HOME || os.homedir();
40
40
  }
41
+ /**
42
+ * False when RIGOUR_USER_MEMORY=off. A server kept apart from the user's other work (a private
43
+ * HOME per employer, a sandbox) then never reads or writes ~/.rigour/memory.json, even if it is
44
+ * started with the real home by mistake.
45
+ */
46
+ export function userMemoryEnabled() {
47
+ return process.env.RIGOUR_USER_MEMORY?.trim().toLowerCase() !== 'off';
48
+ }
49
+ export const USER_MEMORY_OFF = 'User memory is off on this server (RIGOUR_USER_MEMORY=off); use scope "repo".';
50
+ /** The repository a call works in: the call's own cwd, else RIGOUR_CWD, else where the server was started. */
51
+ export function resolveCwd(args) {
52
+ const given = args?.cwd;
53
+ return typeof given === 'string' && given ? given : process.env.RIGOUR_CWD || process.cwd();
54
+ }
41
55
  export async function getMemoryPath(cwd, scope = 'repo') {
42
56
  const rigourDir = scope === 'user' ? path.join(userHome(), ".rigour") : path.join(cwd, ".rigour");
43
57
  await fs.ensureDir(rigourDir);
44
58
  return path.join(rigourDir, "memory.json");
45
59
  }
46
60
  export async function loadMemory(cwd, scope = 'repo') {
61
+ if (scope === 'user' && !userMemoryEnabled())
62
+ return { memories: {} };
47
63
  const memPath = await getMemoryPath(cwd, scope);
48
64
  if (await fs.pathExists(memPath)) {
49
65
  const content = await fs.readFile(memPath, "utf-8");
@@ -60,6 +76,8 @@ export async function loadMemory(cwd, scope = 'repo') {
60
76
  return { memories: {} };
61
77
  }
62
78
  export async function saveMemory(cwd, store, scope = 'repo') {
79
+ if (scope === 'user' && !userMemoryEnabled())
80
+ throw new Error(USER_MEMORY_OFF);
63
81
  const memPath = await getMemoryPath(cwd, scope);
64
82
  await fs.writeFile(memPath, JSON.stringify(store, null, 2));
65
83
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rigour-labs/mcp",
3
- "version": "6.6.0",
3
+ "version": "6.6.1",
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, memory and lessons recalled by meaning, hallucinated import detection, multi-agent governance. Works with Claude, Cursor, VS Code, ChatGPT, Goose, Windsurf. Industry presets for HIPAA, SOC2, FedRAMP.",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -65,7 +65,7 @@
65
65
  "execa": "^8.0.1",
66
66
  "fs-extra": "^11.4.0",
67
67
  "yaml": "^2.8.2",
68
- "@rigour-labs/core": "6.6.0"
68
+ "@rigour-labs/core": "6.6.1"
69
69
  },
70
70
  "devDependencies": {
71
71
  "@types/node": "^25.0.3",