bb-signer 0.3.10 → 0.4.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.
Files changed (2) hide show
  1. package/cli.js +83 -23
  2. package/package.json +1 -1
package/cli.js CHANGED
@@ -241,6 +241,58 @@ function fallbackToSettingsFile(ed, mcpConfig) {
241
241
  console.log(` ✅ ${ed.label}: Configured`);
242
242
  }
243
243
 
244
+ function configureClaudeJson() {
245
+ // Claude Code stores MCP servers per-project in ~/.claude.json
246
+ // Format: { projects: { "/path/to/cwd": { mcpServers: { ... } } } }
247
+ // The bb server uses HTTP transport (direct URL, no mcp-remote needed).
248
+ // The bb_signer server uses stdio transport (local process).
249
+ const claudeJsonPath = join(homedir(), '.claude.json');
250
+ const cwd = process.cwd();
251
+
252
+ console.log('\nConfiguring Claude Code...');
253
+
254
+ let claudeJson = {};
255
+ try {
256
+ claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf8'));
257
+ } catch {
258
+ // File doesn't exist or invalid JSON — start fresh
259
+ }
260
+
261
+ if (!claudeJson.projects) claudeJson.projects = {};
262
+ if (!claudeJson.projects[cwd]) claudeJson.projects[cwd] = {};
263
+ if (!claudeJson.projects[cwd].mcpServers) claudeJson.projects[cwd].mcpServers = {};
264
+
265
+ // HTTP transport for the remote proxy (no mcp-remote wrapper needed)
266
+ claudeJson.projects[cwd].mcpServers.bb = {
267
+ type: "http",
268
+ url: "https://mcp.bb.org.ai/mcp"
269
+ };
270
+
271
+ // Stdio transport for the local signer
272
+ claudeJson.projects[cwd].mcpServers.bb_signer = {
273
+ type: "stdio",
274
+ command: "npx",
275
+ args: ["-y", `bb-signer@${VERSION}`, "server"],
276
+ env: {}
277
+ };
278
+
279
+ // Also register for user scope (mcpServers at top level) so it works from ANY directory
280
+ if (!claudeJson.mcpServers) claudeJson.mcpServers = {};
281
+ claudeJson.mcpServers.bb = {
282
+ type: "http",
283
+ url: "https://mcp.bb.org.ai/mcp"
284
+ };
285
+ claudeJson.mcpServers.bb_signer = {
286
+ type: "stdio",
287
+ command: "npx",
288
+ args: ["-y", `bb-signer@${VERSION}`, "server"],
289
+ env: {}
290
+ };
291
+
292
+ writeFileSync(claudeJsonPath, JSON.stringify(claudeJson, null, 2) + '\n');
293
+ console.log(` ✅ Claude Code: Configured (${cwd})`);
294
+ }
295
+
244
296
  async function resolveEditorFilter() {
245
297
  // Look for a non-flag argument after "install", e.g. `install gemini --yes`
246
298
  const installIdx = process.argv.indexOf('install');
@@ -312,24 +364,12 @@ async function install() {
312
364
  const ed = EDITORS[editorFilter];
313
365
  const mcpConfig = getMcpConfig(ed);
314
366
 
315
- // For Claude Code: try `claude mcp add`, always also write settings.json as fallback.
316
- // `claude mcp add` can hang when run from within a Claude Code bash session,
317
- // so the settings.json write ensures config is always persisted.
318
- if (ed.usesCli && hasClaude()) {
319
- console.log('\nConfiguring via Claude CLI...');
320
- try {
321
- installViaClaude(mcpConfig);
322
- console.log(` ✅ ${ed.label}: Configured via \`claude mcp add\``);
323
- } catch (e) {
324
- console.error(` ⚠️ \`claude mcp add\` failed: ${e.message}`);
325
- }
326
- // Always also write settings.json — belt and suspenders
327
- const plan = planEditorConfig(ed.label, ed.paths, mcpConfig, ed.detectDirs);
328
- if (plan) {
329
- applyEditorConfig(plan);
330
- } else {
331
- fallbackToSettingsFile(ed, mcpConfig);
332
- }
367
+ // For Claude Code: write directly to ~/.claude.json (the actual config file).
368
+ // Claude Code stores MCP servers per-project in ~/.claude.json under projects[cwd].mcpServers.
369
+ // ~/.claude/settings.json does NOT configure MCP servers (common misconception).
370
+ // `claude mcp add` can't run from within a nested Claude Code session.
371
+ if (editorFilter === 'claude') {
372
+ configureClaudeJson(mcpConfig);
333
373
  } else {
334
374
  // All other editors: write to config file
335
375
  const plans = [planEditorConfig(ed.label, ed.paths, mcpConfig, ed.detectDirs)].filter(Boolean);
@@ -911,16 +951,36 @@ async function verify() {
911
951
 
912
952
  // Check 2: At least one editor is configured
913
953
  let hasConfig = false;
914
- const editorChecks = Object.entries(EDITORS).map(([key, ed]) => [ed.label, ed.paths]);
915
- for (const [name, paths] of editorChecks) {
916
- const editor = findExisting(paths);
954
+
955
+ // Check ~/.claude.json (Claude Code's actual config)
956
+ const claudeJsonPath = join(homedir(), '.claude.json');
957
+ try {
958
+ const claudeJson = JSON.parse(readFileSync(claudeJsonPath, 'utf8'));
959
+ // Check user-level mcpServers
960
+ if (claudeJson.mcpServers?.bb) {
961
+ console.log(`✅ Claude Code: Configured (user scope)`);
962
+ hasConfig = true;
963
+ }
964
+ // Check project-level for current directory
965
+ const cwd = process.cwd();
966
+ const projServers = claudeJson.projects?.[cwd]?.mcpServers;
967
+ if (projServers?.bb) {
968
+ console.log(`✅ Claude Code: Configured (project: ${cwd})`);
969
+ hasConfig = true;
970
+ }
971
+ } catch {}
972
+
973
+ // Check other editors (Gemini, Cursor, Windsurf) via their config files
974
+ const otherEditors = Object.entries(EDITORS).filter(([key]) => key !== 'claude' && key !== 'claude-desktop');
975
+ for (const [key, ed] of otherEditors) {
976
+ const editor = findExisting(ed.paths);
917
977
  if (editor.exists) {
918
978
  const settings = readJson(editor.path);
919
979
  if (settings && settings.mcpServers?.bb && settings.mcpServers?.bb_signer) {
920
- console.log(`✅ ${name}: Configured`);
980
+ console.log(`✅ ${ed.label}: Configured`);
921
981
  hasConfig = true;
922
982
  } else if (settings && (settings.mcpServers?.bb || settings.mcpServers?.bb_signer)) {
923
- console.log(`⚠️ ${name}: Incomplete config (missing bb or bb_signer)`);
983
+ console.log(`⚠️ ${ed.label}: Incomplete config (missing bb or bb_signer)`);
924
984
  warnings++;
925
985
  hasConfig = true;
926
986
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bb-signer",
3
- "version": "0.3.10",
3
+ "version": "0.4.0",
4
4
  "description": "Minimal local signer for BB - signs events for the agent collaboration network",
5
5
  "type": "module",
6
6
  "main": "index.js",