Sparda

by zyx77550

Not rated
GitHub

About

Turn any codebase into an MCP server with one command. Express & FastAPI → Claude-ready in 3 minutes.

Details

Author
zyx77550
Categories
Developer Tools, API

Setup

Install Sparda in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/zyx77550/sparda

Follow the installation instructions in the repository README, then restart your MCP client.

🇫🇷FrançaisL'IA écrit. SPARDA prouve.Un gate déterministe et hors-ligne qui détecte quand une modif d'IA retire une garde, expose une route ou casse un invariant — sans clé API, directement dans la boucle d'édition de l'agent. Pour tout comprendre en 10 minutes (douleur, architecture, vision) :SPARDA-EXPLIQUE.md.

The trust layer for AI-written backends.SPARDA compiles your backend — routes, database queries, state mutations, guards, side-effects — into one deterministic behavior graph, thenstatically proves what can and can't break before you ship: no unguarded mutation, no broken invariant, no non-atomic aggregate write.

100% local · deterministic · zero API key · no cloud account. It fails loudly on a real risk, and when it can only see part of your app it saysPROVEN (PARTIAL)— never a false green. And when it can prove it was not even looking at your whole app, it saysPREMISE NOT VERIFIEDand claims nothing at all.

From your Express, FastAPI, Flask, Next.js, NestJS or Medusa app — nothing to configure:

npx sparda-mcp apocalypse # prove the tree is safe to deploy — exit 1 on any real risk, or on an unverified premise npx sparda-mcp prove # the whole verdict: proof + coverage + shareable seal npx sparda-mcp badge # a README badge: proven · coverage% · routes

Under the hood it compiles your backend into one language-agnostic graph — theUnified Behavior Graph (UBG), serialized as.sparda/ubg.jsonunder theSBIRspecification (SPARDA Behavior IR) — and every command is a pass over that graph.

The wedge — catch an AI edit that removes a guard, in the loop

The one thing a text-diff review and a pattern scanner structurally can't do: prove thatthis specific editdropped a protection the previous version had.sparda gatediffs the behavior graph before/after an edit and blocks a regression — deterministic, offline, sub-second, exit 2 (the Claude CodePostToolUsecontract that stops the agent's edit loop). See it end-to-end in one command, zero setup:

npm run wedge # (from a clone) — or drive it on your own app with sparda gate --arm then sparda gate --hook`
1. baseline armed on the guarded code (POST /admin/delete-user · requireAdmin) 2. an AI edit "simplifies" requireAdmin → a pass-through (still compiles, still 200s) 3. sparda gate on the edit: ✗ [critical] GUARD_REMOVED — POST /admin/delete-user was guarded in the baseline and is now reachable without any guard (src/app.js:11) ⏱ ~40 ms · deterministic · offline · no API key ⛔ exit 2 on --hook — Claude Code PostToolUse blocks the edit

Wire it into Claude Code in one line— thepluginregisters aPostToolUsehook that runsnpx -y sparda-mcp gate --hookafter everyEdit/Write, so a guard-removing edit is caught before it lands.

[!IMPORTANT]
The Route-Compilation Proof — reproduce it yourself.SPARDA compiles real open-source monsters to their behavior graph withzero crashes, each in≈1–2 seconds: Next.jsDub(579 routes), NestJSImmich(281),MedusaJS(477). It natively resolves deep Dependency Injection, external controllers, and Next.js handlers. One command clones them and re-measures on your machine:

node bench/repro.mjs # → bench/route-proof.json

Honesty first:compilinga route is a parser result (the number above);provingit safe is a separate per-repo verdict — and most real apps come backNOT_PROVEN, which is the true state, not a failure. (Our full 25-repo corpus stress compiles3,565 routesat ~150 routes/s; that one needs the corpus checked out.)

What the graph unlocks — 100% local, deterministic, 4 exact-pinned dependencies, zero API key:

The prover is the product. The MCP server is oneoutputof the graph, not the point — SPARDA compiles the whole system's behavior, then proves, replays, heals, and (optionally) serves it.

