Skip to main content
Glama

DevSentinel 🛡️

CI License: MIT MCP Server Node TypeScript

The flight controller for coding agents. An MCP server that covers the three fundamental blind spots a coding agent cannot see on its own.

📖 Explore the Interactive Landing Page & Visual Docs (or open docs/index.html locally)


Engine

Question it answers

Tools

💥 BlastRadius

"What breaks across the repo if I change this?"

analyze_blast_radius, detect_breaking_changes

👁️ PixelGuard

"Does the webpage actually look right?"

capture_ui_state, diff_ui_visuals

⏱️ TimeMachine

"Can I undo this experiment safely?"

create_checkpoint, list_checkpoints, diff_checkpoint, rollback_checkpoint

Eight tools, three workflow prompts and two resources over one stdio connection. Built with Node.js + TypeScript (ESM) and zod-validated inputs; every tool returns deterministic, structured JSON.

How it fits together

Claude Desktop / Claude Code
        │  JSON-RPC over stdio
        ▼
  devsentinel  ──▶ BlastRadius  ──▶ your source tree      (Babel AST + Python scanner)
                ├▶ PixelGuard   ──▶ headless Chromium     (Playwright + pngjs)
                └▶ TimeMachine  ──▶ .devsentinel/          (sha1 snapshots, git read-only)

One process, no daemon, no port, no network calls of its own. Chromium is loaded lazily — the six non-visual tools never launch a browser. Nothing is written outside the workspace you point it at, except the screenshots and checkpoints under .devsentinel/.

Related MCP server: uacos

Install

npm install
npm run build
npx playwright install chromium   # only needed for capture_ui_state
npm test

Add .devsentinel/ to your .gitignore — that is where checkpoints and screenshots land.

Register the server

Claude Desktop

Copy claude_desktop_config.example.json into your Claude Desktop config and fix the two absolute paths:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

{
  "mcpServers": {
    "devsentinel": {
      "command": "node",
      "args": ["C:/absolute/path/to/devsentinel/dist/src/index.js"],
      "env": { "DEVSENTINEL_WORKSPACE": "C:/absolute/path/to/your/project" }
    }
  }
}

Restart Claude Desktop afterwards.

Claude Code

claude mcp add devsentinel -e DEVSENTINEL_WORKSPACE=/path/to/your/project -- node /abs/path/to/devsentinel/dist/src/index.js

Use --scope project to commit the server into .mcp.json for the whole team, or --scope user to make it available in every project.

Checking the wiring

node dist/src/index.js --version   # prints the version
node dist/src/index.js --help      # prints the workspace it resolved

Every tool also accepts an explicit workspaceDir, which wins over DEVSENTINEL_WORKSPACE, which in turn wins over the server's working directory. Human-readable output goes to stderr; stdout carries only the JSON-RPC stream.

Tools

analyze_blast_radius({ filePath, symbolName?, workspaceDir? })

Parses every .ts/.tsx/.js/.jsx/.mjs/.cjs file with Babel and every .py file with an import scanner, resolves each import specifier to a real file on disk, and reports who depends on the target:

{
  "target": { "file": "src/math.ts", "symbol": "add", "exists": true },
  "scannedFiles": 11,
  "consumers": [
    { "file": "src/app.ts", "isTest": false, "importedAs": ["add"], "importKind": "esm", "referenceLines": [2, 3], "reexports": false },
    { "file": "test/math.test.ts", "isTest": true, "importedAs": ["add"], "importKind": "esm", "referenceLines": [2], "reexports": false }
  ],
  "testFiles": ["test/math.test.ts"],
  "transitiveConsumers": ["src/via-barrel.ts"],
  "riskScore": 34,
  "riskLevel": "medium",
  "summary": "src/math.ts:add is used by 4 file(s) (1 test file(s), 1 transitive). Risk: medium."
}

Handles ESM imports, require(), dynamic import(), barrel re-exports, and Python import / from ... import. testFiles is the list to run after the edit. Because specifiers are resolved to real files, a change to add never drags in the callers of subtract — something a text search cannot distinguish.

tsconfig path aliases. tsconfig.json, or jsconfig.json if there is no tsconfig.json, is read for compilerOptions.baseUrl and compilerOptions.paths, so @/components/Button, ~utils and @models/user resolve to real files instead of being dropped as package imports. Comments and trailing commas are handled, because that is what these files actually contain; a malformed config degrades to the built-in ~/ and @/ handling rather than failing the scan. Bare specifiers are only tried against baseUrl when baseUrl is actually set, so a node_modules import costs no wasted lookups.

