sentinel-verify 1.0.0 → 1.1.0
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/CHANGELOG.md +11 -0
- package/README.md +37 -2
- package/dist/cli/commands/connect.js +98 -0
- package/dist/cli/commands/connect.js.map +1 -0
- package/dist/cli/index.js +13 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/mcp/projectRoot.js +68 -0
- package/dist/mcp/projectRoot.js.map +1 -0
- package/dist/mcp/server.js +53 -12
- package/dist/mcp/server.js.map +1 -1
- package/dist/storage/db.js +9 -1
- package/dist/storage/db.js.map +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Sentinel are documented here.
|
|
4
4
|
|
|
5
|
+
## 1.1.0 — 2026-07-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- `sentinel connect <agent>`: one-command MCP setup — writes the sentinel entry (absolute paths + `SENTINEL_PROJECT_ROOT` pinned to the current project) into the agent's MCP config, merging safely with existing servers. Supported: `claude-code` (`<project>/.mcp.json`), `cursor` (`<project>/.cursor/mcp.json`), `antigravity` (`~/.gemini/antigravity/mcp_config.json`). `sentinel connect --list` shows the table; unknown agent names print it too. Malformed config files fail with a clear error and are never modified. Adding an agent is one entry in the `AGENTS` table in `src/cli/commands/connect.ts`.
|
|
9
|
+
|
|
10
|
+
## 1.0.1 — 2026-07-12
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- **MCP server crashed with `ENOENT: mkdir '/.sentinel'` when the client launched it from an unexpected working directory** (e.g. `/`). The project root is now resolved defensively: `SENTINEL_PROJECT_ROOT` env var → plausible launch directory → the MCP client's declared workspace roots (`roots` capability) → a clear, actionable tool error. As a last line of defense, Sentinel now refuses to create `.sentinel/` at a filesystem root no matter how it is invoked.
|
|
14
|
+
- Tool enable/disable from `.sentinelrc` is now also enforced per call (previously only at server startup), so it holds even when the config couldn't be read until the root was resolved.
|
|
15
|
+
|
|
5
16
|
## 1.0.0 — 2026-07-10 (Phase 9 — first public release)
|
|
6
17
|
|
|
7
18
|
### Added
|
package/README.md
CHANGED
|
@@ -13,12 +13,47 @@ npm install -g sentinel-verify
|
|
|
13
13
|
cd your-project
|
|
14
14
|
sentinel init # creates the local .sentinel/ data folder
|
|
15
15
|
|
|
16
|
-
# Connect your agent
|
|
17
|
-
|
|
16
|
+
# Connect your agent — one command, no config editing:
|
|
17
|
+
sentinel connect claude-code # or: cursor, antigravity
|
|
18
18
|
```
|
|
19
19
|
|
|
20
20
|
That's it. Your agent now has four verification tools it can call after making changes. In agent mode Sentinel needs **no API key and no local model** — see the two modes below.
|
|
21
21
|
|
|
22
|
+
## Connecting an agent
|
|
23
|
+
|
|
24
|
+
**Recommended: `sentinel connect <agent>`** — run it from your project's root directory and it writes the correct MCP entry (absolute paths, project root pinned via `SENTINEL_PROJECT_ROOT`) into that agent's config, merging safely with any MCP servers already configured there. Malformed config files are never touched — you get an error instead.
|
|
25
|
+
|
|
26
|
+
| Agent | Command | Config it writes |
|
|
27
|
+
|---|---|---|
|
|
28
|
+
| Claude Code | `sentinel connect claude-code` | `<project>/.mcp.json` |
|
|
29
|
+
| Cursor | `sentinel connect cursor` | `<project>/.cursor/mcp.json` |
|
|
30
|
+
| Antigravity | `sentinel connect antigravity` | `~/.gemini/antigravity/mcp_config.json` (global — pinned to the project you ran it from) |
|
|
31
|
+
|
|
32
|
+
`sentinel connect --list` shows this table in the terminal. After connecting, restart/reload the agent so it picks up the new server. Re-run `connect` any time (e.g. after updating Node or Sentinel) — it refreshes the entry in place. Supporting a new agent is one entry in the `AGENTS` table in `src/cli/commands/connect.ts` — PRs welcome.
|
|
33
|
+
|
|
34
|
+
<details>
|
|
35
|
+
<summary><strong>Manual setup (fallback for agents not listed above)</strong></summary>
|
|
36
|
+
|
|
37
|
+
Any MCP client works — configure it to launch `sentinel mcp` as a stdio server. For clients configured via JSON:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{
|
|
41
|
+
"mcpServers": {
|
|
42
|
+
"sentinel": {
|
|
43
|
+
"command": "sentinel",
|
|
44
|
+
"args": ["mcp"],
|
|
45
|
+
"env": { "SENTINEL_PROJECT_ROOT": "/absolute/path/to/your-project" }
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
If the agent launches servers without your shell's PATH, use the absolute path to the `sentinel` binary (find it with `which sentinel`) or `node /path/to/dist/cli/index.js` as the command. Claude Code users can equivalently run `claude mcp add sentinel -e SENTINEL_PROJECT_ROOT="$(pwd)" -- sentinel mcp`.
|
|
52
|
+
|
|
53
|
+
</details>
|
|
54
|
+
|
|
55
|
+
**How Sentinel finds your project:** some MCP clients launch servers from an unexpected working directory (even `/`), so Sentinel resolves the project root defensively, in this order: the `SENTINEL_PROJECT_ROOT` environment variable → a plausible launch directory → the workspace roots your MCP client declares (the protocol's `roots` capability). If none of those work, tool calls fail with a clear message instead of writing anywhere wrong. `sentinel connect` sets the env var for you, which is why it's the recommended path.
|
|
56
|
+
|
|
22
57
|
Optional extras:
|
|
23
58
|
|
|
24
59
|
```bash
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// Purpose: implements `sentinel connect <agent>` — writes the sentinel MCP server entry into a coding agent's config file, merging safely with whatever is already there.
|
|
2
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
import { dirname, join, resolve } from "node:path";
|
|
5
|
+
import { fileURLToPath } from "node:url";
|
|
6
|
+
const AGENTS = [
|
|
7
|
+
{
|
|
8
|
+
key: "claude-code",
|
|
9
|
+
displayName: "Claude Code",
|
|
10
|
+
configPath: (projectRoot) => join(projectRoot, ".mcp.json"),
|
|
11
|
+
scope: "project",
|
|
12
|
+
restartHint: "Restart your Claude Code session (or run /mcp) to pick it up.",
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
key: "cursor",
|
|
16
|
+
displayName: "Cursor",
|
|
17
|
+
configPath: (projectRoot) => join(projectRoot, ".cursor", "mcp.json"),
|
|
18
|
+
scope: "project",
|
|
19
|
+
restartHint: "Reload the Cursor window (or toggle the server in Cursor Settings → MCP).",
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
key: "antigravity",
|
|
23
|
+
displayName: "Antigravity",
|
|
24
|
+
configPath: () => join(homedir(), ".gemini", "antigravity", "mcp_config.json"),
|
|
25
|
+
scope: "user",
|
|
26
|
+
restartHint: "Restart Antigravity (its MCP config is global — it needs absolute paths, which is what was written).",
|
|
27
|
+
},
|
|
28
|
+
];
|
|
29
|
+
function supportedList() {
|
|
30
|
+
return AGENTS.map((agent) => ` ${agent.key.padEnd(12)} ${agent.displayName} — ${agent.scope === "project" ? "<project>/" : ""}${agent.configPath("<project>").replace("<project>/", "")}`).join("\n");
|
|
31
|
+
}
|
|
32
|
+
/** The MCP server entry to write: absolute paths only, so GUI-launched agents work without shell PATH. */
|
|
33
|
+
function sentinelEntry(projectRoot) {
|
|
34
|
+
const cliEntry = resolve(dirname(fileURLToPath(import.meta.url)), "..", "index.js");
|
|
35
|
+
return {
|
|
36
|
+
command: process.execPath,
|
|
37
|
+
args: [cliEntry, "mcp"],
|
|
38
|
+
env: { SENTINEL_PROJECT_ROOT: projectRoot },
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/** `sentinel connect --list` — show supported agents and their config locations. */
|
|
42
|
+
export function runConnectList() {
|
|
43
|
+
console.log("Supported agents:\n" + supportedList());
|
|
44
|
+
console.log('\nUsage: sentinel connect <agent> (run it from your project\'s root directory)');
|
|
45
|
+
}
|
|
46
|
+
/** `sentinel connect <agent>` — add or update the sentinel entry in that agent's MCP config. */
|
|
47
|
+
export function runConnect(agentKey) {
|
|
48
|
+
const agent = AGENTS.find((candidate) => candidate.key === agentKey.toLowerCase());
|
|
49
|
+
if (!agent) {
|
|
50
|
+
throw new Error(`Unknown agent "${agentKey}". Supported agents:\n${supportedList()}`);
|
|
51
|
+
}
|
|
52
|
+
const projectRoot = process.cwd();
|
|
53
|
+
const configPath = agent.configPath(projectRoot);
|
|
54
|
+
// Read the existing config, if any — other MCP servers in it must survive.
|
|
55
|
+
let config = {};
|
|
56
|
+
if (existsSync(configPath)) {
|
|
57
|
+
const raw = readFileSync(configPath, "utf8");
|
|
58
|
+
try {
|
|
59
|
+
config = JSON.parse(raw);
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
throw new Error(`${configPath} exists but is not valid JSON ` +
|
|
63
|
+
`(${error instanceof Error ? error.message : String(error)}). ` +
|
|
64
|
+
`Not touching it — fix the file first, then re-run sentinel connect ${agent.key}.`);
|
|
65
|
+
}
|
|
66
|
+
if (config === null || typeof config !== "object" || Array.isArray(config)) {
|
|
67
|
+
throw new Error(`${configPath} does not contain a JSON object — not touching it. ` +
|
|
68
|
+
`Fix the file first, then re-run sentinel connect ${agent.key}.`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
const servers = (config.mcpServers ??= {});
|
|
72
|
+
if (typeof servers !== "object" || Array.isArray(servers)) {
|
|
73
|
+
throw new Error(`${configPath} has a non-object "mcpServers" field — not touching it.`);
|
|
74
|
+
}
|
|
75
|
+
const existing = "sentinel" in servers;
|
|
76
|
+
const otherServers = Object.keys(servers).filter((name) => name !== "sentinel");
|
|
77
|
+
const entry = sentinelEntry(projectRoot);
|
|
78
|
+
servers.sentinel = entry;
|
|
79
|
+
mkdirSync(dirname(configPath), { recursive: true });
|
|
80
|
+
writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
81
|
+
console.log(`${existing ? "Updated" : "Added"} the sentinel entry in ${agent.displayName}'s MCP config:`);
|
|
82
|
+
console.log(` ${configPath}`);
|
|
83
|
+
if (otherServers.length > 0) {
|
|
84
|
+
console.log(` (${otherServers.length} other MCP server(s) in that file were left untouched: ${otherServers.join(", ")})`);
|
|
85
|
+
}
|
|
86
|
+
console.log("\nEntry written:");
|
|
87
|
+
console.log(JSON.stringify({ sentinel: entry }, null, 2)
|
|
88
|
+
.split("\n")
|
|
89
|
+
.map((line) => " " + line)
|
|
90
|
+
.join("\n"));
|
|
91
|
+
console.log(`\nProject root: ${projectRoot}`);
|
|
92
|
+
console.log(agent.restartHint);
|
|
93
|
+
if (agent.scope === "user") {
|
|
94
|
+
console.log(`Note: ${agent.displayName}'s config is global, so sentinel is pinned to this project. ` +
|
|
95
|
+
`Run sentinel connect ${agent.key} from a different project to repoint it.`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=connect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connect.js","sourceRoot":"","sources":["../../../src/cli/commands/connect.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/index.js
CHANGED
|
@@ -9,6 +9,7 @@ import { runTestStyle } from "./commands/testStyle.js";
|
|
|
9
9
|
import { startMcpServer } from "../mcp/server.js";
|
|
10
10
|
import { startDashboard, DEFAULT_DASHBOARD_PORT } from "../dashboard/server.js";
|
|
11
11
|
import { runInstallHook, runUninstallHook, runHook } from "./commands/hook.js";
|
|
12
|
+
import { runConnect, runConnectList } from "./commands/connect.js";
|
|
12
13
|
import { SENTINEL_VERSION } from "../version.js";
|
|
13
14
|
const program = new Command();
|
|
14
15
|
program
|
|
@@ -67,6 +68,18 @@ program
|
|
|
67
68
|
}
|
|
68
69
|
startDashboard(process.cwd(), port);
|
|
69
70
|
});
|
|
71
|
+
program
|
|
72
|
+
.command("connect")
|
|
73
|
+
.description("Register Sentinel in a coding agent's MCP config (run from your project root).")
|
|
74
|
+
.argument("[agent]", "Which agent to connect: claude-code, cursor, antigravity.")
|
|
75
|
+
.option("--list", "Show all supported agents and their config file locations.")
|
|
76
|
+
.action((agent, options) => {
|
|
77
|
+
if (options.list || !agent) {
|
|
78
|
+
runConnectList();
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
runConnect(agent);
|
|
82
|
+
});
|
|
70
83
|
program
|
|
71
84
|
.command("install-hook")
|
|
72
85
|
.description("Install a git pre-commit hook that checks staged changes before every commit.")
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Purpose: resolves the project root for the MCP server — never trusts a bogus working directory (like "/"), supports SENTINEL_PROJECT_ROOT and the MCP roots capability.
|
|
2
|
+
import { statSync } from "node:fs";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { parse, resolve } from "node:path";
|
|
5
|
+
export const ROOT_HELP = 'Fix it one of two ways: (1) set SENTINEL_PROJECT_ROOT to your project\'s absolute path in the ' +
|
|
6
|
+
'MCP server config (the "env" field), or (2) configure your MCP client to launch "sentinel mcp" ' +
|
|
7
|
+
"with its working directory set to your project.";
|
|
8
|
+
function isUsableDirectory(path) {
|
|
9
|
+
try {
|
|
10
|
+
return statSync(path).isDirectory();
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/** "/" on POSIX, "C:\\" on Windows — never a legitimate project directory. */
|
|
17
|
+
export function isFilesystemRoot(path) {
|
|
18
|
+
const resolved = resolve(path);
|
|
19
|
+
return resolved === parse(resolved).root;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolution that needs no client connection: the SENTINEL_PROJECT_ROOT
|
|
23
|
+
* environment variable (explicit user intent — always wins), then the
|
|
24
|
+
* process working directory if it looks legitimate. Returns null when
|
|
25
|
+
* neither is usable; the caller can then ask the MCP client for its roots.
|
|
26
|
+
* Throws when SENTINEL_PROJECT_ROOT is set but wrong — explicit config that
|
|
27
|
+
* is broken must fail loudly, not fall through.
|
|
28
|
+
*/
|
|
29
|
+
export function resolveStartupRoot() {
|
|
30
|
+
const envRoot = process.env.SENTINEL_PROJECT_ROOT;
|
|
31
|
+
if (envRoot) {
|
|
32
|
+
const resolved = resolve(envRoot);
|
|
33
|
+
if (!isUsableDirectory(resolved) || isFilesystemRoot(resolved)) {
|
|
34
|
+
throw new Error(`SENTINEL_PROJECT_ROOT is set to "${envRoot}", which is not a usable project directory. ${ROOT_HELP}`);
|
|
35
|
+
}
|
|
36
|
+
return resolved;
|
|
37
|
+
}
|
|
38
|
+
const cwd = process.cwd();
|
|
39
|
+
if (!isFilesystemRoot(cwd) && isUsableDirectory(cwd)) {
|
|
40
|
+
return cwd;
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Asks the connected MCP client for its workspace roots (the protocol's
|
|
46
|
+
* standard way to communicate the project directory). Returns the first
|
|
47
|
+
* usable file:// root, or null when the client doesn't support roots or
|
|
48
|
+
* has none. Never throws — this is a fallback, not a requirement.
|
|
49
|
+
*/
|
|
50
|
+
export async function resolveRootViaClient(server) {
|
|
51
|
+
try {
|
|
52
|
+
if (!server.server.getClientCapabilities()?.roots)
|
|
53
|
+
return null;
|
|
54
|
+
const { roots } = await server.server.listRoots();
|
|
55
|
+
for (const root of roots ?? []) {
|
|
56
|
+
if (typeof root.uri === "string" && root.uri.startsWith("file://")) {
|
|
57
|
+
const path = fileURLToPath(root.uri);
|
|
58
|
+
if (isUsableDirectory(path) && !isFilesystemRoot(path))
|
|
59
|
+
return path;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
// Client advertised roots but the request failed — treat as unavailable.
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
//# sourceMappingURL=projectRoot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projectRoot.js","sourceRoot":"","sources":["../../src/mcp/projectRoot.ts"],"names":[],"mappings":"AAAA,0KAA0K;AAE1K,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAG3C,MAAM,CAAC,MAAM,SAAS,GACpB,gGAAgG;IAChG,iGAAiG;IACjG,iDAAiD,CAAC;AAEpD,SAAS,iBAAiB,CAAC,IAAY;IACrC,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IACtC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,QAAQ,KAAK,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;IAClD,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,IAAI,gBAAgB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,KAAK,CACb,oCAAoC,OAAO,+CAA+C,SAAS,EAAE,CACtG,CAAC;QACJ,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QACrD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,MAAiB;IAC1D,IAAI,CAAC;QACH,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,qBAAqB,EAAE,EAAE,KAAK;YAAE,OAAO,IAAI,CAAC;QAC/D,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;QAClD,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;YAC/B,IAAI,OAAO,IAAI,CAAC,GAAG,KAAK,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACnE,MAAM,IAAI,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACrC,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC;oBAAE,OAAO,IAAI,CAAC;YACtE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yEAAyE;IAC3E,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/mcp/server.js
CHANGED
|
@@ -9,6 +9,7 @@ import { gatherSecurityEvidence, SECURITY_TOOL_NAME } from "../verify/security.j
|
|
|
9
9
|
import { gatherStyleEvidence, STYLE_TOOL_NAME } from "../verify/style.js";
|
|
10
10
|
import { loadLocalEnv } from "../config/env.js";
|
|
11
11
|
import { loadSentinelrc, isToolEnabled } from "../config/sentinelrc.js";
|
|
12
|
+
import { resolveStartupRoot, resolveRootViaClient, ROOT_HELP } from "./projectRoot.js";
|
|
12
13
|
export const SERVER_NAME = "sentinel";
|
|
13
14
|
const diffInput = z
|
|
14
15
|
.string()
|
|
@@ -25,11 +26,22 @@ const findingSchema = z.object({
|
|
|
25
26
|
reason: z.string(),
|
|
26
27
|
source: z.literal("static"),
|
|
27
28
|
});
|
|
28
|
-
/**
|
|
29
|
-
function
|
|
29
|
+
/**
|
|
30
|
+
* Wraps an evidence function into an MCP handler: resolves the project root
|
|
31
|
+
* first (never trusting a bogus launch directory), re-checks the tool toggle
|
|
32
|
+
* against that root's .sentinelrc, and reports failures as tool errors.
|
|
33
|
+
*/
|
|
34
|
+
function evidenceHandler(toolName, requireProjectRoot, gather) {
|
|
30
35
|
return async (args) => {
|
|
31
36
|
try {
|
|
32
|
-
const
|
|
37
|
+
const projectRoot = await requireProjectRoot();
|
|
38
|
+
if (!isToolEnabled(loadSentinelrc(projectRoot), toolName)) {
|
|
39
|
+
return {
|
|
40
|
+
content: [{ type: "text", text: `${toolName} is disabled in this project's .sentinelrc.` }],
|
|
41
|
+
isError: true,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const evidence = gather(projectRoot, args);
|
|
33
45
|
return {
|
|
34
46
|
content: [{ type: "text", text: JSON.stringify(evidence, null, 2) }],
|
|
35
47
|
// The cast is safe: every evidence payload is a plain JSON object.
|
|
@@ -56,15 +68,41 @@ function evidenceHandler(toolName, gather) {
|
|
|
56
68
|
* Any human-facing logging from this process must go to stderr.
|
|
57
69
|
*/
|
|
58
70
|
export async function startMcpServer() {
|
|
59
|
-
//
|
|
60
|
-
|
|
71
|
+
// Some MCP clients launch servers from an unexpected directory (even "/"),
|
|
72
|
+
// so the project root is resolved defensively: SENTINEL_PROJECT_ROOT wins,
|
|
73
|
+
// then a plausible working directory, then — lazily, once the client is
|
|
74
|
+
// connected — the MCP roots capability. Throws here only when the env var
|
|
75
|
+
// is set but broken (explicit config must fail loudly).
|
|
76
|
+
const startupRoot = resolveStartupRoot();
|
|
77
|
+
if (startupRoot !== null) {
|
|
78
|
+
loadLocalEnv(startupRoot);
|
|
79
|
+
}
|
|
61
80
|
// Fail fast on a malformed .sentinelrc — a broken config must never be
|
|
62
|
-
// silently ignored. Tools disabled there are not registered at all.
|
|
63
|
-
|
|
81
|
+
// silently ignored. Tools disabled there are not registered at all. When
|
|
82
|
+
// the root is unknown at startup, all tools register and the per-call
|
|
83
|
+
// .sentinelrc check in evidenceHandler takes over.
|
|
84
|
+
const config = startupRoot !== null ? loadSentinelrc(startupRoot) : null;
|
|
64
85
|
const server = new McpServer({
|
|
65
86
|
name: SERVER_NAME,
|
|
66
87
|
version: SENTINEL_VERSION,
|
|
67
88
|
});
|
|
89
|
+
// Memoized, single-flight root resolution shared by all tool handlers.
|
|
90
|
+
let resolvedRoot = startupRoot;
|
|
91
|
+
let pendingResolve = null;
|
|
92
|
+
const requireProjectRoot = async () => {
|
|
93
|
+
if (resolvedRoot !== null)
|
|
94
|
+
return resolvedRoot;
|
|
95
|
+
pendingResolve ??= resolveRootViaClient(server);
|
|
96
|
+
const fromClient = await pendingResolve;
|
|
97
|
+
if (fromClient !== null) {
|
|
98
|
+
resolvedRoot = fromClient;
|
|
99
|
+
loadLocalEnv(fromClient);
|
|
100
|
+
console.error(`[sentinel] project root resolved via MCP roots: ${fromClient}`);
|
|
101
|
+
return fromClient;
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`Could not determine the project root. Sentinel was launched from "${process.cwd()}" ` +
|
|
104
|
+
`(not a usable project directory) and the MCP client did not provide workspace roots. ${ROOT_HELP}`);
|
|
105
|
+
};
|
|
68
106
|
const enabledTools = [];
|
|
69
107
|
if (isToolEnabled(config, TOOL_NAME)) {
|
|
70
108
|
enabledTools.push(TOOL_NAME);
|
|
@@ -84,7 +122,7 @@ export async function startMcpServer() {
|
|
|
84
122
|
diffFiles: z.array(z.string()),
|
|
85
123
|
addedLineCount: z.number(),
|
|
86
124
|
},
|
|
87
|
-
}, evidenceHandler(TOOL_NAME, ({ task, diff }) => gatherTaskMatchEvidence(
|
|
125
|
+
}, evidenceHandler(TOOL_NAME, requireProjectRoot, (root, { task, diff }) => gatherTaskMatchEvidence(root, task, diff)));
|
|
88
126
|
}
|
|
89
127
|
if (isToolEnabled(config, HALLUCINATION_TOOL_NAME)) {
|
|
90
128
|
enabledTools.push(HALLUCINATION_TOOL_NAME);
|
|
@@ -100,7 +138,7 @@ export async function startMcpServer() {
|
|
|
100
138
|
staticFindings: z.array(findingSchema),
|
|
101
139
|
declaredDependencies: z.array(z.string()).nullable(),
|
|
102
140
|
},
|
|
103
|
-
}, evidenceHandler(HALLUCINATION_TOOL_NAME, ({ diff }) => gatherHallucinationEvidence(
|
|
141
|
+
}, evidenceHandler(HALLUCINATION_TOOL_NAME, requireProjectRoot, (root, { diff }) => gatherHallucinationEvidence(root, diff)));
|
|
104
142
|
}
|
|
105
143
|
if (isToolEnabled(config, SECURITY_TOOL_NAME)) {
|
|
106
144
|
enabledTools.push(SECURITY_TOOL_NAME);
|
|
@@ -115,7 +153,7 @@ export async function startMcpServer() {
|
|
|
115
153
|
...evidenceBaseSchema,
|
|
116
154
|
staticFindings: z.array(findingSchema),
|
|
117
155
|
},
|
|
118
|
-
}, evidenceHandler(SECURITY_TOOL_NAME, ({ diff }) => gatherSecurityEvidence(
|
|
156
|
+
}, evidenceHandler(SECURITY_TOOL_NAME, requireProjectRoot, (root, { diff }) => gatherSecurityEvidence(root, diff)));
|
|
119
157
|
}
|
|
120
158
|
if (isToolEnabled(config, STYLE_TOOL_NAME)) {
|
|
121
159
|
enabledTools.push(STYLE_TOOL_NAME);
|
|
@@ -131,11 +169,14 @@ export async function startMcpServer() {
|
|
|
131
169
|
profile: z.string(),
|
|
132
170
|
staticFindings: z.array(findingSchema),
|
|
133
171
|
},
|
|
134
|
-
}, evidenceHandler(STYLE_TOOL_NAME, ({ diff }) => gatherStyleEvidence(
|
|
172
|
+
}, evidenceHandler(STYLE_TOOL_NAME, requireProjectRoot, (root, { diff }) => gatherStyleEvidence(root, diff)));
|
|
135
173
|
}
|
|
136
174
|
const transport = new StdioServerTransport();
|
|
137
175
|
await server.connect(transport);
|
|
138
176
|
console.error(`[sentinel] MCP server running on stdio (${SERVER_NAME} v${SENTINEL_VERSION}, agent-native evidence mode). ` +
|
|
139
|
-
`Tools: ${enabledTools.join(", ") || "(all disabled by .sentinelrc)"}`
|
|
177
|
+
`Tools: ${enabledTools.join(", ") || "(all disabled by .sentinelrc)"}. ` +
|
|
178
|
+
(startupRoot !== null
|
|
179
|
+
? `Project root: ${startupRoot}`
|
|
180
|
+
: "Project root unknown at startup — will ask the MCP client for its workspace roots on first tool call."));
|
|
140
181
|
}
|
|
141
182
|
//# sourceMappingURL=server.js.map
|
package/dist/mcp/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,6JAA6J;AAE7J,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,uBAAuB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAClG,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"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"}
|
package/dist/storage/db.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Purpose: opens (and migrates) Sentinel's local SQLite database at .sentinel/sentinel.db — all persistence is local, nothing leaves the machine.
|
|
2
2
|
import { DatabaseSync } from "node:sqlite";
|
|
3
3
|
import { mkdirSync, writeFileSync, existsSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
4
|
+
import { join, parse, resolve } from "node:path";
|
|
5
5
|
export const SENTINEL_DIR = ".sentinel";
|
|
6
6
|
export const DB_FILENAME = "sentinel.db";
|
|
7
7
|
/**
|
|
@@ -33,6 +33,14 @@ export const CURRENT_SCHEMA_VERSION = MIGRATIONS.length;
|
|
|
33
33
|
* Returns the absolute path to the .sentinel/ folder.
|
|
34
34
|
*/
|
|
35
35
|
export function ensureSentinelDir(projectDir) {
|
|
36
|
+
// Last line of defense: a filesystem root ("/", "C:\") is never a real
|
|
37
|
+
// project — writing there means the caller misresolved its directory.
|
|
38
|
+
const resolved = resolve(projectDir);
|
|
39
|
+
if (resolved === parse(resolved).root) {
|
|
40
|
+
throw new Error(`Refusing to create ${SENTINEL_DIR}/ in the filesystem root ("${resolved}") — ` +
|
|
41
|
+
`the project directory was not resolved correctly. Run Sentinel from your project folder, ` +
|
|
42
|
+
`or set SENTINEL_PROJECT_ROOT when configuring the MCP server.`);
|
|
43
|
+
}
|
|
36
44
|
const dir = join(projectDir, SENTINEL_DIR);
|
|
37
45
|
mkdirSync(dir, { recursive: true });
|
|
38
46
|
// Self-ignoring folder (same trick as .terraform/): keeps local data out of git
|
package/dist/storage/db.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/storage/db.ts"],"names":[],"mappings":"AAAA,kJAAkJ;AAElJ,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../../src/storage/db.ts"],"names":[],"mappings":"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"}
|
package/dist/version.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sentinel-verify",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "A fully local, open-source verification layer for AI coding agents. Plugs into any MCP-compatible agent and lets it self-check its work before a human sees it.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|