Nomenclature:SBIRis the specification (the format, like "JSON");UBGis the compiled graph itself (the artifact,ubg.json). The MCP server is oneoutputof the graph, not the product.

Optional: expose the graph to AI clients (MCP runtime)

Beyond proving, SPARDA can turn your running app into a live MCP server — the graph, executable, with write-safety and an immune layer. This is optional and separate from the prover above.
-

Scan + inject— run once, from your app's directory:

SPARDA parses your routes (AST), generates a marked/mcprouter, injects it into your app (with a backup), and writessparda.json. Every step is reversible.

Connect your client.initprints a ready-to-paste block forclaude_desktop_config.json, pre-filled with your app's name and path:

{ "mcpServers": { "your-app": { "command": "npx", "args": ["sparda-mcp", "dev"], "cwd": "/absolute/path/to/your-app" } } }

Claude Code connects to the same bridge. That's it — your running app is now a set of MCP tools your AI can call.

To see SPARDA in action instantly without modifying your codebase:

This runs the entire MCP lifecycle (detect → parse → generate → inject → remove) on a bundled demo app in a temporary folder, in about 10 seconds. For the compiler itself, runnpx sparda-mcp ubgthenapocalypseon any Express/FastAPI app.

SPARDA is designed as a local organism. To see what it remembers and how much compute it has recycled:

This prints a terminal dashboard aggregating your exposed tools, write opt-ins, proof journal decisions, and crystallized composite tools.

To write a self-contained, offline HTML dashboard at.sparda/report.html, append the--htmlflag:

SPARDA's Behavior Graph is a formal model of your system. Instead of waiting for runtime failures or relying on static analysis vibes, you can statically prove the safety of your backend before any deployment:

This command reads the compiled.sparda/ubg.json(with zero source code parsing at runtime) and discharges five static correctness obligations:

- Unguarded Mutation (Critical): Flags any mutation path that does not cross a securityguard.
- Non-Atomic Aggregate Write (High): Flags when an API writes to multiple tables of the same Consistency Domain (Aggregate) outside a single transaction scope.
- Unvalidated Constrained Write (Medium): Flags writes into columns with declared invariants (CHECK, NOT NULL, UNIQUE — parsed from your
.sqlDDLorschema.prisma, Prisma enums included) without prior validation (Zod/Pydantic).
- Irreversible Observable Effect (High): Flags out-of-process actions (like Stripe charges) that happen alongside state writes without a structural compensation path (like a catch-refund).
- Taint Flow Analysis (High): Tracks untrusted input variables through the AST to ensure they do not corrupt critical sinks.
- Guard Dominance (Medium): Proves that top-level security guards cannot be bypassed by nested or overlapping sibling routes.
- Aggregate Member Bypass (Info): Flags mutating a member table directly without routing through the aggregate root.

To save your current graph as a safe baseline:

npx sparda-mcp apocalypse --save-baseline

Subsequent runs will diff the candidate graph against this baseline to detect regression vectors:

- Deletion of any securityguard(Critical).
- Deletion of a database SQL invariant (High).
- API blast radius expansion (Medium).

If any Critical or High finding is found,apocalypseexits with a non-zero code to block your CI pipeline.

One step in your workflow — findings land in the GitHub Security tab (SARIF):

- uses: zyx77550/sparda@main with: sarif: 'true'

Every production request is deterministic between its effects — the compiler knows exactly where the nondeterminism lives (db, http, clock, random, uuid: the effect nodes of the graph). Timeless records only those points (a few KB per request) and replays the requestbyte-identicallyagainst your current code, with the database, webhooks and clock virtualized from the recording:

npx sparda-mcp timeless # list recorded flights npx sparda-mcp timeless replay <id> # re-fly it — byte-identical or loud divergence npx sparda-mcp timeless export <id> # the production bug is now a vitest test

Recording is two lines in your app (ESM), with deterministic sampling and GDPR redaction built in:

import { getFlightBox } from 'sparda-mcp/src/flight/box.js'; const box = getFlightBox(); box.arm(); app.use(box.middleware({ sample: 100 })); // 1 request in 100; passwords/tokens redacted by default const db = box.wrapClient(pgPool); // your query client, tapped

The closed loop nobody else has:production bug → recorded flight → failing test → AI writes the fix →apocalypseproves the fix breaks no guard, invariant or transaction → deploy.Replay is per-request (concurrent-race capture is out of scope for v1 — stated, not hidden).

The loop above, asone gesture— and the machine judges the fix, whoever wrote it:

npx sparda-mcp heal <flightId> # diagnose + write the fix brief # ...apply the fix (a human, or --agent "your-ai-cli")... npx sparda-mcp heal <flightId> --check --expect '{"status":404}'

The brief is built from the graph itself — it hands the fixer the handler'sfile:line, the capabilities the fix must not grow, and the guards it must not remove. Then thegate— the actual product — proves the fix on three axes at once:
- Behavior— lenient replay of the recorded flight (same deterministic inputs) now produces theexpectedresponse, not the recorded bug. The fix may reformulate a query (the tap is relabeled, allowed); it maynotchange the effect order or kinds.
- Compiler laws
verifystill passes: the graph is still sound and deterministic.
- No regression
apocalypsediff against the frozen pre-fix graph: zero new critical/high findings, no guard removed, no blast radius grown.

✓ HEALED & PROVEN — same recorded inputs, correct output, zero law broken, zero protection lost. Ship it.

The gate is honest in both directions: an unfixed bug, or a "fix" that silently drops a guard, keeps itclosed(exit 1). This is the difference between an AI that writes plausible code and a system thatprovesthe code is correct — the trust layer the agent era is missing.

SPARDA parses Express, FastAPI, Flask and Next.js natively — andevery other stack through the format the industry already agreed on. Go, Java, Rails, Laravel, .NET: if it has an OpenAPI spec, it compiles.

npx sparda-mcp ubg --openapi openapi.json

Security schemes become gatingguardnodes, response schemas become typed returns, declared request bodies count as validated input. Pair the spec with your.sqlorschema.prismafiles and the full state layer — invariants, aggregates, state machines — fills in from declared truth. (JSON specs in v1; we refuse to half-parse YAML with zero dependencies.)

The Mirror VM: delete the framework, the app still answers

The graph is not a diagram — it executes:

MIRROR — the graph is serving. 3 entrypoint(s) on http://127.0.0.1:4477 GET /orders/{orderId} → {amount, id, status} POST /orders 🔒 bearerAuth → {amount, id, status}

No Express. No FastAPI. No source code — justubg.jsonanswering HTTP: guards actually deny (401), responses render the compiled return schemas, unknown paths 404 with the full route table. Front-end teams develop against backends that aren't deployed yet — or aren't written yet (pointmirrorat an OpenAPI spec). Every response carriesx-sparda-mirror: true; the mirror serves declared behavior, it never invents business values.

To undo everything:npx sparda-mcp removerestores your code byte-for-byte.

The promise — every word is backed by a test in CI

- Three minutes, one command.AST scan, router generation, reversible injection — no config. - Try it for free, leave for free.
npx sparda-mcp removerestores your codebyte-for-byte(tested on JS, TS, Python, even Windows CRLF files). No trace, no lock-in. - The AI cannot write until you say so.Every POST/PUT/DELETE is disabled by default; you enable per tool, and your choice survives every re-run. - Your app defends itself.A route failing 3 times in a row is quarantined — the AI can't hammer your broken production. Latency anomalies are flagged. Zero LLM needed. - Nothing leaves your machine.No telemetry to us, no cloud, local key auth, 4 exact-pinned dependencies. - What it learns is never lost.Diagnoses, descriptions, settings — versioned with your git, surviving every re-init.