Nested barrels. Re-export chains are followed up to five hops with cycle detection, so a symbol reached through src/index.tssrc/feature/index.tssrc/feature/impl.ts still names the components that only ever import the outermost barrel. Those arrive in transitiveConsumers, never duplicated into consumers. Pass includeTransitive: false to skip the walk.

detect_breaking_changes({ filePath, newCode, workspaceDir? })

Diffs the exported contract of the file on disk against the code you are about to write. Findings are graded:

  • breaking — removed export, new required parameter, dropped parameter, changed parameter or return type, removed or newly-required interface/class member.

  • warning — renamed parameter, new required member on an interface, changed type of an exported constant.

  • additive — new export, new optional parameter or member.

isBreaking is true when the breaking list is non-empty, so an agent can gate on one field.

capture_ui_state({ url, selector?, viewport?, outputPath?, waitMs?, workspaceDir? })

Loads the URL in headless Chromium, writes a PNG, and runs an in-page audit that reports:

  • horizontal-overflow — the page scrolls sideways, with the offending elements and their widths.

  • clipped-content — text cut off by an overflow: hidden or text-overflow: ellipsis box.

  • overlapping-text — two unrelated text elements whose boxes overlap by more than 25% of the smaller one.

  • console-error, page-error, failed-request — anything the browser complained about while loading.

file:// URLs work, so a static HTML file can be audited without a dev server.

diff_ui_visuals({ beforeImagePath, afterImagePath, diffImagePath?, threshold?, workspaceDir? })

Compares two PNGs pixel by pixel and writes a red-on-grey overlay of what moved. Returns changedPixels, diffPercentage, whether the dimensions changed, and a verdict (identical / minor / significant / major).

create_checkpoint({ label?, description?, workspaceDir? })

Copies the current working state into .devsentinel/checkpoints/<id>/, with a SHA-1 per file. It never touches the git index, working tree, or stash, so it is safe to use mid-rebase or in a directory that is not a repo at all. In a git repo, git ls-files is used to pick files, so .gitignore is respected; otherwise a walk with a built-in ignore list is used. Files over 5MB are skipped, and a workspace over 250MB is refused.

list_checkpoints({ workspaceDir? })

Checkpoints newest first, each with the files modified, added and deleted since it was taken.

diff_checkpoint({ checkpointId, filePath?, workspaceDir? })

What changed in the workspace since a checkpoint, as unified line diffs — the question list_checkpoints leaves open once it has told you a file drifted.

{
  "checkpointId": "20260909T101500000Z-0001",
  "label": "before auth refactor",
  "files": [
    {
      "path": "src/session.ts",
      "status": "modified",
      "additions": 1,
      "deletions": 0,
      "diff": "@@ -12,6 +12,7 @@\n export function createSession(\n   userId: string,\n+  ttlSeconds: number,\n ) {",
      "binary": false,
      "truncated": false
    }
  ],
  "totalAdditions": 1,
  "totalDeletions": 0,
  "summary": "1 file(s) changed since \"before auth refactor\": +1 / -0 line(s)."
}

status is modified, added or deleted. Pass filePath to narrow the report to one file. Binary files come back flagged with no text diff rather than as mojibake, and a change wider than 2000 lines per side degrades to a whole-block replace with truncated: true.

rollback_checkpoint({ checkpointId, deleteNewFiles?, workspaceDir? })

Restores every file in the checkpoint and deletes files created since (pass deleteNewFiles: false to keep them). A safety checkpoint of the current state is always taken first and returned as safetyCheckpointId, so a rollback is itself undoable.

Prompts

Tool descriptions say what each tool does but not what order to call them in, and order is the whole point: a checkpoint taken after the edit is worthless, and a baseline screenshot taken after the markup changed is not a baseline. Three MCP prompts encode the sequences, and show up as slash commands in clients that support them.

Prompt

Arguments

What it drives

safe_refactor_check

filePath, symbolName?

Blast radius → checkpoint → contract check on the proposed code → edit → the tests the scan named

visual_regression_audit

url, changeDescription?, selector?

Baseline capture before the edit, re-capture after, pixel diff, and only the issues that are new

experiment_sandbox

goal, rollbackIf?

Checkpoint, a rollback trigger stated before any code is written, then diff and decide

Resources

URI

Contents

devsentinel://checkpoints/recent

The checkpoint log with per-entry drift — the list_checkpoints payload, attachable as context

devsentinel://workspace/config

Resolved workspace root and where it came from, git branch and HEAD, and the tsconfig baseUrl and paths aliases imports resolve through

Read devsentinel://workspace/config first when a scan comes back empty. That is almost always the server resolving a different directory than you assume, and this resource says which one.

