secufusion-mcp 1.0.3 → 1.0.5

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.
Files changed (3) hide show
  1. package/README.md +496 -141
  2. package/index.js +141 -21
  3. package/package.json +3 -2
package/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # SecuFusion MCP Server
1
+ # SecuFusion MCP Server
2
2
 
3
3
  > **Developer workflow tooling for the SecuFusion platform** — enforces zero-trust architecture standards, tracks task specs, and gates PRs with automated guardrail checks.
4
4
 
@@ -10,306 +10,661 @@
10
10
 
11
11
  ## What is this?
12
12
 
13
- `secufusion-mcp` is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that plugs into AI coding assistants (Claude Desktop, Cursor, Cline, Antigravity, etc.) and gives them three powerful tools to enforce SecuFusion's engineering standards throughout the development lifecycle.
13
+ `secufusion-mcp` is a [Model Context Protocol (MCP)](https://modelcontextprotocol.io) server that plugs into AI coding assistants (Claude Desktop, Cursor, Cline, etc.) and gives them three powerful tools to enforce SecuFusion's engineering standards throughout the development lifecycle:
14
14
 
15
15
  | Tool | Phase | What it does |
16
16
  |---|---|---|
17
- | `manage_feature_spec` | Planning & Execution | Creates/updates a `.current-task-spec.md` blueprint for every feature |
17
+ | `manage_feature_spec` | Planning & Execution | Creates/updates a `.current-task-spec.md` blueprint (works for single-repo or cross-repo tasks) |
18
18
  | `log_rejected_pattern` | Course Correction | Records bad patterns to `.rejected-patterns.json` so they are never repeated |
19
- | `run_pre_pr_checks` | PR Handoff | Scans the codebase and gates PRs with automated guardrail validation |
19
+ | `run_pre_pr_checks` | PR Handoff | Discovers modified microservices across the workspace and gates PRs via AST-level linters + structural checks |
20
20
 
21
21
  ---
22
22
 
23
23
  ## Installation
24
24
 
25
- No installation needed for teammates just add to your MCP config and it runs via `npx`.
26
-
27
- If you want to run it from a local build (faster, fully offline):
25
+ ### Option 1`npx` (no install required)
28
26
 
29
27
  ```bash
30
- git clone https://github.com/your-org/secufusion-mcp
31
- cd secufusion-mcp
32
- npm install
33
- npm run build
28
+ npx secufusion-mcp
34
29
  ```
35
30
 
36
- ---
31
+ ### Option 2 — Global install
37
32
 
38
- ## Setup: Add to Your MCP Client
39
-
40
- ### Which config should I use?
33
+ ```bash
34
+ npm install -g secufusion-mcp
35
+ ```
41
36
 
42
- | Situation | Command to use |
43
- |---|---|
44
- | **You have the source on disk** (faster, offline) | `node C:\path\to\secufusion-mcp\index.js` |
45
- | **Anyone else / fresh machine** (auto-downloads, cached after first run) | `npx -y secufusion-mcp` |
37
+ ### Option 3 Local project install
46
38
 
47
- > `npx` downloads from npm on first run (~3s) then caches it locally. Every run after that is instant and requires no network.
39
+ ```bash
40
+ npm install --save-dev secufusion-mcp
41
+ ```
48
42
 
49
43
  ---
50
44
 
51
- ### Antigravity IDE
45
+ ## Setup: Add to Your MCP Client
46
+
47
+ ### Claude Desktop
52
48
 
53
- Open **Customizations → MCP Servers** → edit `mcp_config.json` directly:
49
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
50
+ `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
54
51
 
55
- **If you have the source on disk:**
56
52
  ```json
57
53
  {
58
54
  "mcpServers": {
59
55
  "secufusion-mcp": {
60
- "command": "node",
61
- "args": ["C:\\Users\\YourName\\path\\to\\secufusion-mcp\\index.js"],
62
- "type": "stdio"
56
+ "command": "npx",
57
+ "args": ["-y", "secufusion-mcp"]
63
58
  }
64
59
  }
65
60
  }
66
61
  ```
67
62
 
68
- **If you are a teammate (no source):**
63
+ ### Cursor
64
+
65
+ Open **Settings → MCP** and add:
66
+
69
67
  ```json
70
68
  {
71
- "mcpServers": {
72
- "secufusion-mcp": {
73
- "command": "npx",
74
- "args": ["-y", "secufusion-mcp"],
75
- "type": "stdio"
76
- }
69
+ "secufusion-mcp": {
70
+ "command": "npx",
71
+ "args": ["-y", "secufusion-mcp"]
77
72
  }
78
73
  }
79
74
  ```
80
75
 
81
- ---
76
+ ### Cline (VS Code Extension)
82
77
 
83
- ### Claude Desktop
78
+ Open Cline settings → MCP Servers → Add:
84
79
 
85
- Edit `%APPDATA%\Claude\claude_desktop_config.json` (Windows) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
80
+ ```json
81
+ {
82
+ "secufusion-mcp": {
83
+ "command": "npx",
84
+ "args": ["-y", "secufusion-mcp"],
85
+ "disabled": false
86
+ }
87
+ }
88
+ ```
89
+
90
+ ### Using a local build (development)
86
91
 
87
92
  ```json
88
93
  {
89
- "mcpServers": {
90
- "secufusion-mcp": {
91
- "command": "npx",
92
- "args": ["-y", "secufusion-mcp"]
93
- }
94
+ "secufusion-mcp": {
95
+ "command": "node",
96
+ "args": ["C:/path/to/secufusion-mcp/index.js"]
94
97
  }
95
98
  }
96
99
  ```
97
100
 
98
101
  ---
99
102
 
100
- ### VS Code — Cline Extension
103
+ ## Tools Reference
104
+
105
+ ### 1. `manage_feature_spec`
106
+
107
+ Creates or updates the `.current-task-spec.md` file — your single source of truth for every task. The AI reads this before writing any code.
101
108
 
102
- Install the **Cline** extension → click ⚙️ Settings → **MCP Servers** → **Edit Config**:
109
+ **Parameters:**
110
+
111
+ | Parameter | Type | Required | Description |
112
+ |---|---|---|---|
113
+ | `action` | `"create"` \| `"update"` \| `"read"` | Yes | What to do with the spec |
114
+ | `task_description` | string | When `action=create` | Full description of the task/feature |
115
+ | `update_content` | string | When `action=update` | Markdown lines to merge (e.g. tick checkboxes) |
116
+ | `work_item_id` | string | No | Azure DevOps work item ID |
117
+ | `reference_file_path` | string | No | Path to an existing source file to extract coding patterns from |
103
118
 
119
+ **Example — Create a spec:**
120
+
121
+ ```
122
+ Ask your AI assistant:
123
+ "Start working on WI-1042: Add tenant-scoped audit log export to CSV.
124
+ Reference file: src/services/AuditService.java"
125
+ ```
126
+
127
+ The AI will call:
104
128
  ```json
105
129
  {
106
- "mcpServers": {
107
- "secufusion-mcp": {
108
- "command": "npx",
109
- "args": ["-y", "secufusion-mcp"],
110
- "disabled": false
111
- }
130
+ "action": "create",
131
+ "task_description": "Add tenant-scoped audit log export to CSV...",
132
+ "work_item_id": "1042",
133
+ "reference_file_path": "src/services/AuditService.java"
134
+ }
135
+ ```
136
+
137
+ This generates `.current-task-spec.md` with:
138
+ - Task description
139
+ - Pre-filled guardrails checklist
140
+ - Acceptance criteria placeholders
141
+ - Reference code snippet
142
+ - Session log
143
+
144
+ **Example — Tick off completed work:**
145
+
146
+ ```
147
+ Ask: "Mark the tenantId scoping and unit tests as done in the spec."
148
+ ```
149
+
150
+ The AI will call:
151
+ ```json
152
+ {
153
+ "action": "update",
154
+ "update_content": "- [x] All DB queries / event payloads are scoped with `tenantId`\n- [x] Unit tests written / updated for new business logic"
155
+ }
156
+ ```
157
+
158
+ **Example — Read current spec:**
159
+
160
+ ```
161
+ Ask: "Where did we leave off? Read the current spec."
162
+ ```
163
+
164
+ ```json
165
+ { "action": "read" }
166
+ ```
167
+
168
+ ---
169
+
170
+ ### 2. `log_rejected_pattern`
171
+
172
+ Appends a rejected code pattern to `.rejected-patterns.json`. The AI checks this file implicitly before every architectural suggestion to avoid repeating past mistakes.
173
+
174
+ **Parameters:**
175
+
176
+ | Parameter | Type | Required | Description |
177
+ |---|---|---|---|
178
+ | `pattern` | string | Yes | The bad pattern or approach |
179
+ | `reason` | string | Yes | Why it was rejected and what to do instead |
180
+ | `category` | enum | No | `architecture` \| `security` \| `database` \| `logging` \| `api-design` \| `testing` \| `other` |
181
+ | `file_context` | string | No | File or area where the pattern was observed |
182
+
183
+ **Example:**
184
+
185
+ ```
186
+ Tell your AI: "Never use a global @Repository bean without tenantId scoping again.
187
+ It was leaking cross-tenant data."
188
+ ```
189
+
190
+ The AI will call:
191
+ ```json
192
+ {
193
+ "pattern": "Injecting global @Repository bean and querying without tenantId filter",
194
+ "reason": "Causes cross-tenant data leakage. Always add .where(tenantId = :tenantId) or use TenantAwareRepository base class.",
195
+ "category": "security",
196
+ "file_context": "src/repositories/AuditLogRepository.java"
197
+ }
198
+ ```
199
+
200
+ This writes to `.rejected-patterns.json`:
201
+ ```json
202
+ [
203
+ {
204
+ "id": 1,
205
+ "timestamp": "2026-08-26T14:35:00.000Z",
206
+ "category": "security",
207
+ "pattern": "Injecting global @Repository bean...",
208
+ "reason": "Causes cross-tenant data leakage...",
209
+ "file_context": "src/repositories/AuditLogRepository.java"
112
210
  }
211
+ ]
212
+ ```
213
+
214
+ ---
215
+
216
+ ### 3. run_pre_pr_checks
217
+
218
+ | Parameter | Type | Required | Description |
219
+ |---|---|---|---|
220
+ | `work_item_id` | string | Yes | Azure DevOps work item ID |
221
+ | `root_dir` | string | No | Directory to scan (defaults to cwd) |
222
+ | `skip_checks` | array | No | `spec_boxes`, `console_logs`, `hardcoded_urls`, `flyway_migrations` |
223
+
224
+ **Guardrail checks:**
225
+
226
+ | Check | Fails when |
227
+ |---|---|
228
+ | **SPEC** | `.current-task-spec.md` is missing or has unchecked `- [ ]` boxes |
229
+ | **LINTING** | AST linters (ESLint, Checkstyle) fail in any discovered microservice. Fix natively, do not suppress! (Falls back to regex if no linters exist) |
230
+ | **SECURITY** | Hardcoded IPs or `uat.*` / `prod.*` / `staging.*` URLs in source or config files |
231
+ | **FLYWAY** | `@Entity`-annotated Java files exist but no `V*__.sql` Flyway migrations found |
232
+
233
+ **Example — Run checks before PR:**
234
+
235
+ ```
236
+ Ask: "Prepare the PR for work item 1042."
237
+ ```
238
+
239
+ The AI will call:
240
+ ```json
241
+ {
242
+ "work_item_id": "1042"
113
243
  }
114
244
  ```
115
245
 
116
- ### VS Code — Workspace level (commit to repo)
246
+ **✅ Passing output:**
247
+ ```
248
+ # ✅ Pre-PR Checks PASSED — Work Item #1042
249
+
250
+ ✅ [SPEC] All spec checkboxes are checked.
251
+ ✅ [LOGGING] No console.log / System.out.println found.
252
+ ✅ [SECURITY] No hardcoded UAT/Prod IPs or environment URLs found.
253
+ ✅ [FLYWAY] Flyway migration coverage looks good.
254
+
255
+ ## PR Summary
256
+ - Work Item: #1042
257
+ - Spec: All acceptance criteria verified ✅
258
+ - Ready to raise PR 🚀
259
+ ```
260
+
261
+ **❌ Failing output (example):**
262
+ ```
263
+ # ❌ Pre-PR Checks FAILED — Work Item #1042
264
+
265
+ ❌ [SPEC] 3 unchecked item(s) in the spec:
266
+ • Flyway SQL migration created for every modified JPA @Entity
267
+ • Unit tests written / updated for new business logic
268
+ • API contract updated if endpoints changed
269
+
270
+ ❌ [LOGGING] Found 2 prohibited log statement(s):
271
+ • console.log() found at src/components/AuditTable.tsx:47
272
+ • System.out.println() found at src/main/java/AuditService.java:112
273
+ ```
274
+
275
+ ---
276
+
277
+ ## Guardrails Summary
278
+
279
+ These rules are enforced automatically — the AI will never violate them:
280
+
281
+ ```
282
+ ✅ All DB queries and event payloads scoped with tenantId
283
+ ✅ No console.log() or System.out.println() in any source file
284
+ ✅ No hardcoded UAT/Prod IPs or environment URLs
285
+ ✅ Every JPA @Entity change accompanied by a Flyway .sql migration
286
+ ✅ Spec must be fully checked before PR is raised
287
+ ```
288
+
289
+ ---
290
+
291
+ ## File Outputs
292
+
293
+ | File | Description |
294
+ |---|---|
295
+ | `.current-task-spec.md` | Living task blueprint — created per feature, updated as work progresses |
296
+ | `.rejected-patterns.json` | Cumulative log of all rejected patterns across sessions |
297
+
298
+ > **Tip:** Commit both files to your repo so the entire team benefits from the shared knowledge.
299
+
300
+ ---
301
+
302
+ ## Workflow Overview
117
303
 
118
- Create `.vscode/mcp.json` in your project root:
304
+ ```
305
+ ┌─────────────────────────────────────────────────────┐
306
+ │ SecuFusion MCP Workflow │
307
+ ├──────────────┬──────────────────────────────────────┤
308
+ │ Phase 1 │ manage_feature_spec (action=create) │
309
+ │ Planning │ → Generates .current-task-spec.md │
310
+ ├──────────────┼──────────────────────────────────────┤
311
+ │ Phase 2 │ manage_feature_spec (action=update) │
312
+ │ Execution │ → Tick off ACs as you complete them │
313
+ ├──────────────┼──────────────────────────────────────┤
314
+ │ Phase 3 │ log_rejected_pattern │
315
+ │ Correction │ → Record mistakes to avoid repeat │
316
+ ├──────────────┼──────────────────────────────────────┤
317
+ │ Phase 4 │ run_pre_pr_checks │
318
+ │ PR Handoff │ → Must pass before raising PR │
319
+ └──────────────┴──────────────────────────────────────┘
320
+ ```
321
+
322
+ ---
119
323
 
324
+ ## Real-World Walkthrough
325
+
326
+ A complete end-to-end example of what you actually type and what happens at each phase.
327
+
328
+ ---
329
+
330
+ ### Step 1 — Integrate (one-time setup)
331
+
332
+ Add this to your MCP client config and restart. That's it.
333
+
334
+ **Antigravity / Claude Desktop / Cline — if you have the source on disk:**
120
335
  ```json
121
336
  {
122
- "servers": {
337
+ "mcpServers": {
123
338
  "secufusion-mcp": {
124
- "type": "stdio",
125
- "command": "npx",
126
- "args": ["-y", "secufusion-mcp"]
339
+ "command": "node",
340
+ "args": ["C:\\Users\\YourName\\Desktop\\mcp\\secufusion-mcp\\index.js"],
341
+ "type": "stdio"
127
342
  }
128
343
  }
129
344
  }
130
345
  ```
131
346
 
132
- ### Cursor
133
-
134
- Open Settings → MCP → Add:
135
-
347
+ **Teammates / fresh machines — pulls from npm, cached after first run:**
136
348
  ```json
137
349
  {
138
- "secufusion-mcp": {
139
- "command": "npx",
140
- "args": ["-y", "secufusion-mcp"]
350
+ "mcpServers": {
351
+ "secufusion-mcp": {
352
+ "command": "npx",
353
+ "args": ["-y", "secufusion-mcp"],
354
+ "type": "stdio"
355
+ }
141
356
  }
142
357
  }
143
358
  ```
144
359
 
145
- ---
360
+ > **Why two options?** If you have the compiled `index.js` on disk, `node` starts instantly and works fully offline. Teammates who don't have the source use `npx` — it downloads from npm once (~3s), then caches it locally so every subsequent run is instant with no network needed.
146
361
 
147
- ## How to Use It (Day-to-Day)
362
+ ---
148
363
 
149
- ### Start a task just paste your Azure work item
364
+ ### Step 2Start a new task (Planning phase)
150
365
 
151
- You do not need to learn any commands. Just tell your AI assistant:
366
+ Just paste your Azure DevOps work item ID and description directly into the chat. No special syntax needed.
152
367
 
368
+ **You type:**
153
369
  ```
154
370
  WI-2847: Add MFA enforcement for admin users on login.
155
371
  Admin users must be forced through TOTP verification before
156
372
  accessing any dashboard route. Exempt service accounts.
157
373
  ```
158
374
 
159
- The AI automatically calls `manage_feature_spec` and creates `.current-task-spec.md` with:
160
- - Your task description
161
- - A guardrails checklist
162
- - Acceptance criteria placeholders
163
- - A direct Azure DevOps link
164
- - A session log
375
+ **The AI automatically calls `manage_feature_spec` and creates `.current-task-spec.md`:**
376
+ ```markdown
377
+ # SecuFusion Feature Spec
378
+
379
+ **Generated:** 2026-08-26T14:35:00.000Z
380
+ **Azure DevOps Work Item:** 2847 → https://dev.azure.com/secufusion/_workitems/edit/2847
381
+
382
+ ## Task Description
383
+ Add MFA enforcement for admin users on login...
384
+
385
+ ## Guardrails Checklist
386
+ - [ ] All DB queries / event payloads are scoped with `tenantId`
387
+ - [ ] No `console.log` / `System.out.println` left in source files
388
+ - [ ] No hardcoded UAT/Prod IPs or environment URLs
389
+ - [ ] Flyway SQL migration created for every modified JPA `@Entity`
390
+ - [ ] Unit tests written / updated for new business logic
391
+ - [ ] API contract updated if endpoints changed
165
392
 
166
- You can be brief or paste the full ticket — both work:
393
+ ## Acceptance Criteria
394
+ - [ ] AC-1: (fill in from ticket)
395
+ - [ ] AC-2: (fill in from ticket)
167
396
 
397
+ ## Session Log
398
+ | 2026-08-26T14:35:00Z | Spec created |
168
399
  ```
169
- # Minimal
400
+
401
+ You can paste as little or as much as you want:
402
+
403
+ ```
404
+ # Minimal — one liner
170
405
  WI-2847: MFA for admin login with TOTP.
171
406
 
172
- # Full Azure paste
407
+ # Full ticket paste — straight from Azure
173
408
  WI-2847
174
409
  Title: Add MFA enforcement for admin users
175
410
  Description: Admin users must complete TOTP verification...
176
411
  Acceptance Criteria:
177
412
  - Given admin logs in, When MFA not done, Then redirect to /mfa
178
413
  - Service accounts in GROUP_SERVICE_ACCOUNTS are exempt
414
+ Priority: High
179
415
  ```
180
416
 
181
417
  ---
182
418
 
183
- ### Tick off completed work
419
+ ### Step 3 Write code normally
420
+
421
+ Just code as usual. With the MCP server active, the AI automatically:
422
+
423
+ - Adds `tenantId` scoping to every DB query it writes
424
+ - Uses a proper logger (e.g., `log.info()`) — never `console.log`
425
+ - Reads `.rejected-patterns.json` before making any architectural suggestion
426
+ - Reminds you to create a Flyway migration if it touches a `@Entity`
427
+ - References any `reference_file_path` you provided to match your coding style
428
+
429
+ ---
430
+
431
+ ### Step 4 — Tick off completed work (Execution phase)
432
+
433
+ As you finish pieces of the feature, tell the AI:
184
434
 
185
435
  ```
186
- I've finished the tenantId scoping and written the unit tests. Update the spec.
436
+ I've finished the tenantId scoping on all queries and written the unit tests.
437
+ Update the spec.
187
438
  ```
188
439
 
189
- The AI checks off the matching boxes in `.current-task-spec.md`.
440
+ The AI calls `manage_feature_spec` with `action=update` and the spec updates:
441
+
442
+ ```markdown
443
+ # Before
444
+ - [ ] All DB queries / event payloads are scoped with `tenantId`
445
+ - [ ] Unit tests written / updated for new business logic
446
+
447
+ # After
448
+ - [x] All DB queries / event payloads are scoped with `tenantId`
449
+ - [x] Unit tests written / updated for new business logic
450
+ ```
451
+
452
+ A new row is also appended to the Session Log automatically, so you always have an audit trail of progress across sessions.
190
453
 
191
454
  ---
192
455
 
193
- ### Record a mistake (so it never happens again)
456
+ ### Step 5 Course correction (if the AI does something wrong)
457
+
458
+ Say the AI used a hardcoded URL or proposed a pattern your team has banned:
194
459
 
195
460
  ```
196
- Never use hardcoded staging URLs like https://staging.secufusion.io.
197
- All env URLs must come from application.properties.
461
+ Stop using hardcoded staging URLs like https://staging.secufusion.io.
462
+ All env URLs must come from application.properties. Never hardcode them.
198
463
  ```
199
464
 
200
- The AI logs it to `.rejected-patterns.json` and checks it before every future suggestion.
465
+ The AI **immediately** calls `log_rejected_pattern`:
466
+
467
+ ```json
468
+ {
469
+ "pattern": "Hardcoded staging URL https://staging.secufusion.io in source files",
470
+ "reason": "Must use @Value('${app.base-url}') from application.properties. Hardcoded URLs break environment parity and expose internal topology.",
471
+ "category": "security",
472
+ "file_context": "src/services/NotificationService.java"
473
+ }
474
+ ```
475
+
476
+ This gets appended to `.rejected-patterns.json`:
477
+
478
+ ```json
479
+ [
480
+ {
481
+ "id": 1,
482
+ "timestamp": "2026-08-26T15:10:00.000Z",
483
+ "category": "security",
484
+ "pattern": "Hardcoded staging URL https://staging.secufusion.io in source files",
485
+ "reason": "Must use @Value from application.properties...",
486
+ "file_context": "src/services/NotificationService.java"
487
+ }
488
+ ]
489
+ ```
490
+
491
+ From this point on, the AI checks this file before every suggestion — the mistake will never be repeated, even in future sessions.
201
492
 
202
493
  ---
203
494
 
204
- ### Run pre-PR checks
495
+ ### Step 6 — Pre-PR checks (PR Handoff phase)
496
+
497
+ When you're done, say:
205
498
 
206
499
  ```
207
500
  Run pre-PR checks for work item 2847.
208
501
  ```
209
502
 
210
- **Pass:**
503
+ The AI scans your entire repo and produces a report.
504
+
505
+ **✅ Everything passes — ready to ship:**
211
506
  ```
507
+ # ✅ Pre-PR Checks PASSED — Work Item #2847
508
+
509
+ Scanned directory: C:\projects\secufusion-backend
510
+ Timestamp: 2026-08-26T16:00:00.000Z
511
+
212
512
  ✅ [SPEC] All spec checkboxes are checked.
213
513
  ✅ [LOGGING] No console.log / System.out.println found.
214
- ✅ [SECURITY] No hardcoded URLs found.
215
- ✅ [FLYWAY] Migration coverage looks good.
216
- Ready to raise PR 🚀
514
+ ✅ [SECURITY] No hardcoded UAT/Prod IPs or environment URLs found.
515
+ ✅ [FLYWAY] Flyway migration coverage looks good.
516
+
517
+ ## PR Summary
518
+ - Work Item: #2847
519
+ - Spec: All acceptance criteria verified ✅
520
+ - Guardrails: tenantId scoping, no debug logs, no hardcoded URLs, Flyway covered ✅
521
+ - Ready to raise PR 🚀
522
+
523
+ 🚫 Rejected Patterns Reminder (1 on record)
524
+ - [security] Hardcoded staging URL https://staging.secufusion.io in source files
217
525
  ```
218
526
 
219
- **Fail (fix and re-run):**
527
+ **❌ Checks fail — you must fix before PR:**
220
528
  ```
221
- [SPEC] 2 unchecked items:
529
+ # Pre-PR Checks FAILED — Work Item #2847
530
+
531
+ ## Errors (must fix before PR)
532
+
533
+ ❌ [SPEC] 2 unchecked item(s) in the spec:
222
534
  • Flyway SQL migration created for every modified JPA @Entity
223
- • API contract updated if endpoints changed
224
- ❌ [LOGGING] console.log() found at src/components/AuditExport.tsx:84
535
+ • API contract (OpenAPI / TS types) updated if endpoints changed
536
+
537
+ ❌ [LINTING] 2 linter error(s) across workspace — fix natively in their respective microservices:
538
+ • [ESLint] apps/admin-dashboard/src/components/MfaSetup.tsx:47 — Unexpected console statement (no-console)
539
+ • [Checkstyle/Maven] Build failed: [ERROR] AuditService.java:[112] Line contains System.out.println
540
+
541
+ ## Passed
542
+ ✅ [SECURITY] No hardcoded UAT/Prod IPs or environment URLs found.
543
+ ✅ [FLYWAY] Flyway migration coverage looks good.
225
544
  ```
226
545
 
546
+ Fix the issues, run checks again, and only raise the PR once it's fully green.
547
+
227
548
  ---
228
549
 
229
550
  ### Quick cheat sheet
230
551
 
231
- | What you want | What to say |
552
+ | What you want to do | What to say to the AI |
232
553
  |---|---|
233
- | Start a task | `WI-XXXX: [description]` |
554
+ | Start a new task | `WI-XXXX: [paste description from Azure]` |
234
555
  | Check where you left off | `Read the current spec` |
235
- | Mark work done | `Mark [X] as complete in the spec` |
556
+ | Mark work as done | `Mark the tenantId scoping as complete in the spec` |
236
557
  | Record a mistake | `Never do [X] again because [Y]` |
237
- | Pre-PR check | `Run pre-PR checks for WI-XXXX` |
238
- | Resume a session | `What's left on the current task?` |
558
+ | Gate the PR | `Run pre-PR checks for WI-XXXX` |
559
+ | Resume after a break | `What's left on the current task?` |
560
+ | Use a reference file | `WI-XXXX: [desc]. Reference: src/services/MyService.java` |
239
561
 
240
562
  ---
241
563
 
242
- ## Tools Reference
564
+ ## How It Actually Works — The Invoker
243
565
 
244
- ### 1. manage_feature_spec
566
+ There are two layers that need to be in place for the MCP server to work automatically.
245
567
 
246
- | Parameter | Type | Required | Description |
247
- |---|---|---|---|
248
- | `action` | `create` / `update` / `read` | Yes | Operation to perform |
249
- | `task_description` | string | When action=create | Full feature/task description |
250
- | `update_content` | string | When action=update | Markdown lines to merge (e.g. tick checkboxes) |
251
- | `work_item_id` | string | No | Azure DevOps work item ID |
252
- | `reference_file_path` | string | No | Existing source file to extract coding patterns from |
568
+ ### Layer 1 `mcp_config.json` (makes tools available)
253
569
 
254
- ---
570
+ This tells the IDE to start the MCP server process when it launches. The tools become registered and ready, but nothing calls them yet.
255
571
 
256
- ### 2. log_rejected_pattern
572
+ ```
573
+ IDE starts → reads mcp_config.json → spawns node index.js → tools registered
574
+ ```
257
575
 
258
- | Parameter | Type | Required | Description |
259
- |---|---|---|---|
260
- | `pattern` | string | Yes | The bad pattern or approach |
261
- | `reason` | string | Yes | Why rejected and what to do instead |
262
- | `category` | enum | No | `architecture`, `security`, `database`, `logging`, `api-design`, `testing`, `other` |
263
- | `file_context` | string | No | File where the pattern was observed |
576
+ ### Layer 2 `AGENTS.md` (the invoker tells AI when to call each tool)
264
577
 
265
- ---
578
+ Without this, the tools sit idle. The AI doesn't know when to invoke them.
579
+ Create `.agents/AGENTS.md` in your project root:
266
580
 
267
- ### 3. run_pre_pr_checks
581
+ ```markdown
582
+ # SecuFusion MCP Workflow Rules
268
583
 
269
- | Parameter | Type | Required | Description |
270
- |---|---|---|---|
271
- | `work_item_id` | string | Yes | Azure DevOps work item ID |
272
- | `root_dir` | string | No | Directory to scan (defaults to cwd) |
273
- | `skip_checks` | array | No | `spec_boxes`, `console_logs`, `hardcoded_urls`, `flyway_migrations` |
584
+ You are an elite Senior Developer and Architect working on the SecuFusion workspace (containing multiple microservice repositories). You prioritize robust cross-service architecture, zero-trust security (tenant isolation), and flawless state management. You rely on standard AST-aware build tools (ESLint/Checkstyle) for code hygiene. You strictly follow project standards and always use the custom MCP tools provided.
274
585
 
275
- **Guardrail checks:**
586
+ ## Phase 1 — Planning (TRIGGER: user assigns a task or work item)
587
+ - Do NOT write code immediately. First, call `manage_feature_spec`.
588
+ - Determine which microservices are likely affected. Pass a `reference_file_path` to observe exact coding patterns.
589
+ - Pass the user's requirements into `task_description` to generate the workspace-level `.current-task-spec.md` blueprint.
590
+ - Wait for the spec to be generated before writing any code.
276
591
 
277
- | Check | Fails when |
278
- |---|---|
279
- | **SPEC** | `.current-task-spec.md` is missing or has unchecked `- [ ]` boxes |
280
- | **LOGGING** | `console.log()` in `.ts/.tsx/.js/.jsx` or `System.out.println()` in `.java` files |
281
- | **SECURITY** | Hardcoded IPs or `uat.*` / `prod.*` / `staging.*` URLs in source or config files |
282
- | **FLYWAY** | `@Entity`-annotated Java files exist but no `V*__.sql` Flyway migrations found |
592
+ ## Phase 2 Execution (TRIGGER: as you complete work)
593
+ - Keep the `.current-task-spec.md` file updated as your source of truth.
594
+ - Whenever you finish a logical chunk, call `manage_feature_spec` with `update_content` to check off the `[ ]` boxes to `[x]`.
595
+ - If you are resuming a session, always call `manage_feature_spec` with `action=read` first to know exactly where you left off.
283
596
 
284
- ---
597
+ ## Phase 3 — Course Correction (TRIGGER: user corrects you or rejects an approach)
598
+ - Immediately call `log_rejected_pattern`.
599
+ - Pass the bad `pattern` you used and the `reason`/correction the user provided.
600
+ - Always check `.rejected-patterns.json` implicitly before suggesting architectural choices to ensure you never repeat past mistakes.
285
601
 
286
- ## Files Created in Your Repo
602
+ ## Phase 4 PR Handoff (TRIGGER: user says "prepare PR", "finish up", or "run checks")
603
+ - Call `run_pre_pr_checks` with the Azure DevOps `work_item_id`. The tool will automatically discover all modified microservices in the workspace and run their native linters.
604
+ - If the tool throws an error for a specific repository (e.g., missing Flyway SQL migration, or a linter failing due to console logs/bad formatting), YOU MUST navigate to that specific microservice, FIX THE ERROR in the codebase, and run the tool again until the entire workspace passes. Do not suppress linter warnings.
287
605
 
288
- | File | Purpose | Commit? |
289
- |---|---|---|
290
- | `.current-task-spec.md` | Living blueprint for the current task | Yes team visibility |
291
- | `.rejected-patterns.json` | Cumulative log of banned patterns across sessions | Yes shared team knowledge |
606
+ ## Guardrails (enforce always, no exceptions)
607
+ - All DB queries and event payloads MUST be scoped with `tenantId` unless the spec explicitly notes it as a global/system operation.
608
+ - Do not ignore linter errors. AST-level tools (ESLint, Checkstyle/Maven) are the source of truth for hygiene. Fix them natively.
609
+ - Never hardcode UAT/Prod IPs or URLs. Use environment variables or configuration properties.
610
+ - If you modify a JPA `@Entity` in any backend repo, you MUST create the corresponding Flyway `.sql` migration script before running PR checks.
611
+ ```
292
612
 
293
- ---
613
+ ### How it all wires together
614
+
615
+ ```
616
+ mcp_config.json → starts the server (tools available)
617
+ +
618
+ .agents/AGENTS.md → tells AI when to invoke each tool (the invoker)
619
+
620
+ You say: "WI-1042: Add audit log export"
621
+
622
+ AI reads AGENTS.md → Phase 1 triggered → calls manage_feature_spec
623
+
624
+ .current-task-spec.md created in your project root
625
+ ```
626
+
627
+ ### Reusing across projects
294
628
 
295
- ## Workflow
629
+ Copy `.agents/AGENTS.md` into any project's root — the invoker follows you everywhere.
296
630
 
297
631
  ```
298
- Phase 1 — Planning → manage_feature_spec (create) → .current-task-spec.md generated
299
- Phase 2 — Execution → manage_feature_spec (update) → tick off ACs as you complete them
300
- Phase 3 — Correction → log_rejected_pattern → .rejected-patterns.json updated
301
- Phase 4 — PR Handoff → run_pre_pr_checks → must pass green before PR is raised
632
+ ProjectA/
633
+ .agents/AGENTS.md same file, copy it here
634
+
635
+ ProjectB/
636
+ .agents/AGENTS.md ← and here
637
+
638
+ mcp_config.json ← global, never changes
302
639
  ```
303
640
 
304
641
  ---
305
642
 
643
+ ## Talking to the AI — 5 Things You'll Ever Say
644
+
645
+ Once both layers are in place, you interact completely naturally:
646
+
647
+ | Situation | What you say |
648
+ |---|---|
649
+ | 🆕 New task | `WI-XXXX: [paste description from Azure]` |
650
+ | ✅ Done a chunk | `Done with the tenantId scoping, update the spec` |
651
+ | ❌ AI did something wrong | `Don't do X, do Y instead` |
652
+ | 🚀 Ready for PR | `Run checks for WI-XXXX` or `Prepare PR` |
653
+ | 🔄 Resuming after a break | `What's left?` or `Resume the current task` |
654
+
655
+ **Before `AGENTS.md`:** You had to remember which tool to invoke and when.
656
+
657
+ **After `AGENTS.md`:** You just describe work. The AI follows the 4-phase workflow automatically — no commands, no syntax, no manual tool calls.
658
+
659
+ ---
660
+
306
661
  ## Requirements
307
662
 
308
- - Node.js >= 18.0.0
663
+ - **Node.js** >= 18.0.0
309
664
  - An MCP-compatible AI client (Antigravity, Claude Desktop, Cursor, Cline, etc.)
310
665
 
311
666
  ---
312
667
 
313
668
  ## License
314
669
 
315
- ISC
670
+ ISC © SecuFusion
package/index.js CHANGED
@@ -5,11 +5,11 @@
5
5
  * Provides developer-workflow tooling for the SecuFusion platform:
6
6
  * - manage_feature_spec : create / update task blueprints (.current-task-spec.md)
7
7
  * - log_rejected_pattern : record bad patterns so they are never repeated (.rejected-patterns.json)
8
- * - run_pre_pr_checks : gate PRs with automated guardrail validation
8
+ * - run_pre_pr_checks : gate PRs via AST-level linters (ESLint / Maven Checkstyle) + structural checks
9
9
  *
10
10
  * Guardrails enforced:
11
11
  * 1. All DB queries and event payloads must carry tenantId.
12
- * 2. No console.log (TS/JS) or System.out.println (Java) in source files.
12
+ * 2. Code hygiene (console.log, unused vars, formatting) enforced via ESLint / Checkstyle — not regex.
13
13
  * 3. No hardcoded UAT/Prod IPs or environment URLs.
14
14
  * 4. Every modified JPA @Entity must have a matching Flyway SQL migration.
15
15
  */
@@ -18,6 +18,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
18
18
  import { z } from "zod";
19
19
  import fs from "fs";
20
20
  import path from "path";
21
+ import { execSync } from "child_process";
21
22
  // ─────────────────────────────────────────────
22
23
  // Constants / helpers
23
24
  // ─────────────────────────────────────────────
@@ -93,7 +94,7 @@ function appendSessionLog(existing, update) {
93
94
  // ─────────────────────────────────────────────
94
95
  // run_pre_pr_checks helpers
95
96
  // ─────────────────────────────────────────────
96
- const CONSOLE_LOG_PATTERNS = [
97
+ const CONSOLE_LOG_REGEX = [
97
98
  { regex: /console\.log\s*\(/g, label: "console.log()", ext: [".ts", ".tsx", ".js", ".jsx"] },
98
99
  { regex: /System\.out\.println\s*\(/g, label: "System.out.println()", ext: [".java"] },
99
100
  ];
@@ -127,9 +128,71 @@ function checkSpecFile() {
127
128
  }
128
129
  return { unchecked, missing: false };
129
130
  }
130
- function checkConsoleLogs(rootDir) {
131
+ // ── AST-level linting via ESLint (preferred over regex for JS/TS) ─────────────
132
+ function runEslint(rootDir) {
133
+ // Check if ESLint is configured in the project
134
+ const eslintConfigs = [".eslintrc", ".eslintrc.js", ".eslintrc.json", ".eslintrc.yml",
135
+ ".eslintrc.yaml", "eslint.config.js", "eslint.config.mjs"];
136
+ const hasEslintConfig = eslintConfigs.some((f) => fs.existsSync(path.join(rootDir, f)));
137
+ const hasPkgEslint = (() => {
138
+ const pkg = readFileSafe(path.join(rootDir, "package.json"));
139
+ if (!pkg)
140
+ return false;
141
+ try {
142
+ return !!(JSON.parse(pkg).eslintConfig);
143
+ }
144
+ catch {
145
+ return false;
146
+ }
147
+ })();
148
+ if (!hasEslintConfig && !hasPkgEslint)
149
+ return { violations: [], available: false };
150
+ try {
151
+ execSync("npx eslint . --format json --max-warnings=0 --no-error-on-unmatched-pattern", { cwd: rootDir, stdio: "pipe" });
152
+ return { violations: [], available: true };
153
+ }
154
+ catch (e) {
155
+ const raw = e.stdout?.toString() ?? "";
156
+ try {
157
+ const results = JSON.parse(raw);
158
+ const violations = [];
159
+ for (const file of results) {
160
+ for (const msg of file.messages) {
161
+ if (msg.severity > 0) {
162
+ violations.push(`[ESLint] ${path.relative(rootDir, file.filePath)}:${msg.line} — ${msg.message}${msg.ruleId ? ` (${msg.ruleId})` : ""}`);
163
+ }
164
+ }
165
+ }
166
+ return { violations, available: true };
167
+ }
168
+ catch {
169
+ // ESLint output not JSON — return raw stderr summary
170
+ const stderr = e.stderr?.toString() ?? "";
171
+ return { violations: stderr ? [`[ESLint] ${stderr.slice(0, 400)}`] : [], available: true };
172
+ }
173
+ }
174
+ }
175
+ // ── Maven + Checkstyle for Java/Spring projects ───────────────────────────────
176
+ function runCheckstyle(rootDir) {
177
+ const hasPom = fs.existsSync(path.join(rootDir, "pom.xml"));
178
+ if (!hasPom)
179
+ return { violations: [], available: false };
180
+ try {
181
+ execSync("mvn checkstyle:check -q --no-transfer-progress", { cwd: rootDir, stdio: "pipe" });
182
+ return { violations: [], available: true };
183
+ }
184
+ catch (e) {
185
+ const output = ((e.stdout?.toString() ?? "") + (e.stderr?.toString() ?? "")).slice(0, 1200);
186
+ return {
187
+ violations: [`[Checkstyle/Maven] Build failed:\n${output}`],
188
+ available: true,
189
+ };
190
+ }
191
+ }
192
+ // ── Regex fallback — used only when no linter is configured ──────────────────
193
+ function checkConsoleLogsRegex(rootDir) {
131
194
  const violations = [];
132
- for (const { regex, label, ext } of CONSOLE_LOG_PATTERNS) {
195
+ for (const { regex, label, ext } of CONSOLE_LOG_REGEX) {
133
196
  const files = walkDir(rootDir, ext);
134
197
  for (const file of files) {
135
198
  const content = readFileSafe(file);
@@ -161,6 +224,28 @@ function checkHardcodedUrls(rootDir) {
161
224
  }
162
225
  return violations;
163
226
  }
227
+ // ── Workspace / Microservice Discovery ───────────────────────────────────────
228
+ function findProjectRoots(dir, depth = 0) {
229
+ if (depth > 3)
230
+ return []; // Limit depth to avoid scanning massive trees
231
+ if (!fs.existsSync(dir))
232
+ return [];
233
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
234
+ const hasPackageJson = entries.some(e => e.name === "package.json");
235
+ const hasPomXml = entries.some(e => e.name === "pom.xml");
236
+ const roots = [];
237
+ if (hasPackageJson || hasPomXml) {
238
+ roots.push(dir);
239
+ }
240
+ for (const entry of entries) {
241
+ if (entry.isDirectory()) {
242
+ if (["node_modules", ".git", "dist", "build", "target", ".idea"].includes(entry.name))
243
+ continue;
244
+ roots.push(...findProjectRoots(path.join(dir, entry.name), depth + 1));
245
+ }
246
+ }
247
+ return [...new Set(roots)];
248
+ }
164
249
  function checkFlywayMigrations(rootDir) {
165
250
  const warnings = [];
166
251
  const javaFiles = walkDir(rootDir, [".java"]);
@@ -195,10 +280,9 @@ const server = new McpServer({
195
280
  version: "1.0.0",
196
281
  });
197
282
  // ─── Tool 1: manage_feature_spec ─────────────────────────────────────────────
198
- server.tool("manage_feature_spec", "Create or update the .current-task-spec.md task blueprint. " +
199
- "Pass `task_description` to create a new spec, or `update_content` to patch the existing one " +
200
- "(e.g., checking off completed acceptance criteria). Optionally provide `reference_file_path` " +
201
- "so the spec generator can observe existing coding patterns.", {
283
+ server.tool("manage_feature_spec", "Create or update the .current-task-spec.md blueprint for the current feature. " +
284
+ "Use this during the Planning and Execution phases. " +
285
+ "Works for both single-repo and cross-repo workspace tasks.", {
202
286
  task_description: z
203
287
  .string()
204
288
  .optional()
@@ -379,10 +463,11 @@ server.tool("log_rejected_pattern", "Record a coding pattern that was rejected b
379
463
  };
380
464
  });
381
465
  // ─── Tool 3: run_pre_pr_checks ───────────────────────────────────────────────
382
- server.tool("run_pre_pr_checks", "Run all SecuFusion pre-PR guardrail checks against the current working directory. " +
383
- "Validates: spec checkboxes, console.log/System.out.println usage, hardcoded IPs/URLs, " +
384
- "and Flyway migration coverage for JPA entities. " +
385
- "MUST pass (exit with no errors) before a PR is raised.", {
466
+ server.tool("run_pre_pr_checks", "Run all SecuFusion pre-PR guardrail checks across the workspace. " +
467
+ "Automatically discovers modified microservices and runs their native linters (ESLint, Maven Checkstyle). " +
468
+ "Also validates: spec checkboxes, hardcoded IPs/URLs, and Flyway migration coverage for JPA entities. " +
469
+ "Linter errors must be fixed natively do not suppress warnings to pass the gate. " +
470
+ "MUST pass with zero errors before a PR is raised.", {
386
471
  work_item_id: z
387
472
  .string()
388
473
  .describe("Azure DevOps work item ID to include in the PR summary."),
@@ -422,21 +507,56 @@ server.tool("run_pre_pr_checks", "Run all SecuFusion pre-PR guardrail checks aga
422
507
  else {
423
508
  warnings.push("⚠️ [SPEC] Spec checkbox check SKIPPED (manually bypassed).");
424
509
  }
425
- // ── 2. Console log check ───────────────────────────────────────────────
510
+ // ── 2. AST-level linting (Workspace Discovery → ESLint/Checkstyle → regex fallback)
426
511
  if (!skip_checks.includes("console_logs")) {
427
- const logViolations = checkConsoleLogs(scanRoot);
428
- if (logViolations.length > 0) {
429
- errors.push(`❌ [LOGGING] Found ${logViolations.length} prohibited log statement(s):\n` +
430
- logViolations.map((v) => ` • ${v}`).join("\n"));
512
+ let projectRoots = findProjectRoots(scanRoot);
513
+ if (projectRoots.length === 0)
514
+ projectRoots.push(scanRoot);
515
+ let anyLinterAvailable = false;
516
+ const allLintViolations = [];
517
+ const usedLinters = new Set();
518
+ for (const pRoot of projectRoots) {
519
+ const eslint = runEslint(pRoot);
520
+ const checkstyle = runCheckstyle(pRoot);
521
+ if (eslint.available) {
522
+ anyLinterAvailable = true;
523
+ usedLinters.add("ESLint");
524
+ allLintViolations.push(...eslint.violations);
525
+ }
526
+ if (checkstyle.available) {
527
+ anyLinterAvailable = true;
528
+ usedLinters.add("Checkstyle");
529
+ allLintViolations.push(...checkstyle.violations);
530
+ }
531
+ }
532
+ if (anyLinterAvailable) {
533
+ // AST linters found and ran — they are the source of truth
534
+ if (allLintViolations.length > 0) {
535
+ errors.push(`❌ [LINTING] ${allLintViolations.length} linter error(s) across workspace — fix natively in their respective microservices:\n` +
536
+ allLintViolations.map((v) => ` • ${v}`).join("\n"));
537
+ }
538
+ else {
539
+ passed.push(`✅ [LINTING] AST-level linting passed across workspace (${Array.from(usedLinters).join(" + ")}).`);
540
+ }
431
541
  }
432
542
  else {
433
- passed.push("✅ [LOGGING] No console.log / System.out.println found.");
543
+ // No linters configured fall back to regex scan with a warning
544
+ const regexViolations = checkConsoleLogsRegex(scanRoot);
545
+ if (regexViolations.length > 0) {
546
+ errors.push(`❌ [LOGGING] ${regexViolations.length} prohibited log statement(s) found via regex fallback\n` +
547
+ ` (No ESLint/Checkstyle config detected in any workspace project — configure a linter for AST-level accuracy):\n` +
548
+ regexViolations.map((v) => ` • ${v}`).join("\n"));
549
+ }
550
+ else {
551
+ warnings.push("⚠️ [LOGGING] No ESLint/Checkstyle config found in workspace — used regex fallback. " +
552
+ "Consider adding a linter for AST-level hygiene.");
553
+ }
434
554
  }
435
555
  }
436
556
  else {
437
- warnings.push("⚠️ [LOGGING] Console log check SKIPPED (manually bypassed).");
557
+ warnings.push("⚠️ [LINTING] Linter check SKIPPED (manually bypassed).");
438
558
  }
439
- // ── 3. Hardcoded URL check ─────────────────────────────────────────────
559
+ // ── 3. Hardcoded URL check (regex — no AST equivalent needed here) ───────
440
560
  if (!skip_checks.includes("hardcoded_urls")) {
441
561
  const urlViolations = checkHardcodedUrls(scanRoot);
442
562
  if (urlViolations.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "secufusion-mcp",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "type": "module",
5
5
  "description": "SecuFusion MCP server - developer workflow tooling with guardrails",
6
6
  "main": "index.js",
@@ -17,7 +17,8 @@
17
17
  },
18
18
  "scripts": {
19
19
  "build": "tsc",
20
- "prepublishOnly": "npm run build",
20
+ "prepublishOnly": "copy ..\\README.md README.md && npm run build",
21
+ "postpublish": "del README.md",
21
22
  "start": "node index.js",
22
23
  "dev": "tsc && node index.js"
23
24
  },