{"_id":"@blithedale/mcpguard","name":"@blithedale/mcpguard","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@blithedale/mcpguard","version":"0.1.0","description":"Defensive, read-only static analyzer for local MCP tool and server definition files","type":"module","bin":{"mcpguard":"dist/cli/index.js"},"main":"./dist/cli/index.js","repository":{"type":"git","url":"git+https://github.com/BlitheBot/MCP.git"},"bugs":{"url":"https://github.com/BlitheBot/MCP/issues"},"homepage":"https://github.com/BlitheBot/MCP#readme","scripts":{"build":"tsc","prepublishOnly":"npm run build && npm test","dev":"tsx src/cli/index.ts","test":"tsc -p tsconfig.json && node --test \"dist/**/*.test.js\"","typecheck":"tsc --noEmit"},"engines":{"node":">=18"},"keywords":["mcp","security","static-analysis","audit"],"license":"MIT","dependencies":{"chalk":"^5.3.0","commander":"^12.1.0","fast-glob":"^3.3.2"},"devDependencies":{"@types/node":"^22.5.0","tsx":"^4.19.0","typescript":"^5.6.0"},"gitHead":"3d0820cbaf9b67683369aaf9aebb0136b2495a12","types":"./dist/cli/index.d.ts","_id":"@blithedale/mcpguard@0.1.0","_nodeVersion":"24.15.0","_npmVersion":"11.12.1","dist":{"integrity":"sha512-xpE78adKn2d8SdBaECsdF4z5CGOgr+EC5MdlkJQllcS1owzoFwPlP0wwoB3X8B6OKWEJL5Y2vKS2v/Kdlnr+3g==","shasum":"4d30f9b199da79f075beb138cdb9bfcfc4f58b5b","tarball":"https://registry.npmjs.org/@blithedale/mcpguard/-/mcpguard-0.1.0.tgz","fileCount":33,"unpackedSize":77208,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIEcoBt0d4Q+PxzWPjvutUe2pEYXLfYybvddmx+cZ/2DSAiEAsQ2jM6ohTtzKiKz/wukN6KIJxGCns6wtk/KdpLGmqlg="}]},"_npmUser":{"name":"blithedale","email":"mjshirley01@gmail.com"},"directories":{},"maintainers":[{"name":"blithedale","email":"mjshirley01@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcpguard_0.1.0_1784383904551_0.41025680900270767"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-18T14:11:44.399Z","0.1.0":"2026-07-18T14:11:44.748Z","modified":"2026-07-18T14:11:44.976Z"},"maintainers":[{"name":"blithedale","email":"mjshirley01@gmail.com"}],"description":"Defensive, read-only static analyzer for local MCP tool and server definition files","homepage":"https://github.com/BlitheBot/MCP#readme","keywords":["mcp","security","static-analysis","audit"],"repository":{"type":"git","url":"git+https://github.com/BlitheBot/MCP.git"},"bugs":{"url":"https://github.com/BlitheBot/MCP/issues"},"license":"MIT","readme":"# mcpguard\n\nA defensive, **read-only static analyzer** for local MCP (Model Context\nProtocol) tool and server definition files.\n\nmcpguard reads local JSON files and reports on their structure — nothing\nelse. It makes **no network calls**, generates **no payloads**, and never\nexecutes or imports the content it scans. Findings are reported with\nseverities, remediation guidance, and an overall 0–100 score with a letter\ngrade.\n\n## Audit pillars\n\n| Pillar | Rules | What it catches |\n| --- | --- | --- |\n| `schema-integrity` | IV-001, IV-002 | Execution-adjacent string inputs (`command`, `path`, `url`, `sql`, …) with no `pattern`/`enum`/`format` constraint; sensitive-named tools with no input schema at all |\n| `text-sanitization` | TS-001…TS-005 | Hidden Unicode in tool names/descriptions: zero-width characters, bidi override controls, tag characters, stray variation selectors, non-printable controls — reported by code point, never echoed |\n| `network-boundaries` | NB-001…NB-004 | Missing egress filtering, filters with no allowlist, and exposed hosts pointing at loopback or private/link-local address space (including the cloud metadata range) |\n\n## Install & build\n\n```sh\nnpm install\nnpm run build     # compile to dist/\nnpm test          # compile + run the test suite (node:test, no extra deps)\n```\n\nRun from source during development with `npm run dev -- <command>`, or via\nthe built CLI with `node dist/cli/index.js <command>`. Installing the\npackage makes the `mcpguard` binary available directly.\n\n## Usage\n\n### `mcpguard scan [paths...]`\n\nDiscovers definition files, runs every rule, and prints a Markdown audit\nreport plus a colored one-line score summary.\n\n- `--dir <dir...>` — additional directories to scan (merged with positional paths; defaults to the current directory)\n- `--json` — print the raw `AuditResult` as JSON on stdout (status goes to stderr, so piping stays clean)\n- `--out <file>` — write the report to a file instead of stdout\n- `--fail-on <severity>` — exit `1` if any finding is at or above the given\n  severity (`critical`, `high`, `medium`, `low`, or `info`), in every output\n  mode. A red status line states what triggered the failure. Without\n  `--fail-on` (or when no finding meets the threshold), `scan` exits `0`\n  regardless of findings.\n- `--fail-on-empty` — exit `1` when no definition files are discovered at\n  all (off by default: normally an empty scan exits `0`, since there is\n  nothing to evaluate).\n\n  Together these make `scan` usable as a CI gate:\n\n  ```sh\n  mcpguard scan --dir ./mcp-configs --fail-on high --fail-on-empty\n  ```\n\n  Use both in CI: `--fail-on` catches dangerous definitions, while\n  `--fail-on-empty` catches a moved or misconfigured scan path — which\n  should fail loudly, not silently pass as \"clean.\" Pair with\n  `mcpguard drift` to also catch individual definitions disappearing\n  between runs.\n\n### `mcpguard snapshot`\n\nRecords a baseline of SHA-256 hashes (key-order independent) of every\ndiscovered tool definition, for later drift detection.\n\n- `--dir <dir...>` — directories to scan\n- `--out <file>` — snapshot file to write (default `.mcpguard-snapshot.json`)\n\n### `mcpguard drift`\n\nCompares current tool definitions against a saved baseline and prints\ncolor-coded changes (cyan = added, red = removed, yellow = changed).\nExits `1` if anything changed or was removed — suitable as a CI gate\nagainst rug-pull style tool redefinition.\n\n- `--dir <dir...>` — directories to scan\n- `--snapshot <file>` — baseline to compare against (default `.mcpguard-snapshot.json`)\n\n> **Windows note:** `--json` output pipes cleanly through Git Bash,\n> PowerShell 7+, and cmd, but Windows PowerShell 5.1 re-encodes piped\n> native output and can mangle the bytes (e.g. prepend a BOM).\n\n## File discovery\n\nmcpguard finds definitions by naming convention, searching each given path\nrecursively:\n\n- **Tool definitions:** `mcp.tools.json`, `tools/*.json`, `*.mcp-tools.json`\n- **Server configs:** `mcp.server.json`, `mcp.config.json`, `*.mcp-server.json`\n\n`node_modules/`, `dist/`, `.git/`, and `examples/` directories are always\nskipped, and symlinks are not followed. A file may contain a single\ndefinition object or an array of them. Malformed or unreadable files are\nskipped with a warning (surfaced in the report and `--json` output), as are\nentries missing a string `name`. Duplicate tool names and files matching\nboth a tool and a server pattern also produce warnings rather than failing\nthe scan.\n\n## Architecture\n\n```\nsrc/\n  cli/        Command-line entry point (commander): scan, snapshot, drift\n  core/       Shared types; auditor (runs rules over discovered files);\n              compliance (scoring + Markdown report rendering, with\n              suspicious code points escaped); snapshot (canonical\n              hashing, baseline load/save, diffing)\n  discovery/  Glob-based file discovery and JSON parsing — filesystem\n              reads only, with graceful degradation to warnings\n  rules/      Rule interfaces and registries; one file per rule\n              (input-validation, text-sanitizer, network-bounds)\n```\n\nRules implement a small `check(definition, context) → Finding[]` interface\nand are registered in `src/rules/index.ts`; the auditor iterates the\nregistries, so adding a rule is one new file plus one registry entry.\nTests live alongside their subjects as `src/**/*.test.ts` and run on\nNode's built-in test runner.\n\n## Scoring\n\nScores start at 100 and subtract severity weights (critical 50, high 30,\nmedium 15, low 5, info 0), dampened by 1/√n for repeated findings from the\nsame rule so one noisy rule doesn't dominate. Grades: A ≥ 90, B ≥ 75,\nC ≥ 60, D ≥ 40, otherwise F.\n","readmeFilename":"README.md","_rev":"1-b3c2838ce07e2be2c1b6929433c510d4"}