Local stdio MCP / signalint-mcp@0.2.0

Engine diagnostics.
Agent-sized responses.

Signalint is a local stdio MCP server that runs Oxlint, TypeScript, and optional Biome checks—then caches unchanged work, clusters repeated issues, and flags fix loops before sending a versioned response back to the coding agent.

Runtime manifestlocal process
Transportlocal / stdio
Packagesignalint-mcp@0.2.0
Enginesoxlint / tsc / biome
ResponseschemaVersion 1.1
LicenseMIT
Install from npmdownloads / last 7 days
npm install --save-dev signalint-mcp && npx signalint-mcp init
Payload reduction86.53%

Current 40-issue fixture: 9,151 B raw versus 1,233 B clustered.

Incremental check3.10 ms

Latest local acceptance run; the enforced ceiling is 300 ms for the 50-file fixture.

Fixture compression404

Forty raw issues grouped into four rule-first clusters.

Input boundary512

Maximum project-relative paths accepted in one MCP call.

01 / response

See what the agent sees.

Scroll through the recorded 40-issue fixture as normalized rows become a bounded schema 1.1 response.

01 / engine output

Forty valid issues can still be a poor agent response.

The engines stay authoritative. Signalint first normalizes their locations, rule IDs, severity, and messages.

02 / rule-first grouping

Repeated symptoms become one review target.

Large rule groups spanning multiple files receive one root-cause summary and distinct sample issue IDs.

03 / bounded response

The agent receives four clusters, not forty rows.

The controlled fixture falls from 9,151 bytes to 1,233 bytes while preserving engine state and issue references.

check_project
raw / 40 issuesclustered / 4 groups
01
TS2322src/file01.ts:10:5

Type 'string' is not assignable to type 'number'.

02
TS2322src/file02.ts:11:5

Type 'string' is not assignable to type 'number'.

03
TS2322src/file03.ts:12:5

Type 'string' is not assignable to type 'number'.

04
TS2322src/file04.ts:13:5

Type 'string' is not assignable to type 'number'.

05
TS2322src/file05.ts:14:5

Type 'string' is not assignable to type 'number'.

06
TS2322src/file06.ts:15:5

Type 'string' is not assignable to type 'number'.

..

34 additional normalized issues

02 / mechanics

A local pipeline with explicit boundaries.

Signalint preserves the diagnostic engines as the source of truth and makes cache, failure, and loop state explicit.

Incoming MCP tool callcheck_files
Input
3 project-relative paths
Working directory
project root
Execution
local process
  1. 01
    Trust boundary

    Validate before reading.

    Zod schemas reject malformed arguments. Canonical path checks keep every accepted file inside the project root.

    3 paths accepted
  2. 02
    Engine fan-out

    Preserve each engine's model.

    File-local engines receive misses. TypeScript runs against the complete configured program when relevant files change.

    oxlint1 cache miss
    tscwhole project
    biomedisabled
  3. 03
    Common contract

    Normalize, then cluster.

    Engine-native diagnostics become normalized issues before rule-first grouping assigns priority and distinct issue references.

    40 issues → 4 clusters
  4. 04
    Bounded response

    Return what completed.

    Schema 1.1 keeps each engine's outcome explicit, so one failure cannot erase another engine's diagnostics.

    schemaVersion 1.1
oxlintok
tscok
biomedisabled

Completed diagnostics remain available even when another engine errors.

01 — cache identity

Version-aware reuse

A result is reused only when file content, the recognized root engine-config hash, Signalint code version, and the installed engine version still match.

sha256(file content)
: engine
: engine config hash
: signalint version
: engine version
02 — loop memory

Oscillation is visible

An issue that disappears and returns repeatedly produces a narrow warning, not a guess about the wider conversation.

{
  "signature": "no-unused-vars:<identifier> is unused",
  "occurrences": 3,
  "hint": "This issue was fixed and reappeared 3 times — consider a different approach"
}
03 — engine fan-out

Partial results survive

One engine can fail without discarding diagnostics another engine already completed.

"engines": {
  "oxlint": { "status": "ok" },
  "tsc": { "status": "error", "message": "..." },
  "biome": { "status": "disabled" }
}
04 — process boundary

Bounded execution

Default deadlines are 30 seconds for Oxlint, 120 seconds for tsc, and 30 seconds for Biome. Timeout and cancellation terminate the process tree.

05 — storage

Local state stays bounded

The SQLite cache evicts least-recently-used rows above 10,000 entries. Session history replays a bounded tail and rotates to a single .1 backup.

03 / engines

Each engine keeps its execution model.

Signalint coordinates three tools without pretending they work alike. Cache decisions follow each engine's real scope.

01

Oxlint

File-local analysis

ReceivesOnly changed cache-miss paths

Signalint batches misses and stores normalized results per engine and file.

Cache scope
engine + file
Deadline
30 s
02

TypeScript

Whole-program analysis

ReceivesThe complete configured project

Normal roots use --project; solution-style roots with references use --build.

Cache scope
run decision
Deadline
120 s
03

Biome

Optional file-local analysis

ReceivesChanged cache-miss paths when enabled

Disabled by default, with an explicit engine status in every check response.

Cache scope
engine + file
Deadline
30 s

04 / clients

Connect the server where the agent works.

One local server, three client-specific configuration paths. The init command detects nearby clients and writes only after confirmation.

01 / project scope

Claude Code

Share a project-local MCP entry through .mcp.json.

claude mcp add --scope project signalint …
02 / project scope

Cursor

Use .cursor/mcp.json with the published npm binary.

npx --no-install signalint-mcp
03 / user config

Antigravity

Set an explicit project working directory in mcp_config.json.

cmd /c npx --no-install signalint-mcp