mcp-ticketer 0.12.0__py3-none-any.whl → 2.2.13__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 +1 -1
- mcp_ticketer/_version_scm.py +1 -0
- mcp_ticketer/adapters/aitrackdown.py +507 -6
- mcp_ticketer/adapters/asana/adapter.py +229 -0
- mcp_ticketer/adapters/asana/mappers.py +14 -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 +47 -5
- 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/adapter.py +2730 -139
- mcp_ticketer/adapters/linear/client.py +175 -3
- mcp_ticketer/adapters/linear/mappers.py +203 -8
- mcp_ticketer/adapters/linear/queries.py +280 -3
- mcp_ticketer/adapters/linear/types.py +120 -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/cli/adapter_diagnostics.py +3 -1
- mcp_ticketer/cli/auggie_configure.py +17 -5
- mcp_ticketer/cli/codex_configure.py +97 -61
- mcp_ticketer/cli/configure.py +1288 -105
- mcp_ticketer/cli/cursor_configure.py +314 -0
- mcp_ticketer/cli/diagnostics.py +13 -12
- mcp_ticketer/cli/discover.py +5 -0
- mcp_ticketer/cli/gemini_configure.py +17 -5
- mcp_ticketer/cli/init_command.py +880 -0
- mcp_ticketer/cli/install_mcp_server.py +418 -0
- mcp_ticketer/cli/instruction_commands.py +6 -0
- mcp_ticketer/cli/main.py +267 -3175
- mcp_ticketer/cli/mcp_configure.py +821 -119
- mcp_ticketer/cli/mcp_server_commands.py +415 -0
- mcp_ticketer/cli/platform_detection.py +77 -12
- mcp_ticketer/cli/platform_installer.py +545 -0
- mcp_ticketer/cli/project_update_commands.py +350 -0
- mcp_ticketer/cli/setup_command.py +795 -0
- mcp_ticketer/cli/simple_health.py +12 -10
- mcp_ticketer/cli/ticket_commands.py +705 -103
- mcp_ticketer/cli/utils.py +113 -0
- mcp_ticketer/core/__init__.py +56 -6
- mcp_ticketer/core/adapter.py +533 -2
- mcp_ticketer/core/config.py +21 -21
- mcp_ticketer/core/exceptions.py +7 -1
- mcp_ticketer/core/label_manager.py +732 -0
- mcp_ticketer/core/mappers.py +31 -19
- mcp_ticketer/core/milestone_manager.py +252 -0
- mcp_ticketer/core/models.py +480 -0
- mcp_ticketer/core/onepassword_secrets.py +1 -1
- mcp_ticketer/core/priority_matcher.py +463 -0
- mcp_ticketer/core/project_config.py +132 -14
- mcp_ticketer/core/project_utils.py +281 -0
- mcp_ticketer/core/project_validator.py +376 -0
- mcp_ticketer/core/session_state.py +176 -0
- mcp_ticketer/core/state_matcher.py +625 -0
- mcp_ticketer/core/url_parser.py +425 -0
- mcp_ticketer/core/validators.py +69 -0
- mcp_ticketer/mcp/server/__main__.py +2 -1
- mcp_ticketer/mcp/server/diagnostic_helper.py +175 -0
- mcp_ticketer/mcp/server/main.py +106 -25
- mcp_ticketer/mcp/server/routing.py +723 -0
- mcp_ticketer/mcp/server/server_sdk.py +58 -0
- mcp_ticketer/mcp/server/tools/__init__.py +33 -11
- mcp_ticketer/mcp/server/tools/analysis_tools.py +854 -0
- mcp_ticketer/mcp/server/tools/attachment_tools.py +5 -5
- 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 +1391 -145
- mcp_ticketer/mcp/server/tools/diagnostic_tools.py +211 -0
- mcp_ticketer/mcp/server/tools/hierarchy_tools.py +870 -460
- mcp_ticketer/mcp/server/tools/instruction_tools.py +7 -5
- 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 +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 +209 -97
- mcp_ticketer/mcp/server/tools/session_tools.py +308 -0
- mcp_ticketer/mcp/server/tools/ticket_tools.py +1107 -124
- mcp_ticketer/mcp/server/tools/user_ticket_tools.py +218 -236
- mcp_ticketer/queue/queue.py +68 -0
- mcp_ticketer/queue/worker.py +1 -1
- mcp_ticketer/utils/__init__.py +5 -0
- mcp_ticketer/utils/token_utils.py +246 -0
- mcp_ticketer-2.2.13.dist-info/METADATA +1396 -0
- mcp_ticketer-2.2.13.dist-info/RECORD +158 -0
- mcp_ticketer-2.2.13.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 -1574
- mcp_ticketer/adapters/jira.py +0 -1258
- mcp_ticketer-0.12.0.dist-info/METADATA +0 -550
- mcp_ticketer-0.12.0.dist-info/RECORD +0 -91
- mcp_ticketer-0.12.0.dist-info/top_level.txt +0 -1
- {mcp_ticketer-0.12.0.dist-info → mcp_ticketer-2.2.13.dist-info}/WHEEL +0 -0
- {mcp_ticketer-0.12.0.dist-info → mcp_ticketer-2.2.13.dist-info}/entry_points.txt +0 -0
- {mcp_ticketer-0.12.0.dist-info → mcp_ticketer-2.2.13.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,445 @@
|
|
|
1
|
+
"""Command builder for MCP server installations.
|
|
2
|
+
|
|
3
|
+
This module provides utilities to build correct command strings for MCP server
|
|
4
|
+
installations, including auto-detection of installation methods (uv, pipx, direct).
|
|
5
|
+
|
|
6
|
+
Design Philosophy:
|
|
7
|
+
- Auto-detect best installation method
|
|
8
|
+
- Build platform-specific command strings
|
|
9
|
+
- Validate commands are executable
|
|
10
|
+
- Support for multiple installation methods
|
|
11
|
+
|
|
12
|
+
Priority:
|
|
13
|
+
1. UV_RUN: uv run mcp-ticketer mcp (fastest, recommended)
|
|
14
|
+
2. PIPX: mcp-ticketer (installed via pipx)
|
|
15
|
+
3. DIRECT: Direct binary in PATH
|
|
16
|
+
4. PYTHON_MODULE: python -m mcp_ticketer mcp (fallback)
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
from typing import Any
|
|
21
|
+
|
|
22
|
+
from .exceptions import CommandNotFoundError
|
|
23
|
+
from .types import InstallMethod, MCPServerConfig, Platform
|
|
24
|
+
from .utils import detect_install_method, resolve_command_path
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CommandBuilder:
|
|
28
|
+
"""Build correct command strings for MCP server installations.
|
|
29
|
+
|
|
30
|
+
Provides methods to auto-detect installation methods and build
|
|
31
|
+
platform-specific command configurations.
|
|
32
|
+
|
|
33
|
+
Example:
|
|
34
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
35
|
+
>>> command, args = builder.build_command(
|
|
36
|
+
... MCPServerConfig(name="mcp-ticketer", command="", args=[]),
|
|
37
|
+
... InstallMethod.UV_RUN
|
|
38
|
+
... )
|
|
39
|
+
>>> print(f"{command} {' '.join(args)}")
|
|
40
|
+
uv run mcp-ticketer mcp
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, platform: Platform) -> None:
|
|
44
|
+
"""Initialize command builder for target platform.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
platform: Target platform for command building
|
|
48
|
+
|
|
49
|
+
Example:
|
|
50
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
51
|
+
"""
|
|
52
|
+
self.platform = platform
|
|
53
|
+
|
|
54
|
+
def build_command(
|
|
55
|
+
self, server: MCPServerConfig, install_method: InstallMethod
|
|
56
|
+
) -> str:
|
|
57
|
+
"""Build command string for server installation.
|
|
58
|
+
|
|
59
|
+
Constructs the appropriate command based on installation method:
|
|
60
|
+
- UV_RUN: "uv run mcp-ticketer mcp"
|
|
61
|
+
- PIPX: "mcp-ticketer mcp"
|
|
62
|
+
- DIRECT: "mcp-ticketer mcp"
|
|
63
|
+
- PYTHON_MODULE: "python -m mcp_ticketer.mcp.server"
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
server: Server configuration
|
|
67
|
+
install_method: Installation method to use
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Command string
|
|
71
|
+
|
|
72
|
+
Example:
|
|
73
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
74
|
+
>>> server = MCPServerConfig(name="mcp-ticketer", command="", args=[])
|
|
75
|
+
>>> cmd = builder.build_command(server, InstallMethod.UV_RUN)
|
|
76
|
+
>>> print(cmd)
|
|
77
|
+
uv
|
|
78
|
+
"""
|
|
79
|
+
if install_method == InstallMethod.UV_RUN:
|
|
80
|
+
# uv run {package} {subcommand}
|
|
81
|
+
return "uv"
|
|
82
|
+
|
|
83
|
+
elif install_method == InstallMethod.PIPX:
|
|
84
|
+
# Binary installed via pipx
|
|
85
|
+
binary_path = resolve_command_path(server.name)
|
|
86
|
+
if binary_path:
|
|
87
|
+
return str(binary_path)
|
|
88
|
+
else:
|
|
89
|
+
raise CommandNotFoundError(
|
|
90
|
+
server.name,
|
|
91
|
+
install_hint=f"pipx install {server.name}",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
elif install_method == InstallMethod.DIRECT:
|
|
95
|
+
# Direct binary in PATH
|
|
96
|
+
binary_path = resolve_command_path(server.name)
|
|
97
|
+
if binary_path:
|
|
98
|
+
return str(binary_path)
|
|
99
|
+
else:
|
|
100
|
+
raise CommandNotFoundError(
|
|
101
|
+
server.name,
|
|
102
|
+
install_hint=f"Install {server.name} and ensure it's in PATH",
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
elif install_method == InstallMethod.PYTHON_MODULE:
|
|
106
|
+
# python -m {module}
|
|
107
|
+
import sys
|
|
108
|
+
|
|
109
|
+
return sys.executable
|
|
110
|
+
|
|
111
|
+
else:
|
|
112
|
+
raise ValueError(f"Unknown install method: {install_method}")
|
|
113
|
+
|
|
114
|
+
def build_args(
|
|
115
|
+
self, server: MCPServerConfig, install_method: InstallMethod
|
|
116
|
+
) -> list[str]:
|
|
117
|
+
"""Build argument list from server config.
|
|
118
|
+
|
|
119
|
+
Constructs arguments based on installation method:
|
|
120
|
+
- UV_RUN: ["run", "{package}", "mcp", ...]
|
|
121
|
+
- PIPX/DIRECT: ["mcp", ...]
|
|
122
|
+
- PYTHON_MODULE: ["-m", "{module}", ...]
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
server: Server configuration
|
|
126
|
+
install_method: Installation method
|
|
127
|
+
|
|
128
|
+
Returns:
|
|
129
|
+
List of arguments
|
|
130
|
+
|
|
131
|
+
Example:
|
|
132
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
133
|
+
>>> server = MCPServerConfig(
|
|
134
|
+
... name="mcp-ticketer",
|
|
135
|
+
... command="",
|
|
136
|
+
... args=["--verbose"]
|
|
137
|
+
... )
|
|
138
|
+
>>> args = builder.build_args(server, InstallMethod.UV_RUN)
|
|
139
|
+
>>> print(args)
|
|
140
|
+
['run', 'mcp-ticketer', 'mcp', '--verbose']
|
|
141
|
+
"""
|
|
142
|
+
if install_method == InstallMethod.UV_RUN:
|
|
143
|
+
# uv run {package} {subcommand} [args...]
|
|
144
|
+
base_args = ["run", server.name, "mcp"]
|
|
145
|
+
return base_args + list(server.args)
|
|
146
|
+
|
|
147
|
+
elif install_method in (InstallMethod.PIPX, InstallMethod.DIRECT):
|
|
148
|
+
# {binary} mcp [args...]
|
|
149
|
+
return ["mcp"] + list(server.args)
|
|
150
|
+
|
|
151
|
+
elif install_method == InstallMethod.PYTHON_MODULE:
|
|
152
|
+
# python -m {module} [args...]
|
|
153
|
+
base_args = ["-m", "mcp_ticketer.mcp.server"]
|
|
154
|
+
return base_args + list(server.args)
|
|
155
|
+
|
|
156
|
+
else:
|
|
157
|
+
raise ValueError(f"Unknown install method: {install_method}")
|
|
158
|
+
|
|
159
|
+
def build_env(self, server: MCPServerConfig) -> dict[str, str]:
|
|
160
|
+
"""Build environment variables dict.
|
|
161
|
+
|
|
162
|
+
Simply returns server's env dict, no platform-specific
|
|
163
|
+
transformations needed.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
server: Server configuration
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Environment variables dictionary
|
|
170
|
+
|
|
171
|
+
Example:
|
|
172
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
173
|
+
>>> server = MCPServerConfig(
|
|
174
|
+
... name="mcp-ticketer",
|
|
175
|
+
... command="",
|
|
176
|
+
... args=[],
|
|
177
|
+
... env={"API_KEY": "secret"}
|
|
178
|
+
... )
|
|
179
|
+
>>> env = builder.build_env(server)
|
|
180
|
+
>>> print(env)
|
|
181
|
+
{'API_KEY': 'secret'}
|
|
182
|
+
"""
|
|
183
|
+
return dict(server.env)
|
|
184
|
+
|
|
185
|
+
def validate_command(self, command: str) -> bool:
|
|
186
|
+
"""Validate command is executable.
|
|
187
|
+
|
|
188
|
+
Checks if command exists in PATH or is an absolute path
|
|
189
|
+
to an executable file.
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
command: Command to validate
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
True if command is executable, False otherwise
|
|
196
|
+
|
|
197
|
+
Example:
|
|
198
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
199
|
+
>>> if builder.validate_command("python"):
|
|
200
|
+
... print("Python is available")
|
|
201
|
+
"""
|
|
202
|
+
# Check if it's an absolute path
|
|
203
|
+
path = Path(command)
|
|
204
|
+
if path.is_absolute():
|
|
205
|
+
return path.exists() and path.is_file()
|
|
206
|
+
|
|
207
|
+
# Check if in PATH
|
|
208
|
+
return resolve_command_path(command) is not None
|
|
209
|
+
|
|
210
|
+
def detect_best_method(self, package: str) -> InstallMethod:
|
|
211
|
+
"""Auto-detect best installation method for package.
|
|
212
|
+
|
|
213
|
+
Checks in priority order:
|
|
214
|
+
1. UV available → UV_RUN
|
|
215
|
+
2. Binary in PATH → DIRECT
|
|
216
|
+
3. Package installed via pip → PYTHON_MODULE
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
package: Package name (e.g., "mcp-ticketer")
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Best available installation method
|
|
223
|
+
|
|
224
|
+
Raises:
|
|
225
|
+
CommandNotFoundError: If no installation method available
|
|
226
|
+
|
|
227
|
+
Example:
|
|
228
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
229
|
+
>>> method = builder.detect_best_method("mcp-ticketer")
|
|
230
|
+
>>> print(method)
|
|
231
|
+
InstallMethod.UV_RUN
|
|
232
|
+
"""
|
|
233
|
+
# Priority 1: uv run (fastest)
|
|
234
|
+
if resolve_command_path("uv"):
|
|
235
|
+
return InstallMethod.UV_RUN
|
|
236
|
+
|
|
237
|
+
# Priority 2: Direct binary in PATH
|
|
238
|
+
if resolve_command_path(package):
|
|
239
|
+
# Check if installed via pipx
|
|
240
|
+
install_method = detect_install_method(package)
|
|
241
|
+
if install_method == "pipx":
|
|
242
|
+
return InstallMethod.PIPX
|
|
243
|
+
else:
|
|
244
|
+
return InstallMethod.DIRECT
|
|
245
|
+
|
|
246
|
+
# Priority 3: Python module (fallback)
|
|
247
|
+
# Try to import the module
|
|
248
|
+
try:
|
|
249
|
+
# Convert package name to module name (mcp-ticketer → mcp_ticketer)
|
|
250
|
+
module_name = package.replace("-", "_")
|
|
251
|
+
__import__(module_name)
|
|
252
|
+
return InstallMethod.PYTHON_MODULE
|
|
253
|
+
except ImportError:
|
|
254
|
+
pass
|
|
255
|
+
|
|
256
|
+
# No installation method found
|
|
257
|
+
raise CommandNotFoundError(
|
|
258
|
+
package,
|
|
259
|
+
install_hint=(
|
|
260
|
+
f"Install {package} using one of:\n"
|
|
261
|
+
f" - uv pip install {package}\n"
|
|
262
|
+
f" - pipx install {package}\n"
|
|
263
|
+
f" - pip install {package}"
|
|
264
|
+
),
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
def build_full_config(
|
|
268
|
+
self,
|
|
269
|
+
package: str,
|
|
270
|
+
install_method: InstallMethod | None = None,
|
|
271
|
+
additional_args: list[str] | None = None,
|
|
272
|
+
env: dict[str, str] | None = None,
|
|
273
|
+
) -> tuple[str, list[str], dict[str, str]]:
|
|
274
|
+
"""Build complete command configuration.
|
|
275
|
+
|
|
276
|
+
Convenience method that builds command, args, and env in one call.
|
|
277
|
+
|
|
278
|
+
Args:
|
|
279
|
+
package: Package name
|
|
280
|
+
install_method: Installation method (auto-detected if None)
|
|
281
|
+
additional_args: Additional arguments to append
|
|
282
|
+
env: Environment variables
|
|
283
|
+
|
|
284
|
+
Returns:
|
|
285
|
+
Tuple of (command, args, env)
|
|
286
|
+
|
|
287
|
+
Example:
|
|
288
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
289
|
+
>>> command, args, env = builder.build_full_config(
|
|
290
|
+
... "mcp-ticketer",
|
|
291
|
+
... additional_args=["--verbose"],
|
|
292
|
+
... env={"API_KEY": "secret"}
|
|
293
|
+
... )
|
|
294
|
+
>>> print(f"{command} {' '.join(args)}")
|
|
295
|
+
uv run mcp-ticketer mcp --verbose
|
|
296
|
+
"""
|
|
297
|
+
# Auto-detect method if not provided
|
|
298
|
+
if install_method is None:
|
|
299
|
+
install_method = self.detect_best_method(package)
|
|
300
|
+
|
|
301
|
+
# Create server config
|
|
302
|
+
server = MCPServerConfig(
|
|
303
|
+
name=package,
|
|
304
|
+
command="", # Will be built
|
|
305
|
+
args=additional_args or [],
|
|
306
|
+
env=env or {},
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
# Build command and args
|
|
310
|
+
command = self.build_command(server, install_method)
|
|
311
|
+
args = self.build_args(server, install_method)
|
|
312
|
+
env_dict = self.build_env(server)
|
|
313
|
+
|
|
314
|
+
return (command, args, env_dict)
|
|
315
|
+
|
|
316
|
+
def to_server_config(
|
|
317
|
+
self,
|
|
318
|
+
package: str,
|
|
319
|
+
install_method: InstallMethod | None = None,
|
|
320
|
+
additional_args: list[str] | None = None,
|
|
321
|
+
env: dict[str, str] | None = None,
|
|
322
|
+
description: str = "",
|
|
323
|
+
) -> MCPServerConfig:
|
|
324
|
+
"""Build MCPServerConfig from package name.
|
|
325
|
+
|
|
326
|
+
Convenience method to create full server configuration
|
|
327
|
+
with auto-detected installation method.
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
package: Package name
|
|
331
|
+
install_method: Installation method (auto-detected if None)
|
|
332
|
+
additional_args: Additional arguments
|
|
333
|
+
env: Environment variables
|
|
334
|
+
description: Server description
|
|
335
|
+
|
|
336
|
+
Returns:
|
|
337
|
+
Complete MCPServerConfig
|
|
338
|
+
|
|
339
|
+
Example:
|
|
340
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
341
|
+
>>> config = builder.to_server_config(
|
|
342
|
+
... "mcp-ticketer",
|
|
343
|
+
... env={"LINEAR_API_KEY": "..."},
|
|
344
|
+
... description="Linear ticket management"
|
|
345
|
+
... )
|
|
346
|
+
>>> print(f"{config.command} {' '.join(config.args)}")
|
|
347
|
+
uv run mcp-ticketer mcp
|
|
348
|
+
"""
|
|
349
|
+
# Build full config
|
|
350
|
+
command, args, env_dict = self.build_full_config(
|
|
351
|
+
package,
|
|
352
|
+
install_method,
|
|
353
|
+
additional_args,
|
|
354
|
+
env,
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
return MCPServerConfig(
|
|
358
|
+
name=package,
|
|
359
|
+
command=command,
|
|
360
|
+
args=args,
|
|
361
|
+
env=env_dict,
|
|
362
|
+
description=description,
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
def get_platform_command_recommendations(self, package: str) -> dict[str, Any]:
|
|
366
|
+
"""Get platform-specific command recommendations.
|
|
367
|
+
|
|
368
|
+
Provides information about best practices for command
|
|
369
|
+
configuration on this platform.
|
|
370
|
+
|
|
371
|
+
Args:
|
|
372
|
+
package: Package name
|
|
373
|
+
|
|
374
|
+
Returns:
|
|
375
|
+
Dict with recommendations and platform-specific info
|
|
376
|
+
|
|
377
|
+
Example:
|
|
378
|
+
>>> builder = CommandBuilder(Platform.CLAUDE_CODE)
|
|
379
|
+
>>> recs = builder.get_platform_command_recommendations("mcp-ticketer")
|
|
380
|
+
>>> print(recs["recommended_method"])
|
|
381
|
+
UV_RUN
|
|
382
|
+
"""
|
|
383
|
+
try:
|
|
384
|
+
best_method = self.detect_best_method(package)
|
|
385
|
+
except CommandNotFoundError:
|
|
386
|
+
best_method = None
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
"platform": self.platform.value,
|
|
390
|
+
"package": package,
|
|
391
|
+
"recommended_method": best_method.value if best_method else None,
|
|
392
|
+
"available_methods": self._get_available_methods(package),
|
|
393
|
+
"platform_notes": self._get_platform_notes(),
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
def _get_available_methods(self, package: str) -> list[str]:
|
|
397
|
+
"""Get list of available installation methods.
|
|
398
|
+
|
|
399
|
+
Args:
|
|
400
|
+
package: Package name
|
|
401
|
+
|
|
402
|
+
Returns:
|
|
403
|
+
List of available method names
|
|
404
|
+
"""
|
|
405
|
+
available = []
|
|
406
|
+
|
|
407
|
+
if resolve_command_path("uv"):
|
|
408
|
+
available.append("UV_RUN")
|
|
409
|
+
|
|
410
|
+
if resolve_command_path(package):
|
|
411
|
+
available.append("DIRECT")
|
|
412
|
+
|
|
413
|
+
# Check if module is importable
|
|
414
|
+
try:
|
|
415
|
+
module_name = package.replace("-", "_")
|
|
416
|
+
__import__(module_name)
|
|
417
|
+
available.append("PYTHON_MODULE")
|
|
418
|
+
except ImportError:
|
|
419
|
+
pass
|
|
420
|
+
|
|
421
|
+
return available
|
|
422
|
+
|
|
423
|
+
def _get_platform_notes(self) -> str:
|
|
424
|
+
"""Get platform-specific notes about command configuration.
|
|
425
|
+
|
|
426
|
+
Returns:
|
|
427
|
+
Platform-specific notes
|
|
428
|
+
"""
|
|
429
|
+
if self.platform in (Platform.CLAUDE_CODE, Platform.CLAUDE_DESKTOP):
|
|
430
|
+
return (
|
|
431
|
+
"Claude supports both CLI and JSON configuration. "
|
|
432
|
+
"Prefer uv run for fastest startup times."
|
|
433
|
+
)
|
|
434
|
+
elif self.platform == Platform.CURSOR:
|
|
435
|
+
return (
|
|
436
|
+
"Cursor only supports JSON configuration. "
|
|
437
|
+
"Use absolute paths for better reliability."
|
|
438
|
+
)
|
|
439
|
+
elif self.platform == Platform.CODEX:
|
|
440
|
+
return (
|
|
441
|
+
"Codex uses TOML configuration. "
|
|
442
|
+
"Environment variables may need special handling."
|
|
443
|
+
)
|
|
444
|
+
else:
|
|
445
|
+
return "Standard MCP server configuration applies."
|