Release candidatev1.1 is ready for external verification; PyPI publication is still pending.Release status
Research notePrecision before coverage

Security analysis for MCP servers + agent skills

Find the gap between what it says and what itdoes.

Divergence compares claims, schemas, source code, installed-set context, and—on supported Linux hosts—sandboxed runtime behaviour. Capabilities stay posture. Contradictions become risk.

v1.1.0 is a release candidate. The package, signed tag, and GitHub release are not published yet.

Candidate evidence

Precision you can reproduce.

0/35false-positive traps
49/50positives with dynamic analysis
100%candidate-corpus precision
110auditable synthetic artifacts

Release-candidate evidence on a project-authored synthetic corpus. Dynamic results were measured on verified unprivileged Linux arm64; independent review and x86-64 reproduction remain open.

The thesis

A capability is not a verdict.

A shell server spawning processes may be doing exactly what it promised. The risk begins when it reaches for something it did not declare—an outbound connection, a credential path, a hidden parameter, or a write behind a read-only claim.

Conventional pattern matchers react to dangerous-looking words. Divergence asks a different question: do the artifact’s independent representations agree?

01

Posture

What it can do.

Informative and non-urgent. A broad capability is not evidence of deception.

Not a verdict
02

Risk

Where its stories disagree.

Every finding carries both halves of the contradiction and exact evidence.

Actionable

How it works

Four representations. One measurable gap.

Each surface is analyzed independently. Set algebra finds the mismatch, then emits risk only when the contradiction has concrete evidence.

01 · Claims

What it says

Names and natural-language descriptions become a fixed capability set—not a verdict.

02 · Schema

What it permits

Parameters, MCP annotations, and skill tool grants expose the declared interface.

03 · Source

What it reaches

Reachable filesystem, network, process, environment, secret, and eval capabilities.

04 · Runtime

What it actually touches

Optional behaviour observed only inside the verified fail-closed Linux sandbox.

CompareC · S · Bstatic · Bdynamic evidence-bound risk

Capabilities

Static first. Dynamic when it earns its place.

The deterministic core ships independently. Optional tiers add evidence without weakening the offline default or silently turning partial analysis into a clean result.

01Default boundary

Offline and non-executing

Local targets are parsed without running them. Remote acquisition, dynamic execution, external baselines, and A9 all require explicit opt-ins.

02Static analysis

Python, TypeScript, and shell

Tree-sitter reachability follows handlers and skill entrypoints into filesystem, network, subprocess, environment, secret, and dynamic-evaluation sinks.

03Installed-set context

Fleet analysis

Detect shadowing, preference manipulation, trigger hijacking, and toxic flows that cannot exist inside a single artifact.

04Time

Approval ledger

Approve a fingerprint, then classify later mutations as cosmetic, capability-expanding, or semantics-inverting.

05Automation

JSON, SARIF, and GitHub Action

Emit deterministic machine-readable results and SARIF 2.1.0, with controls to fail CI on risk or incomplete analysis.

06Optional evidence

Sandbox and adjudication

Observe runtime behaviour inside the Linux boundary. Separately, an evidence-only command backend can adjudicate a capped contested subset when explicitly requested.

The benchmark

Lead with the false-positive traps.

The candidate corpus contains 110 synthetic artifacts: 50 risk-positive and 60 benign or control samples. Every result carries its denominator and provenance.

ScannerTrap false positivesPrecisionRecall
Semgrep 1.173.05/3581.1%30/50
Keyword baseline20/3552.9%27/50

Run it yourself

From clone to first scan.

Python 3.12 and uv are required. Static analysis is local, offline, and non-executing by default.

01

Run from source today

git clone https://github.com/vignesh-chaturvedi/divergence.git
cd divergence
uv sync --frozen --extra dev
uv run divergence scan <path>
02

Fail CI on risk and write SARIF

uv run divergence --fail-on-risk scan <path> \
  --sarif divergence.sarif
After release

One-shot installation

uvx --from divergence-mcp==1.1.0 divergence --help

This command becomes available only after the v1.1.0 PyPI publication.

Before you run it

Questions worth answering plainly.

Security tooling earns trust by explaining its boundary, not hiding it in a footnote.

Does Divergence execute the artifact?

No by default. Static scans parse local files without executing them. Runtime observation happens only when you explicitly pass --dynamic and the verified Linux sandbox is available.

Does it upload my MCP configuration?

The deterministic static path and sandbox execution stay local. Raw source, artifact files, MCP configs, and credentials are never sent through the built-in A9 contract; it receives normalized evidence only. Remote acquisition, external scanners, and adjudication remain separate explicit opt-ins.

Which platforms are supported?

Static analysis is cross-platform. The fail-closed sandbox uses Linux kernel facilities; macOS and Windows remain visibly static-only.

Is Divergence a runtime firewall?

No. It analyzes artifacts before and between runs and emits findings for existing tools to enforce. Inline request interception is intentionally out of scope.

Can a clean dynamic result prove safety?

No. Dynamic evidence only covers paths that actually execute. Divergence reports observed coverage and keeps incomplete analysis visible rather than treating it as clean.

Is v1.1.0 published?

Not yet. Local release engineering is complete, but independent review, Linux x86-64 reproduction, a non-author real-world run, and protected publication remain.