Agent configuration

CLAUDE.md and .cursorrules ship in this repository. Copy the one matching your tool into your own project so its agent reaches for these tools at the right moment without being asked each time.

Suggested workflow

create_checkpoint          →  before a risky multi-file edit
analyze_blast_radius       →  who calls the thing you are about to change
detect_breaking_changes    →  does your new code break that contract
   ... make the edit, run the tests it named ...
capture_ui_state           →  screenshot + layout audit after a UI change
diff_ui_visuals            →  against the screenshot taken before
diff_checkpoint            →  what the experiment actually changed, line by line
rollback_checkpoint        →  if any of the above went badly

A prompt that puts it to work:

Before you touch src/auth/session.ts, run analyze_blast_radius on the
createSession symbol and tell me which tests I need to run.

Project layout

CLAUDE.md         agent protocol for Claude Code and Claude Desktop
.cursorrules      the same protocol as Cursor IDE rules
src/
  index.ts        MCP server: tools, prompts, resources, CLI flags, shutdown
  blastradius.ts  Babel AST scanning, import resolution, signature diffing
  pixelguard.ts   Playwright capture, in-page audit, PNG diffing
  timemachine.ts  content-hashed snapshots, drift detection, unified diffs, rollback
  workspace.ts    file walking, git-aware listing, shared path helpers
test/             one suite per engine, plus an end-to-end MCP client
docs/index.html   the landing page (GitHub Pages)

Development

npm run build      # tsc to dist/
npm run typecheck  # tsc --noEmit
npm test           # build, then node:test across all suites
npm start          # run the server on stdio directly
npm run clean      # remove dist/

60 tests, 13 suites, run on Node 18/20/22 in CI. Coverage by design:

Suite

What it proves

blastradius.test.ts

ESM/CJS/Python fixtures, symbol precision, tsconfig alias resolution, nested and cyclic barrel chains, reference lines, every breaking-change class

pixelguard.test.ts

A real headless-Chromium audit of a deliberately broken page; pixel diffs with a known 4.00% changed area

timemachine.test.ts

Checkpoint → drift → rollback round trips, safety checkpoints, self-exclusion of the store, unified diffs across modified/added/deleted/binary files

server.test.ts

An MCP client speaking JSON-RPC over stdio: all eight tools, prompt rendering and tool ordering, resource reads, and error passthrough

The Chromium tests skip themselves with a message if the browser is not installed, so npm test stays green on a machine without it.

Production notes

  • Failure mode. Tool errors come back as MCP tool errors with a usable message; the server stays alive. SIGINT/SIGTERM close the transport cleanly.

  • Input validation. Every argument is zod-parsed at the boundary. Checkpoint paths are workspace-relative and rejected if they escape the workspace root.

  • Data safety. rollback_checkpoint always snapshots the current state first. Nothing deletes a checkpoint automatically.

  • Privacy. No telemetry, no network calls except the pages capture_ui_state is explicitly asked to open.

  • Cost. A blast-radius scan is file I/O plus a Babel parse per file; there is no model call anywhere in this server.

Known limits

  • Import resolution covers relative, absolute, ~/ and @/ specifiers and tsconfig/jsconfig paths aliases. extends chains are not followed; only the root config is read.

  • Barrel re-export chains are followed five hops.

  • Checkpoint diffs use an LCS line diff over the changed region only. A change wider than 2000 lines per side comes back as a block replace with truncated: true.

  • Python analysis is regex-based, not a full parse: it covers module-level def, class and import statements.

  • Overlap detection compares at most 300 text elements per page.

  • Checkpoints copy file contents; they are not deltas, so a very large workspace is refused rather than slowly copied.

Contributing

Issues and pull requests welcome. Keep npm test green, and add a test alongside any new behaviour — each engine has a suite to extend.

License

MIT © Pritom Biswas

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    F
    maintenance
    AI code impact analysis MCP server that monitors file changes, maps dependency graphs, detects cascading breakage, and gates builds before damage spreads.
    113 npm
    2
    Elastic 2.0
  • A
    license
    Not graded
    quality
    B
    maintenance
    Local-first code intelligence and safety layer for AI coding agents. MCP server exposes dependency graph, impact analysis, and AST-compressed repo context, backed by typed local memory, patch-scope safety gates, and git-independent transaction rollback.
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server that provides impact preview and approval workflow for AI agent actions, allowing users to see diffs and risk assessments before any changes are executed.
    1
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server that watches upstream API providers for breaking changes, scans your codebase for impact, and drafts migration fixes locally, all offline-first with zero network.
    107 npm
    1
    AGPL 3.0