Atlas / MCP servers / 171county / ModWrench

ModWrenchBLOCK

mcp/171county/modwrench

One MCP server for mod platforms and local modding diagnostics. Search Thunderstore, read your real load order from MO2/r2modman/Vortex, and trace a crash log to the mod that caused it — from inside Claude, Cursor, or any MCP client. Free and MIT.

Verdict
BLOCK
Grade
D
Trust score
69 /100
Exposed tools
53 51r · 2w · 0d
Transport
stdio · streamable-http
License
MIT
Stars
0
01

Overview

From the repository's own README, as read at the audited commit. Badges and raw HTML are left out.

[](https://github.com/171county/modwrench/actions/workflows/ci.yml) [](https://www.npmjs.com/package/@modwrench/cli) [](LICENSE)

An MCP server that connects your AI assistant to mod platforms and to your own modding setup, so you can ask questions in your AI client instead of clicking through web UIs.

It runs on your machine. No account, no service, no server anyone operates.

Paste a crash log. Get the mod that caused it.

SomeArmorMod.esp is named as a suspect, and SomeArmorMod.dll is sitting at frame 2 of the call stack. ModWrench parsed the log and laid out what is in it. It did not decide the cause — that is the model's job, and the page says so.

Search every platform you have connected, with the author on every row.

These are not screenshots of a website. Each is an MCP Apps page: one self-contained HTML document with no external scripts, no stylesheets, no fetches and no images. Every tool answers in text that any client can show and a model can read. Crash logs, mod lists, dependencies and load orders, known conflicts, the deck, Patch Day, Crash Whisperer and the Doctors also have a page, drawn only in a client that supports MCP Apps: the tool points at its page, the client fetches it and draws it, and the data the page draws comes with the answer as structured data. A client that can't draw pages never fetches one and is never sent tha

Read from source at commit b68fc65b330bOBSERVED · 2026-10-11
02

Connect

Built from this server's own package name, version and transport as found in its source — not copied from anyone's documentation, so it cannot drift against a page we do not control.

claude-code (npm)
claude mcp add cli -- npx -y @modwrench/[email protected]
03

Exposed tools (53)

51 read · 2 write · 0 destructive.

ToolRiskDescription
modio_game_tagsread
modio_get_fileread
modio_get_gameread
modio_get_modread
modio_list_gamesread
modio_list_modsread
modio_mod_commentsread
modio_mod_dependenciesread
modio_mod_eventsread
modio_mod_filesread
modio_mod_metadata_kvpread
modio_mod_statsread
modio_mod_tagsread
modio_modfile_detailread
modio_popularread
modio_search_modsread
modio_top_gamesread
mw_activate_platformread
mw_check_known_conflictsread
mw_crash_whispererread
mw_critiqueread
mw_deckread
mw_detect_environmentread
mw_diagnose_crashread
mw_doctorread
mw_parse_crashlogread
mw_patch_daywrite
mw_query_mod_metadataread
mw_read_load_orderwrite
nexus_endorse_modread
nexus_file_previewread
nexus_get_fileread
nexus_get_gameread
nexus_get_modread
nexus_latest_addedread
nexus_latest_updatedread
nexus_list_gamesread
nexus_md5_searchread
nexus_mod_changelogsread
nexus_mod_filesread
nexus_searchread
nexus_trendingread
nexus_updatedread
nexus_validate_keyread
thunderstore_get_communityread
thunderstore_get_modread
thunderstore_list_communitiesread
thunderstore_list_modsread
thunderstore_mod_dependenciesread
thunderstore_mod_versionsread
thunderstore_resolve_dependenciesread
thunderstore_search_modsread
thunderstore_top_modsread
04

Trust audit

BLOCKgrade D · trust 69/100 Do not install this without reading the findings. The audit found something that could harm you or your machine.

LayerWhat it checksResult
L0Provenance & inventoryPASS
L1Static analysis of the codeFAIL
L2Instruction surface (what it tells the agent)PASS
L3Class-specific surfacePASS
L4Behavioural (sandbox)SKIPPED

What the source does

Filesystem
declared (2 observation(s))
Network
declared (8 observation(s))
Shell
declared (1 observation(s))
Dependencies
not all pinned
Secrets in source
none-found

Findings (25)

HIGHCode injection · code.eval_exec · CWE-78, CWE-94, CWE-95
packages/nexus/src/auth.ts:47
exec(cmd);
Why it matters. evaluates text as code
Fix. remove; use a parser or a dispatch table
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/nexus/src/auth.ts:61
const reqUrl = new URL(req.url ?? "/", "http://127.0.0.1");
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/nexus/src/auth.ts:107
const redirectUri = `http://127.0.0.1:${addr.port}/callback`;
MEDIUMNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/nexus/src/auth.ts:242
url.searchParams.set("redirect_uri", `http://127.0.0.1:${port}/callback`);
LOWInventory / provenance · inv.hidden_file · CWE-1104
.gitleaks.toml
.gitleaks.toml
Why it matters. hidden member outside the usual dotfiles
Fix. review its purpose
LOWInsecure crypto · crypto.weak_hash · CWE-327, CWE-338
packages/workbench/src/crashwhisper/index.ts:133
const signature = (text: string): string => createHash("sha1").update(text.replace(/\r\n?/g, "\n").trim()).digest("hex");
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/workbench/test/doctor-report.test.ts:412
const nonsense = ["", " ", "\0", "a\0b", "x".repeat(10_000), "../../..", "C:\\", "/", "\n", "{}", "__proto__"];
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/workbench/test/doctor-report.test.ts:595
for (const args of [{ gamePath: "\0" }, { gamePath: "x".repeat(5000) }, { mo2InstancePath: "a\0b", area: "setup" }, { profileName: "../../.." }]) {
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/workbench/test/helpers/person.ts:5
import { summarizeCrashWhisper, whisper, type CrashWhisperReport } from "../../src/crashwhisper/index.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/workbench/test/helpers/person.ts:6
import { VENUES } from "../../src/crashwhisper/types.js";
LOWFilesystem / path · fs.traversal · CWE-22, CWE-59
packages/workbench/test/helpers/person.ts:7
import type { RedactOptions } from "../../src/crashwhisper/redact.js";
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/remote/test/server.test.ts:27
const response = await fetch(`http://127.0.0.1:${address.port}/`);
LOWNetwork egress · net.raw_ip · CWE-200, CWE-319
packages/remote/test/server.test.ts:49
new URL(`http://127.0.0.1:${address.port}/mcp`)
LOWObfuscation / stealth · obf.rtl_override · CWE-506, CWE-94
packages/thunderstore/test/deps-page.test.ts:16
const HOSTILE = "Evil<img src=x onerror=alert(1)>-Mod-1.0.0";
LOWObfuscation / stealth · obf.rtl_override · CWE-506, CWE-94
packages/thunderstore/test/deps-page.test.ts:41
'[\n  "BepInEx-BepInExPack-5.4.2100",\n  "Evil<img src=x onerror=alert(1)>-Mod-1.0.0",\n  "NoHyphen"\n]';
LOWObfuscation / stealth · obf.rtl_override · CWE-506, CWE-94
packages/thunderstore/test/deps-page.test.ts:46
order: ["BepInEx-BepInExPack", "Evil<img src=x onerror=alert(1)>-Mod", "Hostile-Mod"],
LOWObfuscation / stealth · obf.rtl_override · CWE-506, CWE-94
packages/thunderstore/test/deps-page.test.ts:53
dependsOn: ["BepInEx-BepInExPack", "Evil<img src=x onerror=alert(1)>-Mod"],
LOWObfuscation / stealth · obf.rtl_override · CWE-506, CWE-94
packages/thunderstore/test/deps-page.test.ts:58
fullName: "Evil<img src=x onerror=alert(1)>-Mod",
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
packages/modio/test/mods-page.test.ts:24
submitted_by: { username: "evilauthor" },
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
packages/modio/test/mods-page.test.ts:61
author: "evilauthor",
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
packages/modio/test/mods-page.test.ts:92
author: "evilauthor",
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
packages/modio/test/mods-page.test.ts:137
author: "evilauthor",
LOWObfuscation / stealth · obf.zero_width · CWE-506, CWE-94
packages/nexus/test/mods-page.test.ts:22
author: "EvilAuthor",
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
package.json
@types/node, tsx, typescript
Why it matters. 3 dependency range(s) float
Fix. pin exact versions or ship a lockfile
LOWSupply chain · supply.unpinned · CWE-829, CWE-1357
packages/cli/package.json
@modelcontextprotocol/sdk, zod
Why it matters. 2 dependency range(s) float
Fix. pin exact versions or ship a lockfile

Gates applied: no_behavioural_pass.

Audited 2026-10-11 · audit v0.4.1 · source sha b68fc65b330bfull audit observations/trust-audit/mcp-server/171county__modwrench.json · Report an issue / request a re-scan
05

Audit history

Every audit this server has had. A grade with a past is a grade somebody is still checking.

DateSourceVerdictGradeScoreChange
2026-10-11b68fc65b330bBLOCKD69first audit
06

Questions

What is the @modwrench/cli MCP server?

One MCP server for mod platforms and local modding diagnostics. Search Thunderstore, read your real load order from MO2/r2modman/Vortex, and trace a crash log to the mod that caused it — from inside Claude, Cursor, or any MCP client. Free and MIT.

What tools does @modwrench/cli expose?

53 in total: 51 read-only, 2 that write, and 0 that can delete or overwrite. Every one is listed on this page with its risk.

Is @modwrench/cli safe to connect to an agent?

No — not without reading the findings first. The audit graded it D (69/100) and found 1 critical or high issue in the source. Each one is listed on this page with the file and line it is on.

What credentials does @modwrench/cli need?

No credential environment variables were found in its source, so it appears to need none.

How does @modwrench/cli run?

It speaks stdio and streamable-http, so it runs as a local process your client starts. It is published on npm as @modwrench/workbench at 0.3.0.

How current is this page?

The grade is for one exact copy of the source (b68fc65b330b), read on 2026-10-11. The repository is watched and re-audited when it changes.

Advertisement