@rhize/skill-forge 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -15,6 +15,7 @@ Pro Modules
15
15
 
16
16
  - src/license.ts
17
17
  - src/gate/overlap.ts
18
+ - src/gate/mcpOverlap.ts
18
19
  - src/provenance.ts
19
20
  - src/queue.ts
20
21
 
package/README.md CHANGED
@@ -117,6 +117,9 @@ nothing is left behind to record. These are Pro features that run free during th
117
117
  [docs/pro.md](docs/pro.md#beta-pricing-0x)): with no valid license, `add` still writes them, and
118
118
  prints a one-line notice above the report instead of skipping them.
119
119
 
120
+ `add`/`scan` also accept `--artifact mcp` (plus `add`-only `--mcp-target <file>`/`--force`) to gate
121
+ an MCP server instead of a skill — see [MCP gating](#mcp-gating-v05) below.
122
+
120
123
  ### `scan`
121
124
 
122
125
  ```bash
@@ -135,6 +138,90 @@ nonzero when the safety verdict is `block`. `--json` prints the same gate-result
135
138
  promoted or rejected). `status` shows the resolved configuration (skills roots, quarantine dir,
136
139
  strictness) plus a count of held entries.
137
140
 
141
+ ## MCP gating (v0.5)
142
+
143
+ `add` and `scan` can also gate an **MCP server** instead of a skill — the same quarantine →
144
+ profile → safety scan → overlap analysis → report → promote/hold/reject pipeline, applied to an
145
+ MCP server candidate rather than a skill:
146
+
147
+ ```bash
148
+ skill-forge scan ./my-mcp-server --artifact mcp
149
+ skill-forge add @scope/some-mcp-server --artifact mcp --mcp-target ~/.claude.json
150
+ skill-forge add https://github.com/owner/mcp-server.git --artifact mcp --yes
151
+ ```
152
+
153
+ Pass `--artifact mcp` explicitly — skill-forge never guesses. In particular, an npm package name
154
+ (`@scope/name`, or a bare `some-mcp-server` name) is only treated as an npm source with this flag;
155
+ without it, the same string resolves as a skills.sh `owner/name` slug instead (no ambiguity
156
+ guessing between the two).
157
+
158
+ **Source forms**
159
+
160
+ | Form | Example | How it's fetched |
161
+ |---|---|---|
162
+ | Local directory | `./my-mcp-server` | Copied into quarantine, same as a local skill source. |
163
+ | Git URL | `https://github.com/owner/mcp-server.git` | Shallow-cloned into quarantine, same as a git skill source. |
164
+ | npm package | `@scope/name` or `some-mcp-server` | `npm pack <name> --pack-destination <quarantine>`, then tarball **extraction only** — never `npm install`, never lifecycle scripts. |
165
+
166
+ **What's gated**
167
+
168
+ Safety runs the same built-in deny-pattern ruleset used for skills (curl\|bash, credential-file
169
+ access, etc.) plus MCP-specific rules: inline credential values in config/env, unpinned `npx -y`
170
+ launch commands, `--dangerously-*`/`--no-sandbox` flags, and filesystem-root launch args — see the
171
+ [MCP safety ruleset table](docs/gate-policy.md#mcp-safety-ruleset). Overlap analysis (Pro, free
172
+ during the 0.x beta) ranks the candidate against the server entries already present in your
173
+ configured `mcpTargets` files, instead of against a skills root.
174
+
175
+ **Capability profile (v0.6).** The report also includes a **static** capability summary — tool,
176
+ resource, and prompt counts, plus a `declaredConfidence` (`high`/`partial`/`none`) — parsed from
177
+ the candidate's `package.json`, any shipped `.mcp.json`/manifest, and MCP SDK source-text patterns
178
+ (`server.tool(...)`, `setRequestHandler(ListToolsRequestSchema, ...)`, etc.):
179
+
180
+ ```
181
+ Artifact type : mcp
182
+ Capabilities : 2 tools, 1 resource, 0 prompts (declaredConfidence: high)
183
+ ```
184
+
185
+ This is free (it's profiling, not a Pro feature) and **never derived by running the candidate
186
+ server** — anything that can't be determined from source text is reported as undetermined rather
187
+ than discovered by executing it. `--json` includes the full `tools`/`resources`/`prompts` name
188
+ lists under `profile.capabilities`.
189
+
190
+ **Promote semantics**
191
+
192
+ Promoting an MCP candidate writes ONE server entry into a target MCP config file's `mcpServers`
193
+ map — it never touches a skills root:
194
+
195
+ ```json
196
+ { "mcpServers": { "<name>": { "command": "...", "args": ["..."], "env": { "SOME_KEY": "" } } } }
197
+ ```
198
+
199
+ - **Env values are never copied** from the candidate — every declared env var is written as an
200
+ empty string, and skill-forge prints the var names you need to fill in yourself.
201
+ - **Target resolution:** `--mcp-target <file>`, else `config.mcpTargets[0]`, else `<cwd>/.mcp.json`.
202
+ - **Existing target file:** backed up first to `<file>.bak-<timestamp>`.
203
+ - **Existing same-name server entry:** refused unless `--force` is passed.
204
+ - **Missing target file/parent dirs:** created.
205
+ - A candidate config listing more than one server gates/promotes the first (same "N found — using
206
+ the first" convention `add`/`scan` already use for a multi-skill source), noted on stderr.
207
+
208
+ There's no MCP equivalent of the skill provenance ledger (`SOURCES.md`) — the pending-ingestion
209
+ queue (Pro) and `--ingest` handoff both apply the same way, keyed on the written config file path
210
+ instead of an installed skill directory. The queued entry carries the candidate's static capability
211
+ profile (`capabilities`, v0.6, above), so a `--ingest` handoff run on an MCP promote has real
212
+ material to work with: `assets/ingest-prompt.md` branches on `artifactType: "mcp"` and walks the
213
+ same five-verb decide (DEFER/ABSORB/FORK/REJECT/WATCH) applied to a server instead of a skill —
214
+ compare declared capabilities against what's already configured, then keep/tighten/remove the
215
+ promoted config entry accordingly. Same static-only rule as the CLI's own profiling: the deep pass
216
+ never runs or installs the candidate server to inspect it.
217
+
218
+ **TOML-format agents: detect-only.** `skill-forge init` detects MCP config files for every known
219
+ agent, including TOML-format ones (Codex CLI's `config.toml`) — they show up in `init`'s MCP-target
220
+ list and can be selected into `config.mcpTargets` for **overlap ranking**. But **promote only
221
+ writes JSON-shaped targets** (`{ "mcpServers": { ... } }`); pointing `--mcp-target` at (or letting
222
+ `config.mcpTargets[0]` resolve to) a TOML file fails when the promote step tries to parse it as
223
+ JSON. Detection/overlap is agent-format-agnostic; writing is JSON-only.
224
+
138
225
  ## Free vs. Pro
139
226
 
140
227
  | Capability | Free | Pro |
@@ -196,7 +283,10 @@ that deeper judgment (which patterns to keep, whether to absorb into an existing
196
283
  new one, verifying the result beats baseline) is a job for a coding agent, not the gate. `--ingest`
197
284
  hands a promoted skill off to one, running the bundled, agent-neutral prompt at
198
285
  `assets/ingest-prompt.md` (Claude Code users get a deeper experience via the companion
199
- `rhize-skill-forge` plugin skill, but the bundled prompt works with any agent).
286
+ `rhize-skill-forge` plugin skill, but the bundled prompt works with any agent). The same flag works
287
+ on an MCP server promote (`--artifact mcp --ingest`, v0.6): the bundled prompt branches on the
288
+ queue entry's `artifactType` and runs the matching decide pass — see
289
+ [MCP gating](#mcp-gating-v05) above.
200
290
 
201
291
  ```bash
202
292
  skill-forge add owner/name --yes --ingest