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,166 @@
|
|
|
1
|
+
"""CLI command for installing MCP templates."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
9
|
+
|
|
10
|
+
from aiconfigkit.core.mcp.manager import MCPManager
|
|
11
|
+
from aiconfigkit.core.models import InstallationScope
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
console = Console()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def mcp_install_command(
|
|
18
|
+
source: str = typer.Argument(..., help="Source URL or local path to MCP template repository"),
|
|
19
|
+
namespace: str = typer.Option(..., "--as", help="Namespace for this template (unique identifier)"),
|
|
20
|
+
scope: str = typer.Option("project", "--scope", help="Installation scope: project or global"),
|
|
21
|
+
force: bool = typer.Option(False, "--force", help="Overwrite existing template if it exists"),
|
|
22
|
+
json_output: bool = typer.Option(False, "--json", help="Output results as JSON"),
|
|
23
|
+
) -> int:
|
|
24
|
+
"""
|
|
25
|
+
Install MCP server configurations from a template repository.
|
|
26
|
+
|
|
27
|
+
This downloads and caches MCP server definitions from a Git repository or local
|
|
28
|
+
directory into your local library. After installation, use 'inskit mcp configure'
|
|
29
|
+
to set up credentials and 'inskit mcp sync' to apply to AI tools.
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
|
|
33
|
+
# Install from GitHub repository
|
|
34
|
+
inskit mcp install https://github.com/company/backend-tools --as backend
|
|
35
|
+
|
|
36
|
+
# Install from local directory
|
|
37
|
+
inskit mcp install ./my-mcp-configs --as local-tools
|
|
38
|
+
|
|
39
|
+
# Install globally (available in all projects)
|
|
40
|
+
inskit mcp install https://github.com/me/personal-tools --as personal --scope global
|
|
41
|
+
|
|
42
|
+
# Force overwrite existing template
|
|
43
|
+
inskit mcp install https://github.com/company/backend-tools --as backend --force
|
|
44
|
+
"""
|
|
45
|
+
try:
|
|
46
|
+
# Parse scope
|
|
47
|
+
try:
|
|
48
|
+
install_scope = InstallationScope(scope)
|
|
49
|
+
except ValueError:
|
|
50
|
+
console.print(f"[red]Error:[/red] Invalid scope '{scope}'. Must be 'project' or 'global'")
|
|
51
|
+
return 1
|
|
52
|
+
|
|
53
|
+
# Get library root
|
|
54
|
+
library_root = _get_library_root()
|
|
55
|
+
|
|
56
|
+
# Create MCP manager
|
|
57
|
+
manager = MCPManager(library_root)
|
|
58
|
+
|
|
59
|
+
# Install template with progress indicator
|
|
60
|
+
with Progress(
|
|
61
|
+
SpinnerColumn(),
|
|
62
|
+
TextColumn("[progress.description]{task.description}"),
|
|
63
|
+
console=console,
|
|
64
|
+
) as progress:
|
|
65
|
+
task = progress.add_task(f"Installing MCP template '{namespace}'...", total=None)
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
template = manager.install_template(
|
|
69
|
+
source=source,
|
|
70
|
+
namespace=namespace,
|
|
71
|
+
scope=install_scope,
|
|
72
|
+
force=force,
|
|
73
|
+
)
|
|
74
|
+
finally:
|
|
75
|
+
progress.remove_task(task)
|
|
76
|
+
|
|
77
|
+
# Output results
|
|
78
|
+
if json_output:
|
|
79
|
+
import json
|
|
80
|
+
|
|
81
|
+
result = {
|
|
82
|
+
"success": True,
|
|
83
|
+
"namespace": template.namespace,
|
|
84
|
+
"version": template.version,
|
|
85
|
+
"servers": len(template.servers),
|
|
86
|
+
"sets": len(template.sets),
|
|
87
|
+
"scope": install_scope.value,
|
|
88
|
+
}
|
|
89
|
+
console.print(json.dumps(result, indent=2))
|
|
90
|
+
else:
|
|
91
|
+
console.print(f"[green]✓[/green] Installed MCP template: [bold]{namespace}[/bold]")
|
|
92
|
+
console.print(f" Version: {template.version}")
|
|
93
|
+
console.print(f" Description: {template.description}")
|
|
94
|
+
console.print(f" Servers: {len(template.servers)}")
|
|
95
|
+
console.print(f" Sets: {len(template.sets)}")
|
|
96
|
+
console.print(f" Scope: {install_scope.value}")
|
|
97
|
+
|
|
98
|
+
# Show next steps
|
|
99
|
+
console.print("\n[bold]Next steps:[/bold]")
|
|
100
|
+
|
|
101
|
+
# Check which servers need configuration
|
|
102
|
+
servers_needing_config = [s for s in template.servers if s.get_required_env_vars()]
|
|
103
|
+
|
|
104
|
+
if servers_needing_config:
|
|
105
|
+
console.print(" 1. Configure credentials for servers:")
|
|
106
|
+
for server in servers_needing_config[:3]: # Show first 3
|
|
107
|
+
console.print(f" [cyan]inskit mcp configure {namespace}.{server.name}[/cyan]")
|
|
108
|
+
if len(servers_needing_config) > 3:
|
|
109
|
+
console.print(f" ... and {len(servers_needing_config) - 3} more")
|
|
110
|
+
else:
|
|
111
|
+
console.print(" 1. [dim]No credentials needed for servers[/dim]")
|
|
112
|
+
|
|
113
|
+
console.print(" 2. Sync to AI tools: [cyan]inskit mcp sync --tool all[/cyan]")
|
|
114
|
+
|
|
115
|
+
if template.sets:
|
|
116
|
+
set_name = template.sets[0].name
|
|
117
|
+
console.print(f" 3. Or activate a set: [cyan]inskit mcp activate {namespace}.{set_name}[/cyan]")
|
|
118
|
+
|
|
119
|
+
return 0
|
|
120
|
+
|
|
121
|
+
except ValueError as e:
|
|
122
|
+
if json_output:
|
|
123
|
+
import json
|
|
124
|
+
|
|
125
|
+
console.print(json.dumps({"success": False, "error": str(e)}, indent=2))
|
|
126
|
+
else:
|
|
127
|
+
console.print(f"[red]Error:[/red] {e}")
|
|
128
|
+
return 1
|
|
129
|
+
|
|
130
|
+
except FileNotFoundError as e:
|
|
131
|
+
if json_output:
|
|
132
|
+
import json
|
|
133
|
+
|
|
134
|
+
console.print(json.dumps({"success": False, "error": str(e)}, indent=2))
|
|
135
|
+
else:
|
|
136
|
+
console.print(f"[red]Error:[/red] {e}")
|
|
137
|
+
return 1
|
|
138
|
+
|
|
139
|
+
except RuntimeError as e:
|
|
140
|
+
if json_output:
|
|
141
|
+
import json
|
|
142
|
+
|
|
143
|
+
console.print(json.dumps({"success": False, "error": str(e)}, indent=2))
|
|
144
|
+
else:
|
|
145
|
+
console.print(f"[red]Error:[/red] {e}")
|
|
146
|
+
return 1
|
|
147
|
+
|
|
148
|
+
except Exception as e:
|
|
149
|
+
logger.exception("Unexpected error during MCP template installation")
|
|
150
|
+
if json_output:
|
|
151
|
+
import json
|
|
152
|
+
|
|
153
|
+
console.print(json.dumps({"success": False, "error": f"Unexpected error: {e}"}, indent=2))
|
|
154
|
+
else:
|
|
155
|
+
console.print(f"[red]Unexpected error:[/red] {e}")
|
|
156
|
+
return 1
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def _get_library_root() -> Path:
|
|
160
|
+
"""
|
|
161
|
+
Get the library root directory.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
Path to library root (~/.instructionkit/library/)
|
|
165
|
+
"""
|
|
166
|
+
return Path.home() / ".instructionkit" / "library"
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"""CLI command for syncing MCP servers to AI tools."""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
import typer
|
|
7
|
+
from rich.console import Console
|
|
8
|
+
from rich.table import Table
|
|
9
|
+
|
|
10
|
+
from aiconfigkit.ai_tools.mcp_syncer import MCPSyncer
|
|
11
|
+
from aiconfigkit.core.models import InstallationScope
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
console = Console()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def mcp_sync_command(
|
|
18
|
+
tool: str = typer.Option(
|
|
19
|
+
"all",
|
|
20
|
+
"--tool",
|
|
21
|
+
"-t",
|
|
22
|
+
help="AI tool to sync to (claude, cursor, windsurf, or all)",
|
|
23
|
+
),
|
|
24
|
+
scope: str = typer.Option(
|
|
25
|
+
"project",
|
|
26
|
+
"--scope",
|
|
27
|
+
help="Scope to load configurations from (project or global)",
|
|
28
|
+
),
|
|
29
|
+
dry_run: bool = typer.Option(
|
|
30
|
+
False,
|
|
31
|
+
"--dry-run",
|
|
32
|
+
help="Show what would be synced without actually syncing",
|
|
33
|
+
),
|
|
34
|
+
no_backup: bool = typer.Option(
|
|
35
|
+
False,
|
|
36
|
+
"--no-backup",
|
|
37
|
+
help="Skip creating backup of config files before modifying",
|
|
38
|
+
),
|
|
39
|
+
json_output: bool = typer.Option(
|
|
40
|
+
False,
|
|
41
|
+
"--json",
|
|
42
|
+
help="Output results as JSON",
|
|
43
|
+
),
|
|
44
|
+
) -> int:
|
|
45
|
+
"""
|
|
46
|
+
Sync configured MCP servers to AI tool configuration files.
|
|
47
|
+
|
|
48
|
+
This command reads installed MCP servers from the library, resolves their
|
|
49
|
+
environment variables from .instructionkit/.env, and writes them to AI
|
|
50
|
+
tool configuration files (e.g., claude_desktop_config.json).
|
|
51
|
+
|
|
52
|
+
Examples:
|
|
53
|
+
|
|
54
|
+
# Sync to all detected AI tools
|
|
55
|
+
inskit mcp sync --tool all
|
|
56
|
+
|
|
57
|
+
# Sync to specific tool
|
|
58
|
+
inskit mcp sync --tool claude
|
|
59
|
+
|
|
60
|
+
# Dry run to see what would be synced
|
|
61
|
+
inskit mcp sync --tool all --dry-run
|
|
62
|
+
|
|
63
|
+
# Sync without creating backups
|
|
64
|
+
inskit mcp sync --tool claude --no-backup
|
|
65
|
+
|
|
66
|
+
# Sync global configurations
|
|
67
|
+
inskit mcp sync --scope global
|
|
68
|
+
"""
|
|
69
|
+
try:
|
|
70
|
+
# Parse scope
|
|
71
|
+
try:
|
|
72
|
+
install_scope = InstallationScope(scope)
|
|
73
|
+
except ValueError:
|
|
74
|
+
console.print(f"[red]Error:[/red] Invalid scope '{scope}'. Must be 'project' or 'global'")
|
|
75
|
+
return 1
|
|
76
|
+
|
|
77
|
+
# Create syncer
|
|
78
|
+
syncer = MCPSyncer(
|
|
79
|
+
library_root=Path.home() / ".instructionkit" / "library",
|
|
80
|
+
project_root=Path.cwd(),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# Parse tool names
|
|
84
|
+
tool_names = [tool] if tool != "all" else ["all"]
|
|
85
|
+
|
|
86
|
+
# Show sync info
|
|
87
|
+
if not json_output:
|
|
88
|
+
console.print("\n[bold]Syncing MCP servers to AI tools[/bold]")
|
|
89
|
+
console.print(f"Scope: {install_scope.value}")
|
|
90
|
+
console.print(f"Tools: {tool}")
|
|
91
|
+
if dry_run:
|
|
92
|
+
console.print("[yellow]DRY RUN - no changes will be made[/yellow]")
|
|
93
|
+
console.print()
|
|
94
|
+
|
|
95
|
+
# Perform sync
|
|
96
|
+
result = syncer.sync_all(
|
|
97
|
+
tool_names=tool_names,
|
|
98
|
+
scope=install_scope,
|
|
99
|
+
create_backup=not no_backup,
|
|
100
|
+
dry_run=dry_run,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
# Output results
|
|
104
|
+
if json_output:
|
|
105
|
+
import json
|
|
106
|
+
|
|
107
|
+
output = {
|
|
108
|
+
"success": result.success,
|
|
109
|
+
"synced_tools": result.synced_tools,
|
|
110
|
+
"skipped_tools": [{"name": name, "reason": reason} for name, reason in result.skipped_tools],
|
|
111
|
+
"synced_servers": result.synced_servers,
|
|
112
|
+
"skipped_servers": [{"name": name, "reason": reason} for name, reason in result.skipped_servers],
|
|
113
|
+
}
|
|
114
|
+
console.print(json.dumps(output, indent=2))
|
|
115
|
+
else:
|
|
116
|
+
# Show synced tools
|
|
117
|
+
if result.synced_tools:
|
|
118
|
+
console.print(f"[green]✓[/green] Synced to {len(result.synced_tools)} tool(s):")
|
|
119
|
+
for tool_name in result.synced_tools:
|
|
120
|
+
console.print(f" • {tool_name}")
|
|
121
|
+
else:
|
|
122
|
+
console.print("[yellow]⚠[/yellow] No tools were synced")
|
|
123
|
+
|
|
124
|
+
# Show skipped tools
|
|
125
|
+
if result.skipped_tools:
|
|
126
|
+
console.print(f"\n[yellow]⚠[/yellow] Skipped {len(result.skipped_tools)} tool(s):")
|
|
127
|
+
for tool_name, reason in result.skipped_tools:
|
|
128
|
+
console.print(f" • {tool_name}: {reason}")
|
|
129
|
+
|
|
130
|
+
# Show server summary
|
|
131
|
+
console.print("\n[bold]Server Summary:[/bold]")
|
|
132
|
+
console.print(f" Synced: {len(result.synced_servers)} server(s)")
|
|
133
|
+
if result.skipped_servers:
|
|
134
|
+
console.print(f" Skipped: {len(result.skipped_servers)} server(s)")
|
|
135
|
+
|
|
136
|
+
# Show skipped servers details
|
|
137
|
+
if result.skipped_servers:
|
|
138
|
+
console.print("\n[yellow]Skipped Servers:[/yellow]")
|
|
139
|
+
table = Table(show_header=True)
|
|
140
|
+
table.add_column("Server", style="cyan")
|
|
141
|
+
table.add_column("Reason", style="yellow")
|
|
142
|
+
|
|
143
|
+
for server_name, reason in result.skipped_servers:
|
|
144
|
+
table.add_row(server_name, reason)
|
|
145
|
+
|
|
146
|
+
console.print(table)
|
|
147
|
+
|
|
148
|
+
console.print(
|
|
149
|
+
"\n[dim]Tip: Run 'inskit mcp configure <namespace>' to configure missing credentials[/dim]"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
if not result.success:
|
|
153
|
+
return 1
|
|
154
|
+
|
|
155
|
+
return 0
|
|
156
|
+
|
|
157
|
+
except Exception as e:
|
|
158
|
+
logger.exception("Unexpected error during MCP sync")
|
|
159
|
+
if json_output:
|
|
160
|
+
import json
|
|
161
|
+
|
|
162
|
+
console.print(json.dumps({"success": False, "error": str(e)}, indent=2))
|
|
163
|
+
else:
|
|
164
|
+
console.print(f"[red]Unexpected error:[/red] {e}")
|
|
165
|
+
return 1
|