@intellectronica/ruler 0.3.7 → 0.3.8

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.
@@ -333,19 +333,65 @@ async function applyOpenCodeMcpConfiguration(filteredMcpJson, dest, dryRun, verb
333
333
  await (0, propagateOpenCodeMcp_1.propagateMcpToOpenCode)(filteredMcpJson, dest, backup);
334
334
  }
335
335
  }
336
+ /**
337
+ * Transform MCP server types for Claude Code compatibility.
338
+ * Claude expects "http" for HTTP servers and "sse" for SSE servers, not "remote".
339
+ */
340
+ function transformMcpForClaude(mcpJson) {
341
+ if (!mcpJson.mcpServers || typeof mcpJson.mcpServers !== 'object') {
342
+ return mcpJson;
343
+ }
344
+ const transformedMcp = { ...mcpJson };
345
+ const transformedServers = {};
346
+ for (const [name, serverDef] of Object.entries(mcpJson.mcpServers)) {
347
+ if (serverDef && typeof serverDef === 'object') {
348
+ const server = serverDef;
349
+ const transformedServer = { ...server };
350
+ // Transform type: "remote" to appropriate Claude types
351
+ if (server.type === 'remote' &&
352
+ server.url &&
353
+ typeof server.url === 'string') {
354
+ const url = server.url;
355
+ // Check if URL suggests SSE (contains /sse path segment)
356
+ if (/\/sse(\/|$)/i.test(url)) {
357
+ transformedServer.type = 'sse';
358
+ }
359
+ else {
360
+ transformedServer.type = 'http';
361
+ }
362
+ }
363
+ transformedServers[name] = transformedServer;
364
+ }
365
+ else {
366
+ transformedServers[name] = serverDef;
367
+ }
368
+ }
369
+ transformedMcp.mcpServers = transformedServers;
370
+ return transformedMcp;
371
+ }
336
372
  async function applyStandardMcpConfiguration(agent, filteredMcpJson, dest, agentConfig, config, cliMcpStrategy, dryRun, verbose, backup = true) {
337
373
  const strategy = cliMcpStrategy ??
338
374
  agentConfig?.mcp?.strategy ??
339
375
  config.mcp?.strategy ??
340
376
  'merge';
341
377
  const serverKey = agent.getMcpServerKey?.() ?? 'mcpServers';
378
+ // Skip agents with empty server keys (e.g., AgentsMdAgent, GooseAgent)
379
+ if (serverKey === '') {
380
+ (0, constants_1.logVerbose)(`Skipping MCP config for ${agent.getName()} - agent has empty server key`, verbose);
381
+ return;
382
+ }
342
383
  (0, constants_1.logVerbose)(`Applying filtered MCP config for ${agent.getName()} with strategy: ${strategy} and key: ${serverKey}`, verbose);
343
384
  if (dryRun) {
344
385
  (0, constants_1.logVerbose)(`DRY RUN: Would apply MCP config to: ${dest}`, verbose);
345
386
  }
346
387
  else {
388
+ // Transform MCP config for Claude Code compatibility
389
+ let mcpToMerge = filteredMcpJson;
390
+ if (agent.getIdentifier() === 'claude') {
391
+ mcpToMerge = transformMcpForClaude(filteredMcpJson);
392
+ }
347
393
  const existing = await (0, mcp_1.readNativeMcp)(dest);
348
- const merged = (0, merge_1.mergeMcp)(existing, filteredMcpJson, strategy, serverKey);
394
+ const merged = (0, merge_1.mergeMcp)(existing, mcpToMerge, strategy, serverKey);
349
395
  // Only backup and write if content would actually change (idempotent)
350
396
  const currentContent = JSON.stringify(existing, null, 2);
351
397
  const newContent = JSON.stringify(merged, null, 2);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectronica/ruler",
3
- "version": "0.3.7",
3
+ "version": "0.3.8",
4
4
  "description": "Ruler — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
6
  "scripts": {