@intellectronica/ruler 0.3.13 → 0.3.15

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/README.md CHANGED
@@ -74,7 +74,7 @@ Ruler solves this by providing a **single source of truth** for all your AI agen
74
74
  | Junie | `.junie/guidelines.md` | - |
75
75
  | AugmentCode | `.augment/rules/ruler_augment_instructions.md` | - |
76
76
  | Kilo Code | `.kilocode/rules/ruler_kilocode_instructions.md` | `.kilocode/mcp.json` |
77
- | opencode | `AGENTS.md` | `opencode.json` |
77
+ | OpenCode | `AGENTS.md` | `opencode.json` |
78
78
  | Goose | `.goosehints` | - |
79
79
  | Qwen Code | `AGENTS.md` | `.qwen/settings.json` |
80
80
  | RooCode | `AGENTS.md` | `.roo/mcp.json` |
@@ -49,6 +49,37 @@ class CrushAgent {
49
49
  mcp: path.join(projectRoot, '.crush.json'),
50
50
  };
51
51
  }
52
+ /**
53
+ * Transform MCP server types for Crush compatibility.
54
+ * Crush expects "http" for HTTP servers and "sse" for SSE servers, not "remote".
55
+ */
56
+ transformMcpServersForCrush(mcpServers) {
57
+ const transformedServers = {};
58
+ for (const [name, serverDef] of Object.entries(mcpServers)) {
59
+ if (serverDef && typeof serverDef === 'object') {
60
+ const server = serverDef;
61
+ const transformedServer = { ...server };
62
+ // Transform type: "remote" to appropriate Crush types
63
+ if (server.type === 'remote' &&
64
+ server.url &&
65
+ typeof server.url === 'string') {
66
+ const url = server.url;
67
+ // Check if URL suggests SSE (contains /sse path segment)
68
+ if (/\/sse(\/|$)/i.test(url)) {
69
+ transformedServer.type = 'sse';
70
+ }
71
+ else {
72
+ transformedServer.type = 'http';
73
+ }
74
+ }
75
+ transformedServers[name] = transformedServer;
76
+ }
77
+ else {
78
+ transformedServers[name] = serverDef;
79
+ }
80
+ }
81
+ return transformedServers;
82
+ }
52
83
  async applyRulerConfig(concatenatedRules, projectRoot, rulerMcpJson, agentConfig) {
53
84
  const outputPaths = this.getDefaultOutputPath(projectRoot);
54
85
  const instructionsPath = agentConfig?.outputPathInstructions ?? outputPaths['instructions'];
@@ -59,24 +90,27 @@ class CrushAgent {
59
90
  try {
60
91
  const existingMcpConfig = JSON.parse(await fs.readFile(mcpPath, 'utf-8'));
61
92
  if (existingMcpConfig && typeof existingMcpConfig === 'object') {
93
+ const transformedServers = this.transformMcpServersForCrush((rulerMcpJson?.mcpServers ?? {}));
62
94
  finalMcpConfig = {
63
95
  ...existingMcpConfig,
64
96
  mcp: {
65
97
  ...(existingMcpConfig.mcp || {}),
66
- ...(rulerMcpJson?.mcpServers ?? {}),
98
+ ...transformedServers,
67
99
  },
68
100
  };
69
101
  }
70
102
  else if (rulerMcpJson) {
103
+ const transformedServers = this.transformMcpServersForCrush((rulerMcpJson?.mcpServers ?? {}));
71
104
  finalMcpConfig = {
72
- mcp: (rulerMcpJson?.mcpServers ?? {}),
105
+ mcp: transformedServers,
73
106
  };
74
107
  }
75
108
  }
76
109
  catch {
77
110
  if (rulerMcpJson) {
111
+ const transformedServers = this.transformMcpServersForCrush((rulerMcpJson?.mcpServers ?? {}));
78
112
  finalMcpConfig = {
79
- mcp: (rulerMcpJson?.mcpServers ?? {}),
113
+ mcp: transformedServers,
80
114
  };
81
115
  }
82
116
  }
@@ -46,5 +46,11 @@ class KiroAgent extends AbstractAgent_1.AbstractAgent {
46
46
  getDefaultOutputPath(projectRoot) {
47
47
  return path.join(projectRoot, '.kiro', 'steering', 'ruler_kiro_instructions.md');
48
48
  }
49
+ supportsMcpStdio() {
50
+ return true;
51
+ }
52
+ supportsMcpRemote() {
53
+ return true;
54
+ }
49
55
  }
50
56
  exports.KiroAgent = KiroAgent;
@@ -442,7 +442,8 @@ async function applyMcpConfiguration(agent, filteredMcpJson, dest, agentConfig,
442
442
  // Agents that handle MCP configuration internally should not have external MCP handling
443
443
  if (agent.getIdentifier() === 'zed' ||
444
444
  agent.getIdentifier() === 'gemini-cli' ||
445
- agent.getIdentifier() === 'amazon-q-cli') {
445
+ agent.getIdentifier() === 'amazon-q-cli' ||
446
+ agent.getIdentifier() === 'crush') {
446
447
  (0, constants_1.logVerbose)(`Skipping external MCP config for ${agent.getName()} - handled internally by agent`, verbose);
447
448
  return;
448
449
  }
package/dist/paths/mcp.js CHANGED
@@ -77,6 +77,9 @@ async function getNativeMcpPath(adapterName, projectRoot) {
77
77
  case 'Kilo Code':
78
78
  candidates.push(path.join(projectRoot, '.kilocode', 'mcp.json'));
79
79
  break;
80
+ case 'Kiro':
81
+ candidates.push(path.join(projectRoot, '.kiro', 'settings', 'mcp.json'));
82
+ break;
80
83
  case 'OpenCode':
81
84
  candidates.push(path.join(projectRoot, 'opencode.json'));
82
85
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectronica/ruler",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "description": "Ruler — apply the same rules to all coding agents",
5
5
  "main": "dist/lib.js",
6
6
  "scripts": {