mcp-guard-py 0.3.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. mcp_guard_py-0.3.1/LICENSE +21 -0
  2. mcp_guard_py-0.3.1/PKG-INFO +391 -0
  3. mcp_guard_py-0.3.1/README.md +349 -0
  4. mcp_guard_py-0.3.1/mcp_guard/__init__.py +8 -0
  5. mcp_guard_py-0.3.1/mcp_guard/cli.py +398 -0
  6. mcp_guard_py-0.3.1/mcp_guard/formatters.py +206 -0
  7. mcp_guard_py-0.3.1/mcp_guard/injection.py +517 -0
  8. mcp_guard_py-0.3.1/mcp_guard/models.py +110 -0
  9. mcp_guard_py-0.3.1/mcp_guard/npm_scanner.py +207 -0
  10. mcp_guard_py-0.3.1/mcp_guard/parser.py +718 -0
  11. mcp_guard_py-0.3.1/mcp_guard/policy.py +163 -0
  12. mcp_guard_py-0.3.1/mcp_guard/py.typed +0 -0
  13. mcp_guard_py-0.3.1/mcp_guard/rules.py +420 -0
  14. mcp_guard_py-0.3.1/mcp_guard/scanner.py +52 -0
  15. mcp_guard_py-0.3.1/mcp_guard/supply_chain.py +414 -0
  16. mcp_guard_py-0.3.1/mcp_guard_py.egg-info/PKG-INFO +391 -0
  17. mcp_guard_py-0.3.1/mcp_guard_py.egg-info/SOURCES.txt +34 -0
  18. mcp_guard_py-0.3.1/mcp_guard_py.egg-info/dependency_links.txt +1 -0
  19. mcp_guard_py-0.3.1/mcp_guard_py.egg-info/entry_points.txt +2 -0
  20. mcp_guard_py-0.3.1/mcp_guard_py.egg-info/requires.txt +17 -0
  21. mcp_guard_py-0.3.1/mcp_guard_py.egg-info/top_level.txt +1 -0
  22. mcp_guard_py-0.3.1/pyproject.toml +97 -0
  23. mcp_guard_py-0.3.1/setup.cfg +4 -0
  24. mcp_guard_py-0.3.1/tests/test_auth_detection.py +433 -0
  25. mcp_guard_py-0.3.1/tests/test_cli.py +536 -0
  26. mcp_guard_py-0.3.1/tests/test_deny_rules.py +445 -0
  27. mcp_guard_py-0.3.1/tests/test_issue_101_nominal_destructive_keywords.py +89 -0
  28. mcp_guard_py-0.3.1/tests/test_issue_37_38_39.py +147 -0
  29. mcp_guard_py-0.3.1/tests/test_issue_fixes.py +315 -0
  30. mcp_guard_py-0.3.1/tests/test_markup_escaping.py +129 -0
  31. mcp_guard_py-0.3.1/tests/test_mcp_guard.py +899 -0
  32. mcp_guard_py-0.3.1/tests/test_npm_scanner.py +295 -0
  33. mcp_guard_py-0.3.1/tests/test_parser_errors.py +90 -0
  34. mcp_guard_py-0.3.1/tests/test_parser_yaml_js.py +188 -0
  35. mcp_guard_py-0.3.1/tests/test_prompt_injection.py +694 -0
  36. mcp_guard_py-0.3.1/tests/test_supply_chain.py +583 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yunare Maia
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,391 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-guard-py
3
+ Version: 0.3.1
4
+ Summary: Security scanner for MCP servers - audit capabilities, detect risks
5
+ Author-email: Yunare Maia <yunare@gmail.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yunaremaia/mcp-guard
8
+ Project-URL: Repository, https://github.com/yunaremaia/mcp-guard
9
+ Project-URL: Issues, https://github.com/yunaremaia/mcp-guard/issues
10
+ Project-URL: Changelog, https://github.com/yunaremaia/mcp-guard/blob/main/CHANGELOG.md
11
+ Keywords: mcp,security,scanner,ai-agent,audit
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Programming Language :: Python :: 3.14
21
+ Classifier: Topic :: Security
22
+ Classifier: Topic :: Software Development :: Quality Assurance
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: click>=8.1
27
+ Requires-Dist: rich>=13.0
28
+ Requires-Dist: pydantic>=2.0
29
+ Requires-Dist: rapidfuzz>=3.0
30
+ Requires-Dist: pyyaml>=6.0
31
+ Provides-Extra: canary
32
+ Requires-Dist: little-canary<0.5,>=0.4.0; extra == "canary"
33
+ Provides-Extra: dev
34
+ Requires-Dist: pytest>=7.0; extra == "dev"
35
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
36
+ Requires-Dist: ruff>=0.1; extra == "dev"
37
+ Requires-Dist: mypy>=1.0; extra == "dev"
38
+ Requires-Dist: pyright>=1.1.400; extra == "dev"
39
+ Requires-Dist: types-PyYAML>=6.0; extra == "dev"
40
+ Requires-Dist: little-canary<0.5,>=0.4.0; extra == "dev"
41
+ Dynamic: license-file
42
+
43
+ # MCP Guard
44
+
45
+ **Security scanner for MCP servers** — audit capabilities, detect risks, generate security reports.
46
+
47
+ ![CI](https://github.com/yunaremaia/mcp-guard/actions/workflows/ci.yml/badge.svg) ![Docker](https://github.com/yunaremaia/mcp-guard/actions/workflows/docker.yml/badge.svg) ![License](https://img.shields.io/github/license/yunaremaia/mcp-guard) ![Python](https://img.shields.io/badge/python-3.10%2B-blue) ![Release](https://img.shields.io/github/v/release/yunaremaia/mcp-guard)
48
+
49
+ ## Why
50
+
51
+ The MCP ecosystem exploded (67,000+ servers in 18 months), but security hasn't kept up:
52
+ - 87% of MCP servers fail high-trust thresholds
53
+ - 72% expose sensitive capabilities unnecessarily
54
+ - 53% rely on static API keys
55
+
56
+ **MCP Guard** helps you audit MCP servers before connecting agents to them.
57
+
58
+ ## Install
59
+
60
+ `mcp-guard` is not published on PyPI. Install it directly from the repository:
61
+
62
+ ```bash
63
+ pip install git+https://github.com/yunaremaia/mcp-guard.git
64
+ ```
65
+
66
+ Requires Python 3.10 or newer.
67
+
68
+ Alternatively, run it without installing via Docker:
69
+
70
+ ```bash
71
+ docker run --rm -v "$PWD:/work" ghcr.io/yunaremaia/mcp-guard:latest scan /work/my-mcp-server
72
+ ```
73
+
74
+ ## Quick Start
75
+
76
+ _Get started in 5 minutes_:
77
+
78
+ ```bash
79
+ # Scan an MCP server directory
80
+ mcp-guard scan ./my-mcp-server
81
+
82
+ # Scan a specific config file
83
+ mcp-guard scan ./mcp.json
84
+
85
+ # Output as JSON
86
+ mcp-guard scan ./my-mcp-server --format json
87
+
88
+ # Output as SARIF (for GitHub Code Scanning)
89
+ mcp-guard scan ./my-mcp-server --format sarif --output results.sarif
90
+
91
+ # Fail CI if HIGH or CRITICAL findings
92
+ mcp-guard scan ./my-mcp-server --fail-on high
93
+
94
+ # Audit every MCP server installed as an npm dependency under node_modules
95
+ mcp-guard scan ./my-project --npm --format json
96
+
97
+ # Enforce security deny rules from a YAML config
98
+ mcp-guard scan ./my-mcp-server --config policy.yaml --deny
99
+
100
+ # Deny specific servers or tools on the fly
101
+ mcp-guard scan ./my-mcp-server --deny-server "untrusted-*" --deny
102
+
103
+ # Add Little Canary's structural filter to prompt injection checks
104
+ # (requires: pip install "mcp-guard[canary] @ git+https://github.com/yunaremaia/mcp-guard.git")
105
+ mcp-guard scan ./my-mcp-server --strict-injection
106
+
107
+ # Verify npm supply chain (sigstore attestations / provenance)
108
+ mcp-guard verify @modelcontextprotocol/server-memory
109
+
110
+ # Enforce a strict policy: fail if the package is unsigned (no provenance)
111
+ mcp-guard verify @scope/mcp-server@1.2.0 --policy strict --format json
112
+
113
+ # Show server info without scanning
114
+ mcp-guard info ./my-mcp-server
115
+ ```
116
+
117
+ ## npm package scanning
118
+
119
+ MCP servers are commonly published to npm (`@modelcontextprotocol/server-*`,
120
+ `@mcp/*`, `mcp-*`) and ship an `mcp.json` (or another known config name) next to
121
+ their code. Point `scan` at a project root with `--npm` to audit the MCP surface a
122
+ project pulls in:
123
+
124
+ ```bash
125
+ # Report the MCP-related dependencies in package.json and scan every MCP
126
+ # config found under node_modules/ in JSON
127
+ mcp-guard scan ./my-project --npm --format json
128
+
129
+ # Emit a multi-run SARIF document for GitHub Code Scanning
130
+ mcp-guard scan ./my-project --npm --format sarif --output results.sarif
131
+
132
+ # Fail CI if any installed server trips a deny rule
133
+ mcp-guard scan ./my-project --npm --deny-server "untrusted-*" --deny
134
+ ```
135
+
136
+ With `--npm`, the path is treated as a **project root** rather than a single
137
+ manifest:
138
+
139
+ - MCP-related dependencies are listed from `package.json`
140
+ (`dependencies`, `devDependencies`, `optionalDependencies`).
141
+ - Every `mcp.json` / `mcp.config.json` / `.mcp.json` / `server.json` under
142
+ `node_modules/` is scanned; the owning npm package is attributed to each result.
143
+ - A manifest that cannot be parsed is **skipped and reported, not fatal**.
144
+ - `--deny`, `--fail-on`, `--config` and the JSON / SARIF / CLI output formats all
145
+ apply to the aggregated result set.
146
+
147
+ Discovery is filesystem-only: it never runs `npm` or `node`, never executes a
148
+ discovered manifest, and makes no network call (the same offline posture as the
149
+ supply-chain verifier).
150
+
151
+ ## Supported config formats
152
+
153
+ `mcp-guard scan <file>` (and `MCPParser.from_file`) auto-detects the format from the file extension:
154
+
155
+ - **`.json`** — standard JSON manifest; the default.
156
+ - **`.yaml` / `.yml`** — YAML manifest (parsed with a safe loader, no code execution).
157
+ - **`.js`** — a JavaScript object-literal config (`module.exports = { ... }` or `export default { ... }`). The body is read as a JSON-compatible object literal and is **never executed**, so executable JS bodies are not supported. Keys and string values must use double quotes, as in JSON.
158
+
159
+ Directories (the `scan ./my-mcp-server` form) still look for a known JSON config file such as `mcp.json`; pass a YAML or `.js` file directly to use those formats.
160
+
161
+ ## Deny Rules & Policy Enforcement
162
+
163
+ You can configure deny rules in a YAML file (e.g. `policy.yaml` or default `mcp-guard.yaml`). Deny rules support exact matches, wildcards (`*`), and tool-level scoping:
164
+
165
+ ```yaml
166
+ # Security Policy Configuration
167
+ deny:
168
+ # Block unverified or untrusted servers
169
+ servers:
170
+ - "malicious-server"
171
+ - "github-*"
172
+ # Block high-risk tools (exact name, wildcard, or scoped to server)
173
+ tools:
174
+ - "github/delete_repo"
175
+ - "filesystem/write"
176
+ - "sys_*"
177
+ ```
178
+
179
+ Use the `--deny` flag to fail with exit code 1 whenever any denied server or tool is detected:
180
+
181
+ ```bash
182
+ mcp-guard scan ./my-mcp-server --config policy.yaml --deny
183
+ ```
184
+
185
+ ## Supply Chain Verification
186
+
187
+ `mcp-guard verify` checks whether an npm-distributed MCP server was published
188
+ with **sigstore attestations** (provenance / SLSA). It queries the npm registry
189
+ for the attestations attached to a package version and reports whether the
190
+ artifact you are about to run was built with provenance:
191
+
192
+ ```bash
193
+ # Unscoped, scoped, pinned or floating version references all work
194
+ mcp-guard verify some-mcp-server
195
+ mcp-guard verify @scope/some-mcp-server@1.2.0
196
+
197
+ # Machine-readable output for CI pipelines
198
+ mcp-guard verify @scope/some-mcp-server --format json
199
+
200
+ # Strict policy: exit code 1 when the version is unsigned
201
+ mcp-guard verify @scope/some-mcp-server --policy strict
202
+ ```
203
+
204
+ Statuses:
205
+
206
+ | status | meaning |
207
+ |---|---|
208
+ | `signed` | sigstore attestations found (and whether one is a SLSA provenance statement) |
209
+ | `unsigned` | the version exists but no attestations were published with it |
210
+ | `not_found` | the package does not exist on the registry |
211
+ | `registry_error` | the registry could not be reached or answered unexpectedly |
212
+
213
+ Exit codes: `0` when verified signed (or in report mode); `1` when the package
214
+ is unsigned under `--policy strict`, when it is not found, or on registry
215
+ errors — ready to gate CI jobs.
216
+
217
+ Notes:
218
+
219
+ - No new runtime dependencies: the verifier uses only the standard library
220
+ (`urllib`), and the network layer is injectable, so the test suite stays
221
+ fully offline.
222
+ - Verification currently covers npm packages. PyPI (PEP 740 attestations),
223
+ Docker (cosign / SBOM) and reproducible-build checks are tracked as
224
+ follow-ups in [#74](https://github.com/yunaremaia/mcp-guard/issues/74).
225
+
226
+ ## What It Detects
227
+
228
+ | Rule | Level | Description |
229
+ |------|-------|-------------|
230
+ | MCP001 | HIGH | Write operation without authentication |
231
+ | MCP002 | CRITICAL | Destructive operation without authentication |
232
+ | MCP003 | MEDIUM | Capability with excessive permissions |
233
+ | MCP004 | LOW | Capability without description |
234
+ | MCP005 | MEDIUM | Write capability without corresponding read |
235
+ | MCP006 | HIGH | Destructive operation without confirmation |
236
+ | MCP007 | MEDIUM / HIGH / CRITICAL | Explicitly disabled authentication ('auth': false) |
237
+ | MCP008 | LOW / MEDIUM / HIGH | Possible prompt injection in server or capability metadata |
238
+ | MCP009 | HIGH | Command execution without authentication |
239
+ | DENY001 | CRITICAL | Server matches security policy deny rule |
240
+ | DENY002 | CRITICAL | Tool capability matches security policy deny rule |
241
+
242
+ ### Authentication Detection Semantics
243
+
244
+ `mcp-guard` validates that capability authentication fields contain truthy configuration rather than mere key presence:
245
+
246
+ - **Auth Required**: Detected when `auth`, `authorization`, or `security` is present with a truthy value (`true`, configuration object/dict, non-empty string, or non-empty list).
247
+ - **Auth Explicitly Disabled**: Flagged when `auth` or `authorization` is set to `false` or `"disabled"`. Capabilities explicitly disabling authentication trigger rule `MCP007` and cannot bypass `MCP001` (write) or `MCP002` (destructive) checks.
248
+ - **No Auth Field / Falsy**: Falsy values like `null`, `""`, `0`, or `{}` are treated as unauthenticated.
249
+ - **SARIF Integration**: SARIF 2.1.0 output records `properties.auth_status` as `"required"`, `"disabled"`, or `"unknown"` for each capability finding.
250
+
251
+
252
+ ### Prompt Injection Detection (MCP008)
253
+
254
+ MCP clients pass server and tool metadata to the model, so instructions hidden there act like
255
+ part of the prompt. `MCP008` checks the server name and description, every capability name and
256
+ description, and every key and string value in `inputSchema` (parameter names, descriptions,
257
+ titles, `enum`/`default` values, nested objects, array `items`, `anyOf`/`$defs`). `$ref` is not
258
+ resolved; local definitions are scanned where they appear.
259
+
260
+ - **HIGH**: direct injection phrasing, e.g. "ignore previous instructions", "override safety
261
+ checks", "you are now ...", "DAN mode", chat-template tokens such as `<|im_start|>`,
262
+ "do not tell the user".
263
+ - **MEDIUM**: suspicious phrasing with legitimate uses, e.g. a bare "jailbreak", `<IMPORTANT>`
264
+ tags, a line starting with `system:`, directions to read files such as `~/.ssh/id_rsa`, and
265
+ invisible Unicode (zero-width, bidi, tag characters). A HIGH pattern inside quotes (for
266
+ example a security tool describing an attack) is reported as MEDIUM with `quoted: "true"`,
267
+ never suppressed.
268
+ - **LOW**: a field longer than 65,536 characters or a schema nested deeper than 64 levels;
269
+ the remainder is not scanned.
270
+
271
+ Text is normalized before matching: invisible characters are removed, Unicode tag characters
272
+ are decoded to the ASCII they hide, and full-width lookalikes are folded (NFKC).
273
+
274
+ `--strict-injection` also runs [Little Canary](https://github.com/hermes-labs-ai/little-canary)'s
275
+ `StructuralFilter`. It adds a broader signature set and decodes base64/hex/ROT13 payloads
276
+ before re-checking them. It is deterministic pattern matching. It makes no model, API or
277
+ network calls and needs the optional `canary` extra. Strict mode finds more and has more false
278
+ positives (for example `sudo` or "developer mode" in a shell tool's description).
279
+
280
+ To keep scan time linear, the filter sees each field in overlapping 2,000-character windows
281
+ (200-character overlap). A Little Canary match longer than 200 characters that crosses a window
282
+ boundary can be missed. Base64 and hex tokens longer than 200 characters are decoded whole by
283
+ mcp-guard instead, and the decoded text is checked by both detectors. A long token nested
284
+ inside a decoded token is not decoded again. Cue words that enable ROT13 and reversed-text
285
+ decoding ("rot13", "reverse", ...) are passed to every window of the field. ROT13 or reversed
286
+ text longer than 200 characters can still be split across windows.
287
+
288
+ These are pattern matches, not proof of intent, and they do not catch rephrased or novel
289
+ injections. On the hand-written benign fixture in `tests/fixtures/benign_tools.json` (121
290
+ tools), the default mode flags 5 tools (4.13%, all MEDIUM) and strict mode flags 6 (4.96%).
291
+ Those rates describe that fixture only.
292
+
293
+ In JSON and SARIF output each MCP008 finding has `injection_type` (e.g. `instruction-override`,
294
+ `safety-bypass`, `role-hijack`, `jailbreak`, `fake-authority`, `concealment`,
295
+ `prompt-extraction`, `exfiltration`, `hidden-characters`, `encoded-payload`),
296
+ `metadata_field` (e.g. `inputSchema.properties.path.description`), `detector`
297
+ (`mcp-guard` or `little-canary`), `evidence` and `quoted` properties.
298
+
299
+ ### Command Execution Detection (MCP009)
300
+
301
+ "Runs arbitrary code" is a different trust boundary from "mutates data" (`is_write`) and
302
+ "loses data" (`is_destructive`), so command execution gets its own classification: a shell
303
+ tool neither writes nor destroys, and MCP001's "performs write operations" text would be
304
+ false in its output. `MCP009` fires at HIGH when a capability with no authentication matches
305
+ the execution family — `exec`, `execute`, `eval`, `spawn`, `shell`, `bash`, `cmd`, `command`,
306
+ `subprocess`, `popen`, `terminal` — as whole identifier segments or inflected description
307
+ words, exactly like MCP001/MCP002. Read-verb suppression applies, so `get_exec_summary` and
308
+ `get_command_history` stay unflagged, while `get_and_exec` would still match (`and` marks a
309
+ second operation). `run` and `evaluate` are deliberately excluded: measured against this
310
+ repo's own 121-tool corpus, they add read-shaped false positives (`run_query`,
311
+ `evaluate_model`) without catching any execution name the shell/process nouns miss.
312
+
313
+ Known residuals, accepted on purpose: `execute_workflow` and `execute_sql` flag (executing a
314
+ caller-supplied workflow or SQL string is running arbitrary logic), and a description like
315
+ "List the available commands" on a neutral name can trip the phrase match — the same
316
+ description-phrase artifact MCP001/MCP002 have. The rule is not coupled into MCP005 (a shell
317
+ has no meaningful "corresponding read") or MCP006 (a confirmation field does not make an
318
+ unauthenticated shell safe; authentication does).
319
+
320
+ ## Example Output
321
+
322
+ ```
323
+ MCP Server
324
+ test-server v1.0.0
325
+ A test MCP server
326
+
327
+ Risk Score: CRITICAL
328
+
329
+ Summary
330
+ Total Capabilities 3
331
+ Critical 1
332
+ High 1
333
+ Medium 0
334
+ Low 0
335
+
336
+ Findings
337
+ Rule Level Capability Message Suggestion
338
+ MCP002 CRITICAL delete_database Destructive operation without auth Add authentication
339
+ MCP001 HIGH create_user Write operation without auth Add authentication
340
+ ```
341
+
342
+ ## CI Integration
343
+
344
+ ### GitHub Action
345
+
346
+ ```yaml
347
+ name: MCP Security Scan
348
+ on: [push, pull_request]
349
+ jobs:
350
+ scan:
351
+ runs-on: ubuntu-latest
352
+ steps:
353
+ - uses: actions/checkout@v4
354
+ - uses: actions/setup-python@v5
355
+ with:
356
+ python-version: "3.11"
357
+ - run: pip install git+https://github.com/yunaremaia/mcp-guard.git
358
+ - run: mcp-guard scan ./mcp-server --format sarif --output results.sarif
359
+ - uses: github/codeql-action/upload-sarif@v3
360
+ with:
361
+ sarif_file: results.sarif
362
+ ```
363
+
364
+ If this tool is useful to you, a star helps other people find it.
365
+
366
+ ## Related tools
367
+
368
+ - **[driftcheck](https://github.com/yunaremaia/driftcheck)** — detect version drift between docs and toolchain files
369
+ - **[context-bridge](https://github.com/yunaremaia/context-bridge)** — persistent session memory for AI agents
370
+ - **[mcp-reconcile](https://github.com/yunaremaia/mcp-reconcile)** — reconcile conflicting MCP server definitions
371
+ - **[tool-call-retry](https://github.com/yunaremaia/tool-call-retry)** — retry failed tool calls with backoff
372
+
373
+ Part of a family of focused, single-purpose developer tools — each one does one thing
374
+ and does it well.
375
+
376
+ ## License
377
+
378
+ MIT
379
+
380
+ ## Sponsoring / Treasury
381
+
382
+ This project is MIT licensed and free to use. If you want to support its
383
+ maintenance, you can sponsor on GitHub or contribute to the development
384
+ treasury wallet on Solana:
385
+
386
+ - GitHub Sponsors: https://github.com/sponsors/yunaremaia
387
+ - Solana: [`Eeztv1nCYUt1fwGWpzKC948gaWfjejYCAuLtUMgzDWbW`](https://solana.com/solana-wallet?base=SOL&address=Eeztv1nCYUt1fwGWpzKC948gaWfjejYCAuLtUMgzDWbW)
388
+
389
+ ## Trust boundary
390
+
391
+ Treat MCP tool responses as untrusted input until validated by your agent policy.