# Forge MCP Clients

> Forge doctrine for using MCP servers as a client — opt-in, tiered, least-privilege. Use when a Boss needs an external tool grant or when installing/discussing an MCP server.

- Skill: `forgeyclap/forge-mcp-clients` (Agent Skill)
- Install (CLI): `npx skillmds@latest add forgeyclap/forge-mcp-clients`
- Raw SKILL.md: https://api.skillmd.com/api/skills/forgeyclap/forge-mcp-clients/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: ForgeyClap (https://skillmd.com/u/forgeyclap)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/forgeyclap/forge-mcp-clients

---


# Forge playbook — MCP-as-client doctrine (dormant, opt-in)

**Do not duplicate the config — defer to:** `config/orchestration/mcp-registry.json` (the server catalog)
and `config/orchestration/mcp-grants.json` (the per-Boss least-privilege matrix) as the single source of
truth for tiers, servers, and grants. This file is doctrine/orchestration only — it explains *how* to use
those configs correctly, it does not re-list every server or re-derive the matrix.

## Hard rules
- **Nothing here installs, connects to, or activates any MCP server.** The zero-dependency Forge default
  (fs/path only, no live network client) stays 100% intact until the owner explicitly opts a server in.
- A server is usable **only** when both are true: (1) the owner has opted it in (a marker naming the
  server id — see "Opt-in flow" below), **and** (2) the requesting Boss's grant covers it (tier + server
  id, per `mcp-grants.json`). Either condition failing means dormant → honest native fallback.
- **Tier 3 (WRITE-PRIMITIVE) is never auto-used.** Every tier-3 call routes through the existing
  `forge-actiongate.cjs` hard-gate classifier (the same one used for deploy/push/spend/DNS/etc.) — it is
  never bypassed and never reimplemented in parallel.
- Never claim an MCP tool ran, was available, or was opted in when it wasn't. Absence is reported as a
  labeled native fallback, not silently skipped.

## What "MCP-as-client" means here
Forge already ships one MCP artifact: `forge-bin/forge-mcp.cjs`, a **read-only server** that exposes this
project's own Forge run state (runs/events/reports/memory) to an external MCP host. That is Forge acting
as a *server* — unrelated to this skill.

This skill is the opposite direction: Forge (its Bosses) acting as an MCP **client**, consuming *external*
MCP servers (docs lookup, web search, browser automation, GitHub, etc.) as extra tools during a task. The
client side is deliberately **dormant by default** — a catalog and a validator, not a running connection.

## The 4 capability tiers (least-privilege)
| Tier | Class | Examples | Notes |
|------|-------|----------|-------|
| 0 | Read-only LOCAL | LSP/code-intelligence read (`serena-lsp`), local docs | No network call at all. |
| 1 | Read-only REMOTE | web search (`exa`), docs fetch (`context7`), scrape (`firecrawl`), GitHub read (`github-read`) | Network read, no writes; a credential (if any) is a read-scoped key only. |
| 2 | SANDBOXED action | browser-QA drive (`playwright`, `chrome-devtools`) | Can click/type/screenshot a page it navigates to — ephemeral browser state, never a project or repo write. |
| 3 | WRITE-PRIMITIVE | any MCP write (`github-write`, file write, deploy, publish) | Always routes through `forge-actiongate.cjs`; never granted by default to any Boss. |

Tiers and the full server catalog live in `config/orchestration/mcp-registry.json`. Every entry there
starts (and stays, until opted in) at `"status": "not-installed"` — `"active"` in that file is forbidden.

## Per-Boss least-privilege model
Each of the 12 permanent Bosses (`config/agents/agent-registry.json`) has a **max tier** and an explicit
**allow-list** of server ids in `config/orchestration/mcp-grants.json`. Both conditions are checked
independently — a Boss can never get a tool above its max tier, and never a server outside its allow-list,
even if one side alone would technically allow it. A Boss with no entry in that file defaults to
`max_tier: 0, allow_servers: []` (no grant at all — native fallback only); there is no implicit wide grant.

Current defaults (see `mcp-grants.json` for the authoritative, evolving list and the "why" per Boss):
search-boss and integration-boss get tier-1 docs/search; review-boss gets tier-1 read-only GitHub/docs;
test-boss and ui-boss get tier-2 sandboxed browser-QA; build-boss gets tier-0 local LSP only. No Boss gets
tier 3 by default — Boss, head-chef, seo-boss, security-boss, skill-boss, and docs-boss have no default
MCP grant at all in the current matrix.

