@yawlabs/mcph 0.28.0 → 0.29.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/CHANGELOG.md +85 -0
- package/README.md +14 -3
- package/dist/index.js +71 -6
- package/package.json +3 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@yawlabs/mcph` are documented here. This project uses [semantic versioning](https://semver.org) and a CI-gated release flow: pushing a `vX.Y.Z` tag triggers `.github/workflows/release.yml`, which publishes to npm.
|
|
4
|
+
|
|
5
|
+
## 0.29.0 — 2026-04-18
|
|
6
|
+
|
|
7
|
+
- **Compliance-aware routing (`MCPH_MIN_COMPLIANCE`)** — Phase 3 item. Set the env var to `A`, `B`, `C`, `D`, or `F` and `mcp_connect_activate` refuses to load any installed server whose reported `complianceGrade` is below the floor, with an error that names the grade and the env var to unset. `mcp_connect_discover` annotates below-grade servers in place (so the model knows they exist and why they won't auto-activate) and emits a "Compliance filter active" header. Forward-compatible schema: the optional `complianceGrade` field on `UpstreamServerConfig` rides the existing `/api/connect/config` response — the feature kicks in automatically once the backend starts populating grades. Ungraded servers always pass (don't punish unknown).
|
|
8
|
+
|
|
9
|
+
## 0.28.1 — 2026-04-18
|
|
10
|
+
|
|
11
|
+
Docs-only release.
|
|
12
|
+
|
|
13
|
+
- First-ever `CHANGELOG.md`, covering 0.5.0 → 0.28.0. Linked from `README.md`.
|
|
14
|
+
- README catches up with the meta-tools shipped in the 0.20 – 0.28 arc: `mcp_connect_read_tool`, `mcp_connect_exec`, `mcp_connect_bundles` are now documented in the top-level list. Corrected "session-local" phrasing on the Learning ranker signal (cross-session since v0.23.0).
|
|
15
|
+
- New "Multi-device sync" section under "Config sync" — same token, same servers across every machine; no dotfile repos for secrets.
|
|
16
|
+
- Phase 2 "Multi-device config sync" marked shipped in `ROADMAP.md` (docs-only; backing behavior already worked).
|
|
17
|
+
- `package.json` `files` array now includes `CHANGELOG.md` so release notes ship with the npm tarball.
|
|
18
|
+
|
|
19
|
+
## 0.28.0 — 2026-04-18
|
|
20
|
+
|
|
21
|
+
Phase 3 opener. Two client-only intelligence features.
|
|
22
|
+
|
|
23
|
+
- **Tool deduplication** — `mcp_connect_discover` now surfaces an "Overlapping tools" block when two or more currently-connected servers expose the same bare tool name. Top 5 overlaps, sorted by namespace count descending, with a dispatch-to-disambiguate hint.
|
|
24
|
+
- **Curated bundles (`mcp_connect_bundles`)** — New meta-tool returning hand-picked multi-server presets: `devops-incident`, `pr-review`, `growth-stack`, `data-ops`, `product-release`, `support-ops`. `action: "list"` (default) returns all bundles; `action: "match"` partitions them into "ready to activate now" vs. "partially installed" against the user's current config.
|
|
25
|
+
|
|
26
|
+
## 0.27.0 — 2026-04-18
|
|
27
|
+
|
|
28
|
+
Four Phase 2 items shipped together.
|
|
29
|
+
|
|
30
|
+
- **Automatic load (`MCPH_AUTO_LOAD`)** — Opt-in env flag. On startup, after persistence hydration, activates every namespace in the top recurring pack (by frequency, tie-break recency) from pack history, provided every namespace is installed. Silent no-op otherwise.
|
|
31
|
+
- **Per-tool filter on `mcp_connect_activate`** — Pass `tools: [...]` to expose only the named tools via `tools/list`. Hidden tools stay reachable through `mcp_connect_dispatch` (routes are unfiltered). Re-activate without `tools` to clear the filter. `discover()` shows a `(filtered: K of N)` indicator on filtered connections.
|
|
32
|
+
- **Orchestration pipeline (`mcp_connect_exec`)** — Declarative multi-step tool-call pipeline. Each step names a namespaced tool plus args; `{"$ref": "<stepId>[.path]"}` markers in args splice a prior step's output into the next step's input. No eval / no expression language — only sequential dispatch and dot/bracket path resolution. Capped at 16 steps; any step failure fails the pipeline and returns completed outputs as `partial`.
|
|
33
|
+
- **Marketplace pointer** — `discover()` appends `https://mcp.hosting/explore` for users with fewer than 5 installed servers. URL hint only; a full marketplace meta-tool is parked until the backend ships a catalog API.
|
|
34
|
+
|
|
35
|
+
## 0.26.0 — 2026-04-18
|
|
36
|
+
|
|
37
|
+
- **Recurring packs block in `discover()`** — When pack history and installed config overlap, `discover()` now surfaces an "Recurring packs" block at the top of its output with a ready-to-run `mcp_connect_activate` call. Saves the second `mcp_connect_suggest` round-trip when the signal is already there.
|
|
38
|
+
|
|
39
|
+
## 0.25.1 — 2026-04-18
|
|
40
|
+
|
|
41
|
+
- Truthed up "this session" phrasing across user-facing strings and tool descriptions. With cross-session persistence (v0.23.0) shipping, counts and pack history are no longer session-scoped; the copy now matches.
|
|
42
|
+
|
|
43
|
+
## 0.25.0 — 2026-04-18
|
|
44
|
+
|
|
45
|
+
- `mcp_connect_suggest` now emits a ready-to-run `mcp_connect_activate` call with a verbatim `namespaces=[...]` JSON array, rather than pointing at `mcp_connect_dispatch` (the wrong primitive for loading a pack).
|
|
46
|
+
|
|
47
|
+
## 0.24.0 — 2026-04-18
|
|
48
|
+
|
|
49
|
+
- **`mcph doctor` STATE section** — Prints `~/.mcph/state.json` path, last-saved age, learning count, pack history count; shows "disabled" when persistence is opted out.
|
|
50
|
+
- **`MCPH_DISABLE_PERSISTENCE` opt-out** — Env flag skips both load and save. Useful for CI, sandboxed containers, or users who don't want a state file.
|
|
51
|
+
|
|
52
|
+
## 0.23.0 — 2026-04-18
|
|
53
|
+
|
|
54
|
+
- **Cross-session persistence** — Learning counts (`succeeded`/`dispatched`/`lastUsedAt` per namespace) and pack history (co-activation chains) now round-trip through `~/.mcph/state.json`. Schema-versioned, atomic write-rename.
|
|
55
|
+
|
|
56
|
+
## 0.22.0 — 2026-04-17
|
|
57
|
+
|
|
58
|
+
- **Inline usage hints in `discover()`** — `used Nx` success counts and "often loaded with X, Y" co-activation peers are surfaced per-server in discover output.
|
|
59
|
+
|
|
60
|
+
## 0.21.0 — 2026-04-17
|
|
61
|
+
|
|
62
|
+
- **Concurrent server cap** — Default max 6 simultaneously-active servers; `MCPH_SERVER_CAP` env override. Hard cap both as context protection and a business lever.
|
|
63
|
+
|
|
64
|
+
## 0.20.0 — 2026-04-17
|
|
65
|
+
|
|
66
|
+
- **`mcp_connect_read_tool`** — Schema-on-demand: return a single tool's schema + docs without activating its server. For servers with large tool catalogs where the model only needs 1–2 tools, reads 1–2 schemas instead of loading the entire catalog.
|
|
67
|
+
|
|
68
|
+
## 0.19.x and earlier
|
|
69
|
+
|
|
70
|
+
- v0.19.0 — internal refactor around config reconciliation.
|
|
71
|
+
- v0.18.0 — analytics uploads for tool-call patterns, load/unload events, error rates.
|
|
72
|
+
- v0.17.0 — resource + prompt proxying (beyond tools).
|
|
73
|
+
- v0.16.0 — error tracking surfaced in `discover()`.
|
|
74
|
+
- v0.15.x — `install` command gates success on config refresh; misc fixes.
|
|
75
|
+
- v0.14.0 — auto-allow mcph tools in Claude Code settings + discover dedup.
|
|
76
|
+
- v0.13.0 — deferred tools: advertise inactive-but-cached servers in `tools/list`.
|
|
77
|
+
- v0.12.x — legacy-config migrator + `doctor` freshness checks.
|
|
78
|
+
- v0.11.x — stability patches.
|
|
79
|
+
- v0.10.x — 7-feature bundle, adaptive routing, policy profiles.
|
|
80
|
+
- v0.9.0 — `mcph compliance` subcommand.
|
|
81
|
+
- v0.8.0 — runtime detection + test runner + error deep-links.
|
|
82
|
+
- v0.7.0 — two-stage retrieval: BM25 + semantic rerank.
|
|
83
|
+
- v0.6.0 — BM25 dispatch + auto-warm discover + stderr capture.
|
|
84
|
+
- v0.5.0 — `MCPH_POLL_INTERVAL` env var.
|
|
85
|
+
- v0.1.x – v0.4.x — initial public release, core meta-tools, namespace routing, config polling.
|
package/README.md
CHANGED
|
@@ -27,16 +27,19 @@ Your MCP client (Claude Code, Cursor, etc.)
|
|
|
27
27
|
- **`mcp_connect_install`** — install a new MCP server on your mcp.hosting account.
|
|
28
28
|
- **`mcp_connect_import`** — bulk-import servers from an existing client config (`claude_desktop_config.json`, `mcp.json`, etc.).
|
|
29
29
|
- **`mcp_connect_health`** — show call counts, error rates, and latency per loaded server.
|
|
30
|
-
- **`mcp_connect_suggest`** — surface recurring multi-server workflows mcph has
|
|
30
|
+
- **`mcp_connect_suggest`** — surface recurring multi-server workflows mcph has learned from persisted pack history. When you repeatedly use `gh` → `linear` → `slack` for the same kind of task, `suggest` lists the pattern with a ready-to-run `activate` call so you can load the whole pack at once.
|
|
31
|
+
- **`mcp_connect_read_tool`** — return a single tool's schema + docs without activating its server. Reads 1–2 schemas instead of loading a whole catalog when the model only needs a couple of tools from a big server.
|
|
32
|
+
- **`mcp_connect_exec`** — run a short declarative pipeline of tool calls in one round-trip. Steps name namespaced tools + args; `{"$ref": "<stepId>[.path]"}` markers splice prior outputs into later inputs. No eval — only dot/bracket path resolution. Capped at 16 steps.
|
|
33
|
+
- **`mcp_connect_bundles`** — list curated multi-server presets (DevOps incident, PR review, growth stack, data ops, etc.) and/or match them against your current config. Pair it with `mcp_connect_activate` to load a whole bundle at once.
|
|
31
34
|
|
|
32
35
|
Installing a server puts it on your account; loading it brings its tools into the current session's context. mcph loads servers lazily so your context window stays clean.
|
|
33
36
|
|
|
34
37
|
Ranking is two-stage when the backend has a Voyage embeddings key configured: a local BM25 pass narrows to a shortlist, then a `/api/connect/rerank` call semantically reorders. With no key on the backend it gracefully degrades to BM25-only — `dispatch` and `discover(context)` keep working, just with slightly weaker ranking on ambiguous queries.
|
|
35
38
|
|
|
36
|
-
On top of the ranker, mcph applies three
|
|
39
|
+
On top of the ranker, mcph applies three client-side signals to dispatch scores:
|
|
37
40
|
|
|
38
41
|
- **Health-aware**: servers that have recently failed to load or have high error rates get down-ranked. Never boosts above raw — "all else equal, prefer the one that works".
|
|
39
|
-
- **Learning**: servers that have succeeded
|
|
42
|
+
- **Learning**: servers that have succeeded before get a small (+10% max) nudge, so the router remembers what's been useful. Success counts persist across restarts via `~/.mcph/state.json` (opt out with `MCPH_DISABLE_PERSISTENCE=1`).
|
|
40
43
|
- **Sampling tiebreak**: when the top two candidates are within 10% of each other and your client supports [MCP sampling](https://modelcontextprotocol.io/specification/server/sampling), mcph asks your client's LLM to pick. Uses the model you're already running — no extra provider key, no extra cost to mcph.
|
|
41
44
|
|
|
42
45
|
## Install
|
|
@@ -264,6 +267,12 @@ When a load fails (missing token, runtime not on PATH, server crashes on init),
|
|
|
264
267
|
|
|
265
268
|
mcph polls [mcp.hosting](https://mcp.hosting) every 60 seconds for config changes. When you add, remove, or modify a server on the dashboard, mcph picks it up automatically — no restart needed.
|
|
266
269
|
|
|
270
|
+
### Multi-device sync
|
|
271
|
+
|
|
272
|
+
Because every mcph install reads the same account's server list, the same token gives you the same servers across every machine. Install mcph on a second laptop with the same `mcp_pat_...`, and within 60 seconds it sees the same GitHub/Slack/Stripe/etc. servers you configured from the first. Tokens, environment variables, and credentials stay in the dashboard — you don't have to sync a JSON file across machines, copy secrets into a dotfile repo, or re-paste an API key per device.
|
|
273
|
+
|
|
274
|
+
Rotate a credential in one place (the dashboard), every machine picks up the new value on the next poll. Revoke a token in Settings → API Tokens, every install stops working immediately (the token is the only thing authenticating the config pull). This is why `~/.mcph/config.json` holds a token, not a server list — the server list is the cloud's concern.
|
|
275
|
+
|
|
267
276
|
## Environment variables
|
|
268
277
|
|
|
269
278
|
| Variable | Required | Description |
|
|
@@ -277,6 +286,7 @@ mcph polls [mcp.hosting](https://mcp.hosting) every 60 seconds for config change
|
|
|
277
286
|
| `MCPH_PRUNE_RESPONSES` | No | Conservative response pruning (redact large file blobs etc. before returning to the client). Set to `0` or `false` to disable. Default: enabled. |
|
|
278
287
|
| `MCPH_DISABLE_PERSISTENCE` | No | Set to `1` or `true` to keep learning + pack-history scoped to the current process — nothing loaded at start, nothing written on shutdown. Intended for ephemeral / shared environments (CI, containers). Default: cross-session persistence enabled at `~/.mcph/state.json`. |
|
|
279
288
|
| `MCPH_AUTO_LOAD` | No | Set to `1` or `true` to pre-activate the top recurring pack (from persisted pack-history) on startup — no LLM round-trip required. Skips silently when history is empty or no pack's namespaces are all installed. Default: off. Requires persistence to be enabled. |
|
|
289
|
+
| `MCPH_MIN_COMPLIANCE` | No | Minimum compliance grade (`A`, `B`, `C`, `D`, or `F`, case-insensitive) an installed server must report before `mcp_connect_activate` will load it. Ungraded servers always pass (don't punish unknown). `discover()` annotates below-grade servers in place and shows a "Compliance filter active" header when set. Invalid values log a warning and disable the filter. Default: unset (no filter). |
|
|
280
290
|
| `MCP_CONNECT_TIMEOUT` | No | Connection timeout in ms for upstream servers (default: `15000`) |
|
|
281
291
|
| `MCP_CONNECT_IDLE_THRESHOLD` | No | Baseline for idle auto-unload (default: `10`). The per-namespace adaptive cap is `[5, 50]` — bursty namespaces extend past the baseline, long-idle ones unload at it. |
|
|
282
292
|
|
|
@@ -301,4 +311,5 @@ The popular Python-based MCP servers (`fetch`, `sqlite`, `time`, `sentry`, etc.)
|
|
|
301
311
|
|
|
302
312
|
- [mcp.hosting](https://mcp.hosting) — Dashboard and server management
|
|
303
313
|
- [@yawlabs/mcp-compliance](https://www.npmjs.com/package/@yawlabs/mcp-compliance) — Test your MCP servers for spec compliance
|
|
314
|
+
- [CHANGELOG](./CHANGELOG.md) — Release notes
|
|
304
315
|
- [GitHub](https://github.com/YawLabs/mcph) — Source code and issues
|
package/dist/index.js
CHANGED
|
@@ -946,7 +946,7 @@ function errorMessage(err) {
|
|
|
946
946
|
}
|
|
947
947
|
|
|
948
948
|
// src/doctor-cmd.ts
|
|
949
|
-
var VERSION = true ? "0.
|
|
949
|
+
var VERSION = true ? "0.29.0" : "dev";
|
|
950
950
|
async function runDoctor(opts = {}) {
|
|
951
951
|
const lines = [];
|
|
952
952
|
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
@@ -1825,6 +1825,42 @@ function bundleActivateHint(bundle) {
|
|
|
1825
1825
|
return `mcp_connect_activate({ namespaces: ${JSON.stringify(bundle.namespaces)} })`;
|
|
1826
1826
|
}
|
|
1827
1827
|
|
|
1828
|
+
// src/compliance.ts
|
|
1829
|
+
var GRADE_ORDER = {
|
|
1830
|
+
A: 4,
|
|
1831
|
+
B: 3,
|
|
1832
|
+
C: 2,
|
|
1833
|
+
D: 1,
|
|
1834
|
+
F: 0
|
|
1835
|
+
};
|
|
1836
|
+
function gradeRank(grade) {
|
|
1837
|
+
if (!grade) return -1;
|
|
1838
|
+
const up = grade.toUpperCase();
|
|
1839
|
+
if (up in GRADE_ORDER) return GRADE_ORDER[up];
|
|
1840
|
+
return -1;
|
|
1841
|
+
}
|
|
1842
|
+
var invalidWarned = false;
|
|
1843
|
+
function parseMinCompliance(raw) {
|
|
1844
|
+
if (raw === void 0) return null;
|
|
1845
|
+
const trimmed = raw.trim();
|
|
1846
|
+
if (trimmed === "") return null;
|
|
1847
|
+
const up = trimmed.toUpperCase();
|
|
1848
|
+
if (up === "A" || up === "B" || up === "C" || up === "D" || up === "F") {
|
|
1849
|
+
return up;
|
|
1850
|
+
}
|
|
1851
|
+
if (!invalidWarned) {
|
|
1852
|
+
invalidWarned = true;
|
|
1853
|
+
log("warn", "Invalid MCPH_MIN_COMPLIANCE; filter disabled", { value: raw });
|
|
1854
|
+
}
|
|
1855
|
+
return null;
|
|
1856
|
+
}
|
|
1857
|
+
function passesMinCompliance(serverGrade, min) {
|
|
1858
|
+
if (min === null) return true;
|
|
1859
|
+
const serverRank = gradeRank(serverGrade);
|
|
1860
|
+
if (serverRank < 0) return true;
|
|
1861
|
+
return serverRank >= gradeRank(min);
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1828
1864
|
// src/cost-estimate.ts
|
|
1829
1865
|
var BYTES_PER_TOKEN = 4;
|
|
1830
1866
|
var CACHED_TOOL_SCHEMA_PAD_BYTES = 200;
|
|
@@ -2319,7 +2355,7 @@ var META_TOOLS = {
|
|
|
2319
2355
|
},
|
|
2320
2356
|
activate: {
|
|
2321
2357
|
name: "mcp_connect_activate",
|
|
2322
|
-
description: 'Load one or more installed MCP servers\' tools into the current session by namespace. Each server adds its tools to your context, so load only what the current task needs. When you move on, unload servers you\'re done with via `mcp_connect_deactivate` before loading new ones. Tools are prefixed by namespace (e.g., "gh_create_issue"). Pass "server" for one or "servers" for multiple. Optionally pass `tools: [...]` to expose only those tools by name \u2014 the rest stay proxyable via mcp_connect_dispatch.',
|
|
2358
|
+
description: 'Load one or more installed MCP servers\' tools into the current session by namespace. Each server adds its tools to your context, so load only what the current task needs. When you move on, unload servers you\'re done with via `mcp_connect_deactivate` before loading new ones. Tools are prefixed by namespace (e.g., "gh_create_issue"). Pass "server" for one or "servers" for multiple. Optionally pass `tools: [...]` to expose only those tools by name \u2014 the rest stay proxyable via mcp_connect_dispatch. If `MCPH_MIN_COMPLIANCE` is set, activation refuses servers whose reported grade is below the floor (ungraded servers always pass); the refusal message names the grade and the env var to unset.',
|
|
2323
2359
|
inputSchema: {
|
|
2324
2360
|
type: "object",
|
|
2325
2361
|
properties: {
|
|
@@ -3791,7 +3827,7 @@ function categorizeSpawnError(err) {
|
|
|
3791
3827
|
}
|
|
3792
3828
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
3793
3829
|
const client = new Client(
|
|
3794
|
-
{ name: "mcph", version: true ? "0.
|
|
3830
|
+
{ name: "mcph", version: true ? "0.29.0" : "dev" },
|
|
3795
3831
|
{ capabilities: {} }
|
|
3796
3832
|
);
|
|
3797
3833
|
let transport;
|
|
@@ -4242,6 +4278,9 @@ function isPersistenceDisabled() {
|
|
|
4242
4278
|
if (raw === void 0 || raw === "") return false;
|
|
4243
4279
|
return raw === "1" || raw.toLowerCase() === "true";
|
|
4244
4280
|
}
|
|
4281
|
+
function resolveMinCompliance() {
|
|
4282
|
+
return parseMinCompliance(process.env.MCPH_MIN_COMPLIANCE);
|
|
4283
|
+
}
|
|
4245
4284
|
function isAutoLoadEnabled() {
|
|
4246
4285
|
const raw = process.env.MCPH_AUTO_LOAD;
|
|
4247
4286
|
if (raw === void 0 || raw === "") return false;
|
|
@@ -4305,7 +4344,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
4305
4344
|
this.apiUrl = apiUrl6;
|
|
4306
4345
|
this.token = token6;
|
|
4307
4346
|
this.server = new Server(
|
|
4308
|
-
{ name: "mcph", version: true ? "0.
|
|
4347
|
+
{ name: "mcph", version: true ? "0.29.0" : "dev" },
|
|
4309
4348
|
{
|
|
4310
4349
|
capabilities: {
|
|
4311
4350
|
tools: { listChanged: true },
|
|
@@ -5100,6 +5139,11 @@ var ConnectServer = class _ConnectServer {
|
|
|
5100
5139
|
const lines = [context ? "Servers ranked by relevance:\n" : "Installed MCP servers:\n"];
|
|
5101
5140
|
if (autoWarmed && sorted.length > 0) {
|
|
5102
5141
|
lines.push(`Auto-loaded "${sorted[0].namespace}" \u2014 top match for your query.
|
|
5142
|
+
`);
|
|
5143
|
+
}
|
|
5144
|
+
const minCompliance = resolveMinCompliance();
|
|
5145
|
+
if (minCompliance !== null) {
|
|
5146
|
+
lines.push(`Compliance filter active: MCPH_MIN_COMPLIANCE=${minCompliance}
|
|
5103
5147
|
`);
|
|
5104
5148
|
}
|
|
5105
5149
|
if (context) {
|
|
@@ -5160,7 +5204,17 @@ var ConnectServer = class _ConnectServer {
|
|
|
5160
5204
|
costLabel = ` \u2014 ${formatCostLabel(estimateFromToolCache(cached))}`;
|
|
5161
5205
|
}
|
|
5162
5206
|
}
|
|
5163
|
-
|
|
5207
|
+
let complianceLabel = "";
|
|
5208
|
+
if (minCompliance !== null && server.complianceGrade) {
|
|
5209
|
+
if (passesMinCompliance(server.complianceGrade, minCompliance)) {
|
|
5210
|
+
complianceLabel = ` [${server.complianceGrade}]`;
|
|
5211
|
+
} else {
|
|
5212
|
+
complianceLabel = ` (grade ${server.complianceGrade} \u2014 below MCPH_MIN_COMPLIANCE=${minCompliance}, won't auto-activate)`;
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
lines.push(
|
|
5216
|
+
` ${server.namespace} \u2014 ${server.name} [${status}] (${server.type})${relevance}${costLabel}${complianceLabel}`
|
|
5217
|
+
);
|
|
5164
5218
|
const shadow = formatShadowLine(server);
|
|
5165
5219
|
if (shadow) lines.push(` ${shadow}`);
|
|
5166
5220
|
const warning = formatHealthWarning(connection?.health, this.activationFailures.get(server.namespace));
|
|
@@ -5418,10 +5472,21 @@ ${activeCount} loaded in this session, ${totalTools} tools in context${tokenSumm
|
|
|
5418
5472
|
const results = [];
|
|
5419
5473
|
let anyChanged = false;
|
|
5420
5474
|
let anyError = false;
|
|
5475
|
+
const minCompliance = resolveMinCompliance();
|
|
5421
5476
|
const total = namespaces.length;
|
|
5422
5477
|
let i = 0;
|
|
5423
5478
|
for (const namespace of namespaces) {
|
|
5424
5479
|
i += 1;
|
|
5480
|
+
if (minCompliance !== null) {
|
|
5481
|
+
const cfg = this.config?.servers.find((s) => s.namespace === namespace);
|
|
5482
|
+
if (cfg && !passesMinCompliance(cfg.complianceGrade, minCompliance)) {
|
|
5483
|
+
const grade = cfg.complianceGrade ?? "unknown";
|
|
5484
|
+
const message = `Refused to load "${namespace}": compliance grade ${grade} is below MCPH_MIN_COMPLIANCE=${minCompliance}. Unset MCPH_MIN_COMPLIANCE (or lower it) to override.`;
|
|
5485
|
+
results.push(message);
|
|
5486
|
+
anyError = true;
|
|
5487
|
+
continue;
|
|
5488
|
+
}
|
|
5489
|
+
}
|
|
5425
5490
|
progress?.(`Loading ${namespace} (${i}/${total})`, i - 1, total);
|
|
5426
5491
|
const r = await this.activateOne(namespace, progress);
|
|
5427
5492
|
results.push(r.message);
|
|
@@ -6340,7 +6405,7 @@ ${installBlock}
|
|
|
6340
6405
|
);
|
|
6341
6406
|
process.exit(0);
|
|
6342
6407
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
6343
|
-
process.stdout.write(`mcph ${true ? "0.
|
|
6408
|
+
process.stdout.write(`mcph ${true ? "0.29.0" : "dev"}
|
|
6344
6409
|
`);
|
|
6345
6410
|
process.exit(0);
|
|
6346
6411
|
} else {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yawlabs/mcph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"description": "mcp.hosting — one install, all your MCP servers, managed from the cloud",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"author": "Yaw Labs <contact@yaw.sh> (https://yaw.sh)",
|
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
"files": [
|
|
12
12
|
"dist",
|
|
13
13
|
"!dist/**/*.test.*",
|
|
14
|
-
"README.md"
|
|
14
|
+
"README.md",
|
|
15
|
+
"CHANGELOG.md"
|
|
15
16
|
],
|
|
16
17
|
"scripts": {
|
|
17
18
|
"build": "tsup",
|