sticky-note-cli 3.1.29 → 3.1.31

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/bin/cli.js CHANGED
@@ -442,6 +442,35 @@ function detectMcpServers() {
442
442
  } catch (err) { debugLog("detectMcpServers copilot mcp-config: " + (err.message || err)); }
443
443
  }
444
444
 
445
+ // Also detect from ~/.claude/settings.json (global Claude Code settings).
446
+ // This captures servers like Render that users configure globally rather than per-project.
447
+ const globalClaudeSettingsPath = path.join(os.homedir(), ".claude", "settings.json");
448
+ if (fs.existsSync(globalClaudeSettingsPath)) {
449
+ try {
450
+ const globalSettings = JSON.parse(fs.readFileSync(globalClaudeSettingsPath, "utf-8"));
451
+ const globalMcp = globalSettings.mcpServers || {};
452
+ for (const [name, config] of Object.entries(globalMcp)) {
453
+ if (servers.has(name)) continue; // project-level takes precedence
454
+ if (config.type === "permission-detected") continue;
455
+ const entry = {
456
+ name,
457
+ type: config.type || config.transport || "stdio",
458
+ source: "~/.claude/settings.json",
459
+ };
460
+ if (config.command) entry.command = config.command;
461
+ if (config.args) entry.args = config.args;
462
+ if (config.env) entry.env = config.env;
463
+ if (config.url) entry.url = config.url;
464
+ servers.set(name, entry);
465
+ }
466
+ } catch (err) { debugLog("detectMcpServers global settings: " + (err.message || err)); }
467
+ }
468
+
469
+ // Detect servers known only from allow-list permissions (settings.local.json).
470
+ // These are servers Claude Code has permission to call but whose config isn't in
471
+ // any local file — typically account-level cloud MCPs (Figma, Sentry via claude.ai).
472
+ // We mark them "account-mcp" so the manifest records them without treating them
473
+ // as locally-provisionable servers.
445
474
  const localSettingsPath = path.join(process.cwd(), ".claude", "settings.local.json");