## "mcp-write is a write-primitive" → hard-gate
A tier-3 MCP tool call (e.g. `github-write` creating a commit/PR, or any MCP tool that writes files,
deploys, or publishes) is treated exactly like `deploy`, `git-push`, `spend`, or `credential-rotate` in
`config/orchestration/hard-gates.json`. It is classified through the existing
`forge-actiongate.cjs::classify()` — **reuse that hard-gate, never duplicate its regex/logic** — and
requires an explicit per-use `owner_confirmed: true` before proceeding, regardless of autonomy level.
There is no separate "MCP write" bypass path; write is write.

## Defer-loading (token discipline)
Never pre-load every MCP tool schema for a task. A Boss that has a valid grant requests only the specific
tool(s) it needs for the current step via `ToolSearch` (or the equivalent narrow lookup), the same
discipline this project already applies to ECC/Codex/MCP loading generally (see the project's Token
Efficiency governance: "load only the tools needed for the current task; fetch deferred tool schemas on
demand"). A planner-style `planLoad()` step returns only the relevant tool(s) for the task at hand — never
the full catalog.

## Opt-in flow (dormant until the owner acts)
1. Nothing is active out of the box. `config/orchestration/mcp-registry.json` is a catalog, not a
   connection — every entry starts at `"status": "not-installed"`.
2. The owner opts a specific server in explicitly (naming its registry `id`). Until that marker exists for
   a given server id, that server stays dormant for every Boss, no matter what its grant would allow.
3. See `config/mcp/.mcp.json.example` in this project for a worked, DORMANT example of what opting one
   server in looks like end-to-end (host wiring + the explicit opt-in marker) — copy and adapt it, do not
   activate it by editing this skill.
4. Opting in a server does **not** widen any Boss's grant. Opt-in only makes a server *reachable*;
   `mcp-grants.json` still decides *who* may use it and at what tier.

## Requesting + validating a grant
Before a Boss calls any MCP tool it must validate, not assume, that it may:
1. Confirm the server id has been opted in (step 2 above) — if not, stop here and use the native fallback.
2. Look up its own entry in `config/orchestration/mcp-grants.json`: is the server id in its
   `allow_servers`, and is the server's tier (from `mcp-registry.json`) `<= max_tier`? Both must hold.
3. If the server is tier 3, additionally run it through `forge-actiongate.cjs::classify()` and require
   `owner_confirmed: true` before the call — no exception, even if steps 1–2 passed.
4. Only after all applicable checks pass does the Boss call the tool, and only the specific tool it needs
   (defer-loading, above) — never the server's full toolset just because access exists.
5. Log the outcome honestly: a real MCP call is reported as used; a denied/ungranted/not-opted-in request
   is reported as a labeled native fallback (see below), never silently absorbed into "it worked."

## Honest native fallback
When a server is absent, not opted in, or the requesting Boss's grant does not cover it, the Boss does
**not** stall the task — it falls back to its existing native capability (repo read, Claude's own
reasoning, WebSearch/WebFetch if separately available, manual QA, etc.) and **says so explicitly** in its
report: which server/tool was wanted, why it wasn't available (not opted in / grant denied / tier too
low), and what native path was used instead. Never claim an MCP tool ran, or imply a capability gap didn't
exist, when a fallback was actually used.

## Skills / commands / MCP
`config/orchestration/mcp-registry.json` (catalog), `config/orchestration/mcp-grants.json` (per-Boss
matrix), `forge-bin/forge-actiongate.cjs` (tier-3 hard-gate, reused not duplicated),
`config/mcp/.mcp.json.example` (dormant worked example — never a live `.mcp.json`).

## Fan-out & flow
No dedicated team — this is a cross-cutting doctrine every Boss consults inline before attempting an MCP
call. No fan-out of its own; it does not spawn agents.

## Ship-readiness (unique)
Zero-dep default provably unbroken (no new runtime dependency, no auto-started connection); every tier-3
attempt is provably routed through `forge-actiongate.cjs`; no Boss ever exceeds its `max_tier` or
`allow_servers`; every MCP absence is reported as a labeled native fallback, never silently dropped or
falsely claimed as success.

