Skip to content

MCP / dev-tool suite — policy, gating, and fleet rollout

Status: active (WorkWingman slice landed on branch wt/WT-9a4c/mcp-suite). Council-reviewed 2026-07-14 (fable tier; report: llm-council/reports/2026-07-14_153346_review-this-mcpdev-tool-suite-gating-proposal.md).

This documents which AI/dev tools are wired into WorkWingman (and the wider fleet), how they are gated, and — importantly — which were deferred or rejected and why, so the decisions are not silently re-litigated.

Dispositions

Tool Call Where Form
ESLint MCP (@eslint/mcp@0.3.8) SHIP WorkWingman frontend/ .mcp.json, version-pinned, autofix behind allowlist
Angular CLI MCP (@angular/cli@22.0.5 mcp) SHIP WorkWingman frontend/ .mcp.json, pinned to workspace CLI major
ReSharper CLT (JetBrains.ReSharper.GlobalTools@2026.1.4) SHIP all C# repos .config/dotnet-tools.json (jb CLI), not an MCP
Prettier keep as CLI frontend already a devDep; run npx prettier; no MCP
SQLite MCP SHIP (narrow) fleet-telegram only read-only, pinned; the only real SQLite consumer in the fleet
MSSQL MCP DEFER nowhere zero SQL Server targets; doc pointer + security profile only
Alumnium MCP HOLD WorkWingman (opt-in) exploratory only, never in CI, not in committed config
autoheal (willfarrell/docker-autoheal) SHIP (ops) claude-mem-house compose container keepalive; not a repo MCP
autoheal (headout, AI test-healer) REJECT corrupts the mocked + Stryker test oracle
KittySploit REJECT as fleet tooling isolated only offensive framework; never in any .mcp.json or agent tool list

Why MSSQL MCP is deferred, not staged

No repo uses SQL Server (grep for SqlConnection/UseSqlServer = 0). There is also no Entity Framework anywhere in the fleet (UseSqlite/DbContext/EF packages = 0). WorkWingman is deliberately LocalJsonStore (no EF/SQLite). The only SQLite in play is fleet-telegram reading Antigravity/agy .db conversation stores via raw read-only Microsoft.Data.Sqlite — that is a SQLite need, not SQL Server, so a SQLite MCP is the fit, not MSSQL.

Security profile for any future MSSQL enablement (do not skip): the C#-first candidate Aaronontheweb/mssql-mcp exposes a full execute_sql tool including DML/DDL — "read-only by config" is not achievable. Enablement requires (1) a least-privilege read-only DB account and (2) a fork/wrapper that rejects non-SELECT. Until a real SQL app exists, ship no config anywhere.

Why KittySploit is rejected as fleet tooling

An exploit framework reachable via MCP from an always-on agent host is one prompt injection away from live exploitation, plus unauthorized-scan legal exposure, and adds little over Metasploit even legitimately. DAST for our own apps is covered by OWASP ZAP (see below), which is the workhorse. If a genuine authorized engagement arises: isolated VM, written scope + target list, time-box, dual approval, full logging, no access to app secrets, and never in any repo .mcp.json or the fleet allowlist. Per-engagement decision, not standing infra.

Gating model (applies to every shipped MCP)

  1. Pin everything. No @latest / bare npx -y pkg in .mcp.json — that is a supply-chain injection path straight into agent context. Exact version or hash.
  2. Read-only-first. Angular mutation/exec tools (run_target, onpush_zoneless_migration, devserver.start/stop/wait_for_build) are set to ask in .claude/settings.json; read tools (lint-files, ai_tutor, get_best_practices, list_projects, search_documentation) are explicitly allowed. Tool names are verified against the pinned package sources — @eslint/mcp@0.3.8 exposes a single read-only lint-files (no autofix tool). Any future SQL-write tool gets the same ask/deny treatment.
  3. Per-server env scoping. MCP servers are child processes that inherit the full environment; secret-grep cannot catch inherited leakage. Give each server only the vars it needs via its env block. (Residual caveat: launchers merge over inherited env rather than clearing it — keep secrets out of the session env where agents run these servers.)
  4. Secrets via env only + secret-grep hard-gate before any push.
  5. CI keeps plain CLIs (eslint, prettier, jb inspectcode → SARIF, dotnet format) for determinism. No AI-driven tools in CI (no Alumnium, no test-healer).
  6. C#-first is a tiebreaker, not an override. Official-and-maintained beats language purity — we ship the official JS MCPs for lint/Angular.

