mcp-ticketer 0.2.0__py3-none-any.whl → 2.2.9__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.
Files changed (160) hide show
  1. mcp_ticketer/__init__.py +10 -10
  2. mcp_ticketer/__version__.py +3 -3
  3. mcp_ticketer/_version_scm.py +1 -0
  4. mcp_ticketer/adapters/__init__.py +2 -0
  5. mcp_ticketer/adapters/aitrackdown.py +930 -52
  6. mcp_ticketer/adapters/asana/__init__.py +15 -0
  7. mcp_ticketer/adapters/asana/adapter.py +1537 -0
  8. mcp_ticketer/adapters/asana/client.py +292 -0
  9. mcp_ticketer/adapters/asana/mappers.py +348 -0
  10. mcp_ticketer/adapters/asana/types.py +146 -0
  11. mcp_ticketer/adapters/github/__init__.py +26 -0
  12. mcp_ticketer/adapters/github/adapter.py +3229 -0
  13. mcp_ticketer/adapters/github/client.py +335 -0
  14. mcp_ticketer/adapters/github/mappers.py +797 -0
  15. mcp_ticketer/adapters/github/queries.py +692 -0
  16. mcp_ticketer/adapters/github/types.py +460 -0
  17. mcp_ticketer/adapters/hybrid.py +58 -16
  18. mcp_ticketer/adapters/jira/__init__.py +35 -0
  19. mcp_ticketer/adapters/jira/adapter.py +1351 -0
  20. mcp_ticketer/adapters/jira/client.py +271 -0
  21. mcp_ticketer/adapters/jira/mappers.py +246 -0
  22. mcp_ticketer/adapters/jira/queries.py +216 -0
  23. mcp_ticketer/adapters/jira/types.py +304 -0
  24. mcp_ticketer/adapters/linear/__init__.py +1 -1
  25. mcp_ticketer/adapters/linear/adapter.py +3810 -462
  26. mcp_ticketer/adapters/linear/client.py +312 -69
  27. mcp_ticketer/adapters/linear/mappers.py +305 -85
  28. mcp_ticketer/adapters/linear/queries.py +317 -17
  29. mcp_ticketer/adapters/linear/types.py +187 -64
  30. mcp_ticketer/adapters/linear.py +2 -2
  31. mcp_ticketer/analysis/__init__.py +56 -0
  32. mcp_ticketer/analysis/dependency_graph.py +255 -0
  33. mcp_ticketer/analysis/health_assessment.py +304 -0
  34. mcp_ticketer/analysis/orphaned.py +218 -0
  35. mcp_ticketer/analysis/project_status.py +594 -0
  36. mcp_ticketer/analysis/similarity.py +224 -0
  37. mcp_ticketer/analysis/staleness.py +266 -0
  38. mcp_ticketer/automation/__init__.py +11 -0
  39. mcp_ticketer/automation/project_updates.py +378 -0
  40. mcp_ticketer/cache/memory.py +9 -8
  41. mcp_ticketer/cli/adapter_diagnostics.py +421 -0
  42. mcp_ticketer/cli/auggie_configure.py +116 -15
  43. mcp_ticketer/cli/codex_configure.py +274 -82
  44. mcp_ticketer/cli/configure.py +1323 -151
  45. mcp_ticketer/cli/cursor_configure.py +314 -0
  46. mcp_ticketer/cli/diagnostics.py +209 -114
  47. mcp_ticketer/cli/discover.py +297 -26
  48. mcp_ticketer/cli/gemini_configure.py +119 -26
  49. mcp_ticketer/cli/init_command.py +880 -0
  50. mcp_ticketer/cli/install_mcp_server.py +418 -0
  51. mcp_ticketer/cli/instruction_commands.py +435 -0
  52. mcp_ticketer/cli/linear_commands.py +256 -130
  53. mcp_ticketer/cli/main.py +140 -1284
  54. mcp_ticketer/cli/mcp_configure.py +1013 -100
  55. mcp_ticketer/cli/mcp_server_commands.py +415 -0
  56. mcp_ticketer/cli/migrate_config.py +12 -8
  57. mcp_ticketer/cli/platform_commands.py +123 -0
  58. mcp_ticketer/cli/platform_detection.py +477 -0
  59. mcp_ticketer/cli/platform_installer.py +545 -0
  60. mcp_ticketer/cli/project_update_commands.py +350 -0
  61. mcp_ticketer/cli/python_detection.py +126 -0
  62. mcp_ticketer/cli/queue_commands.py +15 -15
  63. mcp_ticketer/cli/setup_command.py +794 -0
  64. mcp_ticketer/cli/simple_health.py +84 -59
  65. mcp_ticketer/cli/ticket_commands.py +1375 -0
  66. mcp_ticketer/cli/update_checker.py +313 -0
  67. mcp_ticketer/cli/utils.py +195 -72
  68. mcp_ticketer/core/__init__.py +64 -1
  69. mcp_ticketer/core/adapter.py +618 -18
  70. mcp_ticketer/core/config.py +77 -68
  71. mcp_ticketer/core/env_discovery.py +75 -16
  72. mcp_ticketer/core/env_loader.py +121 -97
  73. mcp_ticketer/core/exceptions.py +32 -24
  74. mcp_ticketer/core/http_client.py +26 -26
  75. mcp_ticketer/core/instructions.py +405 -0
  76. mcp_ticketer/core/label_manager.py +732 -0
  77. mcp_ticketer/core/mappers.py +42 -30
  78. mcp_ticketer/core/milestone_manager.py +252 -0
  79. mcp_ticketer/core/models.py +566 -19
  80. mcp_ticketer/core/onepassword_secrets.py +379 -0
  81. mcp_ticketer/core/priority_matcher.py +463 -0
  82. mcp_ticketer/core/project_config.py +189 -49
  83. mcp_ticketer/core/project_utils.py +281 -0
  84. mcp_ticketer/core/project_validator.py +376 -0
  85. mcp_ticketer/core/registry.py +3 -3
  86. mcp_ticketer/core/session_state.py +176 -0
  87. mcp_ticketer/core/state_matcher.py +592 -0
  88. mcp_ticketer/core/url_parser.py +425 -0
  89. mcp_ticketer/core/validators.py +69 -0
  90. mcp_ticketer/defaults/ticket_instructions.md +644 -0
  91. mcp_ticketer/mcp/__init__.py +29 -1
  92. mcp_ticketer/mcp/__main__.py +60 -0
  93. mcp_ticketer/mcp/server/__init__.py +25 -0
  94. mcp_ticketer/mcp/server/__main__.py +60 -0
  95. mcp_ticketer/mcp/server/constants.py +58 -0
  96. mcp_ticketer/mcp/server/diagnostic_helper.py +175 -0
  97. mcp_ticketer/mcp/server/dto.py +195 -0
  98. mcp_ticketer/mcp/server/main.py +1343 -0
  99. mcp_ticketer/mcp/server/response_builder.py +206 -0
  100. mcp_ticketer/mcp/server/routing.py +723 -0
  101. mcp_ticketer/mcp/server/server_sdk.py +151 -0
  102. mcp_ticketer/mcp/server/tools/__init__.py +69 -0
  103. mcp_ticketer/mcp/server/tools/analysis_tools.py +854 -0
  104. mcp_ticketer/mcp/server/tools/attachment_tools.py +224 -0
  105. mcp_ticketer/mcp/server/tools/bulk_tools.py +330 -0
  106. mcp_ticketer/mcp/server/tools/comment_tools.py +152 -0
  107. mcp_ticketer/mcp/server/tools/config_tools.py +1564 -0
  108. mcp_ticketer/mcp/server/tools/diagnostic_tools.py +211 -0
  109. mcp_ticketer/mcp/server/tools/hierarchy_tools.py +942 -0
  110. mcp_ticketer/mcp/server/tools/instruction_tools.py +295 -0
  111. mcp_ticketer/mcp/server/tools/label_tools.py +942 -0
  112. mcp_ticketer/mcp/server/tools/milestone_tools.py +338 -0
  113. mcp_ticketer/mcp/server/tools/pr_tools.py +150 -0
  114. mcp_ticketer/mcp/server/tools/project_status_tools.py +158 -0
  115. mcp_ticketer/mcp/server/tools/project_update_tools.py +473 -0
  116. mcp_ticketer/mcp/server/tools/search_tools.py +318 -0
  117. mcp_ticketer/mcp/server/tools/session_tools.py +308 -0
  118. mcp_ticketer/mcp/server/tools/ticket_tools.py +1413 -0
  119. mcp_ticketer/mcp/server/tools/user_ticket_tools.py +364 -0
  120. mcp_ticketer/queue/__init__.py +1 -0
  121. mcp_ticketer/queue/health_monitor.py +168 -136
  122. mcp_ticketer/queue/manager.py +78 -63
  123. mcp_ticketer/queue/queue.py +108 -21
  124. mcp_ticketer/queue/run_worker.py +2 -2
  125. mcp_ticketer/queue/ticket_registry.py +213 -155
  126. mcp_ticketer/queue/worker.py +96 -58
  127. mcp_ticketer/utils/__init__.py +5 -0
  128. mcp_ticketer/utils/token_utils.py +246 -0
  129. mcp_ticketer-2.2.9.dist-info/METADATA +1396 -0
  130. mcp_ticketer-2.2.9.dist-info/RECORD +158 -0
  131. mcp_ticketer-2.2.9.dist-info/top_level.txt +2 -0
  132. py_mcp_installer/examples/phase3_demo.py +178 -0
  133. py_mcp_installer/scripts/manage_version.py +54 -0
  134. py_mcp_installer/setup.py +6 -0
  135. py_mcp_installer/src/py_mcp_installer/__init__.py +153 -0
  136. py_mcp_installer/src/py_mcp_installer/command_builder.py +445 -0
  137. py_mcp_installer/src/py_mcp_installer/config_manager.py +541 -0
  138. py_mcp_installer/src/py_mcp_installer/exceptions.py +243 -0
  139. py_mcp_installer/src/py_mcp_installer/installation_strategy.py +617 -0
  140. py_mcp_installer/src/py_mcp_installer/installer.py +656 -0
  141. py_mcp_installer/src/py_mcp_installer/mcp_inspector.py +750 -0
  142. py_mcp_installer/src/py_mcp_installer/platform_detector.py +451 -0
  143. py_mcp_installer/src/py_mcp_installer/platforms/__init__.py +26 -0
  144. py_mcp_installer/src/py_mcp_installer/platforms/claude_code.py +225 -0
  145. py_mcp_installer/src/py_mcp_installer/platforms/codex.py +181 -0
  146. py_mcp_installer/src/py_mcp_installer/platforms/cursor.py +191 -0
  147. py_mcp_installer/src/py_mcp_installer/types.py +222 -0
  148. py_mcp_installer/src/py_mcp_installer/utils.py +463 -0
  149. py_mcp_installer/tests/__init__.py +0 -0
  150. py_mcp_installer/tests/platforms/__init__.py +0 -0
  151. py_mcp_installer/tests/test_platform_detector.py +17 -0
  152. mcp_ticketer/adapters/github.py +0 -1354
  153. mcp_ticketer/adapters/jira.py +0 -1011
  154. mcp_ticketer/mcp/server.py +0 -1895
  155. mcp_ticketer-0.2.0.dist-info/METADATA +0 -414
  156. mcp_ticketer-0.2.0.dist-info/RECORD +0 -58
  157. mcp_ticketer-0.2.0.dist-info/top_level.txt +0 -1
  158. {mcp_ticketer-0.2.0.dist-info → mcp_ticketer-2.2.9.dist-info}/WHEEL +0 -0
  159. {mcp_ticketer-0.2.0.dist-info → mcp_ticketer-2.2.9.dist-info}/entry_points.txt +0 -0
  160. {mcp_ticketer-0.2.0.dist-info → mcp_ticketer-2.2.9.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,418 @@
1
+ """Install mcp-ticketer as an MCP server using py-mcp-installer-service."""
2
+
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ import typer
7
+ from rich.console import Console
8
+ from rich.table import Table
9
+
10
+ console = Console()
11
+
12
+
13
+ def install_mcp_server(
14
+ linear_key: str | None = typer.Option(
15
+ None, "--linear-key", help="Linear API key", envvar="LINEAR_API_KEY"
16
+ ),
17
+ github_token: str | None = typer.Option(
18
+ None, "--github-token", help="GitHub token", envvar="GITHUB_TOKEN"
19
+ ),
20
+ jira_token: str | None = typer.Option(
21
+ None, "--jira-token", help="Jira token", envvar="JIRA_API_TOKEN"
22
+ ),
23
+ scope: str = typer.Option(
24
+ "project", "--scope", help="Installation scope: project or global"
25
+ ),
26
+ method: str | None = typer.Option(
27
+ None, "--method", help="Installation method: uv, pipx, direct, python"
28
+ ),
29
+ dry_run: bool = typer.Option(
30
+ False, "--dry-run", help="Preview changes without applying"
31
+ ),
32
+ platform: str | None = typer.Option(
33
+ None, "--platform", help="Target platform (auto-detect if not specified)"
34
+ ),
35
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
36
+ ) -> None:
37
+ """Install mcp-ticketer as an MCP server on AI coding platforms.
38
+
39
+ This command uses py-mcp-installer-service to install mcp-ticketer as an MCP
40
+ server on detected AI coding platforms (Claude Desktop, Cline, Roo-Code, etc.).
41
+
42
+ The installer will:
43
+ 1. Auto-detect available platforms (or use --platform)
44
+ 2. Choose optimal installation method (or use --method)
45
+ 3. Configure environment variables for API keys
46
+ 4. Update platform configuration files atomically
47
+
48
+ Examples:
49
+ # Auto-detect platform and install
50
+ mcp-ticketer install-mcp-server
51
+
52
+ # Install with API keys
53
+ mcp-ticketer install-mcp-server --linear-key=... --github-token=...
54
+
55
+ # Install globally instead of project-scoped
56
+ mcp-ticketer install-mcp-server --scope global
57
+
58
+ # Install with specific method
59
+ mcp-ticketer install-mcp-server --method uv
60
+
61
+ # Preview changes without applying
62
+ mcp-ticketer install-mcp-server --dry-run
63
+
64
+ # Install on specific platform
65
+ mcp-ticketer install-mcp-server --platform claude-desktop
66
+
67
+ Supported Platforms:
68
+ - claude-desktop: Claude Desktop (global)
69
+ - cline: Cline extension (project/global)
70
+ - roo-code: Roo-Code extension (project)
71
+ - continue: Continue extension (project/global)
72
+ - zed: Zed editor (global)
73
+ - windsurf: Windsurf editor (global)
74
+ - cursor: Cursor editor (global)
75
+ - void: Void editor (project/global)
76
+
77
+ """
78
+ try:
79
+ # Import py_mcp_installer from services submodule
80
+ # Add services path to sys.path if not already there
81
+ services_path = (
82
+ Path(__file__).parent.parent.parent
83
+ / "services"
84
+ / "py_mcp_installer"
85
+ / "src"
86
+ )
87
+ if str(services_path) not in sys.path:
88
+ sys.path.insert(0, str(services_path))
89
+
90
+ from py_mcp_installer import InstallMethod, MCPInstaller, Platform, Scope
91
+ from py_mcp_installer.exceptions import PyMCPInstallerError
92
+ except ImportError as e:
93
+ console.print(
94
+ "[red]Error: py-mcp-installer not found. This should not happen.[/red]"
95
+ )
96
+ console.print(f"[yellow]ImportError: {e}[/yellow]")
97
+ console.print(
98
+ "[yellow]The installer is included as a submodule in this project.[/yellow]"
99
+ )
100
+ raise typer.Exit(1) from None
101
+
102
+ console.print("[bold cyan]🚀 Installing mcp-ticketer as MCP Server[/bold cyan]\n")
103
+
104
+ # Validate scope
105
+ try:
106
+ scope_enum = Scope(scope)
107
+ except ValueError:
108
+ console.print(f"[red]Invalid scope: {scope}. Use 'project' or 'global'[/red]")
109
+ raise typer.Exit(1) from None
110
+
111
+ # Validate method if specified
112
+ install_method = None
113
+ if method:
114
+ try:
115
+ install_method = InstallMethod(method)
116
+ except ValueError:
117
+ console.print(
118
+ f"[red]Invalid method: {method}. Use 'uv', 'pipx', 'direct', or 'python'[/red]"
119
+ )
120
+ raise typer.Exit(1) from None
121
+
122
+ # Validate platform if specified
123
+ platform_enum = None
124
+ if platform:
125
+ try:
126
+ platform_enum = Platform(platform)
127
+ except ValueError:
128
+ console.print(f"[red]Invalid platform: {platform}[/red]")
129
+ console.print("[yellow]Supported platforms:[/yellow]")
130
+ for p in Platform:
131
+ console.print(f" - {p.value}")
132
+ raise typer.Exit(1) from None
133
+
134
+ try:
135
+ # Create installer
136
+ if platform_enum:
137
+ installer = MCPInstaller(
138
+ platform=platform_enum, dry_run=dry_run, verbose=verbose
139
+ )
140
+ console.print(f"[green]Platform: {platform_enum.value}[/green]\n")
141
+ else:
142
+ installer = MCPInstaller.auto_detect(dry_run=dry_run, verbose=verbose)
143
+ console.print(
144
+ f"[green]Detected platform: {installer.platform.value}[/green]\n"
145
+ )
146
+
147
+ # Build environment variables from API keys
148
+ env = {}
149
+ if linear_key:
150
+ env["LINEAR_API_KEY"] = linear_key
151
+ if github_token:
152
+ env["GITHUB_TOKEN"] = github_token
153
+ if jira_token:
154
+ env["JIRA_API_TOKEN"] = jira_token
155
+
156
+ if env:
157
+ console.print("[cyan]Environment variables configured:[/cyan]")
158
+ for key in env:
159
+ console.print(f" • {key}")
160
+ console.print()
161
+
162
+ # Determine command and args based on installation method
163
+ if install_method == InstallMethod.UV_RUN or (
164
+ not install_method and _is_uv_available()
165
+ ):
166
+ command = "uv"
167
+ args = ["run", "mcp-ticketer", "mcp"]
168
+ if not install_method:
169
+ install_method = InstallMethod.UV_RUN
170
+ else:
171
+ command = "mcp-ticketer"
172
+ args = ["mcp"]
173
+
174
+ # Install server
175
+ console.print("[cyan]Installing mcp-ticketer...[/cyan]\n")
176
+ result = installer.install_server(
177
+ name="mcp-ticketer",
178
+ command=command,
179
+ args=args,
180
+ env=env if env else None,
181
+ description="Universal ticket management interface for AI agents",
182
+ scope=scope_enum,
183
+ method=install_method,
184
+ )
185
+
186
+ # Display results
187
+ if result.success:
188
+ console.print("[bold green]✅ Installation Successful![/bold green]\n")
189
+
190
+ # Show installation details in table
191
+ table = Table(title="Installation Details", show_header=False)
192
+ table.add_column("Field", style="cyan")
193
+ table.add_column("Value", style="white")
194
+
195
+ table.add_row("Platform", result.platform.value)
196
+ table.add_row("Method", result.method.value)
197
+ table.add_row("Scope", scope)
198
+ table.add_row("Config Path", str(result.config_path))
199
+ table.add_row("Command", f"{result.command} {' '.join(result.args or [])}")
200
+
201
+ if dry_run:
202
+ table.add_row("Mode", "[yellow]DRY RUN - No changes made[/yellow]")
203
+
204
+ console.print(table)
205
+ console.print()
206
+
207
+ # Next steps
208
+ if not dry_run:
209
+ console.print("[bold]Next Steps:[/bold]")
210
+ console.print(
211
+ "1. Restart your AI coding platform to load the new MCP server"
212
+ )
213
+ console.print(
214
+ "2. The mcp-ticketer commands will be available in your AI assistant"
215
+ )
216
+ console.print(
217
+ "3. Configure adapter credentials with: mcp-ticketer setup\n"
218
+ )
219
+ else:
220
+ console.print(
221
+ "[yellow]This was a dry run. Run without --dry-run to apply changes.[/yellow]\n"
222
+ )
223
+
224
+ else:
225
+ console.print("[bold red]❌ Installation Failed[/bold red]\n")
226
+ console.print(f"[red]Error: {result.message}[/red]")
227
+ if result.error:
228
+ console.print(f"[dim]{result.error}[/dim]")
229
+ raise typer.Exit(1)
230
+
231
+ except PyMCPInstallerError as e:
232
+ console.print("[bold red]❌ Installation Error[/bold red]\n")
233
+ console.print(f"[red]{e}[/red]")
234
+ if verbose:
235
+ import traceback
236
+
237
+ console.print(f"\n[dim]{traceback.format_exc()}[/dim]")
238
+ raise typer.Exit(1) from None
239
+ except Exception as e:
240
+ console.print("[bold red]❌ Unexpected Error[/bold red]\n")
241
+ console.print(f"[red]{e}[/red]")
242
+ if verbose:
243
+ import traceback
244
+
245
+ console.print(f"\n[dim]{traceback.format_exc()}[/dim]")
246
+ raise typer.Exit(1) from None
247
+
248
+
249
+ def _is_uv_available() -> bool:
250
+ """Check if uv is available on the system.
251
+
252
+ Returns:
253
+ True if uv is available, False otherwise
254
+
255
+ """
256
+ import shutil
257
+
258
+ return shutil.which("uv") is not None
259
+
260
+
261
+ def list_mcp_servers(
262
+ platform: str | None = typer.Option(
263
+ None, "--platform", help="Target platform (auto-detect if not specified)"
264
+ ),
265
+ ) -> None:
266
+ """List installed MCP servers on detected platform.
267
+
268
+ Examples:
269
+ # List servers on auto-detected platform
270
+ mcp-ticketer list-mcp-servers
271
+
272
+ # List servers on specific platform
273
+ mcp-ticketer list-mcp-servers --platform claude-desktop
274
+
275
+ """
276
+ try:
277
+ # Import py_mcp_installer from services submodule
278
+ services_path = (
279
+ Path(__file__).parent.parent.parent
280
+ / "services"
281
+ / "py_mcp_installer"
282
+ / "src"
283
+ )
284
+ if str(services_path) not in sys.path:
285
+ sys.path.insert(0, str(services_path))
286
+
287
+ from py_mcp_installer import MCPInstaller, Platform
288
+ from py_mcp_installer.exceptions import PyMCPInstallerError
289
+ except ImportError as e:
290
+ console.print("[red]Error: py-mcp-installer not found[/red]")
291
+ console.print(f"[yellow]ImportError: {e}[/yellow]")
292
+ raise typer.Exit(1) from None
293
+
294
+ console.print("[bold cyan]📋 Installed MCP Servers[/bold cyan]\n")
295
+
296
+ try:
297
+ # Create installer
298
+ if platform:
299
+ try:
300
+ platform_enum = Platform(platform)
301
+ installer = MCPInstaller(platform=platform_enum)
302
+ console.print(f"[green]Platform: {platform_enum.value}[/green]\n")
303
+ except ValueError:
304
+ console.print(f"[red]Invalid platform: {platform}[/red]")
305
+ raise typer.Exit(1) from None
306
+ else:
307
+ installer = MCPInstaller.auto_detect()
308
+ console.print(
309
+ f"[green]Detected platform: {installer.platform.value}[/green]\n"
310
+ )
311
+
312
+ # List servers
313
+ servers = installer.list_servers()
314
+
315
+ if not servers:
316
+ console.print("[yellow]No MCP servers installed[/yellow]")
317
+ return
318
+
319
+ # Display in table
320
+ table = Table(title=f"MCP Servers ({len(servers)} total)")
321
+ table.add_column("Name", style="cyan", no_wrap=True)
322
+ table.add_column("Command", style="white")
323
+ table.add_column("Description", style="dim")
324
+
325
+ for server in servers:
326
+ cmd = f"{server.command} {' '.join(server.args or [])}"
327
+ desc = server.description or ""
328
+ table.add_row(server.name, cmd, desc)
329
+
330
+ console.print(table)
331
+
332
+ except PyMCPInstallerError as e:
333
+ console.print(f"[red]Error: {e}[/red]")
334
+ raise typer.Exit(1) from None
335
+ except Exception as e:
336
+ console.print(f"[red]Unexpected error: {e}[/red]")
337
+ raise typer.Exit(1) from None
338
+
339
+
340
+ def uninstall_mcp_server(
341
+ platform: str | None = typer.Option(
342
+ None, "--platform", help="Target platform (auto-detect if not specified)"
343
+ ),
344
+ dry_run: bool = typer.Option(
345
+ False, "--dry-run", help="Preview changes without applying"
346
+ ),
347
+ ) -> None:
348
+ """Uninstall mcp-ticketer MCP server from platform.
349
+
350
+ Examples:
351
+ # Uninstall from auto-detected platform
352
+ mcp-ticketer uninstall-mcp-server
353
+
354
+ # Uninstall from specific platform
355
+ mcp-ticketer uninstall-mcp-server --platform claude-desktop
356
+
357
+ # Preview uninstall without applying
358
+ mcp-ticketer uninstall-mcp-server --dry-run
359
+
360
+ """
361
+ try:
362
+ # Import py_mcp_installer from services submodule
363
+ services_path = (
364
+ Path(__file__).parent.parent.parent
365
+ / "services"
366
+ / "py_mcp_installer"
367
+ / "src"
368
+ )
369
+ if str(services_path) not in sys.path:
370
+ sys.path.insert(0, str(services_path))
371
+
372
+ from py_mcp_installer import MCPInstaller, Platform
373
+ from py_mcp_installer.exceptions import PyMCPInstallerError
374
+ except ImportError as e:
375
+ console.print("[red]Error: py-mcp-installer not found[/red]")
376
+ console.print(f"[yellow]ImportError: {e}[/yellow]")
377
+ raise typer.Exit(1) from None
378
+
379
+ console.print("[bold cyan]🗑️ Uninstalling mcp-ticketer MCP Server[/bold cyan]\n")
380
+
381
+ try:
382
+ # Create installer
383
+ if platform:
384
+ try:
385
+ platform_enum = Platform(platform)
386
+ installer = MCPInstaller(platform=platform_enum, dry_run=dry_run)
387
+ console.print(f"[green]Platform: {platform_enum.value}[/green]\n")
388
+ except ValueError:
389
+ console.print(f"[red]Invalid platform: {platform}[/red]")
390
+ raise typer.Exit(1) from None
391
+ else:
392
+ installer = MCPInstaller.auto_detect(dry_run=dry_run)
393
+ console.print(
394
+ f"[green]Detected platform: {installer.platform.value}[/green]\n"
395
+ )
396
+
397
+ # Uninstall
398
+ success = installer.uninstall_server(name="mcp-ticketer")
399
+
400
+ if success:
401
+ if dry_run:
402
+ console.print("[yellow]DRY RUN: Would uninstall mcp-ticketer[/yellow]")
403
+ else:
404
+ console.print("[green]✅ Successfully uninstalled mcp-ticketer[/green]")
405
+ console.print(
406
+ "\n[dim]Restart your AI coding platform to apply changes[/dim]"
407
+ )
408
+ else:
409
+ console.print(
410
+ "[yellow]mcp-ticketer not found or already uninstalled[/yellow]"
411
+ )
412
+
413
+ except PyMCPInstallerError as e:
414
+ console.print(f"[red]Error: {e}[/red]")
415
+ raise typer.Exit(1) from None
416
+ except Exception as e:
417
+ console.print(f"[red]Unexpected error: {e}[/red]")
418
+ raise typer.Exit(1) from None