@holdyourvoice/hyv 2.9.24 → 2.9.25

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 CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  All notable CLI changes. Also mirrored to [holdyourvoice.com/changelog](https://holdyourvoice.com/changelog) for user-facing releases.
4
4
 
5
+ ## [2.9.25] — 2026-07-04
6
+
7
+ ### Fixed
8
+ - **MCP stdio pollution** — `hyv mcp` no longer prints setup banners to stdout when spawned by Cursor/Claude/ChatGPT (fixes "Unexpected token … is not valid JSON" toast spam on app open)
9
+ - Auto-detects piped stdout (`!isTTY`) or explicit `--stdio` flag; MCP configs now use `mcp --stdio`
10
+ - Interactive terminal runs still show setup on stderr before the JSON-RPC server starts
11
+
5
12
  ## [2.9.15] — 2026-06-18
6
13
 
7
14
  ### Added
package/dist/index.js CHANGED
@@ -5413,7 +5413,7 @@ function printFreePaidMatrix(opts = {}) {
5413
5413
  First month $1 \u2192 ${PRICING_URL}`));
5414
5414
  console.log(import_chalk.default.dim(" hyv init | hyv plan --upgrade\n"));
5415
5415
  }
5416
- var import_chalk, NPX_EXAMPLES, FREE_CLI_COMMANDS, PAID_FEATURES, FREE_WEB_TOOLS, COMMUNITY_URL, PRICING_URL, DASHBOARD_BILLING_URL;
5416
+ var import_chalk, NPX_EXAMPLES, FREE_CLI_COMMANDS, PAID_FEATURES, FREE_WEB_TOOLS, COMMUNITY_URL, X_URL, PRICING_URL, DASHBOARD_BILLING_URL;
5417
5417
  var init_free_paid = __esm({
5418
5418
  "src/lib/free-paid.ts"() {
5419
5419
  "use strict";
@@ -5460,6 +5460,7 @@ var init_free_paid = __esm({
5460
5460
  { name: "Blog", url: "https://holdyourvoice.com/blog" }
5461
5461
  ];
5462
5462
  COMMUNITY_URL = "https://holdyourvoice.com/community";
5463
+ X_URL = "https://x.com/istupidpreneur";
5463
5464
  PRICING_URL = "https://holdyourvoice.com/#pricing";
5464
5465
  DASHBOARD_BILLING_URL = "https://holdyourvoice.com/dashboard?tab=billing";
5465
5466
  }
@@ -17766,6 +17767,18 @@ var import_child_process4 = require("child_process");
17766
17767
  // src/lib/cli-entry.ts
17767
17768
  var fs18 = __toESM(require("fs"));
17768
17769
  var path17 = __toESM(require("path"));
17770
+
17771
+ // src/lib/mcp-stdio.ts
17772
+ function isMcpStdioMode(opts) {
17773
+ if (opts?.stdio)
17774
+ return true;
17775
+ if (process.env.HYV_MCP_STDIO === "1" || process.env.HYV_MCP_STDIO === "true")
17776
+ return true;
17777
+ return !process.stdout.isTTY;
17778
+ }
17779
+ var MCP_SERVER_ARGS = ["mcp", "--stdio"];
17780
+
17781
+ // src/lib/cli-entry.ts
17769
17782
  function resolveCliEntry() {
17770
17783
  const candidates = [
17771
17784
  path17.resolve(process.argv[1] || ""),
@@ -17777,9 +17790,9 @@ function resolveCliEntry() {
17777
17790
  function mcpServerCommand() {
17778
17791
  const entry = resolveCliEntry();
17779
17792
  if (entry) {
17780
- return { command: process.execPath, args: [entry, "mcp"] };
17793
+ return { command: process.execPath, args: [entry, ...MCP_SERVER_ARGS] };
17781
17794
  }
17782
- return { command: "hyv", args: ["mcp"] };
17795
+ return { command: "hyv", args: [...MCP_SERVER_ARGS] };
17783
17796
  }
17784
17797
  function mcpServerSnippet() {
17785
17798
  const { command, args: args2 } = mcpServerCommand();
@@ -17792,9 +17805,9 @@ async function testMcpStdioSubprocess() {
17792
17805
  if (!entry)
17793
17806
  return { ok: false };
17794
17807
  return new Promise((resolve18) => {
17795
- const child = (0, import_child_process4.spawn)(process.execPath, [entry, "mcp"], {
17808
+ const child = (0, import_child_process4.spawn)(process.execPath, [entry, "mcp", "--stdio"], {
17796
17809
  stdio: ["pipe", "pipe", "pipe"],
17797
- env: { ...process.env, HYV_POSTINSTALL_QUIET: "1" }
17810
+ env: { ...process.env, HYV_POSTINSTALL_QUIET: "1", HYV_MCP_STDIO: "1" }
17798
17811
  });
17799
17812
  let buffer = "";
17800
17813
  let settled = false;
@@ -19159,16 +19172,17 @@ More: hyv content ci`
19159
19172
  },
19160
19173
  share: {
19161
19174
  title: "Share your voice fingerprint",
19162
- body: `Social post template:
19175
+ body: `Social post template (X / LinkedIn):
19163
19176
 
19164
19177
  I run my AI drafts through @holdyourvoice/hyv before they ship.
19165
19178
 
19166
- Free local scan caught [N] patterns in 2 seconds \u2014 no API, offline.
19179
+ Free local scan caught 34 patterns in 2 seconds \u2014 score 0/100. no API, offline.
19167
19180
 
19168
19181
  Cursor/Claude agents can call hyv mcp tools directly.
19169
19182
 
19170
19183
  Try: npx @holdyourvoice/hyv welcome
19171
19184
 
19185
+ ${X_URL}
19172
19186
  ${COMMUNITY_URL}`
19173
19187
  }
19174
19188
  };
@@ -19448,7 +19462,7 @@ function formatChatGptConnectorGuide() {
19448
19462
  "2. Settings \u2192 Connectors \u2192 Add connector",
19449
19463
  "3. Name: **hold your voice**",
19450
19464
  "4. Command: **hyv** (or absolute path below if connector fails)",
19451
- "5. Arguments: **mcp**",
19465
+ "5. Arguments: **mcp --stdio**",
19452
19466
  "",
19453
19467
  "If the connector fails to start, use absolute paths:",
19454
19468
  ` command: ${mcpCmd.command}`,
@@ -20334,7 +20348,7 @@ function printMcpSetup() {
20334
20348
  console.log(import_chalk35.default.dim(" Skill: ~/.commandcode/skills/hyv/SKILL.md\n"));
20335
20349
  console.log(import_chalk35.default.bold("ChatGPT Desktop (manual connector)"));
20336
20350
  console.log(import_chalk35.default.dim(" Settings \u2192 Connectors \u2192 add connector"));
20337
- console.log(import_chalk35.default.dim(" Name: hold your voice | Command: hyv | Arguments: mcp"));
20351
+ console.log(import_chalk35.default.dim(" Name: hold your voice | Command: hyv | Arguments: mcp --stdio"));
20338
20352
  console.log(import_chalk35.default.dim(" Guide: ~/.chatgpt/hyv-mcp-connector.txt (after hyv doctor --fix-agents)"));
20339
20353
  console.log(import_chalk35.default.dim(" hyv mcp --setup-chatgpt"));
20340
20354
  if (IS_WIN2) {
@@ -20638,7 +20652,7 @@ registerWelcomeCommand(program2);
20638
20652
  registerContentCommand(program2);
20639
20653
  registerUpgradeCommand(program2);
20640
20654
  registerShareCommand(program2);
20641
- program2.command("mcp").description("Detect installed apps, configure MCP, and start the MCP server").option("--setup", "Show MCP setup for Claude Desktop, Cursor, Windsurf, Codex").option("--test", "Run MCP health check (tools, profile, stdio)").option("--setup-chatgpt", "Show ChatGPT connector setup instructions").option("--force", "Force re-configure MCP even if already integrated").action(async (opts) => {
20655
+ program2.command("mcp").description("Detect installed apps, configure MCP, and start the MCP server").option("--setup", "Show MCP setup for Claude Desktop, Cursor, Windsurf, Codex").option("--test", "Run MCP health check (tools, profile, stdio)").option("--setup-chatgpt", "Show ChatGPT connector setup instructions").option("--force", "Force re-configure MCP even if already integrated").option("--stdio", "Stdio MCP mode \u2014 no stdout banners (auto when stdout is piped)").action(async (opts) => {
20642
20656
  if (opts.setup) {
20643
20657
  printMcpSetup();
20644
20658
  return;
@@ -20675,7 +20689,7 @@ program2.command("mcp").description("Detect installed apps, configure MCP, and s
20675
20689
  console.log(import_chalk36.default.dim(" 3. Add connector:"));
20676
20690
  console.log(import_chalk36.default.dim(" Name: ") + import_chalk36.default.cyan("hold your voice"));
20677
20691
  console.log(import_chalk36.default.dim(" Command: ") + import_chalk36.default.cyan("hyv") + import_chalk36.default.dim(" (full path on Windows if needed)"));
20678
- console.log(import_chalk36.default.dim(" Arguments: ") + import_chalk36.default.cyan("mcp"));
20692
+ console.log(import_chalk36.default.dim(" Arguments: ") + import_chalk36.default.cyan("mcp --stdio"));
20679
20693
  console.log(import_chalk36.default.dim(" 4. Save, restart ChatGPT Desktop"));
20680
20694
  console.log(import_chalk36.default.dim(' 5. Test: "scan this with hold your voice"\n'));
20681
20695
  console.log(import_chalk36.default.dim(" If connector fails to start, use full paths from:"));
@@ -20697,20 +20711,26 @@ program2.command("mcp").description("Detect installed apps, configure MCP, and s
20697
20711
  console.log("");
20698
20712
  return;
20699
20713
  }
20700
- console.log(import_chalk36.default.bold("\nhold your voice \u2014 detecting and configuring mcp...\n"));
20714
+ if (isMcpStdioMode(opts)) {
20715
+ await startMcpServer();
20716
+ return;
20717
+ }
20718
+ const err = (msg) => process.stderr.write(msg + "\n");
20719
+ err(import_chalk36.default.bold("\nhold your voice \u2014 detecting and configuring mcp...\n"));
20701
20720
  const result = runMcpAutoIntegrate({ force: Boolean(opts.force) });
20721
+ const reportLines = [];
20722
+ const origLog = console.log;
20723
+ console.log = (...args2) => {
20724
+ reportLines.push(args2.map(String).join(" "));
20725
+ };
20702
20726
  printMcpIntegrateReport(result, { force: Boolean(opts.force) });
20703
- console.log(import_chalk36.default.green.bold("\n\u2713 hold your voice \u2014 mcp setup complete\n"));
20704
- console.log(import_chalk36.default.dim(" " + import_chalk36.default.bold("To integrate HYV with all MCP-compatible apps on your machine")));
20705
- console.log(import_chalk36.default.dim(" (Cursor, Claude Desktop, Windsurf, Antigravity, OpenCode, ChatGPT, Codex,"));
20706
- console.log(import_chalk36.default.dim(" Command Code, and more) \u2014 simply run:"));
20707
- console.log("");
20708
- console.log(import_chalk36.default.cyan(" hyv mcp"));
20709
- console.log("");
20710
- console.log(import_chalk36.default.dim(" It auto-detects installed apps, configures MCP servers, and is ready"));
20711
- console.log(import_chalk36.default.dim(" for scanning, rewriting, and voice-profile validation in any tool.\n"));
20712
- console.log(import_chalk36.default.dim("\nstarting MCP server (press Ctrl+C to stop)...\n"));
20713
- startMcpServer();
20727
+ console.log = origLog;
20728
+ for (const line of reportLines)
20729
+ err(line);
20730
+ err(import_chalk36.default.green.bold("\n\u2713 hold your voice \u2014 mcp setup complete\n"));
20731
+ err(import_chalk36.default.dim(" restart cursor / claude desktop if they were open during setup"));
20732
+ err(import_chalk36.default.dim("\nstarting MCP server (press Ctrl+C to stop) \u2014 JSON-RPC on stdout...\n"));
20733
+ await startMcpServer();
20714
20734
  });
20715
20735
  program2.command("export").description("Export voice profile for LLMs").argument("[format]", "Export format (claude, chatgpt, generic, cursor)", "claude").option("--output <file>", "Write to file instead of stdout").option("--json", "Output as JSON").action(async (format, opts) => {
20716
20736
  await exportCommand(format, opts);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@holdyourvoice/hyv",
3
- "version": "2.9.24",
3
+ "version": "2.9.25",
4
4
  "description": "Free local AI writing scan for cursor & claude. MCP server, 220+ pattern detection, voice profiles. npx @holdyourvoice/hyv welcome",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -78,9 +78,9 @@ function markOnboardingComplete(hyvDir, pkgVersion) {
78
78
  function resolveHyvMcpCommand(pkgDir) {
79
79
  const entry = path.join(pkgDir, 'dist', 'index.js');
80
80
  if (fs.existsSync(entry)) {
81
- return { command: process.execPath, args: [entry, 'mcp'] };
81
+ return { command: process.execPath, args: [entry, 'mcp', '--stdio'] };
82
82
  }
83
- return { command: 'hyv', args: ['mcp'] };
83
+ return { command: 'hyv', args: ['mcp', '--stdio'] };
84
84
  }
85
85
 
86
86
  /** OpenCode local MCP uses a command array: [node, entry, mcp] */