What wedon'tpromise: the honest limits indocs/SECURITY.md.
-
npx sparda-mcp initparses your codebase (AST), extracts every route, and injects a tiny marked router (/mcp) into your app — fully reversible withnpx sparda-mcp remove.
- Tool calls runinside your live app process— warm DB pools, real auth chain, real data. SPARDA adds no infrastructure: compute comes from your host process, intelligence from your AI client's own model (MCP sampling), storage from
sparda.json+ git.
- Write tools (POST/PUT/DELETE) aredisabled by default. You opt in per tool in
sparda.json— your choices survive re-runs.
- Suspicious docstrings are sanitized before they ever reach the AI (prompt-injection defense).
-
npx sparda-mcp doctor --appaudits your codebase for drift: it detects stale tools (IA seeing ghosts), unsynced routes, schema drift via fingerprints, and zombie configurations. High severity issues trigger a non-zero exit code for your CI pipeline.
-
npx sparda-mcp seed export/importlets you package and share your app's "genome" (semantic memory, workflows, antibodies) securely, transferring immune memory between environments or across similar stacks with zero data leak.
-
npx sparda-mcp twinstarts a safe, simulated mock server of your backend on the original port. It serves GET calls from learned exemplars (observed response shapes & mock data) and returns simulated 202 writes without ever touching your real database or production APIs. Learn exemplars by runningnpx sparda-mcp twin --learn.
-
npx sparda-mcp grammarmaps the graph of valid sequences of tool calls (observed circuits and candidate hypotheses) to prevent LLM hallucination of routes.
-
npx sparda-mcp evolvemutates candidate chains and tests them against the twin in-memory, promoting successful chains to evolved workflow suggestions.

Every route becomes a tool that runs against your live process — real auth, real data, warm connections. One call tosparda_get_contexthands the AI the whole living picture: enabled tools, suggested workflows, runtime telemetry, quarantine state, and immune memory — so every session resumes where the last one stopped.

Prove the edit before you commit — the one check an LLM can't do to itself

The AI just edited a route. Did it quietly drop a guard? It callssparda_proveand finds outnow, not in a CI run later. The tool recompiles the app to its behavior graph, discharges the same static obligations assparda apocalypse, and returns a deterministic verdict — the exact word the CLI and badge emit, so it can never over-claim (a low-coverage clean app readsSURFACE, never a barePROVEN). Save a baseline once (sparda apocalypse --save-baseline) and every latersparda_proveflags any finding withregression: true— the guard your edit removed, the route it dropped, the blast radius it grew. That's"AI writes. SPARDA proves."inside the edit loop. Clients that list MCP prompts also get theprove-my-editworkflow.

Write-safety: the AI can't write until you say so

- Writes (POST/PUT/DELETE) shipdisabled. Enable them per tool insparda.json; your choice survives every re-init.
- An enabled write isnever executed on the first call. SPARDA returns an
awaiting_confirmationenvelope — a single-use token plus a preview of the action — and commits only after an explicit confirm step.
- When your client supports MCP elicitation, that confirmation prompt appearsin the AI's own UI.
- Proof-after-write: every successful write is followed by a read-back of the same resource, so the AI — and you — see the real effect, not a hopeful guess.

Your app defends itself — zero LLM on the hot path

- Quarantine.A tool that returns 3 consecutive 5xx is quarantined: further calls get a503with a reason and a retry delay instead of hammering your broken route. After a cooldown it half-opens for a single probe.
- Latency & anomaly flags.The router learns each route's baseline and flags deviations locally, in a few lines of math.
- Adaptive diagnosis, only on surprise.A genuinely new failure wakes your AI client's own model to diagnose it once; the diagnosis is cached as an "antibody" in
sparda.json, so the same failure later costs zero tokens. Cloning your code doesn't clone its immune memory.

On first connection your AI client's own model (via MCP sampling) rewrites raw routes into business-language tool descriptions and proposes multi-step workflows — cached insparda.jsonand exposed as MCP prompts. Nothing to configure, nothing to pay.

