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)¶
- Pin everything. No
@latest/ barenpx -y pkgin.mcp.json— that is a supply-chain injection path straight into agent context. Exact version or hash. - 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.8exposes a single read-onlylint-files(no autofix tool). Any future SQL-write tool gets the same ask/deny treatment. - Per-server env scoping. MCP servers are child processes that inherit the
full environment;
secret-grepcannot catch inherited leakage. Give each server only the vars it needs via itsenvblock. (Residual caveat: launchers merge over inherited env rather than clearing it — keep secrets out of the session env where agents run these servers.) - Secrets via env only +
secret-grephard-gate before any push. - CI keeps plain CLIs (eslint, prettier,
jb inspectcode→ SARIF,dotnet format) for determinism. No AI-driven tools in CI (no Alumnium, no test-healer). - 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 —typeandurl. ThemcpOAuthgrant in~/.claude/.credentials.jsonis stored underserverName|<hash>and recordsserverUrlinside 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_targetand 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.