mcp-ticketer 0.4.11__py3-none-any.whl → 2.0.1__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.
Potentially problematic release.
This version of mcp-ticketer might be problematic. Click here for more details.
- mcp_ticketer/__init__.py +10 -10
- mcp_ticketer/__version__.py +3 -3
- mcp_ticketer/adapters/__init__.py +2 -0
- mcp_ticketer/adapters/aitrackdown.py +394 -9
- mcp_ticketer/adapters/asana/__init__.py +15 -0
- mcp_ticketer/adapters/asana/adapter.py +1416 -0
- mcp_ticketer/adapters/asana/client.py +292 -0
- mcp_ticketer/adapters/asana/mappers.py +348 -0
- mcp_ticketer/adapters/asana/types.py +146 -0
- mcp_ticketer/adapters/github.py +836 -105
- mcp_ticketer/adapters/hybrid.py +47 -5
- mcp_ticketer/adapters/jira.py +772 -1
- mcp_ticketer/adapters/linear/adapter.py +2293 -108
- mcp_ticketer/adapters/linear/client.py +146 -12
- mcp_ticketer/adapters/linear/mappers.py +105 -11
- mcp_ticketer/adapters/linear/queries.py +168 -1
- mcp_ticketer/adapters/linear/types.py +80 -4
- mcp_ticketer/analysis/__init__.py +56 -0
- mcp_ticketer/analysis/dependency_graph.py +255 -0
- mcp_ticketer/analysis/health_assessment.py +304 -0
- mcp_ticketer/analysis/orphaned.py +218 -0
- mcp_ticketer/analysis/project_status.py +594 -0
- mcp_ticketer/analysis/similarity.py +224 -0
- mcp_ticketer/analysis/staleness.py +266 -0
- mcp_ticketer/automation/__init__.py +11 -0
- mcp_ticketer/automation/project_updates.py +378 -0
- mcp_ticketer/cache/memory.py +3 -3
- mcp_ticketer/cli/adapter_diagnostics.py +4 -2
- mcp_ticketer/cli/auggie_configure.py +18 -6
- mcp_ticketer/cli/codex_configure.py +175 -60
- mcp_ticketer/cli/configure.py +884 -146
- mcp_ticketer/cli/cursor_configure.py +314 -0
- mcp_ticketer/cli/diagnostics.py +31 -28
- mcp_ticketer/cli/discover.py +293 -21
- mcp_ticketer/cli/gemini_configure.py +18 -6
- mcp_ticketer/cli/init_command.py +880 -0
- mcp_ticketer/cli/instruction_commands.py +435 -0
- mcp_ticketer/cli/linear_commands.py +99 -15
- mcp_ticketer/cli/main.py +109 -2055
- mcp_ticketer/cli/mcp_configure.py +673 -99
- mcp_ticketer/cli/mcp_server_commands.py +415 -0
- mcp_ticketer/cli/migrate_config.py +12 -8
- mcp_ticketer/cli/platform_commands.py +6 -6
- mcp_ticketer/cli/platform_detection.py +477 -0
- mcp_ticketer/cli/platform_installer.py +536 -0
- mcp_ticketer/cli/project_update_commands.py +350 -0
- mcp_ticketer/cli/queue_commands.py +15 -15
- mcp_ticketer/cli/setup_command.py +639 -0
- mcp_ticketer/cli/simple_health.py +13 -11
- mcp_ticketer/cli/ticket_commands.py +277 -36
- mcp_ticketer/cli/update_checker.py +313 -0
- mcp_ticketer/cli/utils.py +45 -41
- mcp_ticketer/core/__init__.py +35 -1
- mcp_ticketer/core/adapter.py +170 -5
- mcp_ticketer/core/config.py +38 -31
- mcp_ticketer/core/env_discovery.py +33 -3
- mcp_ticketer/core/env_loader.py +7 -6
- mcp_ticketer/core/exceptions.py +10 -4
- mcp_ticketer/core/http_client.py +10 -10
- mcp_ticketer/core/instructions.py +405 -0
- mcp_ticketer/core/label_manager.py +732 -0
- mcp_ticketer/core/mappers.py +32 -20
- mcp_ticketer/core/models.py +136 -1
- mcp_ticketer/core/onepassword_secrets.py +379 -0
- mcp_ticketer/core/priority_matcher.py +463 -0
- mcp_ticketer/core/project_config.py +148 -14
- mcp_ticketer/core/registry.py +1 -1
- mcp_ticketer/core/session_state.py +171 -0
- mcp_ticketer/core/state_matcher.py +592 -0
- mcp_ticketer/core/url_parser.py +425 -0
- mcp_ticketer/core/validators.py +69 -0
- mcp_ticketer/defaults/ticket_instructions.md +644 -0
- mcp_ticketer/mcp/__init__.py +2 -2
- mcp_ticketer/mcp/server/__init__.py +2 -2
- mcp_ticketer/mcp/server/diagnostic_helper.py +175 -0
- mcp_ticketer/mcp/server/main.py +187 -93
- mcp_ticketer/mcp/server/routing.py +655 -0
- mcp_ticketer/mcp/server/server_sdk.py +58 -0
- mcp_ticketer/mcp/server/tools/__init__.py +37 -9
- mcp_ticketer/mcp/server/tools/analysis_tools.py +854 -0
- mcp_ticketer/mcp/server/tools/attachment_tools.py +65 -20
- mcp_ticketer/mcp/server/tools/bulk_tools.py +259 -202
- mcp_ticketer/mcp/server/tools/comment_tools.py +74 -12
- mcp_ticketer/mcp/server/tools/config_tools.py +1429 -0
- mcp_ticketer/mcp/server/tools/diagnostic_tools.py +211 -0
- mcp_ticketer/mcp/server/tools/hierarchy_tools.py +878 -319
- mcp_ticketer/mcp/server/tools/instruction_tools.py +295 -0
- mcp_ticketer/mcp/server/tools/label_tools.py +942 -0
- mcp_ticketer/mcp/server/tools/pr_tools.py +3 -7
- mcp_ticketer/mcp/server/tools/project_status_tools.py +158 -0
- mcp_ticketer/mcp/server/tools/project_update_tools.py +473 -0
- mcp_ticketer/mcp/server/tools/search_tools.py +180 -97
- mcp_ticketer/mcp/server/tools/session_tools.py +308 -0
- mcp_ticketer/mcp/server/tools/ticket_tools.py +1182 -82
- mcp_ticketer/mcp/server/tools/user_ticket_tools.py +364 -0
- mcp_ticketer/queue/health_monitor.py +1 -0
- mcp_ticketer/queue/manager.py +4 -4
- mcp_ticketer/queue/queue.py +3 -3
- mcp_ticketer/queue/run_worker.py +1 -1
- mcp_ticketer/queue/ticket_registry.py +2 -2
- mcp_ticketer/queue/worker.py +15 -13
- mcp_ticketer/utils/__init__.py +5 -0
- mcp_ticketer/utils/token_utils.py +246 -0
- mcp_ticketer-2.0.1.dist-info/METADATA +1366 -0
- mcp_ticketer-2.0.1.dist-info/RECORD +122 -0
- mcp_ticketer-0.4.11.dist-info/METADATA +0 -496
- mcp_ticketer-0.4.11.dist-info/RECORD +0 -77
- {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/WHEEL +0 -0
- {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/entry_points.txt +0 -0
- {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/licenses/LICENSE +0 -0
- {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,536 @@
|
|
|
1
|
+
"""Platform installation commands for mcp-ticketer MCP server.
|
|
2
|
+
|
|
3
|
+
This module provides commands for installing and removing mcp-ticketer
|
|
4
|
+
MCP server configuration for various AI platforms (Claude, Gemini, Codex, Auggie).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
from rich.table import Table
|
|
12
|
+
|
|
13
|
+
# Import for typing compatibility
|
|
14
|
+
from .init_command import init
|
|
15
|
+
from .platform_detection import PlatformDetector, get_platform_by_name
|
|
16
|
+
|
|
17
|
+
console = Console()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def install(
|
|
21
|
+
platform: str | None = typer.Argument(
|
|
22
|
+
None,
|
|
23
|
+
help="Platform to install (claude-code, cursor, gemini, codex, auggie). Use claude-desktop for desktop AI assistant.",
|
|
24
|
+
),
|
|
25
|
+
auto_detect: bool = typer.Option(
|
|
26
|
+
False,
|
|
27
|
+
"--auto-detect",
|
|
28
|
+
"-d",
|
|
29
|
+
help="Auto-detect and show all code editors (excludes desktop AI assistants by default)",
|
|
30
|
+
),
|
|
31
|
+
install_all: bool = typer.Option(
|
|
32
|
+
False,
|
|
33
|
+
"--all",
|
|
34
|
+
help="Install for all detected code editors (excludes Claude Desktop unless --include-desktop specified)",
|
|
35
|
+
),
|
|
36
|
+
include_desktop: bool = typer.Option(
|
|
37
|
+
False,
|
|
38
|
+
"--include-desktop",
|
|
39
|
+
help="Include Claude Desktop in auto-detection and --all installation",
|
|
40
|
+
),
|
|
41
|
+
adapter: str | None = typer.Option(
|
|
42
|
+
None,
|
|
43
|
+
"--adapter",
|
|
44
|
+
"-a",
|
|
45
|
+
help="Adapter type to use (interactive prompt if not specified)",
|
|
46
|
+
),
|
|
47
|
+
project_path: str | None = typer.Option(
|
|
48
|
+
None, "--path", help="Project path (default: current directory)"
|
|
49
|
+
),
|
|
50
|
+
global_config: bool = typer.Option(
|
|
51
|
+
False,
|
|
52
|
+
"--global",
|
|
53
|
+
"-g",
|
|
54
|
+
help="Save to global config instead of project-specific",
|
|
55
|
+
),
|
|
56
|
+
base_path: str | None = typer.Option(
|
|
57
|
+
None,
|
|
58
|
+
"--base-path",
|
|
59
|
+
"-p",
|
|
60
|
+
help="Base path for ticket storage (AITrackdown only)",
|
|
61
|
+
),
|
|
62
|
+
api_key: str | None = typer.Option(
|
|
63
|
+
None, "--api-key", help="API key for Linear or API token for JIRA"
|
|
64
|
+
),
|
|
65
|
+
team_id: str | None = typer.Option(
|
|
66
|
+
None, "--team-id", help="Linear team ID (required for Linear adapter)"
|
|
67
|
+
),
|
|
68
|
+
jira_server: str | None = typer.Option(
|
|
69
|
+
None,
|
|
70
|
+
"--jira-server",
|
|
71
|
+
help="JIRA server URL (e.g., https://company.atlassian.net)",
|
|
72
|
+
),
|
|
73
|
+
jira_email: str | None = typer.Option(
|
|
74
|
+
None, "--jira-email", help="JIRA user email for authentication"
|
|
75
|
+
),
|
|
76
|
+
jira_project: str | None = typer.Option(
|
|
77
|
+
None, "--jira-project", help="Default JIRA project key"
|
|
78
|
+
),
|
|
79
|
+
github_owner: str | None = typer.Option(
|
|
80
|
+
None, "--github-owner", help="GitHub repository owner"
|
|
81
|
+
),
|
|
82
|
+
github_repo: str | None = typer.Option(
|
|
83
|
+
None, "--github-repo", help="GitHub repository name"
|
|
84
|
+
),
|
|
85
|
+
github_token: str | None = typer.Option(
|
|
86
|
+
None, "--github-token", help="GitHub Personal Access Token"
|
|
87
|
+
),
|
|
88
|
+
dry_run: bool = typer.Option(
|
|
89
|
+
False,
|
|
90
|
+
"--dry-run",
|
|
91
|
+
help="Show what would be done without making changes (for platform installation)",
|
|
92
|
+
),
|
|
93
|
+
) -> None:
|
|
94
|
+
"""Install MCP server configuration for AI platforms.
|
|
95
|
+
|
|
96
|
+
This command configures mcp-ticketer as an MCP server for various AI
|
|
97
|
+
platforms. It updates platform-specific configuration files to enable
|
|
98
|
+
mcp-ticketer integration.
|
|
99
|
+
|
|
100
|
+
RECOMMENDED: Use 'mcp-ticketer setup' for first-time setup, which
|
|
101
|
+
handles both adapter configuration and platform installation together.
|
|
102
|
+
|
|
103
|
+
Platform Installation:
|
|
104
|
+
# Auto-detect and prompt for platform selection
|
|
105
|
+
mcp-ticketer install
|
|
106
|
+
|
|
107
|
+
# Show all detected platforms
|
|
108
|
+
mcp-ticketer install --auto-detect
|
|
109
|
+
|
|
110
|
+
# Install for all detected platforms
|
|
111
|
+
mcp-ticketer install --all
|
|
112
|
+
|
|
113
|
+
# Install for specific platform
|
|
114
|
+
mcp-ticketer install claude-code # Claude Code (project-level)
|
|
115
|
+
mcp-ticketer install claude-desktop # Claude Desktop (global)
|
|
116
|
+
mcp-ticketer install gemini # Gemini CLI
|
|
117
|
+
mcp-ticketer install codex # Codex
|
|
118
|
+
mcp-ticketer install auggie # Auggie
|
|
119
|
+
|
|
120
|
+
Legacy Usage (adapter setup, deprecated - use 'init' or 'setup' instead):
|
|
121
|
+
mcp-ticketer install --adapter linear # Use 'init' or 'setup' instead
|
|
122
|
+
|
|
123
|
+
"""
|
|
124
|
+
detector = PlatformDetector()
|
|
125
|
+
|
|
126
|
+
# Handle auto-detect flag (just show detected platforms and exit)
|
|
127
|
+
if auto_detect:
|
|
128
|
+
detected = detector.detect_all(
|
|
129
|
+
project_path=Path(project_path) if project_path else Path.cwd(),
|
|
130
|
+
exclude_desktop=not include_desktop,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if not detected:
|
|
134
|
+
console.print("[yellow]No code editors detected.[/yellow]")
|
|
135
|
+
console.print("\n[bold]Supported code editors:[/bold]")
|
|
136
|
+
console.print(" • Claude Code - Project-level AI code assistant")
|
|
137
|
+
console.print(" • Cursor - AI-powered code editor")
|
|
138
|
+
console.print(" • Auggie - CLI code assistant")
|
|
139
|
+
console.print(" • Codex - CLI code assistant")
|
|
140
|
+
console.print(" • Gemini - CLI code assistant")
|
|
141
|
+
if not include_desktop:
|
|
142
|
+
console.print(
|
|
143
|
+
"\n[dim]Use --include-desktop to also detect Claude Desktop (desktop AI assistant)[/dim]"
|
|
144
|
+
)
|
|
145
|
+
console.print(
|
|
146
|
+
"\n[dim]Install these platforms to use them with mcp-ticketer.[/dim]"
|
|
147
|
+
)
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
console.print("[bold]Detected AI platforms:[/bold]\n")
|
|
151
|
+
table = Table(show_header=True, header_style="bold cyan")
|
|
152
|
+
table.add_column("Platform", style="green")
|
|
153
|
+
table.add_column("Status", style="yellow")
|
|
154
|
+
table.add_column("Scope", style="blue")
|
|
155
|
+
table.add_column("Config Path", style="dim")
|
|
156
|
+
|
|
157
|
+
for plat in detected:
|
|
158
|
+
status = "✓ Installed" if plat.is_installed else "⚠ Config Issue"
|
|
159
|
+
table.add_row(plat.display_name, status, plat.scope, str(plat.config_path))
|
|
160
|
+
|
|
161
|
+
console.print(table)
|
|
162
|
+
console.print(
|
|
163
|
+
"\n[dim]Run 'mcp-ticketer install <platform>' to configure a specific platform[/dim]"
|
|
164
|
+
)
|
|
165
|
+
console.print(
|
|
166
|
+
"[dim]Run 'mcp-ticketer install --all' to configure all detected platforms[/dim]"
|
|
167
|
+
)
|
|
168
|
+
return
|
|
169
|
+
|
|
170
|
+
# Handle --all flag (install for all detected platforms)
|
|
171
|
+
if install_all:
|
|
172
|
+
detected = detector.detect_all(
|
|
173
|
+
project_path=Path(project_path) if project_path else Path.cwd(),
|
|
174
|
+
exclude_desktop=not include_desktop,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
if not detected:
|
|
178
|
+
console.print("[yellow]No AI platforms detected.[/yellow]")
|
|
179
|
+
console.print(
|
|
180
|
+
"Run 'mcp-ticketer install --auto-detect' to see supported platforms."
|
|
181
|
+
)
|
|
182
|
+
return
|
|
183
|
+
|
|
184
|
+
# Handle dry-run mode - show what would be installed without actually installing
|
|
185
|
+
if dry_run:
|
|
186
|
+
console.print(
|
|
187
|
+
"\n[yellow]DRY RUN - The following platforms would be configured:[/yellow]\n"
|
|
188
|
+
)
|
|
189
|
+
|
|
190
|
+
installable_count = 0
|
|
191
|
+
for plat in detected:
|
|
192
|
+
if plat.is_installed:
|
|
193
|
+
console.print(f" ✓ {plat.display_name} ({plat.scope})")
|
|
194
|
+
installable_count += 1
|
|
195
|
+
else:
|
|
196
|
+
console.print(
|
|
197
|
+
f" ⚠ {plat.display_name} ({plat.scope}) - would be skipped (configuration issue)"
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
console.print(
|
|
201
|
+
f"\n[dim]Would configure {installable_count} platform(s)[/dim]"
|
|
202
|
+
)
|
|
203
|
+
return
|
|
204
|
+
|
|
205
|
+
console.print(
|
|
206
|
+
f"[bold]Installing for {len(detected)} detected platform(s)...[/bold]\n"
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
# Import configuration functions
|
|
210
|
+
from .auggie_configure import configure_auggie_mcp
|
|
211
|
+
from .codex_configure import configure_codex_mcp
|
|
212
|
+
from .cursor_configure import configure_cursor_mcp
|
|
213
|
+
from .gemini_configure import configure_gemini_mcp
|
|
214
|
+
from .mcp_configure import configure_claude_mcp
|
|
215
|
+
|
|
216
|
+
# Map platform names to configuration functions
|
|
217
|
+
platform_mapping = {
|
|
218
|
+
"claude-code": lambda: configure_claude_mcp(
|
|
219
|
+
global_config=False, force=True
|
|
220
|
+
),
|
|
221
|
+
"claude-desktop": lambda: configure_claude_mcp(
|
|
222
|
+
global_config=True, force=True
|
|
223
|
+
),
|
|
224
|
+
"cursor": lambda: configure_cursor_mcp(force=True),
|
|
225
|
+
"auggie": lambda: configure_auggie_mcp(force=True),
|
|
226
|
+
"gemini": lambda: configure_gemini_mcp(scope="project", force=True),
|
|
227
|
+
"codex": lambda: configure_codex_mcp(force=True),
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
success_count = 0
|
|
231
|
+
failed = []
|
|
232
|
+
|
|
233
|
+
for plat in detected:
|
|
234
|
+
if not plat.is_installed:
|
|
235
|
+
console.print(
|
|
236
|
+
f"[yellow]⚠[/yellow] Skipping {plat.display_name} (configuration issue)"
|
|
237
|
+
)
|
|
238
|
+
continue
|
|
239
|
+
|
|
240
|
+
config_func = platform_mapping.get(plat.name)
|
|
241
|
+
if not config_func:
|
|
242
|
+
console.print(
|
|
243
|
+
f"[yellow]⚠[/yellow] No installer for {plat.display_name}"
|
|
244
|
+
)
|
|
245
|
+
continue
|
|
246
|
+
|
|
247
|
+
try:
|
|
248
|
+
console.print(f"[cyan]Installing for {plat.display_name}...[/cyan]")
|
|
249
|
+
config_func()
|
|
250
|
+
success_count += 1
|
|
251
|
+
except Exception as e:
|
|
252
|
+
console.print(
|
|
253
|
+
f"[red]✗[/red] Failed to install for {plat.display_name}: {e}"
|
|
254
|
+
)
|
|
255
|
+
failed.append(plat.display_name)
|
|
256
|
+
|
|
257
|
+
console.print(
|
|
258
|
+
f"\n[bold]Installation complete:[/bold] {success_count} succeeded"
|
|
259
|
+
)
|
|
260
|
+
if failed:
|
|
261
|
+
console.print(f"[red]Failed:[/red] {', '.join(failed)}")
|
|
262
|
+
return
|
|
263
|
+
|
|
264
|
+
# If no platform argument and no adapter flag, auto-detect and prompt
|
|
265
|
+
if platform is None and adapter is None:
|
|
266
|
+
detected = detector.detect_all(
|
|
267
|
+
project_path=Path(project_path) if project_path else Path.cwd()
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
# Filter to only installed platforms
|
|
271
|
+
installed = [p for p in detected if p.is_installed]
|
|
272
|
+
|
|
273
|
+
if not installed:
|
|
274
|
+
console.print("[yellow]No AI platforms detected.[/yellow]")
|
|
275
|
+
console.print("\n[bold]To see supported platforms:[/bold]")
|
|
276
|
+
console.print(" mcp-ticketer install --auto-detect")
|
|
277
|
+
console.print("\n[bold]Or run legacy adapter setup:[/bold]")
|
|
278
|
+
console.print(" mcp-ticketer install --adapter <adapter-type>")
|
|
279
|
+
return
|
|
280
|
+
|
|
281
|
+
# Show detected platforms and prompt for selection
|
|
282
|
+
console.print("[bold]Detected AI platforms:[/bold]\n")
|
|
283
|
+
for idx, plat in enumerate(installed, 1):
|
|
284
|
+
console.print(f" {idx}. {plat.display_name} ({plat.scope})")
|
|
285
|
+
|
|
286
|
+
console.print(
|
|
287
|
+
"\n[dim]Enter the number of the platform to configure, or 'q' to quit:[/dim]"
|
|
288
|
+
)
|
|
289
|
+
choice = typer.prompt("Select platform")
|
|
290
|
+
|
|
291
|
+
if choice.lower() == "q":
|
|
292
|
+
console.print("Installation cancelled.")
|
|
293
|
+
return
|
|
294
|
+
|
|
295
|
+
try:
|
|
296
|
+
idx = int(choice) - 1
|
|
297
|
+
if idx < 0 or idx >= len(installed):
|
|
298
|
+
console.print("[red]Invalid selection.[/red]")
|
|
299
|
+
raise typer.Exit(1) from None
|
|
300
|
+
platform = installed[idx].name
|
|
301
|
+
except ValueError as e:
|
|
302
|
+
console.print("[red]Invalid input. Please enter a number.[/red]")
|
|
303
|
+
raise typer.Exit(1) from e
|
|
304
|
+
|
|
305
|
+
# If platform argument is provided, handle MCP platform installation (NEW SYNTAX)
|
|
306
|
+
if platform is not None:
|
|
307
|
+
# Validate that the platform is actually installed
|
|
308
|
+
platform_info = get_platform_by_name(
|
|
309
|
+
platform, project_path=Path(project_path) if project_path else Path.cwd()
|
|
310
|
+
)
|
|
311
|
+
|
|
312
|
+
if platform_info and not platform_info.is_installed:
|
|
313
|
+
console.print(
|
|
314
|
+
f"[yellow]⚠[/yellow] {platform_info.display_name} was detected but has a configuration issue."
|
|
315
|
+
)
|
|
316
|
+
console.print(f"[dim]Config path: {platform_info.config_path}[/dim]\n")
|
|
317
|
+
|
|
318
|
+
proceed = typer.confirm(
|
|
319
|
+
"Do you want to proceed with installation anyway?", default=False
|
|
320
|
+
)
|
|
321
|
+
if not proceed:
|
|
322
|
+
console.print("Installation cancelled.")
|
|
323
|
+
return
|
|
324
|
+
|
|
325
|
+
elif not platform_info:
|
|
326
|
+
# Platform not detected at all - warn but allow proceeding
|
|
327
|
+
console.print(
|
|
328
|
+
f"[yellow]⚠[/yellow] Platform '{platform}' not detected on this system."
|
|
329
|
+
)
|
|
330
|
+
console.print(
|
|
331
|
+
"[dim]Run 'mcp-ticketer install --auto-detect' to see detected platforms.[/dim]\n"
|
|
332
|
+
)
|
|
333
|
+
|
|
334
|
+
proceed = typer.confirm(
|
|
335
|
+
"Do you want to proceed with installation anyway?", default=False
|
|
336
|
+
)
|
|
337
|
+
if not proceed:
|
|
338
|
+
console.print("Installation cancelled.")
|
|
339
|
+
return
|
|
340
|
+
|
|
341
|
+
# Import configuration functions
|
|
342
|
+
from .auggie_configure import configure_auggie_mcp
|
|
343
|
+
from .codex_configure import configure_codex_mcp
|
|
344
|
+
from .cursor_configure import configure_cursor_mcp
|
|
345
|
+
from .gemini_configure import configure_gemini_mcp
|
|
346
|
+
from .mcp_configure import configure_claude_mcp
|
|
347
|
+
|
|
348
|
+
# Map platform names to configuration functions
|
|
349
|
+
platform_mapping = {
|
|
350
|
+
"claude-code": {
|
|
351
|
+
"func": lambda: configure_claude_mcp(global_config=False, force=True),
|
|
352
|
+
"name": "Claude Code",
|
|
353
|
+
},
|
|
354
|
+
"claude-desktop": {
|
|
355
|
+
"func": lambda: configure_claude_mcp(global_config=True, force=True),
|
|
356
|
+
"name": "Claude Desktop",
|
|
357
|
+
},
|
|
358
|
+
"cursor": {
|
|
359
|
+
"func": lambda: configure_cursor_mcp(force=True),
|
|
360
|
+
"name": "Cursor",
|
|
361
|
+
},
|
|
362
|
+
"auggie": {
|
|
363
|
+
"func": lambda: configure_auggie_mcp(force=True),
|
|
364
|
+
"name": "Auggie",
|
|
365
|
+
},
|
|
366
|
+
"gemini": {
|
|
367
|
+
"func": lambda: configure_gemini_mcp(scope="project", force=True),
|
|
368
|
+
"name": "Gemini CLI",
|
|
369
|
+
},
|
|
370
|
+
"codex": {
|
|
371
|
+
"func": lambda: configure_codex_mcp(force=True),
|
|
372
|
+
"name": "Codex",
|
|
373
|
+
},
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
if platform not in platform_mapping:
|
|
377
|
+
console.print(f"[red]Unknown platform: {platform}[/red]")
|
|
378
|
+
console.print("\n[bold]Available platforms:[/bold]")
|
|
379
|
+
for p in platform_mapping.keys():
|
|
380
|
+
console.print(f" • {p}")
|
|
381
|
+
raise typer.Exit(1) from None
|
|
382
|
+
|
|
383
|
+
config = platform_mapping[platform]
|
|
384
|
+
|
|
385
|
+
if dry_run:
|
|
386
|
+
console.print(f"[cyan]DRY RUN - Would install for {config['name']}[/cyan]")
|
|
387
|
+
return
|
|
388
|
+
|
|
389
|
+
try:
|
|
390
|
+
config["func"]()
|
|
391
|
+
except Exception as e:
|
|
392
|
+
console.print(f"[red]Installation failed: {e}[/red]")
|
|
393
|
+
raise typer.Exit(1) from e
|
|
394
|
+
return
|
|
395
|
+
|
|
396
|
+
# Otherwise, delegate to init for adapter initialization (LEGACY BEHAVIOR)
|
|
397
|
+
# This makes 'install' and 'init' synonymous when called without platform argument
|
|
398
|
+
init(
|
|
399
|
+
adapter=adapter,
|
|
400
|
+
project_path=project_path,
|
|
401
|
+
global_config=global_config,
|
|
402
|
+
base_path=base_path,
|
|
403
|
+
api_key=api_key,
|
|
404
|
+
team_id=team_id,
|
|
405
|
+
jira_server=jira_server,
|
|
406
|
+
jira_email=jira_email,
|
|
407
|
+
jira_project=jira_project,
|
|
408
|
+
github_owner=github_owner,
|
|
409
|
+
github_repo=github_repo,
|
|
410
|
+
github_token=github_token,
|
|
411
|
+
)
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
def remove(
|
|
415
|
+
platform: str | None = typer.Argument(
|
|
416
|
+
None,
|
|
417
|
+
help="Platform to remove (claude-code, claude-desktop, cursor, auggie, gemini, codex)",
|
|
418
|
+
),
|
|
419
|
+
dry_run: bool = typer.Option(
|
|
420
|
+
False, "--dry-run", help="Show what would be done without making changes"
|
|
421
|
+
),
|
|
422
|
+
) -> None:
|
|
423
|
+
"""Remove mcp-ticketer from AI platforms.
|
|
424
|
+
|
|
425
|
+
Without arguments, shows help and available platforms.
|
|
426
|
+
With a platform argument, removes MCP configuration for that platform.
|
|
427
|
+
|
|
428
|
+
Examples:
|
|
429
|
+
# Remove from Claude Code (project-level)
|
|
430
|
+
mcp-ticketer remove claude-code
|
|
431
|
+
|
|
432
|
+
# Remove from Claude Desktop (global)
|
|
433
|
+
mcp-ticketer remove claude-desktop
|
|
434
|
+
|
|
435
|
+
# Remove from Auggie
|
|
436
|
+
mcp-ticketer remove auggie
|
|
437
|
+
|
|
438
|
+
# Dry run to preview changes
|
|
439
|
+
mcp-ticketer remove claude-code --dry-run
|
|
440
|
+
|
|
441
|
+
"""
|
|
442
|
+
# If no platform specified, show help message
|
|
443
|
+
if platform is None:
|
|
444
|
+
console.print("[bold]Remove mcp-ticketer from AI platforms[/bold]\n")
|
|
445
|
+
console.print("Usage: mcp-ticketer remove <platform>\n")
|
|
446
|
+
console.print("[bold]Available platforms:[/bold]")
|
|
447
|
+
console.print(" • claude-code - Claude Code (project-level)")
|
|
448
|
+
console.print(" • claude-desktop - Claude Desktop (global)")
|
|
449
|
+
console.print(" • auggie - Auggie (global)")
|
|
450
|
+
console.print(" • gemini - Gemini CLI (project-level by default)")
|
|
451
|
+
console.print(" • codex - Codex (global)")
|
|
452
|
+
return
|
|
453
|
+
|
|
454
|
+
# Import removal functions
|
|
455
|
+
from .auggie_configure import remove_auggie_mcp
|
|
456
|
+
from .codex_configure import remove_codex_mcp
|
|
457
|
+
from .cursor_configure import remove_cursor_mcp
|
|
458
|
+
from .gemini_configure import remove_gemini_mcp
|
|
459
|
+
from .mcp_configure import remove_claude_mcp
|
|
460
|
+
|
|
461
|
+
# Map platform names to removal functions
|
|
462
|
+
platform_mapping = {
|
|
463
|
+
"claude-code": {
|
|
464
|
+
"func": lambda: remove_claude_mcp(global_config=False, dry_run=dry_run),
|
|
465
|
+
"name": "Claude Code",
|
|
466
|
+
},
|
|
467
|
+
"claude-desktop": {
|
|
468
|
+
"func": lambda: remove_claude_mcp(global_config=True, dry_run=dry_run),
|
|
469
|
+
"name": "Claude Desktop",
|
|
470
|
+
},
|
|
471
|
+
"cursor": {
|
|
472
|
+
"func": lambda: remove_cursor_mcp(dry_run=dry_run),
|
|
473
|
+
"name": "Cursor",
|
|
474
|
+
},
|
|
475
|
+
"auggie": {
|
|
476
|
+
"func": lambda: remove_auggie_mcp(dry_run=dry_run),
|
|
477
|
+
"name": "Auggie",
|
|
478
|
+
},
|
|
479
|
+
"gemini": {
|
|
480
|
+
"func": lambda: remove_gemini_mcp(scope="project", dry_run=dry_run),
|
|
481
|
+
"name": "Gemini CLI",
|
|
482
|
+
},
|
|
483
|
+
"codex": {
|
|
484
|
+
"func": lambda: remove_codex_mcp(dry_run=dry_run),
|
|
485
|
+
"name": "Codex",
|
|
486
|
+
},
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
if platform not in platform_mapping:
|
|
490
|
+
console.print(f"[red]Unknown platform: {platform}[/red]")
|
|
491
|
+
console.print("\n[bold]Available platforms:[/bold]")
|
|
492
|
+
for p in platform_mapping.keys():
|
|
493
|
+
console.print(f" • {p}")
|
|
494
|
+
raise typer.Exit(1) from None
|
|
495
|
+
|
|
496
|
+
config = platform_mapping[platform]
|
|
497
|
+
|
|
498
|
+
try:
|
|
499
|
+
config["func"]()
|
|
500
|
+
except Exception as e:
|
|
501
|
+
console.print(f"[red]Removal failed: {e}[/red]")
|
|
502
|
+
raise typer.Exit(1) from e
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def uninstall(
|
|
506
|
+
platform: str | None = typer.Argument(
|
|
507
|
+
None,
|
|
508
|
+
help="Platform to uninstall (claude-code, claude-desktop, auggie, gemini, codex)",
|
|
509
|
+
),
|
|
510
|
+
dry_run: bool = typer.Option(
|
|
511
|
+
False, "--dry-run", help="Show what would be done without making changes"
|
|
512
|
+
),
|
|
513
|
+
) -> None:
|
|
514
|
+
"""Uninstall mcp-ticketer from AI platforms (alias for remove).
|
|
515
|
+
|
|
516
|
+
This is an alias for the 'remove' command.
|
|
517
|
+
|
|
518
|
+
Without arguments, shows help and available platforms.
|
|
519
|
+
With a platform argument, removes MCP configuration for that platform.
|
|
520
|
+
|
|
521
|
+
Examples:
|
|
522
|
+
# Uninstall from Claude Code (project-level)
|
|
523
|
+
mcp-ticketer uninstall claude-code
|
|
524
|
+
|
|
525
|
+
# Uninstall from Claude Desktop (global)
|
|
526
|
+
mcp-ticketer uninstall claude-desktop
|
|
527
|
+
|
|
528
|
+
# Uninstall from Auggie
|
|
529
|
+
mcp-ticketer uninstall auggie
|
|
530
|
+
|
|
531
|
+
# Dry run to preview changes
|
|
532
|
+
mcp-ticketer uninstall claude-code --dry-run
|
|
533
|
+
|
|
534
|
+
"""
|
|
535
|
+
# Call the remove command with the same parameters
|
|
536
|
+
remove(platform=platform, dry_run=dry_run)
|