- Response recycling.When a read keeps returning the same answer, SPARDA serves the next identical call straight from memory — without touching your host app. Reads only; writes always hit the host.
- A recycling gauge.
GET /mcp/statscounts how many calls were answered from SPARDA's own knowledge vs. how many paid the host route. It reads 0% on day one and fills with usage — a measure, never a promise.

Tools nobody wrote — Labs, opt-in, default OFF

Turn it on with"labs": { "recordSequences": true }insparda.json. SPARDA then notices when one tool's output feeds the next tool's input and records thecircuit— structure only (tool names, argument names, counts), never your data. A read-only circuit seen enough timescrystallizes into a composite tool, announced mid-session: one call runs the whole chain, auto-feeding each step from the previous step's real response. Write routes are never absorbed — their per-call confirmation always stands.

GET /mcp/stats(per-tool calls/errors, tool "purity", quarantine state) andGET /mcp/events(errors, latency anomalies, cached diagnoses) expose exactly what your app is doing — surfaced to the AI as live notifications.

SPARDA ships with an Agent Skill (SKILL.md) that teaches any compatible AI client how to drive a SPARDA server to itsfull potential— callsparda_get_contextfirst, exploit response recycling, honor quarantine, prefer crystallized circuits over re-walking a chain, and follow the two-phase write-confirm protocol. The live, per-project tool list always comes fromsparda_get_contextat runtime, so the guidance never goes stale.

- Next.js App Router (13/14/15)— file-based injection. SPARDA creates a catch-all route handler. It natively resolves wrapped handlers (export const POST = withAuth(h)) and deep effect chains.
- NestJS— AST-based router injection. Deeply resolves Multi-hop Dependency Injection (Controller → Service → Repository), inherited DI, and
baseUrl/pathsimports. Fully supports composite decorators (applyDecorators). Resolves ORM writes: Prisma, Kysely, and TypeORM injected repositories (@InjectRepository(Entity)this.repo.save()).
- Strapi— Native AST ingestion of Strapi content-types, core controllers, and custom routes.
- Express 4/5(JS/TS, ESM/CJS) — AST-based router injection. Deeply resolves external controllers, Mongoose schemas, barrel re-exports, and inline handlers. Uses dynamic tree-scanning to find non-standard entry points (
bootstrap.ts, etc).
- MedusaJS— Native AST ingestion of complex e-commerce routing.
- Any Backend On Earth (Go, Java, Rails, Laravel)— Compiles flawlessly from OpenAPI 3.x specs.
- FastAPI(Python >= 3.9) — AST-based router injection.

Effects it resolves (what makes the irreversibility & atomicity proofs bite)

- Databases— Prisma (incl. named/multiline relations and interactive$transaction(tx ⇒ …)), TypeORM, Kysely, Drizzle, Knex, Sequelize, Mongoose, and raw SQL. Foreign keys become aggregate/consistency domains, so a multi-table write outside a transaction is caught.
- External side-effects— recognized by call shape and by import origin, so an irreversible outbound effect next to a DB write is proven compensable-or-not:
fetch/axios/got, Stripe, Twilio, SendGrid/Resend/nodemailer, AWS SDK v3 (send(new PutObjectCommand())), and other payment/mail/cloud/queue clients. A read on such a client stays a non-observable GET — no false alarms.

- 4 runtime dependencies, exact-pinned.
- Dynamic Local Key Resolution.The generated router contains no baked secrets. It resolves authorization keys at runtime from the
SPARDA_LOCAL_KEYenvironment variable or the local gitignored.sparda/keyfile, and fails closed (503) when neither is found. For custom production or staging setups, you can override this behavior by exposingSPARDA_LOCAL_KEYin your environment.
- Local key on every router call; self-reference loop protection; 30s timeouts; 8 KB output truncation.
- AST-positioned injection with backup and post-injection re-parse;
npx sparda-mcp remove`leaves a clean git diff.
- Persistence isvalue-free: SPARDA records structure (tool names, field names, fingerprints), never your payloads.

No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.