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.
- mcp_ticketer/__init__.py +10 -10
- mcp_ticketer/__version__.py +3 -3
- mcp_ticketer/_version_scm.py +1 -0
- mcp_ticketer/adapters/__init__.py +2 -0
- mcp_ticketer/adapters/aitrackdown.py +930 -52
- mcp_ticketer/adapters/asana/__init__.py +15 -0
- mcp_ticketer/adapters/asana/adapter.py +1537 -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/__init__.py +26 -0
- mcp_ticketer/adapters/github/adapter.py +3229 -0
- mcp_ticketer/adapters/github/client.py +335 -0
- mcp_ticketer/adapters/github/mappers.py +797 -0
- mcp_ticketer/adapters/github/queries.py +692 -0
- mcp_ticketer/adapters/github/types.py +460 -0
- mcp_ticketer/adapters/hybrid.py +58 -16
- mcp_ticketer/adapters/jira/__init__.py +35 -0
- mcp_ticketer/adapters/jira/adapter.py +1351 -0
- mcp_ticketer/adapters/jira/client.py +271 -0
- mcp_ticketer/adapters/jira/mappers.py +246 -0
- mcp_ticketer/adapters/jira/queries.py +216 -0
- mcp_ticketer/adapters/jira/types.py +304 -0
- mcp_ticketer/adapters/linear/__init__.py +1 -1
- mcp_ticketer/adapters/linear/adapter.py +3810 -462
- mcp_ticketer/adapters/linear/client.py +312 -69
- mcp_ticketer/adapters/linear/mappers.py +305 -85
- mcp_ticketer/adapters/linear/queries.py +317 -17
- mcp_ticketer/adapters/linear/types.py +187 -64
- mcp_ticketer/adapters/linear.py +2 -2
- 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 +9 -8
- mcp_ticketer/cli/adapter_diagnostics.py +421 -0
- mcp_ticketer/cli/auggie_configure.py +116 -15
- mcp_ticketer/cli/codex_configure.py +274 -82
- mcp_ticketer/cli/configure.py +1323 -151
- mcp_ticketer/cli/cursor_configure.py +314 -0
- mcp_ticketer/cli/diagnostics.py +209 -114
- mcp_ticketer/cli/discover.py +297 -26
- mcp_ticketer/cli/gemini_configure.py +119 -26
- mcp_ticketer/cli/init_command.py +880 -0
- mcp_ticketer/cli/install_mcp_server.py +418 -0
- mcp_ticketer/cli/instruction_commands.py +435 -0
- mcp_ticketer/cli/linear_commands.py +256 -130
- mcp_ticketer/cli/main.py +140 -1284
- mcp_ticketer/cli/mcp_configure.py +1013 -100
- mcp_ticketer/cli/mcp_server_commands.py +415 -0
- mcp_ticketer/cli/migrate_config.py +12 -8
- mcp_ticketer/cli/platform_commands.py +123 -0
- mcp_ticketer/cli/platform_detection.py +477 -0
- mcp_ticketer/cli/platform_installer.py +545 -0
- mcp_ticketer/cli/project_update_commands.py +350 -0
- mcp_ticketer/cli/python_detection.py +126 -0
- mcp_ticketer/cli/queue_commands.py +15 -15
- mcp_ticketer/cli/setup_command.py +794 -0
- mcp_ticketer/cli/simple_health.py +84 -59
- mcp_ticketer/cli/ticket_commands.py +1375 -0
- mcp_ticketer/cli/update_checker.py +313 -0
- mcp_ticketer/cli/utils.py +195 -72
- mcp_ticketer/core/__init__.py +64 -1
- mcp_ticketer/core/adapter.py +618 -18
- mcp_ticketer/core/config.py +77 -68
- mcp_ticketer/core/env_discovery.py +75 -16
- mcp_ticketer/core/env_loader.py +121 -97
- mcp_ticketer/core/exceptions.py +32 -24
- mcp_ticketer/core/http_client.py +26 -26
- mcp_ticketer/core/instructions.py +405 -0
- mcp_ticketer/core/label_manager.py +732 -0
- mcp_ticketer/core/mappers.py +42 -30
- mcp_ticketer/core/milestone_manager.py +252 -0
- mcp_ticketer/core/models.py +566 -19
- mcp_ticketer/core/onepassword_secrets.py +379 -0
- mcp_ticketer/core/priority_matcher.py +463 -0
- mcp_ticketer/core/project_config.py +189 -49
- mcp_ticketer/core/project_utils.py +281 -0
- mcp_ticketer/core/project_validator.py +376 -0
- mcp_ticketer/core/registry.py +3 -3
- mcp_ticketer/core/session_state.py +176 -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 +29 -1
- mcp_ticketer/mcp/__main__.py +60 -0
- mcp_ticketer/mcp/server/__init__.py +25 -0
- mcp_ticketer/mcp/server/__main__.py +60 -0
- mcp_ticketer/mcp/server/constants.py +58 -0
- mcp_ticketer/mcp/server/diagnostic_helper.py +175 -0
- mcp_ticketer/mcp/server/dto.py +195 -0
- mcp_ticketer/mcp/server/main.py +1343 -0
- mcp_ticketer/mcp/server/response_builder.py +206 -0
- mcp_ticketer/mcp/server/routing.py +723 -0
- mcp_ticketer/mcp/server/server_sdk.py +151 -0
- mcp_ticketer/mcp/server/tools/__init__.py +69 -0
- mcp_ticketer/mcp/server/tools/analysis_tools.py +854 -0
- mcp_ticketer/mcp/server/tools/attachment_tools.py +224 -0
- mcp_ticketer/mcp/server/tools/bulk_tools.py +330 -0
- mcp_ticketer/mcp/server/tools/comment_tools.py +152 -0
- mcp_ticketer/mcp/server/tools/config_tools.py +1564 -0
- mcp_ticketer/mcp/server/tools/diagnostic_tools.py +211 -0
- mcp_ticketer/mcp/server/tools/hierarchy_tools.py +942 -0
- 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/milestone_tools.py +338 -0
- mcp_ticketer/mcp/server/tools/pr_tools.py +150 -0
- 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 +318 -0
- mcp_ticketer/mcp/server/tools/session_tools.py +308 -0
- mcp_ticketer/mcp/server/tools/ticket_tools.py +1413 -0
- mcp_ticketer/mcp/server/tools/user_ticket_tools.py +364 -0
- mcp_ticketer/queue/__init__.py +1 -0
- mcp_ticketer/queue/health_monitor.py +168 -136
- mcp_ticketer/queue/manager.py +78 -63
- mcp_ticketer/queue/queue.py +108 -21
- mcp_ticketer/queue/run_worker.py +2 -2
- mcp_ticketer/queue/ticket_registry.py +213 -155
- mcp_ticketer/queue/worker.py +96 -58
- mcp_ticketer/utils/__init__.py +5 -0
- mcp_ticketer/utils/token_utils.py +246 -0
- mcp_ticketer-2.2.9.dist-info/METADATA +1396 -0
- mcp_ticketer-2.2.9.dist-info/RECORD +158 -0
- mcp_ticketer-2.2.9.dist-info/top_level.txt +2 -0
- py_mcp_installer/examples/phase3_demo.py +178 -0
- py_mcp_installer/scripts/manage_version.py +54 -0
- py_mcp_installer/setup.py +6 -0
- py_mcp_installer/src/py_mcp_installer/__init__.py +153 -0
- py_mcp_installer/src/py_mcp_installer/command_builder.py +445 -0
- py_mcp_installer/src/py_mcp_installer/config_manager.py +541 -0
- py_mcp_installer/src/py_mcp_installer/exceptions.py +243 -0
- py_mcp_installer/src/py_mcp_installer/installation_strategy.py +617 -0
- py_mcp_installer/src/py_mcp_installer/installer.py +656 -0
- py_mcp_installer/src/py_mcp_installer/mcp_inspector.py +750 -0
- py_mcp_installer/src/py_mcp_installer/platform_detector.py +451 -0
- py_mcp_installer/src/py_mcp_installer/platforms/__init__.py +26 -0
- py_mcp_installer/src/py_mcp_installer/platforms/claude_code.py +225 -0
- py_mcp_installer/src/py_mcp_installer/platforms/codex.py +181 -0
- py_mcp_installer/src/py_mcp_installer/platforms/cursor.py +191 -0
- py_mcp_installer/src/py_mcp_installer/types.py +222 -0
- py_mcp_installer/src/py_mcp_installer/utils.py +463 -0
- py_mcp_installer/tests/__init__.py +0 -0
- py_mcp_installer/tests/platforms/__init__.py +0 -0
- py_mcp_installer/tests/test_platform_detector.py +17 -0
- mcp_ticketer/adapters/github.py +0 -1354
- mcp_ticketer/adapters/jira.py +0 -1011
- mcp_ticketer/mcp/server.py +0 -1895
- mcp_ticketer-0.2.0.dist-info/METADATA +0 -414
- mcp_ticketer-0.2.0.dist-info/RECORD +0 -58
- mcp_ticketer-0.2.0.dist-info/top_level.txt +0 -1
- {mcp_ticketer-0.2.0.dist-info → mcp_ticketer-2.2.9.dist-info}/WHEEL +0 -0
- {mcp_ticketer-0.2.0.dist-info → mcp_ticketer-2.2.9.dist-info}/entry_points.txt +0 -0
- {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
|