secufusion-mcp 1.0.13 → 1.0.15
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 +25 -11
- package/index.js +35 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
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, etc.) and gives them **
|
|
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 **nine powerful tools** to enforce SecuFusion's engineering standards throughout the development lifecycle:
|
|
14
14
|
|
|
15
15
|
| Tool | Phase | What it does |
|
|
16
16
|
|---|---|---|
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
| `manage_branch_state` | Legacy — Branch State | Backward-compatible branch-scoped JSON state tracker (for tasks before `manage_task`) |
|
|
23
23
|
| `log_rejected_pattern` | **Phase 3** — Course Correction | Records bad patterns to `.rejected-patterns.json` so they are never repeated |
|
|
24
24
|
| `run_pre_pr_checks` | **Phase 4** — PR Handoff | Discovers modified microservices and gates PRs via AST-level linters + structural checks |
|
|
25
|
+
| `get_secufusion_rules` | **Setup** | Returns the `AGENTS.md` rules for AI clients that don't natively support MCP Resources |
|
|
25
26
|
|
|
26
27
|
---
|
|
27
28
|
|
|
@@ -342,6 +343,19 @@ Loads and manages `.secufusion-project-spec.json` — the permanent project memo
|
|
|
342
343
|
1. Same directory as `index.js`
|
|
343
344
|
2. `process.cwd()`
|
|
344
345
|
3. Walk up from `cwd` (up to 5 levels)
|
|
346
|
+
4. The global MCP package installation directory (bundled spec fallback)
|
|
347
|
+
|
|
348
|
+
---
|
|
349
|
+
|
|
350
|
+
### 5. `get_secufusion_rules`
|
|
351
|
+
|
|
352
|
+
A simple utility tool that returns the raw text of the `AGENTS.md` workflow rules. This is designed as a workaround for AI clients (like older versions of Cline or Claude Code) that do not support the MCP **Resources** capability.
|
|
353
|
+
|
|
354
|
+
By calling this tool, the AI can read the globally bundled rules without you needing to copy the `.agents` folder into your local repository.
|
|
355
|
+
|
|
356
|
+
**Example:**
|
|
357
|
+
> "Call the get_secufusion_rules tool and read the rules before we begin."
|
|
358
|
+
|
|
345
359
|
|
|
346
360
|
---
|
|
347
361
|
|
|
@@ -623,7 +637,7 @@ The SecuFusion MCP operates across three complementary layers to prevent AI amne
|
|
|
623
637
|
### How it all wires together
|
|
624
638
|
|
|
625
639
|
```
|
|
626
|
-
mcp_config.json → starts the server (
|
|
640
|
+
mcp_config.json → starts the server (9 tools available)
|
|
627
641
|
+
|
|
628
642
|
.agents/AGENTS.md → tells AI when to invoke each tool
|
|
629
643
|
↓
|
|
@@ -648,19 +662,19 @@ Phase 4: manage_task complete → pr-summary.md generated
|
|
|
648
662
|
+ run_pre_pr_checks → must pass before raising PR
|
|
649
663
|
```
|
|
650
664
|
|
|
651
|
-
### Reusing across projects
|
|
665
|
+
### Reusing across projects (Global Bundling)
|
|
652
666
|
|
|
653
|
-
|
|
667
|
+
As of version **1.0.13+**, `secufusion-mcp` globally bundles both `.secufusion-project-spec.json` and `AGENTS.md`. You **no longer need to copy these files** into every single repository!
|
|
654
668
|
|
|
655
|
-
|
|
656
|
-
ProjectA/
|
|
657
|
-
.agents/AGENTS.md ← same file, copy it here
|
|
669
|
+
When you install globally (`npm install -g secufusion-mcp@latest`), the AI can automatically read your rules and project spec on the fly from the global installation.
|
|
658
670
|
|
|
659
|
-
|
|
660
|
-
|
|
671
|
+
**How to load the Rules in a new project:**
|
|
672
|
+
Depending on your AI client's capabilities, you can load the rules instantly by telling the AI:
|
|
673
|
+
- **"Use the `secufusion_developer` prompt"** (if Prompts are supported)
|
|
674
|
+
- **"Read the `secufusion://rules` resource"** (if Resources are supported)
|
|
675
|
+
- **"Call the `get_secufusion_rules` tool"** (if only Tools are supported)
|
|
661
676
|
|
|
662
|
-
|
|
663
|
-
```
|
|
677
|
+
*(If you prefer the legacy method, you can still copy `.agents/AGENTS.md` and `.secufusion-project-spec.json` into your project root).*
|
|
664
678
|
|
|
665
679
|
---
|
|
666
680
|
|
package/index.js
CHANGED
|
@@ -25,9 +25,26 @@ import { execSync } from "child_process";
|
|
|
25
25
|
const STATE_FILE = ".secufusion-state.json";
|
|
26
26
|
const REJECTED_FILE = ".rejected-patterns.json";
|
|
27
27
|
const TOKEN_FILE = ".secufusion-tokens.json";
|
|
28
|
-
/**
|
|
28
|
+
/** Find the workspace root by walking up from cwd to find a project marker. */
|
|
29
|
+
function getWorkspaceRoot() {
|
|
30
|
+
let currentDir = process.cwd();
|
|
31
|
+
const rootMarkers = [".git", "package.json", "pom.xml", ".secufusion-project-spec.json", ".agents"];
|
|
32
|
+
for (let i = 0; i < 10; i++) {
|
|
33
|
+
for (const marker of rootMarkers) {
|
|
34
|
+
if (fs.existsSync(path.join(currentDir, marker))) {
|
|
35
|
+
return currentDir;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const parent = path.dirname(currentDir);
|
|
39
|
+
if (parent === currentDir)
|
|
40
|
+
break; // Reached filesystem root
|
|
41
|
+
currentDir = parent;
|
|
42
|
+
}
|
|
43
|
+
return process.cwd(); // Fallback to current directory
|
|
44
|
+
}
|
|
45
|
+
/** Resolve a path relative to workspace root (where the MCP server is invoked). */
|
|
29
46
|
function resolve(file) {
|
|
30
|
-
return path.resolve(
|
|
47
|
+
return path.resolve(getWorkspaceRoot(), file);
|
|
31
48
|
}
|
|
32
49
|
function readFileSafe(filePath) {
|
|
33
50
|
try {
|
|
@@ -328,9 +345,9 @@ server.tool("manage_branch_state", "Manage the structured JSON state for the cur
|
|
|
328
345
|
.describe("Explicit actionable instruction for resuming. Required for 'update'."),
|
|
329
346
|
}, async ({ action, task_description, reference_file_path, pending_acs, completed_acs, next_step }) => {
|
|
330
347
|
const inputChars = JSON.stringify({ action, task_description, reference_file_path, pending_acs, completed_acs, next_step }).length;
|
|
331
|
-
const cwd =
|
|
348
|
+
const cwd = getWorkspaceRoot();
|
|
332
349
|
const branch = getCurrentBranch(cwd);
|
|
333
|
-
const statePath =
|
|
350
|
+
const statePath = resolve(STATE_FILE);
|
|
334
351
|
let state = {};
|
|
335
352
|
if (fs.existsSync(statePath)) {
|
|
336
353
|
try {
|
|
@@ -507,7 +524,7 @@ server.tool("run_pre_pr_checks", "Run all SecuFusion pre-PR guardrail checks acr
|
|
|
507
524
|
.describe("Explicitly skip specific checks. Use sparingly — document the reason in your PR description."),
|
|
508
525
|
}, async ({ work_item_id, root_dir, skip_checks = [] }) => {
|
|
509
526
|
const inputChars = JSON.stringify({ work_item_id, root_dir, skip_checks }).length;
|
|
510
|
-
const scanRoot = root_dir ? path.resolve(root_dir) :
|
|
527
|
+
const scanRoot = root_dir ? path.resolve(root_dir) : getWorkspaceRoot();
|
|
511
528
|
const errors = [];
|
|
512
529
|
const warnings = [];
|
|
513
530
|
const passed = [];
|
|
@@ -701,10 +718,10 @@ server.tool("manage_project_spec", "Manages the .secufusion-project-spec.json fi
|
|
|
701
718
|
const candidates = [];
|
|
702
719
|
// 1. Same directory as index.ts/index.js
|
|
703
720
|
candidates.push(path.resolve(path.dirname(new URL(import.meta.url).pathname.replace(/^\/([A-Z]:)/, "$1")), SPEC_FILE));
|
|
704
|
-
// 2.
|
|
705
|
-
candidates.push(path.resolve(
|
|
706
|
-
// 3. Walk up from
|
|
707
|
-
let walkDir =
|
|
721
|
+
// 2. getWorkspaceRoot()
|
|
722
|
+
candidates.push(path.resolve(getWorkspaceRoot(), SPEC_FILE));
|
|
723
|
+
// 3. Walk up from getWorkspaceRoot() until found (up to 5 levels)
|
|
724
|
+
let walkDir = getWorkspaceRoot();
|
|
708
725
|
for (let i = 0; i < 5; i++) {
|
|
709
726
|
const parent = path.dirname(walkDir);
|
|
710
727
|
if (parent === walkDir)
|
|
@@ -1097,5 +1114,14 @@ server.prompt("secufusion_developer", "Starts a conversation with the SecuFusion
|
|
|
1097
1114
|
// ─────────────────────────────────────────────
|
|
1098
1115
|
// Start transport
|
|
1099
1116
|
// ─────────────────────────────────────────────
|
|
1117
|
+
server.tool("get_secufusion_rules", "Fetches the mandatory AGENTS.md workflow rules for the SecuFusion project. Call this before starting any work.", {}, async () => {
|
|
1118
|
+
const content = readFileSafe(AGENTS_MD_PATH);
|
|
1119
|
+
if (!content) {
|
|
1120
|
+
throw new Error(`Rules file not found at ${AGENTS_MD_PATH}`);
|
|
1121
|
+
}
|
|
1122
|
+
return appendTelemetry({
|
|
1123
|
+
content: [{ type: "text", text: content }]
|
|
1124
|
+
}, 0);
|
|
1125
|
+
});
|
|
1100
1126
|
const transport = new StdioServerTransport();
|
|
1101
1127
|
await server.connect(transport);
|