446
475
  if (fs.existsSync(localSettingsPath)) {
447
476
  try {
@@ -456,7 +485,7 @@ function detectMcpServers() {
456
485
  if (serverName && !servers.has(serverName)) {
457
486
  servers.set(serverName, {
458
487
  name: serverName,
459
- type: "permission-detected",
488
+ type: "account-mcp",
460
489
  source: "settings.local.json",
461
490
  });
462
491
  }
@@ -1121,8 +1150,8 @@ async function cmdInit() {
1121
1150
  mkdirSafe(path.join(envDir, "commands"));
1122
1151
  if (!fs.existsSync(envManifestDest)) {
1123
1152
  // Build manifest from detected MCP servers and skills.
1124
- // Skip permission-detected entries — they are not real server configs and would
1125
- // be synced back into .mcp.json by session-start.js, breaking Claude Code.
1153
+ // Skip permission-detected (legacy marker with no real config).
1154
+ // account-mcp entries are included — they're real cloud MCPs the team uses.
1126
1155
  const manifestData = { version: "1", mcp_servers: {}, permissions: [], env_vars: {} };
1127
1156
  for (const server of mcpServers.filter((s) => s.type !== "permission-detected")) {
1128
1157
  const entry = { type: server.type || "stdio", description: server.name, required: false };
@@ -1462,8 +1491,8 @@ function cmdUpdate() {
1462
1491
  mkdirSafe(path.join(envDir, "agents"));
1463
1492
  mkdirSafe(path.join(envDir, "commands"));
1464
1493
  if (!fs.existsSync(envManifestDest)) {
1465
- // Skip permission-detected entries — they are not real server configs and would
1466
- // be synced back into .mcp.json by session-start.js, breaking Claude Code.
1494
+ // Create manifest from scratch, skipping permission-detected (legacy marker with no real config).
1495
+ // account-mcp entries are included — they're real cloud MCPs the team uses.
1467
1496
  const detectedServers = Array.from(detectMcpServers().values()).filter((s) => s.type !== "permission-detected");
1468
1497
  const manifestData = { version: "1", mcp_servers: {}, permissions: [], env_vars: {} };
1469
1498
  for (const server of detectedServers) {
@@ -1495,6 +1524,22 @@ function cmdUpdate() {
1495
1524
  }
1496
1525
  fs.writeFileSync(envManifestDest, JSON.stringify(manifestData, null, 2) + "\n");
1497
1526
  print(` [OK] Created environment/ in ${envDir} (${detectedServers.length} MCP server(s) detected)`);
1527
+ } else {
1528
+ // Manifest already exists — strip any permission-detected entries that may have
1529
+ // been written by an older version of sticky-note. These are not real server
1530
+ // configs and cause get_environment_status to report false "missing" servers.
1531
+ const manifest = readJsonSafe(envManifestDest, {});
1532
+ const servers = manifest.mcp_servers || {};
1533
+ const stale = Object.keys(servers).filter((k) => servers[k].type === "permission-detected");
1534
+ if (stale.length > 0) {
1535
+ // Convert permission-detected → account-mcp rather than deleting.
1536
+ // These are real servers the team uses (e.g. Figma, Sentry via claude.ai account);
1537
+ // they can't be locally provisioned but should still be documented in the manifest.
1538
+ for (const k of stale) servers[k].type = "account-mcp";
1539
+ manifest.mcp_servers = servers;
1540
+ fs.writeFileSync(envManifestDest, JSON.stringify(manifest, null, 2) + "\n");
1541
+ print(` [OK] environment/manifest.json: upgraded ${stale.length} entry(s) from permission-detected to account-mcp`);
1542
+ }
1498
1543
  }
1499
1544
 
1500
1545
  print(`\n ✨ Scripts updated to v${VERSION}`);
package/bin/mcp-server.js CHANGED
@@ -529,10 +529,18 @@ async function toolGetEnvironmentStatus() {
529
529
 
530
530
  const provisioned = { mcp_servers: [], skills: [], agents: [], commands: [] };
531
531
  const missing = { mcp_servers: [] };
532
+ const accountMcp = []; // account-level cloud MCPs — connect via claude.ai, not locally provisioned
532
533
 
533
534
  // Check MCP servers
534
535
  if (manifest.mcp_servers) {
535
536
  for (const [name, config] of Object.entries(manifest.mcp_servers)) {
537
+ // Account-level cloud MCPs (Figma, Sentry, etc.) are managed by the claude.ai
538
+ // account, not local config. Report them separately — not as missing.
539
+ if (config.type === "account-mcp") {
540
+ accountMcp.push({ name, description: config.description || name });
541
+ continue;
542
+ }
543
+
536
544
  if (registeredServers.includes(name)) {
537
545
  provisioned.mcp_servers.push(name);
538
546
  } else {
@@ -598,6 +606,11 @@ async function toolGetEnvironmentStatus() {
598
606
  action: hasMissing ? "inform_user_of_missing" : "none",
599
607
  };
600
608
 
609
+ if (accountMcp.length > 0) {
610
+ result.account_mcp = accountMcp;
611
+ result.account_mcp_note = "These MCP servers are managed by the claude.ai account. Each team member connects them via their own claude.ai account — no local provisioning needed.";
612
+ }
613
+
601
614
  if (hasMissing) {
602
615
  result.missing = missing;
603
616
  const requiredMissing = missing.mcp_servers.filter((s) => s.required);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sticky-note-cli",
3
- "version": "3.1.29",
3
+ "version": "3.1.31",
4
4
  "description": "Human-to-human handoff for AI coding assistants. Git-backed shared memory for Claude Code and Copilot CLI.",
5
5
  "license": "MIT",
6
6
  "bin": {