devsync 0.5.5__py3-none-any.whl
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.
- aiconfigkit/__init__.py +0 -0
- aiconfigkit/__main__.py +6 -0
- aiconfigkit/ai_tools/__init__.py +0 -0
- aiconfigkit/ai_tools/base.py +236 -0
- aiconfigkit/ai_tools/capability_registry.py +262 -0
- aiconfigkit/ai_tools/claude.py +91 -0
- aiconfigkit/ai_tools/claude_desktop.py +97 -0
- aiconfigkit/ai_tools/cline.py +92 -0
- aiconfigkit/ai_tools/copilot.py +92 -0
- aiconfigkit/ai_tools/cursor.py +109 -0
- aiconfigkit/ai_tools/detector.py +169 -0
- aiconfigkit/ai_tools/kiro.py +85 -0
- aiconfigkit/ai_tools/mcp_syncer.py +291 -0
- aiconfigkit/ai_tools/roo.py +110 -0
- aiconfigkit/ai_tools/translator.py +390 -0
- aiconfigkit/ai_tools/winsurf.py +102 -0
- aiconfigkit/cli/__init__.py +0 -0
- aiconfigkit/cli/delete.py +118 -0
- aiconfigkit/cli/download.py +274 -0
- aiconfigkit/cli/install.py +237 -0
- aiconfigkit/cli/install_new.py +937 -0
- aiconfigkit/cli/list.py +275 -0
- aiconfigkit/cli/main.py +454 -0
- aiconfigkit/cli/mcp_configure.py +232 -0
- aiconfigkit/cli/mcp_install.py +166 -0
- aiconfigkit/cli/mcp_sync.py +165 -0
- aiconfigkit/cli/package.py +383 -0
- aiconfigkit/cli/package_create.py +323 -0
- aiconfigkit/cli/package_install.py +472 -0
- aiconfigkit/cli/template.py +19 -0
- aiconfigkit/cli/template_backup.py +261 -0
- aiconfigkit/cli/template_init.py +499 -0
- aiconfigkit/cli/template_install.py +261 -0
- aiconfigkit/cli/template_list.py +172 -0
- aiconfigkit/cli/template_uninstall.py +146 -0
- aiconfigkit/cli/template_update.py +225 -0
- aiconfigkit/cli/template_validate.py +234 -0
- aiconfigkit/cli/tools.py +47 -0
- aiconfigkit/cli/uninstall.py +125 -0
- aiconfigkit/cli/update.py +309 -0
- aiconfigkit/core/__init__.py +0 -0
- aiconfigkit/core/checksum.py +211 -0
- aiconfigkit/core/component_detector.py +905 -0
- aiconfigkit/core/conflict_resolution.py +329 -0
- aiconfigkit/core/git_operations.py +539 -0
- aiconfigkit/core/mcp/__init__.py +1 -0
- aiconfigkit/core/mcp/credentials.py +279 -0
- aiconfigkit/core/mcp/manager.py +308 -0
- aiconfigkit/core/mcp/set_manager.py +1 -0
- aiconfigkit/core/mcp/validator.py +1 -0
- aiconfigkit/core/models.py +1661 -0
- aiconfigkit/core/package_creator.py +743 -0
- aiconfigkit/core/package_manifest.py +248 -0
- aiconfigkit/core/repository.py +298 -0
- aiconfigkit/core/secret_detector.py +438 -0
- aiconfigkit/core/template_manifest.py +283 -0
- aiconfigkit/core/version.py +201 -0
- aiconfigkit/storage/__init__.py +0 -0
- aiconfigkit/storage/library.py +429 -0
- aiconfigkit/storage/mcp_tracker.py +1 -0
- aiconfigkit/storage/package_tracker.py +234 -0
- aiconfigkit/storage/template_library.py +229 -0
- aiconfigkit/storage/template_tracker.py +296 -0
- aiconfigkit/storage/tracker.py +416 -0
- aiconfigkit/tui/__init__.py +5 -0
- aiconfigkit/tui/installer.py +511 -0
- aiconfigkit/utils/__init__.py +0 -0
- aiconfigkit/utils/atomic_write.py +90 -0
- aiconfigkit/utils/backup.py +169 -0
- aiconfigkit/utils/dotenv.py +128 -0
- aiconfigkit/utils/git_helpers.py +187 -0
- aiconfigkit/utils/logging.py +60 -0
- aiconfigkit/utils/namespace.py +134 -0
- aiconfigkit/utils/paths.py +205 -0
- aiconfigkit/utils/project.py +109 -0
- aiconfigkit/utils/streaming.py +216 -0
- aiconfigkit/utils/ui.py +194 -0
- aiconfigkit/utils/validation.py +187 -0
- devsync-0.5.5.dist-info/LICENSE +21 -0
- devsync-0.5.5.dist-info/METADATA +477 -0
- devsync-0.5.5.dist-info/RECORD +84 -0
- devsync-0.5.5.dist-info/WHEEL +5 -0
- devsync-0.5.5.dist-info/entry_points.txt +2 -0
- devsync-0.5.5.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""Cross-tool MCP server synchronization orchestration."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import logging
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any, Optional
|
|
7
|
+
|
|
8
|
+
from aiconfigkit.ai_tools.base import AITool
|
|
9
|
+
from aiconfigkit.ai_tools.detector import AIToolDetector
|
|
10
|
+
from aiconfigkit.core.mcp.credentials import CredentialManager
|
|
11
|
+
from aiconfigkit.core.mcp.manager import MCPManager
|
|
12
|
+
from aiconfigkit.core.models import EnvironmentConfig, InstallationScope, MCPServer, MCPTemplate
|
|
13
|
+
from aiconfigkit.utils.atomic_write import atomic_write
|
|
14
|
+
|
|
15
|
+
logger = logging.getLogger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class MCPSyncResult:
|
|
19
|
+
"""Result of MCP synchronization operation."""
|
|
20
|
+
|
|
21
|
+
def __init__(self) -> None:
|
|
22
|
+
"""Initialize sync result."""
|
|
23
|
+
self.synced_tools: list[str] = []
|
|
24
|
+
self.skipped_tools: list[tuple[str, str]] = [] # (tool_name, reason)
|
|
25
|
+
self.synced_servers: list[str] = []
|
|
26
|
+
self.skipped_servers: list[tuple[str, str]] = [] # (server_name, reason)
|
|
27
|
+
|
|
28
|
+
def add_synced_tool(self, tool_name: str) -> None:
|
|
29
|
+
"""Mark tool as successfully synced."""
|
|
30
|
+
self.synced_tools.append(tool_name)
|
|
31
|
+
|
|
32
|
+
def add_skipped_tool(self, tool_name: str, reason: str) -> None:
|
|
33
|
+
"""Mark tool as skipped with reason."""
|
|
34
|
+
self.skipped_tools.append((tool_name, reason))
|
|
35
|
+
|
|
36
|
+
def add_synced_server(self, server_name: str) -> None:
|
|
37
|
+
"""Mark server as successfully synced."""
|
|
38
|
+
if server_name not in self.synced_servers:
|
|
39
|
+
self.synced_servers.append(server_name)
|
|
40
|
+
|
|
41
|
+
def add_skipped_server(self, server_name: str, reason: str) -> None:
|
|
42
|
+
"""Mark server as skipped with reason."""
|
|
43
|
+
if not any(s[0] == server_name for s in self.skipped_servers):
|
|
44
|
+
self.skipped_servers.append((server_name, reason))
|
|
45
|
+
|
|
46
|
+
@property
|
|
47
|
+
def success(self) -> bool:
|
|
48
|
+
"""Check if any tools were successfully synced."""
|
|
49
|
+
return len(self.synced_tools) > 0
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class MCPSyncer:
|
|
53
|
+
"""Orchestrates MCP server synchronization to AI tools."""
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
library_root: Optional[Path] = None,
|
|
58
|
+
project_root: Optional[Path] = None,
|
|
59
|
+
):
|
|
60
|
+
"""
|
|
61
|
+
Initialize MCP syncer.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
library_root: Root directory for MCP library (defaults to ~/.instructionkit/library/)
|
|
65
|
+
project_root: Project root directory (defaults to current directory)
|
|
66
|
+
"""
|
|
67
|
+
self.library_root = library_root or Path.home() / ".instructionkit" / "library"
|
|
68
|
+
self.project_root = project_root or Path.cwd()
|
|
69
|
+
|
|
70
|
+
self.mcp_manager = MCPManager(self.library_root)
|
|
71
|
+
self.cred_manager = CredentialManager(self.project_root)
|
|
72
|
+
self.tool_detector = AIToolDetector()
|
|
73
|
+
|
|
74
|
+
def sync_all(
|
|
75
|
+
self,
|
|
76
|
+
tool_names: Optional[list[str]] = None,
|
|
77
|
+
scope: InstallationScope = InstallationScope.PROJECT,
|
|
78
|
+
create_backup: bool = True,
|
|
79
|
+
dry_run: bool = False,
|
|
80
|
+
) -> MCPSyncResult:
|
|
81
|
+
"""
|
|
82
|
+
Sync all MCP servers to AI tools.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
tool_names: List of tool names to sync to (None = all detected tools)
|
|
86
|
+
scope: Scope to load configurations from (PROJECT, GLOBAL, or merge)
|
|
87
|
+
create_backup: Create backup of config files before modifying
|
|
88
|
+
dry_run: Don't actually write configs, just report what would be done
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
MCPSyncResult with sync status
|
|
92
|
+
"""
|
|
93
|
+
result = MCPSyncResult()
|
|
94
|
+
|
|
95
|
+
# Load all installed MCP templates
|
|
96
|
+
templates = self._load_templates(scope)
|
|
97
|
+
|
|
98
|
+
if not templates:
|
|
99
|
+
logger.info("No MCP templates installed")
|
|
100
|
+
return result
|
|
101
|
+
|
|
102
|
+
# Collect all MCP servers from templates
|
|
103
|
+
all_servers: list[MCPServer] = []
|
|
104
|
+
for template in templates:
|
|
105
|
+
all_servers.extend(template.servers)
|
|
106
|
+
|
|
107
|
+
if not all_servers:
|
|
108
|
+
logger.info("No MCP servers found in installed templates")
|
|
109
|
+
return result
|
|
110
|
+
|
|
111
|
+
# Load environment configuration
|
|
112
|
+
env_config = self.cred_manager.merge_scopes()
|
|
113
|
+
|
|
114
|
+
# Validate servers have required credentials
|
|
115
|
+
validated_servers = []
|
|
116
|
+
for server in all_servers:
|
|
117
|
+
is_valid, missing = self._validate_server_credentials(server, env_config)
|
|
118
|
+
if is_valid:
|
|
119
|
+
validated_servers.append(server)
|
|
120
|
+
result.add_synced_server(server.get_fully_qualified_name())
|
|
121
|
+
else:
|
|
122
|
+
reason = f"Missing credentials: {', '.join(missing)}"
|
|
123
|
+
result.add_skipped_server(server.get_fully_qualified_name(), reason)
|
|
124
|
+
logger.warning(f"Skipping {server.get_fully_qualified_name()}: {reason}")
|
|
125
|
+
|
|
126
|
+
if not validated_servers:
|
|
127
|
+
logger.warning("No servers have complete credentials configured")
|
|
128
|
+
return result
|
|
129
|
+
|
|
130
|
+
# Resolve environment variables in server configurations
|
|
131
|
+
resolved_servers = self._resolve_env_vars(validated_servers, env_config)
|
|
132
|
+
|
|
133
|
+
# Get tools to sync to
|
|
134
|
+
if tool_names and "all" not in tool_names:
|
|
135
|
+
tools = []
|
|
136
|
+
for name in tool_names:
|
|
137
|
+
tool = self.tool_detector.get_tool_by_name(name)
|
|
138
|
+
if tool:
|
|
139
|
+
tools.append(tool)
|
|
140
|
+
else:
|
|
141
|
+
result.add_skipped_tool(name, "Unknown tool")
|
|
142
|
+
else:
|
|
143
|
+
tools = self.tool_detector.detect_installed_tools()
|
|
144
|
+
|
|
145
|
+
if not tools:
|
|
146
|
+
logger.warning("No AI tools detected")
|
|
147
|
+
return result
|
|
148
|
+
|
|
149
|
+
# Sync to each tool
|
|
150
|
+
for tool in tools:
|
|
151
|
+
tool_name = tool.tool_type.value
|
|
152
|
+
try:
|
|
153
|
+
logger.info(f"Syncing MCP servers to {tool.tool_name}")
|
|
154
|
+
|
|
155
|
+
if dry_run:
|
|
156
|
+
logger.info(f"[DRY RUN] Would sync {len(resolved_servers)} servers to {tool.tool_name}")
|
|
157
|
+
result.add_synced_tool(tool_name)
|
|
158
|
+
else:
|
|
159
|
+
# Check if tool has MCP config support
|
|
160
|
+
if not hasattr(tool, "get_mcp_config_path"):
|
|
161
|
+
result.add_skipped_tool(tool_name, "MCP config not supported")
|
|
162
|
+
logger.warning(f"{tool.tool_name} does not support MCP configuration sync")
|
|
163
|
+
continue
|
|
164
|
+
|
|
165
|
+
# Sync servers to tool
|
|
166
|
+
self._sync_to_tool(tool, resolved_servers, create_backup)
|
|
167
|
+
result.add_synced_tool(tool_name)
|
|
168
|
+
logger.info(f"Successfully synced to {tool.tool_name}")
|
|
169
|
+
|
|
170
|
+
except Exception as e:
|
|
171
|
+
result.add_skipped_tool(tool_name, str(e))
|
|
172
|
+
logger.error(f"Failed to sync to {tool.tool_name}: {e}")
|
|
173
|
+
|
|
174
|
+
return result
|
|
175
|
+
|
|
176
|
+
def _load_templates(self, scope: InstallationScope) -> list[MCPTemplate]:
|
|
177
|
+
"""
|
|
178
|
+
Load all installed MCP templates.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
scope: Scope to load from
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
List of MCPTemplate objects
|
|
185
|
+
"""
|
|
186
|
+
templates = []
|
|
187
|
+
|
|
188
|
+
# Load project templates
|
|
189
|
+
if scope in (InstallationScope.PROJECT, InstallationScope.PROJECT):
|
|
190
|
+
templates.extend(self.mcp_manager.list_templates(InstallationScope.PROJECT))
|
|
191
|
+
|
|
192
|
+
# Load global templates
|
|
193
|
+
if scope == InstallationScope.GLOBAL:
|
|
194
|
+
templates.extend(self.mcp_manager.list_templates(InstallationScope.GLOBAL))
|
|
195
|
+
|
|
196
|
+
return templates
|
|
197
|
+
|
|
198
|
+
def _validate_server_credentials(self, server: MCPServer, env_config: EnvironmentConfig) -> tuple[bool, list[str]]:
|
|
199
|
+
"""
|
|
200
|
+
Validate that server has all required credentials.
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
server: MCP server to validate
|
|
204
|
+
env_config: Environment configuration
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
Tuple of (is_valid, missing_vars)
|
|
208
|
+
"""
|
|
209
|
+
required_vars = server.get_required_env_vars()
|
|
210
|
+
missing_vars = []
|
|
211
|
+
|
|
212
|
+
for var_name in required_vars:
|
|
213
|
+
if not env_config.has(var_name):
|
|
214
|
+
missing_vars.append(var_name)
|
|
215
|
+
|
|
216
|
+
return (len(missing_vars) == 0, missing_vars)
|
|
217
|
+
|
|
218
|
+
def _resolve_env_vars(self, servers: list[MCPServer], env_config: EnvironmentConfig) -> list[dict[str, Any]]:
|
|
219
|
+
"""
|
|
220
|
+
Resolve environment variables in server configurations.
|
|
221
|
+
|
|
222
|
+
Args:
|
|
223
|
+
servers: List of MCP servers
|
|
224
|
+
env_config: Environment configuration
|
|
225
|
+
|
|
226
|
+
Returns:
|
|
227
|
+
List of resolved server configurations as dicts
|
|
228
|
+
"""
|
|
229
|
+
resolved = []
|
|
230
|
+
|
|
231
|
+
for server in servers:
|
|
232
|
+
# Build server config dict
|
|
233
|
+
config: dict[str, Any] = {
|
|
234
|
+
"command": server.command,
|
|
235
|
+
"args": server.args,
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
# Resolve environment variables
|
|
239
|
+
if server.env:
|
|
240
|
+
resolved_env = {}
|
|
241
|
+
for var_name, var_value in server.env.items():
|
|
242
|
+
# Get value from env_config
|
|
243
|
+
actual_value = env_config.get(var_name)
|
|
244
|
+
if actual_value:
|
|
245
|
+
resolved_env[var_name] = actual_value
|
|
246
|
+
|
|
247
|
+
if resolved_env:
|
|
248
|
+
config["env"] = resolved_env
|
|
249
|
+
|
|
250
|
+
# Add to resolved list with server name
|
|
251
|
+
resolved.append(
|
|
252
|
+
{
|
|
253
|
+
"name": server.get_fully_qualified_name(),
|
|
254
|
+
"config": config,
|
|
255
|
+
}
|
|
256
|
+
)
|
|
257
|
+
|
|
258
|
+
return resolved
|
|
259
|
+
|
|
260
|
+
def _sync_to_tool(self, tool: AITool, servers: list[dict[str, Any]], create_backup: bool) -> None:
|
|
261
|
+
"""
|
|
262
|
+
Sync MCP servers to a specific AI tool.
|
|
263
|
+
|
|
264
|
+
Args:
|
|
265
|
+
tool: AITool instance
|
|
266
|
+
servers: List of resolved server configurations
|
|
267
|
+
create_backup: Create backup before modifying
|
|
268
|
+
|
|
269
|
+
Raises:
|
|
270
|
+
RuntimeError: If sync fails
|
|
271
|
+
"""
|
|
272
|
+
config_path = tool.get_mcp_config_path()
|
|
273
|
+
|
|
274
|
+
# Load existing config if it exists
|
|
275
|
+
if config_path.exists():
|
|
276
|
+
with open(config_path, "r", encoding="utf-8") as f:
|
|
277
|
+
config = json.load(f)
|
|
278
|
+
else:
|
|
279
|
+
config = {}
|
|
280
|
+
|
|
281
|
+
# Ensure mcpServers section exists
|
|
282
|
+
if "mcpServers" not in config:
|
|
283
|
+
config["mcpServers"] = {}
|
|
284
|
+
|
|
285
|
+
# Update mcpServers with our servers
|
|
286
|
+
for server in servers:
|
|
287
|
+
config["mcpServers"][server["name"]] = server["config"]
|
|
288
|
+
|
|
289
|
+
# Write config atomically
|
|
290
|
+
with atomic_write(config_path, create_backup=create_backup) as f:
|
|
291
|
+
json.dump(config, f, indent=2)
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Roo Code AI tool integration."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from aiconfigkit.ai_tools.base import AITool
|
|
6
|
+
from aiconfigkit.core.models import AIToolType
|
|
7
|
+
from aiconfigkit.utils.paths import get_roo_config_dir
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class RooTool(AITool):
|
|
11
|
+
"""Integration for Roo Code AI coding tool (VS Code extension).
|
|
12
|
+
|
|
13
|
+
Roo Code (formerly Roo Cline) uses .roo/rules/ directory at the project root
|
|
14
|
+
for AI instructions. Files are .md (Markdown) and are read recursively in
|
|
15
|
+
alphabetical order by filename. Numeric prefixes control load order.
|
|
16
|
+
|
|
17
|
+
Mode-specific rules can be placed in .roo/rules-{mode-slug}/ directories.
|
|
18
|
+
Project-level MCP config is at .roo/mcp.json.
|
|
19
|
+
|
|
20
|
+
Detection is based on the VS Code extension rooveterinaryinc.roo-cline
|
|
21
|
+
globalStorage directory.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def tool_type(self) -> AIToolType:
|
|
26
|
+
"""Return the AI tool type identifier."""
|
|
27
|
+
return AIToolType.ROO
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def tool_name(self) -> str:
|
|
31
|
+
"""Return human-readable tool name."""
|
|
32
|
+
return "Roo Code"
|
|
33
|
+
|
|
34
|
+
def is_installed(self) -> bool:
|
|
35
|
+
"""
|
|
36
|
+
Check if Roo Code is installed on the system.
|
|
37
|
+
|
|
38
|
+
Checks for existence of the Roo Code VS Code extension globalStorage directory
|
|
39
|
+
(rooveterinaryinc.roo-cline).
|
|
40
|
+
|
|
41
|
+
Returns:
|
|
42
|
+
True if Roo Code is detected
|
|
43
|
+
"""
|
|
44
|
+
try:
|
|
45
|
+
config_dir = get_roo_config_dir()
|
|
46
|
+
return config_dir.exists()
|
|
47
|
+
except Exception:
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
def get_instructions_directory(self) -> Path:
|
|
51
|
+
"""
|
|
52
|
+
Get the directory where Roo Code global instructions should be installed.
|
|
53
|
+
|
|
54
|
+
Roo Code supports global rules at ~/.roo/rules/.
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Path to Roo Code global instructions directory
|
|
58
|
+
|
|
59
|
+
Raises:
|
|
60
|
+
FileNotFoundError: If Roo Code is not installed
|
|
61
|
+
"""
|
|
62
|
+
if not self.is_installed():
|
|
63
|
+
raise FileNotFoundError(f"{self.tool_name} is not installed")
|
|
64
|
+
from aiconfigkit.utils.paths import get_home_directory
|
|
65
|
+
|
|
66
|
+
global_dir = get_home_directory() / ".roo" / "rules"
|
|
67
|
+
global_dir.mkdir(parents=True, exist_ok=True)
|
|
68
|
+
return global_dir
|
|
69
|
+
|
|
70
|
+
def get_instruction_file_extension(self) -> str:
|
|
71
|
+
"""
|
|
72
|
+
Get the file extension for Roo Code instructions.
|
|
73
|
+
|
|
74
|
+
Roo Code uses markdown (.md) files in the .roo/rules/ directory.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
File extension including the dot
|
|
78
|
+
"""
|
|
79
|
+
return ".md"
|
|
80
|
+
|
|
81
|
+
def get_project_instructions_directory(self, project_root: Path) -> Path:
|
|
82
|
+
"""
|
|
83
|
+
Get the directory for project-specific Roo Code instructions.
|
|
84
|
+
|
|
85
|
+
Roo Code stores project-specific rules in .roo/rules/ directory at the
|
|
86
|
+
project root. It reads .md files recursively from this directory.
|
|
87
|
+
Numeric prefixes (e.g., 01-coding-standards.md) control load order.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
project_root: Path to the project root directory
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Path to project instructions directory (.roo/rules/)
|
|
94
|
+
"""
|
|
95
|
+
instructions_dir = project_root / ".roo" / "rules"
|
|
96
|
+
instructions_dir.mkdir(parents=True, exist_ok=True)
|
|
97
|
+
return instructions_dir
|
|
98
|
+
|
|
99
|
+
def get_mcp_config_path(self) -> Path:
|
|
100
|
+
"""
|
|
101
|
+
Get the path to the MCP configuration file for Roo Code.
|
|
102
|
+
|
|
103
|
+
Roo Code stores project-level MCP config at .roo/mcp.json.
|
|
104
|
+
Global MCP config is at the globalStorage settings directory.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
Path to global MCP configuration file
|
|
108
|
+
"""
|
|
109
|
+
config_dir = get_roo_config_dir()
|
|
110
|
+
return config_dir / "settings" / "cline_mcp_settings.json"
|