Claude Code, Skill
toolsmelt
Turn an OpenAPI file, a website, an app, a Postman collection or a database into curated, tested MCP tools.
Compatibility: Not stated.
Grade C
One Medium finding. Read the report before installing.
Not a guarantee. A hygiene check of the source at the commit shown, not a security audit.
NETWORK_HOST_FROM_INPUT
Why this grade
- NETWORK_HOST_FROM_INPUT Medium
A file takes a URL or endpoint as input and has no fixed host list.
src/toolsmelt/browser.py, line 51
r = httpx.get(f"http://127.0.0.1:{port}/json/version", timeout=2, trust_env=False)
Any High, or two or more Medium findings, give D. One Medium gives C. Low findings or a security Note give B. Each code names a finding behind the letter.
Grades are a hygiene check of the source at the commit shown, on the date checked, not a security audit or a guarantee. The free directory grades are automated. Before release, a PlugVet engineer reviews every paid report and any grade we hold back, including all F grades, against the source code and the evidence we quote.
What was checked
Plain notes from the hygiene checks.
Permissions
Concern
can delete files.
PERMISSION_DELETE_FILES
src/toolsmelt/browser.py, line 94
subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, **detach)
src/toolsmelt/codegen.py, line 75
shutil.rmtree(path)
src/toolsmelt/codegen.py, line 92
subprocess.run([ruff, "format", "--quiet", "--no-cache", *map(str, paths)], check=False, capture_output=True)
Show more
src/toolsmelt/hub.py, line 98
shutil.rmtree(dest, ignore_errors=True)
src/toolsmelt/hub.py, line 110
shutil.rmtree(self._dir(name), ignore_errors=True)
src/toolsmelt/importers/jadx.py, line 71
proc = subprocess.run(args, cwd=CACHE, capture_output=True, text=True, errors="replace")
src/toolsmelt/importers/jadx.py, line 77
shutil.rmtree(tmp, ignore_errors=True)
src/toolsmelt/importers/jadx.py, line 84
shutil.rmtree(tmp, ignore_errors=True)
src/toolsmelt/setup/run.py, line 177
def apply(changes, runner=subprocess.run) -> list[str]:
src/toolsmelt/setup/run.py, line 197
shutil.rmtree(dest)
src/toolsmelt/setup/run.py, line 290
def cmd(args, home=None, environ=None, which=shutil.which, runner=subprocess.run, stdin=None) -> int:
docs/superpowers/plans/2026-10-21-app-path-task2.md, line 42
- `android.rea_class_source(apk: Path, class_name: str, runner=subprocess.run) -> str` - thin wrapper that asks REA for a class's source; raises `RuntimeError` with REA's install/c
docs/superpowers/plans/2026-10-21-app-path-task2.md, line 43
- `android.find_api_classes(apk: Path, runner=subprocess.run) -> list[str]` - class names whose code contains a path-like string (`"api/`, `"/v1/`, …), via REA's code search.
docs/superpowers/plans/2026-10-21-hub-core.md, line 139
- [ ] **Step 1: Failing tests** against `fake_cdp`: `status()` returns the json when the fake answers, `None` otherwise; `cookies_for("za.example.test")` returns only matching-doma
Install and update
Pass
No install-time script found, and dependencies are pinned or absent.
Network
Serious
accepts a host from input, with no fixed list in this file.
NETWORK_HOST_FROM_INPUT
src/toolsmelt/browser.py, line 51
r = httpx.get(f"http://127.0.0.1:{port}/json/version", timeout=2, trust_env=False)
src/toolsmelt/importers/__init__.py, line 64
resp = httpx.get(path_or_url, follow_redirects=True, timeout=60, verify=tls_context())
src/toolsmelt/importers/curl.py, line 31
"""True when the first line that is not blank or a comment is a curl command."""
Show more
src/toolsmelt/importers/curl.py, line 34
return line.lstrip().startswith("curl ")
src/toolsmelt/importers/curl.py, line 42
raise ValueError("no curl command with an http(s) URL found" + (f" ({'; '.join(notes)})" if notes else ""))
src/toolsmelt/importers/curl.py, line 50
"""The words of each curl command in the text."""
src/toolsmelt/importers/curl.py, line 56
raise ValueError(f"cannot read the curl commands: {e}") from e
src/toolsmelt/importers/curl.py, line 104
"""A HAR entry for one curl command; None (with a note) when it has no URL."""
src/toolsmelt/importers/curl.py, line 184
# curl shows no response; a JSON one is assumed so the HAR rules keep every call
src/toolsmelt/importers/electron.py, line 209
text = _blank_comments(text) # a comment saying "fetch (like..." is not a call
src/toolsmelt/runtime/http.py, line 69
"""The Chrome profile sends navigation-only headers; a None value makes curl drop them (API calls are XHR)."""
src/toolsmelt/runtime/http.py, line 356
if self.impersonate and (curl := _curl()):
src/toolsmelt/runtime/oauth.py, line 54
r = http.get(url)
src/toolsmelt/runtime/oauth.py, line 79
r = await http.get(self.jwks_url)
src/toolsmelt/runtime/sql.py, line 161
def fetch(self, sql: str, params: dict[str, Any], read_only: bool, max_rows: int) -> Any:
docs/superpowers/plans/2026-10-21-app-path-task3.md, line 7
**Architecture:** The app ships its JavaScript, and usually its original sources inside `.map` files (`sourcesContent`). mcpsmith reads those files, prefers the original sources wh
Secrets
Note
reads an environment variable.
SECRETS_ENV_READ
src/toolsmelt/runtime/server.py, line 118
token = os.environ.get("MCP_AUTH_TOKEN", "")
Agent instructions
Pass
No instruction to ignore earlier instructions or to hide a step.
Obfuscation
Note
a file was over the read cap and was not fully read.
OBFUSCATION_FILE_OVER_READ_CAP
uv.lock, line 1
version = 1
Licence
Pass
A licence file is present (LICENSE).
Maintainer activity
Pass
The latest commit is within the last 365 days.
Note
Hygiene check of commit b5c7518bc6f9. can delete files. accepts a host from input, with no fixed list in this file. reads an environment variable. a file was over the read cap and was not fully read.
Date and source
Date checked:
github.com
Commit graded: b5c7518bc6f947e4785b6c6da780601bd38bbfff
This link goes to the original host. PlugVet does not host or check what you download from there, and installing it is your own decision and risk.