@yawlabs/mcph 0.40.0 → 0.42.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 +8 -0
- package/dist/index.js +342 -6
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
|
|
3
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
4
|
|
|
5
|
+
## 0.42.0 — 2026-04-18
|
|
6
|
+
|
|
7
|
+
- **`mcph completion <shell>` — shell completion scripts** — Prints a completion script for `bash`, `zsh`, `fish`, or `powershell` to stdout so users can one-line it into their completions directory. Each script covers every known subcommand (install, doctor, servers, bundles, compliance, reset-learning, completion) with positional choices (install clients, bundles actions, completion shells) and per-subcommand flags (`--json`, `--scope`, `--token`, `--force`, etc.). Every template derives from a single `SUBCOMMAND_SPEC` table so adding a new subcommand elsewhere updates all four shells at once — no drift between what the CLI accepts and what it completes. Install hints are inlined as comments at the top of each generated script: the bash file drops into `~/.local/share/bash-completion/completions/mcph`, zsh into any `$fpath` dir as `_mcph`, fish into `~/.config/fish/completions/mcph.fish`, pwsh appended to `$PROFILE`.
|
|
8
|
+
|
|
9
|
+
## 0.41.0 — 2026-04-18
|
|
10
|
+
|
|
11
|
+
- **`mcph doctor --json` — machine-readable diagnostic output** — Doctor already tracks a lot of state (config files, token source, env overrides, persisted learning, installed clients, shell-history shadow hits, upgrade availability, diagnosis summary) and the text output optimises for pasting into a support ticket. `--json` emits the same data as a single structured blob so dashboards, CI scripts, and support tooling can pick fields with `jq` instead of parsing the text layout. Token is fingerprinted the same way in both modes (never raw). Section data is 1:1 with the text renderer: config (token/apiBase/loadedFiles/warnings), env overrides (null when unset), state (path/savedAt/entries; `disabled: true` when `MCPH_DISABLE_PERSISTENCE` is set), reliability (same `selectFlakyNamespaces` rollup that `mcp_connect_health` and the text RELIABILITY section use), clients probe results, shell shadow hits, upgrade info, and the exit-code diagnosis. Completes the `--json` pattern across `servers`, `bundles`, and now `doctor` — every CLI that reads state has a pipeline mode.
|
|
12
|
+
|
|
5
13
|
## 0.40.0 — 2026-04-18
|
|
6
14
|
|
|
7
15
|
- **`mcph bundles` CLI subcommand** — CLI counterpart to the `mcp_connect_bundles` meta-tool (v0.28.0). Two actions mirror the meta-tool's `action` parameter: `list` prints every curated bundle grouped by category with activate hints (static, no network, no token needed — good for browsing or sharing in onboarding docs), and `match` partitions the curated set against the user's enabled servers from the backend into ready-to-activate vs partially-installed, so a human can see in the terminal what the LLM-facing tool would suggest. The LLM tool has always been primary surface, but "what bundles exist?" is a frequent enough support question that surfacing them in the CLI earns its keep. Match only counts `isActive: true` servers — disabled ones don't auto-activate, so they shouldn't count toward "ready" — matching the LLM tool's filter so both surfaces agree. Partial bundles sort fewest-missing first to match the discover inline hint ranking. `--json` emits machine-readable output (`{bundles}` for list, `{installed, ready, partial}` for match). Exit codes: 0 success, 1 match needs a token and none resolved, 2 match couldn't reach the backend.
|
package/dist/index.js
CHANGED
|
@@ -648,6 +648,222 @@ function renderMatch(match, installed, print) {
|
|
|
648
648
|
}
|
|
649
649
|
}
|
|
650
650
|
|
|
651
|
+
// src/completion-cmd.ts
|
|
652
|
+
var COMPLETION_USAGE = `Usage: mcph completion <bash|zsh|fish|powershell>
|
|
653
|
+
|
|
654
|
+
Print a shell completion script to stdout. Redirect it to the right
|
|
655
|
+
location for your shell:
|
|
656
|
+
|
|
657
|
+
bash mcph completion bash > ~/.local/share/bash-completion/completions/mcph
|
|
658
|
+
zsh mcph completion zsh > "\${fpath[1]}/_mcph" (must be on $fpath)
|
|
659
|
+
fish mcph completion fish > ~/.config/fish/completions/mcph.fish
|
|
660
|
+
powershell mcph completion powershell >> $PROFILE`;
|
|
661
|
+
var INSTALL_CLIENTS = ["claude-code", "claude-desktop", "cursor", "vscode"];
|
|
662
|
+
var SUBCOMMAND_SPEC = [
|
|
663
|
+
{
|
|
664
|
+
name: "install",
|
|
665
|
+
positional: [...INSTALL_CLIENTS],
|
|
666
|
+
flags: ["--scope", "--token", "--project-dir", "--os", "--force", "--skip", "--dry-run", "--no-mcph-config"]
|
|
667
|
+
},
|
|
668
|
+
{ name: "doctor", flags: ["--json", "--help"] },
|
|
669
|
+
{ name: "servers", flags: ["--json", "--help"] },
|
|
670
|
+
{ name: "bundles", positional: ["list", "match"], flags: ["--json", "--help"] },
|
|
671
|
+
{ name: "compliance", flags: ["--publish", "--help"] },
|
|
672
|
+
{ name: "reset-learning", flags: ["--help"] },
|
|
673
|
+
{ name: "completion", positional: ["bash", "zsh", "fish", "powershell"], flags: ["--help"] },
|
|
674
|
+
{ name: "help", flags: [] }
|
|
675
|
+
];
|
|
676
|
+
function parseCompletionArgs(argv) {
|
|
677
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
678
|
+
return { ok: false, error: COMPLETION_USAGE };
|
|
679
|
+
}
|
|
680
|
+
const positional = argv.filter((a) => !a.startsWith("-"));
|
|
681
|
+
if (positional.length === 0) {
|
|
682
|
+
return { ok: false, error: `mcph completion: missing shell argument
|
|
683
|
+
|
|
684
|
+
${COMPLETION_USAGE}` };
|
|
685
|
+
}
|
|
686
|
+
if (positional.length > 1) {
|
|
687
|
+
return { ok: false, error: `mcph completion: too many arguments
|
|
688
|
+
|
|
689
|
+
${COMPLETION_USAGE}` };
|
|
690
|
+
}
|
|
691
|
+
const shell = positional[0];
|
|
692
|
+
if (shell !== "bash" && shell !== "zsh" && shell !== "fish" && shell !== "powershell") {
|
|
693
|
+
return { ok: false, error: `mcph completion: unknown shell "${shell}"
|
|
694
|
+
|
|
695
|
+
${COMPLETION_USAGE}` };
|
|
696
|
+
}
|
|
697
|
+
return { ok: true, options: { shell } };
|
|
698
|
+
}
|
|
699
|
+
async function runCompletion(opts = {}) {
|
|
700
|
+
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
701
|
+
const writeErr = opts.err ?? ((s) => process.stderr.write(s));
|
|
702
|
+
const lines = [];
|
|
703
|
+
const print = (s) => {
|
|
704
|
+
lines.push(s);
|
|
705
|
+
write(`${s}
|
|
706
|
+
`);
|
|
707
|
+
};
|
|
708
|
+
if (!opts.shell) {
|
|
709
|
+
writeErr(`mcph completion: missing shell argument
|
|
710
|
+
${COMPLETION_USAGE}
|
|
711
|
+
`);
|
|
712
|
+
return { exitCode: 2, lines };
|
|
713
|
+
}
|
|
714
|
+
const script = renderScript(opts.shell);
|
|
715
|
+
print(script);
|
|
716
|
+
return { exitCode: 0, lines };
|
|
717
|
+
}
|
|
718
|
+
function renderScript(shell) {
|
|
719
|
+
switch (shell) {
|
|
720
|
+
case "bash":
|
|
721
|
+
return renderBash();
|
|
722
|
+
case "zsh":
|
|
723
|
+
return renderZsh();
|
|
724
|
+
case "fish":
|
|
725
|
+
return renderFish();
|
|
726
|
+
case "powershell":
|
|
727
|
+
return renderPowershell();
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
function renderBash() {
|
|
731
|
+
const subcommandList = SUBCOMMAND_SPEC.map((s) => s.name).join(" ");
|
|
732
|
+
const topLevelFlags = "--help -h --version -V";
|
|
733
|
+
const cases = SUBCOMMAND_SPEC.map((spec) => {
|
|
734
|
+
const posClause = spec.positional ? ` if [[ $cword -eq 2 ]]; then
|
|
735
|
+
COMPREPLY=( $(compgen -W "${spec.positional.join(" ")} ${spec.flags.join(" ")}" -- "$cur") )
|
|
736
|
+
return 0
|
|
737
|
+
fi` : "";
|
|
738
|
+
return ` ${spec.name})
|
|
739
|
+
${posClause}
|
|
740
|
+
COMPREPLY=( $(compgen -W "${spec.flags.join(" ")}" -- "$cur") )
|
|
741
|
+
return 0
|
|
742
|
+
;;`;
|
|
743
|
+
}).join("\n");
|
|
744
|
+
return `# bash completion for mcph \u2014 generated by \`mcph completion bash\`
|
|
745
|
+
# Install: save this to ~/.local/share/bash-completion/completions/mcph
|
|
746
|
+
# or source it from your .bashrc.
|
|
747
|
+
_mcph() {
|
|
748
|
+
local cur prev words cword
|
|
749
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
750
|
+
cword=$COMP_CWORD
|
|
751
|
+
|
|
752
|
+
if [[ $cword -eq 1 ]]; then
|
|
753
|
+
COMPREPLY=( $(compgen -W "${subcommandList} ${topLevelFlags}" -- "$cur") )
|
|
754
|
+
return 0
|
|
755
|
+
fi
|
|
756
|
+
|
|
757
|
+
case "\${COMP_WORDS[1]}" in
|
|
758
|
+
${cases}
|
|
759
|
+
esac
|
|
760
|
+
}
|
|
761
|
+
complete -F _mcph mcph
|
|
762
|
+
`;
|
|
763
|
+
}
|
|
764
|
+
function renderZsh() {
|
|
765
|
+
const subcommandDescriptions = {
|
|
766
|
+
install: "Auto-edit an MCP client's config",
|
|
767
|
+
doctor: "Print diagnostic of mcph setup",
|
|
768
|
+
servers: "List servers in your mcp.hosting dashboard",
|
|
769
|
+
bundles: "Browse curated multi-server bundles",
|
|
770
|
+
compliance: "Run the compliance suite against a server",
|
|
771
|
+
"reset-learning": "Clear cross-session learning history",
|
|
772
|
+
completion: "Print a shell completion script",
|
|
773
|
+
help: "Show usage"
|
|
774
|
+
};
|
|
775
|
+
const subcommandList = SUBCOMMAND_SPEC.map((s) => ` '${s.name}:${subcommandDescriptions[s.name] ?? ""}'`).join(
|
|
776
|
+
"\n"
|
|
777
|
+
);
|
|
778
|
+
const argsCases = SUBCOMMAND_SPEC.map((spec) => {
|
|
779
|
+
const lines = [` ${spec.name})`];
|
|
780
|
+
if (spec.positional) {
|
|
781
|
+
lines.push(` _arguments '1: :(${spec.positional.join(" ")})' '*: :(${spec.flags.join(" ")})'`);
|
|
782
|
+
} else {
|
|
783
|
+
lines.push(` _arguments '*: :(${spec.flags.join(" ")})'`);
|
|
784
|
+
}
|
|
785
|
+
lines.push(" ;;");
|
|
786
|
+
return lines.join("\n");
|
|
787
|
+
}).join("\n");
|
|
788
|
+
return `#compdef mcph
|
|
789
|
+
# zsh completion for mcph \u2014 generated by \`mcph completion zsh\`
|
|
790
|
+
# Install: save this to a file on your $fpath named _mcph
|
|
791
|
+
# (e.g., ~/.zsh/completions/_mcph), then rebuild completions:
|
|
792
|
+
# autoload -U compinit && compinit
|
|
793
|
+
_mcph() {
|
|
794
|
+
local context state line
|
|
795
|
+
_arguments -C \\
|
|
796
|
+
'1: :->cmd' \\
|
|
797
|
+
'*::arg:->args'
|
|
798
|
+
|
|
799
|
+
case $state in
|
|
800
|
+
cmd)
|
|
801
|
+
_values 'mcph subcommand' \\
|
|
802
|
+
${subcommandList}
|
|
803
|
+
;;
|
|
804
|
+
args)
|
|
805
|
+
case $line[1] in
|
|
806
|
+
${argsCases}
|
|
807
|
+
esac
|
|
808
|
+
;;
|
|
809
|
+
esac
|
|
810
|
+
}
|
|
811
|
+
_mcph "$@"
|
|
812
|
+
`;
|
|
813
|
+
}
|
|
814
|
+
function renderFish() {
|
|
815
|
+
const header = `# fish completion for mcph \u2014 generated by \`mcph completion fish\`
|
|
816
|
+
# Install: save this to ~/.config/fish/completions/mcph.fish
|
|
817
|
+
complete -c mcph -f`;
|
|
818
|
+
const subcommandLines = SUBCOMMAND_SPEC.map((spec) => {
|
|
819
|
+
return `complete -c mcph -n __fish_use_subcommand -a ${spec.name}`;
|
|
820
|
+
});
|
|
821
|
+
const positionalLines = [];
|
|
822
|
+
const flagLines = [];
|
|
823
|
+
for (const spec of SUBCOMMAND_SPEC) {
|
|
824
|
+
if (spec.positional) {
|
|
825
|
+
for (const p of spec.positional) {
|
|
826
|
+
positionalLines.push(`complete -c mcph -n "__fish_seen_subcommand_from ${spec.name}" -a ${p}`);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
for (const f of spec.flags) {
|
|
830
|
+
const long = f.replace(/^--/, "");
|
|
831
|
+
flagLines.push(`complete -c mcph -n "__fish_seen_subcommand_from ${spec.name}" -l ${long}`);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
return [header, "", ...subcommandLines, "", ...positionalLines, "", ...flagLines, ""].join("\n");
|
|
835
|
+
}
|
|
836
|
+
function renderPowershell() {
|
|
837
|
+
const subcommandNames = SUBCOMMAND_SPEC.map((s) => `'${s.name}'`).join(", ");
|
|
838
|
+
const caseBranches = SUBCOMMAND_SPEC.map((spec) => {
|
|
839
|
+
const positional = spec.positional ? spec.positional.map((p) => `'${p}'`).join(", ") : "";
|
|
840
|
+
const flags = spec.flags.map((f) => `'${f}'`).join(", ");
|
|
841
|
+
const positionalLine = positional ? ` $completions += @(${positional})
|
|
842
|
+
` : "";
|
|
843
|
+
return ` '${spec.name}' {
|
|
844
|
+
${positionalLine} $completions += @(${flags})
|
|
845
|
+
}`;
|
|
846
|
+
}).join("\n");
|
|
847
|
+
return `# PowerShell completion for mcph \u2014 generated by \`mcph completion powershell\`
|
|
848
|
+
# Install: append this script to your profile ($PROFILE) and reload.
|
|
849
|
+
Register-ArgumentCompleter -CommandName mcph -ScriptBlock {
|
|
850
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
851
|
+
$tokens = $commandAst.CommandElements | ForEach-Object { $_.ToString() }
|
|
852
|
+
$completions = @()
|
|
853
|
+
if ($tokens.Count -le 2) {
|
|
854
|
+
$completions = @(${subcommandNames}, '--help', '-h', '--version', '-V')
|
|
855
|
+
} else {
|
|
856
|
+
switch ($tokens[1]) {
|
|
857
|
+
${caseBranches}
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
$completions | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
|
|
861
|
+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
`;
|
|
865
|
+
}
|
|
866
|
+
|
|
651
867
|
// src/compliance-cmd.ts
|
|
652
868
|
import { spawn } from "child_process";
|
|
653
869
|
import { request as request2 } from "undici";
|
|
@@ -1219,8 +1435,9 @@ function selectFlakyNamespaces(entries, limit) {
|
|
|
1219
1435
|
}
|
|
1220
1436
|
|
|
1221
1437
|
// src/doctor-cmd.ts
|
|
1222
|
-
var VERSION = true ? "0.
|
|
1438
|
+
var VERSION = true ? "0.42.0" : "dev";
|
|
1223
1439
|
async function runDoctor(opts = {}) {
|
|
1440
|
+
if (opts.json) return runDoctorJson(opts);
|
|
1224
1441
|
const lines = [];
|
|
1225
1442
|
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
1226
1443
|
const print = (s = "") => {
|
|
@@ -1309,6 +1526,101 @@ async function runDoctor(opts = {}) {
|
|
|
1309
1526
|
}
|
|
1310
1527
|
return { exitCode, lines, snapshot: { version: VERSION, config, clients } };
|
|
1311
1528
|
}
|
|
1529
|
+
async function runDoctorJson(opts) {
|
|
1530
|
+
const lines = [];
|
|
1531
|
+
const write = opts.out ?? ((s) => process.stdout.write(s));
|
|
1532
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
1533
|
+
const home = opts.home ?? homedir4();
|
|
1534
|
+
const os = opts.os ?? CURRENT_OS;
|
|
1535
|
+
const env = opts.env ?? process.env;
|
|
1536
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
1537
|
+
const config = await loadMcphConfig({ cwd, home, env });
|
|
1538
|
+
const clients = probeClients({ home, os, cwd });
|
|
1539
|
+
const envVarNames = [
|
|
1540
|
+
"MCPH_POLL_INTERVAL",
|
|
1541
|
+
"MCPH_SERVER_CAP",
|
|
1542
|
+
"MCPH_MIN_COMPLIANCE",
|
|
1543
|
+
"MCPH_AUTO_LOAD",
|
|
1544
|
+
"MCPH_PRUNE_RESPONSES"
|
|
1545
|
+
];
|
|
1546
|
+
const envOverrides = {};
|
|
1547
|
+
for (const name of envVarNames) {
|
|
1548
|
+
const raw = env[name];
|
|
1549
|
+
envOverrides[name] = raw === void 0 || raw === "" ? null : raw;
|
|
1550
|
+
}
|
|
1551
|
+
const persistRaw = env.MCPH_DISABLE_PERSISTENCE;
|
|
1552
|
+
const persistDisabled = persistRaw !== void 0 && persistRaw !== "" && (persistRaw === "1" || persistRaw.toLowerCase() === "true");
|
|
1553
|
+
const state = persistDisabled ? { disabled: true, path: null, savedAt: null, learningEntries: null, packHistoryEntries: null } : await (async () => {
|
|
1554
|
+
const filePath = join4(userConfigDir(home), STATE_FILENAME);
|
|
1555
|
+
const persisted = await loadState(filePath);
|
|
1556
|
+
const fresh = persisted.savedAt === 0;
|
|
1557
|
+
return {
|
|
1558
|
+
disabled: false,
|
|
1559
|
+
path: filePath,
|
|
1560
|
+
savedAt: fresh ? null : new Date(persisted.savedAt).toISOString(),
|
|
1561
|
+
learningEntries: fresh ? 0 : Object.keys(persisted.learning).length,
|
|
1562
|
+
packHistoryEntries: fresh ? 0 : persisted.packHistory.length
|
|
1563
|
+
};
|
|
1564
|
+
})();
|
|
1565
|
+
const reliability = [];
|
|
1566
|
+
if (!persistDisabled) {
|
|
1567
|
+
const filePath = join4(userConfigDir(home), STATE_FILENAME);
|
|
1568
|
+
const persisted = await loadState(filePath);
|
|
1569
|
+
if (persisted.savedAt !== 0) {
|
|
1570
|
+
const entries = Object.entries(persisted.learning).map(([namespace, usage]) => ({ namespace, usage }));
|
|
1571
|
+
for (const { namespace, usage } of selectFlakyNamespaces(entries, 5)) {
|
|
1572
|
+
reliability.push({
|
|
1573
|
+
namespace,
|
|
1574
|
+
dispatched: usage.dispatched,
|
|
1575
|
+
succeeded: usage.succeeded,
|
|
1576
|
+
successRate: usage.succeeded / usage.dispatched,
|
|
1577
|
+
lastUsedAt: new Date(usage.lastUsedAt).toISOString()
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
const shellShadows = scanShellHistoryForShadows({ home, env });
|
|
1583
|
+
const skipCheck = opts.skipRegistryCheck === true || Boolean(process.env.VITEST);
|
|
1584
|
+
const latest = skipCheck ? null : await fetchLatestVersion(opts.registryFetch);
|
|
1585
|
+
const stale = latest !== null && VERSION !== "dev" && compareSemver(VERSION, latest) < 0;
|
|
1586
|
+
let exitCode = 0;
|
|
1587
|
+
let summary;
|
|
1588
|
+
if (config.token === null) {
|
|
1589
|
+
exitCode = 1;
|
|
1590
|
+
summary = "No token resolved \u2014 mcph cannot start.";
|
|
1591
|
+
} else if (config.warnings.length > 0) {
|
|
1592
|
+
exitCode = 2;
|
|
1593
|
+
summary = "Token present, but warnings need attention.";
|
|
1594
|
+
} else {
|
|
1595
|
+
summary = stale ? "Healthy, but an upgrade is available." : "All good. mcph should start cleanly.";
|
|
1596
|
+
}
|
|
1597
|
+
const snapshotJson = {
|
|
1598
|
+
timestamp,
|
|
1599
|
+
version: VERSION,
|
|
1600
|
+
platform: os,
|
|
1601
|
+
token: { fingerprint: tokenFingerprint(config.token), source: config.tokenSource },
|
|
1602
|
+
apiBase: { value: config.apiBase, source: config.apiBaseSource },
|
|
1603
|
+
loadedFiles: config.loadedFiles.map((f) => ({
|
|
1604
|
+
scope: f.scope,
|
|
1605
|
+
path: f.path,
|
|
1606
|
+
...f.version !== void 0 ? { schemaVersion: f.version } : {},
|
|
1607
|
+
schemaAhead: f.version !== void 0 && f.version > CURRENT_SCHEMA_VERSION
|
|
1608
|
+
})),
|
|
1609
|
+
warnings: config.warnings,
|
|
1610
|
+
env: envOverrides,
|
|
1611
|
+
state,
|
|
1612
|
+
reliability,
|
|
1613
|
+
clients,
|
|
1614
|
+
shellShadows,
|
|
1615
|
+
upgrade: { current: VERSION, latest, stale },
|
|
1616
|
+
diagnosis: { exitCode, summary }
|
|
1617
|
+
};
|
|
1618
|
+
const blob = JSON.stringify(snapshotJson, null, 2);
|
|
1619
|
+
lines.push(blob);
|
|
1620
|
+
write(`${blob}
|
|
1621
|
+
`);
|
|
1622
|
+
return { exitCode, lines, snapshot: { version: VERSION, config, clients } };
|
|
1623
|
+
}
|
|
1312
1624
|
function renderEnvSection(opts) {
|
|
1313
1625
|
const { env, print } = opts;
|
|
1314
1626
|
const vars = [
|
|
@@ -4207,7 +4519,7 @@ function categorizeSpawnError(err) {
|
|
|
4207
4519
|
}
|
|
4208
4520
|
async function connectToUpstream(config, onDisconnect, onListChanged) {
|
|
4209
4521
|
const client = new Client(
|
|
4210
|
-
{ name: "mcph", version: true ? "0.
|
|
4522
|
+
{ name: "mcph", version: true ? "0.42.0" : "dev" },
|
|
4211
4523
|
{ capabilities: {} }
|
|
4212
4524
|
);
|
|
4213
4525
|
let transport;
|
|
@@ -4688,7 +5000,7 @@ var ConnectServer = class _ConnectServer {
|
|
|
4688
5000
|
this.apiUrl = apiUrl6;
|
|
4689
5001
|
this.token = token6;
|
|
4690
5002
|
this.server = new Server(
|
|
4691
|
-
{ name: "mcph", version: true ? "0.
|
|
5003
|
+
{ name: "mcph", version: true ? "0.42.0" : "dev" },
|
|
4692
5004
|
{
|
|
4693
5005
|
capabilities: {
|
|
4694
5006
|
tools: { listChanged: true },
|
|
@@ -6852,6 +7164,7 @@ var KNOWN_SUBCOMMANDS = [
|
|
|
6852
7164
|
"reset-learning",
|
|
6853
7165
|
"servers",
|
|
6854
7166
|
"bundles",
|
|
7167
|
+
"completion",
|
|
6855
7168
|
"help",
|
|
6856
7169
|
"--help",
|
|
6857
7170
|
"-h",
|
|
@@ -6870,7 +7183,21 @@ if (subcommand === "compliance") {
|
|
|
6870
7183
|
}
|
|
6871
7184
|
runInstall(parsed.options).then((r) => process.exit(r.exitCode));
|
|
6872
7185
|
} else if (subcommand === "doctor") {
|
|
6873
|
-
|
|
7186
|
+
const doctorArgs = process.argv.slice(3);
|
|
7187
|
+
const doctorJson = doctorArgs.includes("--json");
|
|
7188
|
+
const doctorUnknown = doctorArgs.find((a) => a !== "--json" && a !== "--help" && a !== "-h");
|
|
7189
|
+
if (doctorArgs.includes("--help") || doctorArgs.includes("-h")) {
|
|
7190
|
+
process.stdout.write(
|
|
7191
|
+
"Usage: mcph doctor [--json]\n\n Print a diagnostic of your mcph setup.\n\n --json Emit machine-readable JSON instead of text.\n"
|
|
7192
|
+
);
|
|
7193
|
+
process.exit(0);
|
|
7194
|
+
}
|
|
7195
|
+
if (doctorUnknown) {
|
|
7196
|
+
process.stderr.write(`mcph doctor: unknown argument "${doctorUnknown}"
|
|
7197
|
+
`);
|
|
7198
|
+
process.exit(2);
|
|
7199
|
+
}
|
|
7200
|
+
runDoctor({ json: doctorJson }).then((r) => process.exit(r.exitCode));
|
|
6874
7201
|
} else if (subcommand === "reset-learning") {
|
|
6875
7202
|
runResetLearning().then((r) => process.exit(r.exitCode));
|
|
6876
7203
|
} else if (subcommand === "servers") {
|
|
@@ -6889,6 +7216,14 @@ if (subcommand === "compliance") {
|
|
|
6889
7216
|
process.exit(2);
|
|
6890
7217
|
}
|
|
6891
7218
|
runBundlesCommand(parsed.options).then((r) => process.exit(r.exitCode));
|
|
7219
|
+
} else if (subcommand === "completion") {
|
|
7220
|
+
const parsed = parseCompletionArgs(process.argv.slice(3));
|
|
7221
|
+
if (!parsed.ok) {
|
|
7222
|
+
process.stderr.write(`${parsed.error}
|
|
7223
|
+
`);
|
|
7224
|
+
process.exit(2);
|
|
7225
|
+
}
|
|
7226
|
+
runCompletion(parsed.options).then((r) => process.exit(r.exitCode));
|
|
6892
7227
|
} else if (subcommand === "--help" || subcommand === "-h" || subcommand === "help") {
|
|
6893
7228
|
const installBlock = ` ${INSTALL_USAGE.replace(/^Usage: /, "").replace(/\n/g, "\n ")}`;
|
|
6894
7229
|
process.stdout.write(
|
|
@@ -6898,11 +7233,12 @@ if (subcommand === "compliance") {
|
|
|
6898
7233
|
Usage:
|
|
6899
7234
|
mcph Run as MCP server (requires a token)
|
|
6900
7235
|
mcph install <client> [flags] Auto-edit an MCP client's config to launch mcph
|
|
6901
|
-
mcph doctor
|
|
7236
|
+
mcph doctor [--json] Print loaded config + detected clients (support diagnostic)
|
|
6902
7237
|
mcph servers [--json] List servers configured in your mcp.hosting dashboard
|
|
6903
7238
|
mcph bundles [list|match] Browse curated multi-server bundles
|
|
6904
7239
|
mcph compliance <target> [flags] Run the compliance suite against an MCP server
|
|
6905
7240
|
mcph reset-learning Clear cross-session learning history (~/.mcph/state.json)
|
|
7241
|
+
mcph completion <shell> Print a shell completion script (bash|zsh|fish|powershell)
|
|
6906
7242
|
mcph --version Print version
|
|
6907
7243
|
|
|
6908
7244
|
Install:
|
|
@@ -6923,7 +7259,7 @@ ${installBlock}
|
|
|
6923
7259
|
);
|
|
6924
7260
|
process.exit(0);
|
|
6925
7261
|
} else if (subcommand === "--version" || subcommand === "-V") {
|
|
6926
|
-
process.stdout.write(`mcph ${true ? "0.
|
|
7262
|
+
process.stdout.write(`mcph ${true ? "0.42.0" : "dev"}
|
|
6927
7263
|
`);
|
|
6928
7264
|
process.exit(0);
|
|
6929
7265
|
} else if (subcommand && !subcommand.startsWith("-")) {
|
package/package.json
CHANGED