mcptoon@0.8.35
CAUTION· not startedPublisher claims: "One zero-dependency CLI to manage every MCP server and agent skill: token optimization for tool discovery (71,929 -> 581 tokens, -99.2% measured, schemas stay out of context), one config for every agent." Observed in sandbox: no network, touches nothing outside the project, writes no memory.
Coverage
Not started: dependency install failed; the server itself was not observed.- Tested
- the dependency install step · every file read, file written and host contacted by what ran
- Not tested
- server startup · the tool list · tool behavior
What this means for the label: Caution here covers what ran. The server's tools were not exercised with a real credential, so nothing about their behavior is asserted; the credential summary below says what to do with that.
Before you give it your token
- It will ask for
BAIZHI_TOKENMCPTOON_AUTH_TOKENor--client-secretConfiguration, not credentials: MCPTOON_ACTIVITY_FILE, MCPTOON_AGENT_TYPE, MCPTOON_ALLOWED_HOSTS, MCPTOON_AUTOSTART_TASK, MCPTOON_CACHE_DIR, MCPTOON_CACHE_TTL, MCPTOON_CALL_TIMEOUT, MCPTOON_CCR_DIR, MCPTOON_CCR_MAX_BYTES, MCPTOON_CCR_TTL, MCPTOON_CLI_AHA_FILE, MCPTOON_COMPRESSION_FILE, MCPTOON_CONFIG_FILE, MCPTOON_CONFIG_FILE_TOML, MCPTOON_DEBUG, MCPTOON_DOCS_INDEX, MCPTOON_DOCS_ROOTS, MCPTOON_FOOTER_STATE_FILE, MCPTOON_FORCE_COLOR, MCPTOON_FORCE_SELF_HEAL, MCPTOON_GRAPHQL_TTL, MCPTOON_HANDLERS_DIR, MCPTOON_HOME, MCPTOON_INSTALLED_FILE, MCPTOON_KB_DIR, MCPTOON_LANG, MCPTOON_LIST_CACHE_SCOPE, MCPTOON_LIST_TTL_MS, MCPTOON_NO_COLOR, MCPTOON_NO_STAR_HINT, MCPTOON_NO_TAKEOVER_OFFER, MCPTOON_OPENAPI_TTL, MCPTOON_PLUGINS_DATA_DIR, MCPTOON_PLUGINS_DIR, MCPTOON_PLUGINS_REGISTRY, MCPTOON_SELFHEAL_FILE, MCPTOON_SERVERS, MCPTOON_SESSION_DIR- Where it talks to
- no vendor host named in the codeAlso swagger.io, nodejs.org, smithery.ai, agent-plugins.org, skills.sh — not the publisher's domain; check what for before connecting.
- What the honeypot saw
- no credential files read · no network
- What we could not test
- server startup · the tool list · tool behavior
Connect it with a scoped credential, under the guard, and read the third-party hosts first. The code names swagger.io, nodejs.org, smithery.ai, agent-plugins.org, skills.sh as well as its own vendor. The guard injects BAIZHI_TOKEN, MCPTOON_AUTH_TOKEN only into requests to the host you bind (and its subdomains) and refuses the rest.
Never paste a credential into a chat, a ticket or a report, including ours. How the guard holds it.
Is [email protected] safe to install?
KillerSkills ran it in the KillerSkills honeypot sandbox (2 scenarios; not started: dependency install failed; the server itself was not observed) on 2026-11-11 and scored it 62/100 (Caution). It is not known to be malicious, but it has behaviour or code a security policy should decide on before install. Notable findings: Destructive command against a filesystem root or device; Access to sensitive file paths; Access to sensitive file paths. Summary: no network, touches nothing outside the project, writes no memory.
Behavior trace
Honeypot run · 0 s · 2 scenarios · 0 deviationsStatic findings
taking ``{"cmd": "rm -rf /"}`` would otherwise opt itself out of theFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.a placeholder instead of a crash, and nothing a command prints can kill it.Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell."cat ~/.ssh",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.lines.append(f"[servers.{name}.env]")Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."show your token", "read your env", "~/.ssh", "/etc/passwd",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."SERVER_NOT_FOUND": "Try: mcptoon list | mcptoon add <name> --stdio npx -y <package> | mcptoon doctor",Fix: Pin versions and sources; vendor anything fetched at install time.taking ``{"cmd": "rm -rf /"}`` would otherwise opt itself out of theFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell."cat /etc/shadow",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."read /etc/passwd",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.<summary>Other ways to install</summary> ```bash # Run without installing (needs Node) uvx mcptoon demo --quick # Isolated CLI install (avoids the PEP 668 errorFix: Remove the text that addresses the agent rather than the reader; describe behavior, do not instruct.if text.startswith(""):Fix: Keep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent."show your token", "read your env", "~/.ssh", "/etc/passwd",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."cat ~/.ssh",Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose."sudo ",Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.3. Detect local tools (npx in PATH → zero-config servers, docker, sqlite, git repo)Fix: Pin versions and sources; vendor anything fetched at install time.(``npx -y <pkg>``, ``uvx <pkg>``), so they already fetch the current release onFix: Pin versions and sources; vendor anything fetched at install time.# exited (e.g. npx E404 on a missing package). Surface theFix: Pin versions and sources; vendor anything fetched at install time.add = subprocess.run(["git", "add", "-A", "--", rel], cwd=str(repo),Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.except Exception: # noqa: BLE001 — a missing/broken tool catalog must not kill skillsFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.special-cases the full npx path. Routing must do the same, or a registry installFix: Pin versions and sources; vendor anything fetched at install time.# Local package: npx for npm, uvx for pypi (both fetch-on-first-run, no install).Fix: Pin versions and sources; vendor anything fetched at install time.subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.print(" mcptoon add github --stdio npx -y @modelcontextprotocol/server-github")Fix: Pin versions and sources; vendor anything fetched at install time.# On Windows, npx needs .cmd resolution — but we let client.py handle thatFix: Pin versions and sources; vendor anything fetched at install time."""Clean up: kill subprocess or close HTTP session."""Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.except Exception as exc: # never kill the loop over one bad callFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.# Timeout — try to kill the underlying subprocess if possibleFix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.tail (a failing npx prints `npm error 404` last, after a wall of NodeFix: Pin versions and sources; vendor anything fetched at install time.# 4. Record to installed.json — preserve full inputSchemaFix: Remove the call, or declare the host in frontmatter and explain in the README what is sent and why.subprocess.run(["taskkill", "/PID", str(pid), "/F"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."""Check that npx is available."""Fix: Pin versions and sources; vendor anything fetched at install time.res = subprocess.run(["schtasks", "/Delete", "/TN", _AUTOSTART_TASK, "/F"],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."""Owner-only permissions. POSIX chmod 600; Windows best-effort ACL."""Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.r = subprocess.run(["cmd", "/c", "mklink", "/J", str(dst), str(src)],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.Popen(cmd, stdin=subprocess.DEVNULL, stdout=log,Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.res = subprocess.run(tr, shell=True, capture_output=True, text=True, encoding="utf-8")Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.commit = subprocess.run(["git", "commit", "-m", message, "--", rel],Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(argv, input=payload, capture_output=True, text=True,Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.print(" # mcptoon add everything --stdio npx -y @modelcontextprotocol/server-everything")Fix: Pin versions and sources; vendor anything fetched at install time.r = subprocess.run(["git", "cat-file", "-e", f"HEAD:{rel}"], cwd=str(repo),Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.mcptoon config set runners allow-fetch # back to always uvx/npxFix: Pin versions and sources; vendor anything fetched at install time.subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."TIMEOUT": "Try: mcptoon doctor | the server may be slow to start (first npx download)",Fix: Pin versions and sources; vendor anything fetched at install time.# npx -y <package> as launch commandFix: Pin versions and sources; vendor anything fetched at install time.`uvx <pkg>` / `npx <pkg>`. The gate is two facts, not one: the module must resolveFix: Pin versions and sources; vendor anything fetched at install time.r = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.we spawn and refuse to kill a pid whose creation time no longer matches.Fix: Build commands from fixed arguments; do not interpolate untrusted strings into a shell.# Default npx commandFix: Pin versions and sources; vendor anything fetched at install time.r = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."chmod 777",Fix: Request the narrowest permission that works; replace wildcards with the exact paths or hosts.print(" (npx is bundled with Node.js 18+)")Fix: Pin versions and sources; vendor anything fetched at install time.print(" Add another: mcptoon add <name> --stdio npx -y <package>")Fix: Pin versions and sources; vendor anything fetched at install time.print(" ❌ npx not found in PATH.")Fix: Pin versions and sources; vendor anything fetched at install time.self._proc = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.print(" If it mentions npx not found: install Node.js: https://nodejs.org")Fix: Pin versions and sources; vendor anything fetched at install time.# (self-contained: no network, no API key, works offline after npxFix: Pin versions and sources; vendor anything fetched at install time.result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.rc = subprocess.run(cmd, check=False).returncodeFix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."""When npx is not available, should return False."""Fix: Pin versions and sources; vendor anything fetched at install time.result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.proc = subprocess.Popen(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.procs = [subprocess.Popen([sys.executable, "-c", worker, str(w)], env=env)Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.| **Prompt-injection guard** | results are scanned for injection patterns like "ignore previous instructions" and blocked |Fix: Keep SKILL.md to visible, descriptive text. Remove comments and encoded text that address the agent.r = subprocess.run([sys.executable, "-c", code], capture_output=True,Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out."""When npx is available, should return True."""Fix: Pin versions and sources; vendor anything fetched at install time.used by the existing test suite. No external network or npx needed.Fix: Pin versions and sources; vendor anything fetched at install time.self.assertIsNone(ccr.retrieve("../../etc/passwd"))Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.return subprocess.run([sys.executable, "-m", "mcptoon"] + args,Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.result = subprocess.run(Fix: Build commands from fixed arguments, never from interpolated strings; prefer an API client over shelling out.self.assertEqual(self._at(1000.0, "../../etc/passwd")[0], "bad-handle")Fix: Stop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.Cost to the agent
Tokens estimated at four characters each. The tool list is re-read by the agent on every turn, so it is the number to compare between servers that do the same job: ranked across the index.
Known vulnerabilities
No advisories in OSV for mcptoon@0.8.35 as of 3d ago. This is the package itself, not its dependencies.
What would make this Verified
18 points to 80 · weights: behavior 45%, static 25%, prompt 15%, publisher 15%- Destructive command against a filesystem root or device≈ +9 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.
- Reads credential paths from the home directory≈ +9 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
- Unclaimed publisher≈ +8 on the totalClaim activeing123: a verified publisher gets +50 on publisher trust. It is free and usually instant with GitHub sign-in.
- Hidden instructions≈ +6 on the totalRemove HTML comments, zero-width characters and white-on-white text that carry instructions. Everything the agent is meant to read should be visible to the person reading the file.
- Access to sensitive file paths≈ +4 on the totalStop enumerating or reading credential locations; take secrets from a declared environment variable the user sets on purpose.
- Destructive file system command detected≈ +4 on the totalBuild commands from fixed arguments; do not interpolate untrusted strings into a shell.