rulesync 0.34.0 → 0.36.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.
- package/README.ja.md +95 -6
- package/README.md +95 -6
- package/dist/chunk-6PQ4APY4.mjs +70 -0
- package/dist/chunk-QHXMJZTJ.mjs +62 -0
- package/dist/chunk-QVPQ2X4L.mjs +77 -0
- package/dist/chunk-SBYRCTWS.mjs +64 -0
- package/dist/chunk-UNTCJDMQ.mjs +73 -0
- package/dist/chunk-YGXGGUBG.mjs +80 -0
- package/dist/claude-O4SRX6VC.mjs +8 -0
- package/dist/cline-H5JF2OPT.mjs +8 -0
- package/dist/copilot-GCIYHK4Q.mjs +8 -0
- package/dist/cursor-N75OH6WS.mjs +8 -0
- package/dist/geminicli-AGOQ32ZE.mjs +8 -0
- package/dist/index.js +1232 -218
- package/dist/index.mjs +929 -209
- package/dist/roo-V5YVC222.mjs +8 -0
- package/package.json +14 -6
package/README.ja.md
CHANGED
|
@@ -60,10 +60,7 @@ yarn global add rulesync
|
|
|
60
60
|
|
|
61
61
|
1. **既存設定をインポート:**
|
|
62
62
|
```bash
|
|
63
|
-
#
|
|
64
|
-
npx rulesync import --claudecode --cursor --copilot
|
|
65
|
-
|
|
66
|
-
# または特定のツールからインポート
|
|
63
|
+
# 特定のツールからインポート(一度に1つのツールのみ指定可能)
|
|
67
64
|
npx rulesync import --claudecode # CLAUDE.mdと.claude/memories/*.mdから
|
|
68
65
|
npx rulesync import --cursor # .cursorrulesと.cursor/rules/*.mdcから
|
|
69
66
|
npx rulesync import --copilot # .github/copilot-instructions.mdから
|
|
@@ -226,8 +223,10 @@ npx rulesync import --cline # .cline/instructions.mdからインポート
|
|
|
226
223
|
npx rulesync import --roo # .roo/instructions.mdからインポート
|
|
227
224
|
npx rulesync import --geminicli # GEMINI.mdと.gemini/memories/*.mdからインポート
|
|
228
225
|
|
|
229
|
-
#
|
|
230
|
-
npx rulesync import --claudecode
|
|
226
|
+
# 各ツールを個別にインポート
|
|
227
|
+
npx rulesync import --claudecode
|
|
228
|
+
npx rulesync import --cursor
|
|
229
|
+
npx rulesync import --copilot
|
|
231
230
|
|
|
232
231
|
# インポート時の詳細出力
|
|
233
232
|
npx rulesync import --claudecode --verbose
|
|
@@ -278,6 +277,33 @@ npx rulesync gitignore
|
|
|
278
277
|
└── custom.md # プロジェクト固有ルール (root: false)
|
|
279
278
|
```
|
|
280
279
|
|
|
280
|
+
### .rulesyncignoreでファイルを除外
|
|
281
|
+
|
|
282
|
+
プロジェクトルートに`.rulesyncignore`ファイルを作成することで、特定のルールファイルを処理から除外できます。このファイルはgitignoreスタイルのパターンを使用します。
|
|
283
|
+
|
|
284
|
+
`.rulesyncignore`の例:
|
|
285
|
+
```
|
|
286
|
+
# テスト用ルールファイルを無視
|
|
287
|
+
**/*.test.md
|
|
288
|
+
|
|
289
|
+
# 一時ファイルを無視
|
|
290
|
+
tmp/**/*
|
|
291
|
+
|
|
292
|
+
# ドラフトルールを無視
|
|
293
|
+
draft-*.md
|
|
294
|
+
*-draft.md
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
`.rulesyncignore`が存在する場合、rulesyncは:
|
|
298
|
+
1. 処理時にマッチするファイルをスキップ
|
|
299
|
+
2. ツール固有のignoreファイルを生成:
|
|
300
|
+
- Cursor用の`.cursorignore`
|
|
301
|
+
- Cline用の`.clineignore`
|
|
302
|
+
- Roo Code用の`.rooignore`
|
|
303
|
+
- GitHub Copilot用の`.copilotignore`(コミュニティツール用)
|
|
304
|
+
- Gemini CLI用の`.aiexclude`
|
|
305
|
+
- Claude Code用に`.claude/settings.json`のpermissions.denyに`Read()`ルールを追加
|
|
306
|
+
|
|
281
307
|
### フロントマタースキーマ
|
|
282
308
|
|
|
283
309
|
各ルールファイルには以下のフィールドを含むフロントマターが必要です:
|
|
@@ -348,6 +374,69 @@ npx rulesync validate
|
|
|
348
374
|
- ファイルパターン(globs)が有効な構文を使用
|
|
349
375
|
- ターゲットツールが認識される値である
|
|
350
376
|
|
|
377
|
+
## MCP(Model Context Protocol)サポート
|
|
378
|
+
|
|
379
|
+
rulesyncは、対応するAIツール用のMCPサーバー設定も管理できます。これにより、言語サーバーやその他のMCP互換サービスを一度設定すれば、複数のAIコーディングアシスタントにデプロイできます。
|
|
380
|
+
|
|
381
|
+
### MCPをサポートするツール
|
|
382
|
+
|
|
383
|
+
- **Claude Code** (`.mcp.json`)
|
|
384
|
+
- **GitHub Copilot** (`.vscode/mcp.json`)
|
|
385
|
+
- **Cursor** (`.cursor/mcp.json`)
|
|
386
|
+
- **Cline** (`.cline/mcp.json`)
|
|
387
|
+
- **Gemini CLI** (`.gemini/settings.json`)
|
|
388
|
+
- **Roo Code** (`.roo/mcp.json`)
|
|
389
|
+
|
|
390
|
+
### MCP設定
|
|
391
|
+
|
|
392
|
+
プロジェクトに`.rulesync/.mcp.json`ファイルを作成:
|
|
393
|
+
|
|
394
|
+
```json
|
|
395
|
+
{
|
|
396
|
+
"mcpServers": {
|
|
397
|
+
"github": {
|
|
398
|
+
"command": "docker",
|
|
399
|
+
"args": [
|
|
400
|
+
"run", "-i", "--rm",
|
|
401
|
+
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
|
|
402
|
+
"ghcr.io/github/github-mcp-server"
|
|
403
|
+
],
|
|
404
|
+
"env": {},
|
|
405
|
+
"rulesyncTargets": ["*"]
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### MCP設定フィールド
|
|
412
|
+
|
|
413
|
+
- **`mcpServers`**: MCPサーバー設定を含むオブジェクト
|
|
414
|
+
- **`command`**: stdioベースのサーバー用の実行可能コマンド
|
|
415
|
+
- **`args`**: コマンド引数
|
|
416
|
+
- **`url`**: HTTP/SSEベースのサーバー用URL
|
|
417
|
+
- **`env`**: サーバーに渡す環境変数
|
|
418
|
+
- **`rulesyncTargets`**: このサーバーをデプロイするツール名の配列
|
|
419
|
+
- 特定のツール名を使用: `["claude", "cursor", "copilot"]`
|
|
420
|
+
- すべてのサポートツールにデプロイするには`["*"]`を使用
|
|
421
|
+
- 省略した場合、デフォルトですべてのツールにデプロイ
|
|
422
|
+
|
|
423
|
+
### MCP設定の生成
|
|
424
|
+
|
|
425
|
+
MCP設定はルールファイルと一緒に生成されます:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
# ルールとMCP設定の両方を生成
|
|
429
|
+
npx rulesync generate
|
|
430
|
+
|
|
431
|
+
# 特定のツールのみ生成
|
|
432
|
+
npx rulesync generate --claudecode --cursor
|
|
433
|
+
|
|
434
|
+
# 特定のディレクトリに生成(monorepo)
|
|
435
|
+
npx rulesync generate --base-dir ./packages/frontend
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
MCP設定は各ツールの適切な場所に生成され、ツールは起動時に自動的にそれらを読み込みます。
|
|
439
|
+
|
|
351
440
|
## ライセンス
|
|
352
441
|
|
|
353
442
|
MIT License
|
package/README.md
CHANGED
|
@@ -60,10 +60,7 @@ If you already have AI tool configurations, you can import them into rulesync fo
|
|
|
60
60
|
|
|
61
61
|
1. **Import existing configurations:**
|
|
62
62
|
```bash
|
|
63
|
-
# Import from
|
|
64
|
-
npx rulesync import --claudecode --cursor --copilot
|
|
65
|
-
|
|
66
|
-
# Or import from specific tools
|
|
63
|
+
# Import from specific tools (only one tool can be specified at a time)
|
|
67
64
|
npx rulesync import --claudecode # From CLAUDE.md and .claude/memories/*.md
|
|
68
65
|
npx rulesync import --cursor # From .cursorrules and .cursor/rules/*.mdc
|
|
69
66
|
npx rulesync import --copilot # From .github/copilot-instructions.md
|
|
@@ -226,8 +223,10 @@ npx rulesync import --cline # Import from .cline/instructions.md
|
|
|
226
223
|
npx rulesync import --roo # Import from .roo/instructions.md
|
|
227
224
|
npx rulesync import --geminicli # Import from GEMINI.md and .gemini/memories/*.md
|
|
228
225
|
|
|
229
|
-
# Import
|
|
230
|
-
npx rulesync import --claudecode
|
|
226
|
+
# Import each tool individually
|
|
227
|
+
npx rulesync import --claudecode
|
|
228
|
+
npx rulesync import --cursor
|
|
229
|
+
npx rulesync import --copilot
|
|
231
230
|
|
|
232
231
|
# Verbose output during import
|
|
233
232
|
npx rulesync import --claudecode --verbose
|
|
@@ -278,6 +277,33 @@ npx rulesync gitignore
|
|
|
278
277
|
└── custom.md # Project-specific rules (root: false)
|
|
279
278
|
```
|
|
280
279
|
|
|
280
|
+
### Excluding Files with .rulesyncignore
|
|
281
|
+
|
|
282
|
+
You can exclude specific rule files from being processed by creating a `.rulesyncignore` file in your project root. This file uses gitignore-style patterns.
|
|
283
|
+
|
|
284
|
+
Example `.rulesyncignore`:
|
|
285
|
+
```
|
|
286
|
+
# Ignore test rule files
|
|
287
|
+
**/*.test.md
|
|
288
|
+
|
|
289
|
+
# Ignore temporary files
|
|
290
|
+
tmp/**/*
|
|
291
|
+
|
|
292
|
+
# Ignore draft rules
|
|
293
|
+
draft-*.md
|
|
294
|
+
*-draft.md
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
When `.rulesyncignore` exists, rulesync will:
|
|
298
|
+
1. Skip matching files during rule processing
|
|
299
|
+
2. Generate tool-specific ignore files:
|
|
300
|
+
- `.cursorignore` for Cursor
|
|
301
|
+
- `.clineignore` for Cline
|
|
302
|
+
- `.rooignore` for Roo Code
|
|
303
|
+
- `.copilotignore` for GitHub Copilot (community tools)
|
|
304
|
+
- `.aiexclude` for Gemini CLI
|
|
305
|
+
- Update `.claude/settings.json` permissions.deny with `Read()` rules for Claude Code
|
|
306
|
+
|
|
281
307
|
### Frontmatter Schema
|
|
282
308
|
|
|
283
309
|
Each rule file must include frontmatter with the following fields:
|
|
@@ -348,6 +374,69 @@ Common validation rules:
|
|
|
348
374
|
- File patterns (globs) use valid syntax
|
|
349
375
|
- Target tools are recognized values
|
|
350
376
|
|
|
377
|
+
## MCP (Model Context Protocol) Support
|
|
378
|
+
|
|
379
|
+
rulesync can also manage MCP server configurations for supported AI tools. This allows you to configure language servers and other MCP-compatible services once and deploy them across multiple AI coding assistants.
|
|
380
|
+
|
|
381
|
+
### Supported MCP Tools
|
|
382
|
+
|
|
383
|
+
- **Claude Code** (`.mcp.json`)
|
|
384
|
+
- **GitHub Copilot** (`.vscode/mcp.json`)
|
|
385
|
+
- **Cursor** (`.cursor/mcp.json`)
|
|
386
|
+
- **Cline** (`.cline/mcp.json`)
|
|
387
|
+
- **Gemini CLI** (`.gemini/settings.json`)
|
|
388
|
+
- **Roo Code** (`.roo/mcp.json`)
|
|
389
|
+
|
|
390
|
+
### MCP Configuration
|
|
391
|
+
|
|
392
|
+
Create a `.rulesync/.mcp.json` file in your project:
|
|
393
|
+
|
|
394
|
+
```json
|
|
395
|
+
{
|
|
396
|
+
"mcpServers": {
|
|
397
|
+
"github": {
|
|
398
|
+
"command": "docker",
|
|
399
|
+
"args": [
|
|
400
|
+
"run", "-i", "--rm",
|
|
401
|
+
"-e", "GITHUB_PERSONAL_ACCESS_TOKEN",
|
|
402
|
+
"ghcr.io/github/github-mcp-server"
|
|
403
|
+
],
|
|
404
|
+
"env": {},
|
|
405
|
+
"rulesyncTargets": ["*"]
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
```
|
|
410
|
+
|
|
411
|
+
### MCP Configuration Fields
|
|
412
|
+
|
|
413
|
+
- **`mcpServers`**: Object containing MCP server configurations
|
|
414
|
+
- **`command`**: Executable command for stdio-based servers
|
|
415
|
+
- **`args`**: Command arguments
|
|
416
|
+
- **`url`**: URL for HTTP/SSE-based servers
|
|
417
|
+
- **`env`**: Environment variables to pass to the server
|
|
418
|
+
- **`rulesyncTargets`**: Array of tool names to deploy this server to
|
|
419
|
+
- Use specific tool names: `["claude", "cursor", "copilot"]`
|
|
420
|
+
- Use `["*"]` to deploy to all supported tools
|
|
421
|
+
- If omitted, server is deployed to all tools by default
|
|
422
|
+
|
|
423
|
+
### Generating MCP Configurations
|
|
424
|
+
|
|
425
|
+
MCP configurations are generated alongside rule files:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
# Generate both rules and MCP configurations
|
|
429
|
+
npx rulesync generate
|
|
430
|
+
|
|
431
|
+
# Generate only for specific tools
|
|
432
|
+
npx rulesync generate --claudecode --cursor
|
|
433
|
+
|
|
434
|
+
# Generate in specific directories (monorepo)
|
|
435
|
+
npx rulesync generate --base-dir ./packages/frontend
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
The MCP configurations will be generated in the appropriate locations for each tool, and the tools will automatically load them when started.
|
|
439
|
+
|
|
351
440
|
## License
|
|
352
441
|
|
|
353
442
|
MIT License
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// src/generators/mcp/geminicli.ts
|
|
2
|
+
function generateGeminiCliMcp(config, _target) {
|
|
3
|
+
const geminiSettings = {
|
|
4
|
+
mcpServers: {}
|
|
5
|
+
};
|
|
6
|
+
const shouldInclude = (server) => {
|
|
7
|
+
const targets = server.rulesyncTargets;
|
|
8
|
+
if (!targets || targets.length === 0) return true;
|
|
9
|
+
if (targets.length === 1 && targets[0] === "*") return true;
|
|
10
|
+
return targets.includes("geminicli");
|
|
11
|
+
};
|
|
12
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
13
|
+
if (!shouldInclude(server)) continue;
|
|
14
|
+
const geminiServer = {};
|
|
15
|
+
if (server.command) {
|
|
16
|
+
geminiServer.command = server.command;
|
|
17
|
+
if (server.args) geminiServer.args = server.args;
|
|
18
|
+
} else if (server.url || server.httpUrl) {
|
|
19
|
+
if (server.httpUrl) {
|
|
20
|
+
geminiServer.httpUrl = server.httpUrl;
|
|
21
|
+
} else if (server.url) {
|
|
22
|
+
geminiServer.url = server.url;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (server.env) {
|
|
26
|
+
geminiServer.env = {};
|
|
27
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
28
|
+
if (value.startsWith("${") && value.endsWith("}")) {
|
|
29
|
+
geminiServer.env[key] = value;
|
|
30
|
+
} else {
|
|
31
|
+
geminiServer.env[key] = `\${${value}}`;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (server.timeout !== void 0) {
|
|
36
|
+
geminiServer.timeout = server.timeout;
|
|
37
|
+
}
|
|
38
|
+
if (server.trust !== void 0) {
|
|
39
|
+
geminiServer.trust = server.trust;
|
|
40
|
+
}
|
|
41
|
+
geminiSettings.mcpServers[serverName] = geminiServer;
|
|
42
|
+
}
|
|
43
|
+
return JSON.stringify(geminiSettings, null, 2);
|
|
44
|
+
}
|
|
45
|
+
function generateGeminiCliMcpConfiguration(mcpServers, baseDir = "") {
|
|
46
|
+
const filepath = baseDir ? `${baseDir}/.gemini/settings.json` : ".gemini/settings.json";
|
|
47
|
+
const config = {
|
|
48
|
+
mcpServers: {}
|
|
49
|
+
};
|
|
50
|
+
for (const [serverName, server] of Object.entries(mcpServers)) {
|
|
51
|
+
const targets = server.rulesyncTargets;
|
|
52
|
+
if (targets && !targets.includes("*") && !targets.includes("geminicli")) {
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
const { rulesyncTargets: _, ...serverConfig } = server;
|
|
56
|
+
config.mcpServers[serverName] = serverConfig;
|
|
57
|
+
}
|
|
58
|
+
return [
|
|
59
|
+
{
|
|
60
|
+
filepath,
|
|
61
|
+
content: `${JSON.stringify(config, null, 2)}
|
|
62
|
+
`
|
|
63
|
+
}
|
|
64
|
+
];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export {
|
|
68
|
+
generateGeminiCliMcp,
|
|
69
|
+
generateGeminiCliMcpConfiguration
|
|
70
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/generators/mcp/cline.ts
|
|
2
|
+
function generateClineMcp(config, _target) {
|
|
3
|
+
const clineConfig = {
|
|
4
|
+
mcpServers: {}
|
|
5
|
+
};
|
|
6
|
+
const shouldInclude = (server) => {
|
|
7
|
+
const targets = server.rulesyncTargets;
|
|
8
|
+
if (!targets || targets.length === 0) return true;
|
|
9
|
+
if (targets.length === 1 && targets[0] === "*") return true;
|
|
10
|
+
return targets.includes("cline");
|
|
11
|
+
};
|
|
12
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
13
|
+
if (!shouldInclude(server)) continue;
|
|
14
|
+
const clineServer = {};
|
|
15
|
+
if (server.command) {
|
|
16
|
+
clineServer.command = server.command;
|
|
17
|
+
if (server.args) clineServer.args = server.args;
|
|
18
|
+
} else if (server.url) {
|
|
19
|
+
clineServer.url = server.url;
|
|
20
|
+
}
|
|
21
|
+
if (server.env) {
|
|
22
|
+
clineServer.env = server.env;
|
|
23
|
+
}
|
|
24
|
+
if (server.disabled !== void 0) {
|
|
25
|
+
clineServer.disabled = server.disabled;
|
|
26
|
+
}
|
|
27
|
+
if (server.alwaysAllow) {
|
|
28
|
+
clineServer.alwaysAllow = server.alwaysAllow;
|
|
29
|
+
}
|
|
30
|
+
if (server.networkTimeout !== void 0) {
|
|
31
|
+
clineServer.networkTimeout = server.networkTimeout;
|
|
32
|
+
}
|
|
33
|
+
clineConfig.mcpServers[serverName] = clineServer;
|
|
34
|
+
}
|
|
35
|
+
return JSON.stringify(clineConfig, null, 2);
|
|
36
|
+
}
|
|
37
|
+
function generateClineMcpConfiguration(mcpServers, baseDir = "") {
|
|
38
|
+
const filepath = baseDir ? `${baseDir}/.cline/mcp.json` : ".cline/mcp.json";
|
|
39
|
+
const config = {
|
|
40
|
+
mcpServers: {}
|
|
41
|
+
};
|
|
42
|
+
for (const [serverName, server] of Object.entries(mcpServers)) {
|
|
43
|
+
const targets = server.rulesyncTargets;
|
|
44
|
+
if (targets && !targets.includes("*") && !targets.includes("cline")) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
const { rulesyncTargets: _, ...serverConfig } = server;
|
|
48
|
+
config.mcpServers[serverName] = serverConfig;
|
|
49
|
+
}
|
|
50
|
+
return [
|
|
51
|
+
{
|
|
52
|
+
filepath,
|
|
53
|
+
content: `${JSON.stringify(config, null, 2)}
|
|
54
|
+
`
|
|
55
|
+
}
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export {
|
|
60
|
+
generateClineMcp,
|
|
61
|
+
generateClineMcpConfiguration
|
|
62
|
+
};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// src/generators/mcp/roo.ts
|
|
2
|
+
function generateRooMcp(config, _target) {
|
|
3
|
+
const rooConfig = {
|
|
4
|
+
mcpServers: {}
|
|
5
|
+
};
|
|
6
|
+
const shouldInclude = (server) => {
|
|
7
|
+
const targets = server.rulesyncTargets;
|
|
8
|
+
if (!targets || targets.length === 0) return true;
|
|
9
|
+
if (targets.length === 1 && targets[0] === "*") return true;
|
|
10
|
+
return targets.includes("roo");
|
|
11
|
+
};
|
|
12
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
13
|
+
if (!shouldInclude(server)) continue;
|
|
14
|
+
const rooServer = {};
|
|
15
|
+
if (server.command) {
|
|
16
|
+
rooServer.command = server.command;
|
|
17
|
+
if (server.args) rooServer.args = server.args;
|
|
18
|
+
} else if (server.url || server.httpUrl) {
|
|
19
|
+
const url = server.httpUrl || server.url;
|
|
20
|
+
if (url) {
|
|
21
|
+
rooServer.url = url;
|
|
22
|
+
}
|
|
23
|
+
if (server.httpUrl || server.transport === "http") {
|
|
24
|
+
rooServer.type = "streamable-http";
|
|
25
|
+
} else if (server.transport === "sse" || server.type === "sse") {
|
|
26
|
+
rooServer.type = "sse";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (server.env) {
|
|
30
|
+
rooServer.env = {};
|
|
31
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
32
|
+
if (value.startsWith("${env:") && value.endsWith("}")) {
|
|
33
|
+
rooServer.env[key] = value;
|
|
34
|
+
} else {
|
|
35
|
+
rooServer.env[key] = `\${env:${value}}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (server.disabled !== void 0) {
|
|
40
|
+
rooServer.disabled = server.disabled;
|
|
41
|
+
}
|
|
42
|
+
if (server.alwaysAllow) {
|
|
43
|
+
rooServer.alwaysAllow = server.alwaysAllow;
|
|
44
|
+
}
|
|
45
|
+
if (server.networkTimeout !== void 0) {
|
|
46
|
+
rooServer.networkTimeout = Math.max(3e4, Math.min(3e5, server.networkTimeout));
|
|
47
|
+
}
|
|
48
|
+
rooConfig.mcpServers[serverName] = rooServer;
|
|
49
|
+
}
|
|
50
|
+
return JSON.stringify(rooConfig, null, 2);
|
|
51
|
+
}
|
|
52
|
+
function generateRooMcpConfiguration(mcpServers, baseDir = "") {
|
|
53
|
+
const filepath = baseDir ? `${baseDir}/.roo/mcp.json` : ".roo/mcp.json";
|
|
54
|
+
const config = {
|
|
55
|
+
mcpServers: {}
|
|
56
|
+
};
|
|
57
|
+
for (const [serverName, server] of Object.entries(mcpServers)) {
|
|
58
|
+
const targets = server.rulesyncTargets;
|
|
59
|
+
if (targets && !targets.includes("*") && !targets.includes("roo")) {
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const { rulesyncTargets, ...serverConfig } = server;
|
|
63
|
+
config.mcpServers[serverName] = serverConfig;
|
|
64
|
+
}
|
|
65
|
+
return [
|
|
66
|
+
{
|
|
67
|
+
filepath,
|
|
68
|
+
content: `${JSON.stringify(config, null, 2)}
|
|
69
|
+
`
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export {
|
|
75
|
+
generateRooMcp,
|
|
76
|
+
generateRooMcpConfiguration
|
|
77
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// src/generators/mcp/cursor.ts
|
|
2
|
+
function generateCursorMcp(config, _target) {
|
|
3
|
+
const cursorConfig = {
|
|
4
|
+
mcpServers: {}
|
|
5
|
+
};
|
|
6
|
+
const shouldInclude = (server) => {
|
|
7
|
+
const targets = server.rulesyncTargets;
|
|
8
|
+
if (!targets || targets.length === 0) return true;
|
|
9
|
+
if (targets.length === 1 && targets[0] === "*") return true;
|
|
10
|
+
return targets.includes("cursor");
|
|
11
|
+
};
|
|
12
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
13
|
+
if (!shouldInclude(server)) continue;
|
|
14
|
+
const cursorServer = {};
|
|
15
|
+
if (server.command) {
|
|
16
|
+
cursorServer.command = server.command;
|
|
17
|
+
if (server.args) cursorServer.args = server.args;
|
|
18
|
+
} else if (server.url || server.httpUrl) {
|
|
19
|
+
const url = server.httpUrl || server.url;
|
|
20
|
+
if (url) {
|
|
21
|
+
cursorServer.url = url;
|
|
22
|
+
}
|
|
23
|
+
if (server.httpUrl || server.transport === "http") {
|
|
24
|
+
cursorServer.type = "streamable-http";
|
|
25
|
+
} else if (server.transport === "sse" || server.type === "sse") {
|
|
26
|
+
cursorServer.type = "sse";
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
if (server.env) {
|
|
30
|
+
cursorServer.env = server.env;
|
|
31
|
+
}
|
|
32
|
+
if (server.cwd) {
|
|
33
|
+
cursorServer.cwd = server.cwd;
|
|
34
|
+
}
|
|
35
|
+
cursorConfig.mcpServers[serverName] = cursorServer;
|
|
36
|
+
}
|
|
37
|
+
return JSON.stringify(cursorConfig, null, 2);
|
|
38
|
+
}
|
|
39
|
+
function generateCursorMcpConfiguration(mcpServers, baseDir = "") {
|
|
40
|
+
const filepath = baseDir ? `${baseDir}/.cursor/mcp.json` : ".cursor/mcp.json";
|
|
41
|
+
const config = {
|
|
42
|
+
mcpServers: {}
|
|
43
|
+
};
|
|
44
|
+
for (const [serverName, server] of Object.entries(mcpServers)) {
|
|
45
|
+
const targets = server.rulesyncTargets;
|
|
46
|
+
if (targets && !targets.includes("*") && !targets.includes("cursor")) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const { rulesyncTargets, ...serverConfig } = server;
|
|
50
|
+
config.mcpServers[serverName] = serverConfig;
|
|
51
|
+
}
|
|
52
|
+
return [
|
|
53
|
+
{
|
|
54
|
+
filepath,
|
|
55
|
+
content: `${JSON.stringify(config, null, 2)}
|
|
56
|
+
`
|
|
57
|
+
}
|
|
58
|
+
];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export {
|
|
62
|
+
generateCursorMcp,
|
|
63
|
+
generateCursorMcpConfiguration
|
|
64
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
// src/generators/mcp/claude.ts
|
|
2
|
+
function generateClaudeMcp(config, _target) {
|
|
3
|
+
const claudeSettings = {
|
|
4
|
+
mcpServers: {}
|
|
5
|
+
};
|
|
6
|
+
const shouldInclude = (server) => {
|
|
7
|
+
if (!server.rulesyncTargets || server.rulesyncTargets.length === 0) {
|
|
8
|
+
return true;
|
|
9
|
+
}
|
|
10
|
+
if (server.rulesyncTargets.length === 1 && server.rulesyncTargets[0] === "*") {
|
|
11
|
+
return true;
|
|
12
|
+
}
|
|
13
|
+
return server.rulesyncTargets.includes("claude");
|
|
14
|
+
};
|
|
15
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
16
|
+
if (!shouldInclude(server)) continue;
|
|
17
|
+
const claudeServer = {};
|
|
18
|
+
if (server.command) {
|
|
19
|
+
claudeServer.command = server.command;
|
|
20
|
+
if (server.args) claudeServer.args = server.args;
|
|
21
|
+
} else if (server.url || server.httpUrl) {
|
|
22
|
+
const url = server.httpUrl || server.url;
|
|
23
|
+
if (url) {
|
|
24
|
+
claudeServer.url = url;
|
|
25
|
+
}
|
|
26
|
+
if (server.httpUrl) {
|
|
27
|
+
claudeServer.transport = "http";
|
|
28
|
+
} else if (server.transport === "sse") {
|
|
29
|
+
claudeServer.transport = "sse";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (server.env) {
|
|
33
|
+
claudeServer.env = server.env;
|
|
34
|
+
}
|
|
35
|
+
claudeSettings.mcpServers[serverName] = claudeServer;
|
|
36
|
+
}
|
|
37
|
+
return JSON.stringify(claudeSettings, null, 2);
|
|
38
|
+
}
|
|
39
|
+
function generateClaudeMcpConfiguration(mcpServers, baseDir = "") {
|
|
40
|
+
const filepath = baseDir ? `${baseDir}/.claude/settings.json` : ".claude/settings.json";
|
|
41
|
+
const settings = {
|
|
42
|
+
mcpServers: {}
|
|
43
|
+
};
|
|
44
|
+
for (const [serverName, server] of Object.entries(mcpServers)) {
|
|
45
|
+
const targets = server.rulesyncTargets;
|
|
46
|
+
if (targets && targets.length > 0) {
|
|
47
|
+
const targetsArray = targets;
|
|
48
|
+
if (!targetsArray.includes("*") && !targetsArray.includes("claudecode")) {
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const { rulesyncTargets: _, transport, ...serverConfig } = server;
|
|
53
|
+
const claudeServer = {
|
|
54
|
+
...serverConfig
|
|
55
|
+
};
|
|
56
|
+
if (transport && transport !== "stdio") {
|
|
57
|
+
claudeServer.transport = transport;
|
|
58
|
+
}
|
|
59
|
+
settings.mcpServers[serverName] = claudeServer;
|
|
60
|
+
}
|
|
61
|
+
return [
|
|
62
|
+
{
|
|
63
|
+
filepath,
|
|
64
|
+
content: `${JSON.stringify(settings, null, 2)}
|
|
65
|
+
`
|
|
66
|
+
}
|
|
67
|
+
];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export {
|
|
71
|
+
generateClaudeMcp,
|
|
72
|
+
generateClaudeMcpConfiguration
|
|
73
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// src/generators/mcp/copilot.ts
|
|
2
|
+
function generateCopilotMcp(config, target) {
|
|
3
|
+
const shouldInclude = (server) => {
|
|
4
|
+
const targets = server.rulesyncTargets;
|
|
5
|
+
if (!targets || targets.length === 0) return true;
|
|
6
|
+
if (targets.length === 1 && targets[0] === "*") return true;
|
|
7
|
+
return targets.includes("copilot");
|
|
8
|
+
};
|
|
9
|
+
const servers = {};
|
|
10
|
+
const inputs = [];
|
|
11
|
+
const inputMap = /* @__PURE__ */ new Map();
|
|
12
|
+
for (const [serverName, server] of Object.entries(config.mcpServers)) {
|
|
13
|
+
if (!shouldInclude(server)) continue;
|
|
14
|
+
const copilotServer = {};
|
|
15
|
+
if (server.command) {
|
|
16
|
+
copilotServer.command = server.command;
|
|
17
|
+
if (server.args) copilotServer.args = server.args;
|
|
18
|
+
} else if (server.url || server.httpUrl) {
|
|
19
|
+
const url = server.httpUrl || server.url;
|
|
20
|
+
if (url) {
|
|
21
|
+
copilotServer.url = url;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (server.env) {
|
|
25
|
+
copilotServer.env = {};
|
|
26
|
+
for (const [key, value] of Object.entries(server.env)) {
|
|
27
|
+
if (target === "editor" && value.includes("SECRET")) {
|
|
28
|
+
const inputId = `${serverName}_${key}`;
|
|
29
|
+
inputMap.set(inputId, value);
|
|
30
|
+
copilotServer.env[key] = `\${input:${inputId}}`;
|
|
31
|
+
inputs.push({
|
|
32
|
+
id: inputId,
|
|
33
|
+
type: "password",
|
|
34
|
+
description: `${key} for ${serverName}`
|
|
35
|
+
});
|
|
36
|
+
} else {
|
|
37
|
+
copilotServer.env[key] = value;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
if (server.tools) {
|
|
42
|
+
copilotServer.tools = server.tools;
|
|
43
|
+
} else if (server.alwaysAllow) {
|
|
44
|
+
copilotServer.tools = server.alwaysAllow;
|
|
45
|
+
}
|
|
46
|
+
servers[serverName] = copilotServer;
|
|
47
|
+
}
|
|
48
|
+
if (target === "codingAgent") {
|
|
49
|
+
const config2 = { mcpServers: servers };
|
|
50
|
+
return JSON.stringify(config2, null, 2);
|
|
51
|
+
} else {
|
|
52
|
+
const config2 = { servers };
|
|
53
|
+
if (inputs.length > 0) {
|
|
54
|
+
config2.inputs = inputs;
|
|
55
|
+
}
|
|
56
|
+
return JSON.stringify(config2, null, 2);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function generateCopilotMcpConfiguration(mcpServers, baseDir = "") {
|
|
60
|
+
const configs = [];
|
|
61
|
+
const rulesyncConfig = { mcpServers };
|
|
62
|
+
const editorContent = generateCopilotMcp(rulesyncConfig, "editor");
|
|
63
|
+
configs.push({
|
|
64
|
+
filepath: baseDir ? `${baseDir}/.vscode/mcp.json` : ".vscode/mcp.json",
|
|
65
|
+
content: `${editorContent}
|
|
66
|
+
`
|
|
67
|
+
});
|
|
68
|
+
const codingAgentContent = generateCopilotMcp(rulesyncConfig, "codingAgent");
|
|
69
|
+
configs.push({
|
|
70
|
+
filepath: baseDir ? `${baseDir}/.copilot/mcp.json` : ".copilot/mcp.json",
|
|
71
|
+
content: `${codingAgentContent}
|
|
72
|
+
`
|
|
73
|
+
});
|
|
74
|
+
return configs;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export {
|
|
78
|
+
generateCopilotMcp,
|
|
79
|
+
generateCopilotMcpConfiguration
|
|
80
|
+
};
|