Atlassian Rovo MCP (atlassian-rovo) — the pinning exception

Registered user-scope as a remote OAuth MCP (Streamable HTTP, type: "http", https://mcp.atlassian.com/v1/mcp) against Jira project FLT (https://workwingman.atlassian.net). OAuth grant for the new /v1/mcp URL is pending — Andrew runs /mcp → authenticate; it reports "Needs authentication" until then. The old /v1/sse grant is orphaned, not reused.

Was HTTP+SSE at /v1/sse; Atlassian ended support for that endpoint after 30 June 2026 (notice). Migrating takes both fields — type and url. The mcpOAuth grant in ~/.claude/.credentials.json is stored under serverName|<hash> and records serverUrl inside the grant; changing the URL creates a second grant, so the prior cached grant is orphaned and the next connect re-runs consent.

It is the one server that cannot follow rule 1 (pin everything): it is a hosted service, so there is no version or hash to pin and its tool surface can change under us without a diff — the SSE retirement above is that risk landing in practice. That makes the permission gate the only control, so it carries more weight here than for the pinned local servers:

  • Allowlist read/search tools only.
  • Mutation tools (create / transition / comment) stay ask-gated, same treatment as run_target and the SQLite write tools.
  • This matches the council prescription for Jira write access — manager controls transitions, child agents get narrow read tools — which is the same read-only-first shape as the rest of this suite.
  • Because the tool surface is not pinnable, re-check the allowlist against the live tool list at each quarterly allowlist review (gating rule 6), not just on config change.

Board note: Jira does not replace the existing boards. Standing rule is three-board redundancy — fleet-harness/docs/BOARD.md (canonical, wins conflicts) + Vikunja + Jira FLT, kept in lockstep. docs/BOARD.md and the artifact boards stay until the board-as-contract checklist passes (local export, stable IDs, API transitions, token-roi hooks, offline fallback).

DAST (OWASP ZAP) — already present

Replaces the KittySploit impulse, and already exists: .github/workflows/ci.yml boots WorkWingman.Api on 127.0.0.1:5211 and runs zaproxy/zap-stable zap-baseline.py -t http://127.0.0.1:5211 -I. No new workflow needed — this is the fleet's DAST. KittySploit adds nothing over it for own-app testing and stays out of all repo configs (see above).

Fleet rollout — ReSharper CLT across all C# repos

C# repos received .config/dotnet-tools.json (ReSharper CLT, jb CLI) on branch wt/WT-9a4c/resharper-clt, each in its own worktree (hazard-class isolation): FamilyRenewedScraper, LearnDSAlgorithms, PavlokPager, audio-loop-mcp, cgspectrum2notebooklm, fleet-dispatch, fleet-telegram, llm-council, membus, token-roi, usage-governor, worktree-identity (+ its wtid-council-fixes worktree — same repo). WorkWingman is on this branch. jb inspectcode emits SARIF/XML for CI consumption without any MCP. All branches unpushed pending review.

Landed alongside (this rollout, unpushed): - docker-autoheal (willfarrell/autoheal:1.2.0) in the claude-mem compose (homelab-dr-blueprint, branch wt/WT-9a4c/docker-autoheal) — restarts unhealthy postgres/valkey/worker. - Read-only SQLite MCP in fleet-telegram (branch wt/WT-9a4c/resharper-clt), write/DDL tools denied — see that repo's docs/sqlite-mcp.md.