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
|
@@ -24,6 +24,7 @@ def find_codex_config() -> Path:
|
|
|
24
24
|
No project-level or user-scoped configuration is available.
|
|
25
25
|
|
|
26
26
|
Returns:
|
|
27
|
+
-------
|
|
27
28
|
Path to Codex global config file at ~/.codex/config.toml
|
|
28
29
|
|
|
29
30
|
"""
|
|
@@ -36,9 +37,11 @@ def load_codex_config(config_path: Path) -> dict[str, Any]:
|
|
|
36
37
|
"""Load existing Codex configuration or return empty structure.
|
|
37
38
|
|
|
38
39
|
Args:
|
|
40
|
+
----
|
|
39
41
|
config_path: Path to Codex config.toml file
|
|
40
42
|
|
|
41
43
|
Returns:
|
|
44
|
+
-------
|
|
42
45
|
Codex configuration dict with mcp_servers section
|
|
43
46
|
|
|
44
47
|
"""
|
|
@@ -61,6 +64,7 @@ def save_codex_config(config_path: Path, config: dict[str, Any]) -> None:
|
|
|
61
64
|
"""Save Codex configuration to TOML file.
|
|
62
65
|
|
|
63
66
|
Args:
|
|
67
|
+
----
|
|
64
68
|
config_path: Path to Codex config.toml file
|
|
65
69
|
config: Configuration to save
|
|
66
70
|
|
|
@@ -78,81 +82,146 @@ def create_codex_server_config(
|
|
|
78
82
|
) -> dict[str, Any]:
|
|
79
83
|
"""Create Codex MCP server configuration for mcp-ticketer.
|
|
80
84
|
|
|
85
|
+
Uses the CLI command (mcp-ticketer mcp) which implements proper
|
|
86
|
+
Content-Length framing via FastMCP SDK, required for modern MCP clients.
|
|
87
|
+
|
|
81
88
|
Args:
|
|
89
|
+
----
|
|
82
90
|
python_path: Path to Python executable in mcp-ticketer venv
|
|
83
91
|
project_config: Project configuration from .mcp-ticketer/config.json
|
|
84
|
-
project_path: Project directory path (optional
|
|
92
|
+
project_path: Project directory path (optional)
|
|
85
93
|
|
|
86
94
|
Returns:
|
|
95
|
+
-------
|
|
87
96
|
Codex MCP server configuration dict
|
|
88
97
|
|
|
89
98
|
"""
|
|
90
|
-
# Use Python module invocation
|
|
91
|
-
|
|
92
|
-
#
|
|
93
|
-
adapter = project_config.get("default_adapter", "aitrackdown")
|
|
94
|
-
adapters_config = project_config.get("adapters", {})
|
|
95
|
-
adapter_config = adapters_config.get(adapter, {})
|
|
99
|
+
# IMPORTANT: Use CLI command, NOT Python module invocation
|
|
100
|
+
# The CLI uses FastMCP SDK which implements proper Content-Length framing
|
|
101
|
+
# Legacy python -m mcp_ticketer.mcp.server uses line-delimited JSON (incompatible)
|
|
96
102
|
|
|
97
|
-
#
|
|
98
|
-
|
|
103
|
+
# Get mcp-ticketer CLI path from Python path
|
|
104
|
+
# If python_path is /path/to/venv/bin/python, CLI is /path/to/venv/bin/mcp-ticketer
|
|
105
|
+
python_dir = Path(python_path).parent
|
|
106
|
+
cli_path = str(python_dir / "mcp-ticketer")
|
|
99
107
|
|
|
100
|
-
#
|
|
101
|
-
|
|
102
|
-
env_vars["PYTHONPATH"] = project_path
|
|
103
|
-
|
|
104
|
-
# Add adapter type
|
|
105
|
-
env_vars["MCP_TICKETER_ADAPTER"] = adapter
|
|
106
|
-
|
|
107
|
-
# Add adapter-specific environment variables
|
|
108
|
-
if adapter == "aitrackdown":
|
|
109
|
-
# Set base path for local adapter
|
|
110
|
-
base_path = adapter_config.get("base_path", ".aitrackdown")
|
|
111
|
-
if project_path:
|
|
112
|
-
# Use absolute path if project_path is provided
|
|
113
|
-
env_vars["MCP_TICKETER_BASE_PATH"] = str(Path(project_path) / base_path)
|
|
114
|
-
else:
|
|
115
|
-
env_vars["MCP_TICKETER_BASE_PATH"] = base_path
|
|
116
|
-
|
|
117
|
-
elif adapter == "linear":
|
|
118
|
-
if "api_key" in adapter_config:
|
|
119
|
-
env_vars["LINEAR_API_KEY"] = adapter_config["api_key"]
|
|
120
|
-
if "team_id" in adapter_config:
|
|
121
|
-
env_vars["LINEAR_TEAM_ID"] = adapter_config["team_id"]
|
|
122
|
-
|
|
123
|
-
elif adapter == "github":
|
|
124
|
-
if "token" in adapter_config:
|
|
125
|
-
env_vars["GITHUB_TOKEN"] = adapter_config["token"]
|
|
126
|
-
if "owner" in adapter_config:
|
|
127
|
-
env_vars["GITHUB_OWNER"] = adapter_config["owner"]
|
|
128
|
-
if "repo" in adapter_config:
|
|
129
|
-
env_vars["GITHUB_REPO"] = adapter_config["repo"]
|
|
130
|
-
|
|
131
|
-
elif adapter == "jira":
|
|
132
|
-
if "api_token" in adapter_config:
|
|
133
|
-
env_vars["JIRA_API_TOKEN"] = adapter_config["api_token"]
|
|
134
|
-
if "email" in adapter_config:
|
|
135
|
-
env_vars["JIRA_EMAIL"] = adapter_config["email"]
|
|
136
|
-
if "server" in adapter_config:
|
|
137
|
-
env_vars["JIRA_SERVER"] = adapter_config["server"]
|
|
138
|
-
if "project_key" in adapter_config:
|
|
139
|
-
env_vars["JIRA_PROJECT_KEY"] = adapter_config["project_key"]
|
|
140
|
-
|
|
141
|
-
# Use Python module invocation pattern
|
|
142
|
-
args = ["-m", "mcp_ticketer.mcp.server"]
|
|
108
|
+
# Build CLI arguments
|
|
109
|
+
args = ["mcp"]
|
|
143
110
|
if project_path:
|
|
144
|
-
args.
|
|
111
|
+
args.extend(["--path", project_path])
|
|
145
112
|
|
|
146
113
|
# Create server configuration with Codex-specific structure
|
|
114
|
+
# No environment variables needed - config loaded from .mcp-ticketer/config.json
|
|
147
115
|
config: dict[str, Any] = {
|
|
148
|
-
"command":
|
|
116
|
+
"command": cli_path,
|
|
149
117
|
"args": args,
|
|
150
|
-
"env": env_vars,
|
|
151
118
|
}
|
|
152
119
|
|
|
153
120
|
return config
|
|
154
121
|
|
|
155
122
|
|
|
123
|
+
def _test_configuration(adapter: str, project_config: dict) -> bool:
|
|
124
|
+
"""Test the configuration by validating adapter credentials.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
----
|
|
128
|
+
adapter: Adapter type (linear, github, jira, aitrackdown)
|
|
129
|
+
project_config: Project configuration dict
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
-------
|
|
133
|
+
True if validation passed, False otherwise
|
|
134
|
+
|
|
135
|
+
"""
|
|
136
|
+
try:
|
|
137
|
+
from ..core import AdapterRegistry
|
|
138
|
+
|
|
139
|
+
# Get adapter configuration
|
|
140
|
+
adapters_config = project_config.get("adapters", {})
|
|
141
|
+
adapter_config = adapters_config.get(adapter, {})
|
|
142
|
+
|
|
143
|
+
# Test adapter instantiation
|
|
144
|
+
console.print(f" Testing {adapter} adapter...")
|
|
145
|
+
|
|
146
|
+
try:
|
|
147
|
+
adapter_instance = AdapterRegistry.get_adapter(adapter, adapter_config)
|
|
148
|
+
console.print(" [green]โ[/green] Adapter instantiated successfully")
|
|
149
|
+
|
|
150
|
+
# Test credentials if validation method exists
|
|
151
|
+
if hasattr(adapter_instance, "validate_credentials"):
|
|
152
|
+
console.print(f" Validating {adapter} credentials...")
|
|
153
|
+
is_valid, error_msg = adapter_instance.validate_credentials()
|
|
154
|
+
|
|
155
|
+
if is_valid:
|
|
156
|
+
console.print(" [green]โ[/green] Credentials are valid")
|
|
157
|
+
return True
|
|
158
|
+
else:
|
|
159
|
+
console.print(
|
|
160
|
+
f" [red]โ[/red] Credential validation failed: {error_msg}"
|
|
161
|
+
)
|
|
162
|
+
return False
|
|
163
|
+
else:
|
|
164
|
+
# No validation method, assume valid
|
|
165
|
+
console.print(
|
|
166
|
+
f" [yellow]โ[/yellow] No credential validation available for {adapter}"
|
|
167
|
+
)
|
|
168
|
+
return True
|
|
169
|
+
|
|
170
|
+
except Exception as e:
|
|
171
|
+
console.print(f" [red]โ[/red] Adapter instantiation failed: {e}")
|
|
172
|
+
|
|
173
|
+
# Provide helpful error messages based on adapter type
|
|
174
|
+
if adapter == "linear":
|
|
175
|
+
console.print(
|
|
176
|
+
"\n [yellow]Linear requires:[/yellow] LINEAR_API_KEY and LINEAR_TEAM_ID"
|
|
177
|
+
)
|
|
178
|
+
elif adapter == "github":
|
|
179
|
+
console.print(
|
|
180
|
+
"\n [yellow]GitHub requires:[/yellow] GITHUB_TOKEN, GITHUB_OWNER, GITHUB_REPO"
|
|
181
|
+
)
|
|
182
|
+
elif adapter == "jira":
|
|
183
|
+
console.print(
|
|
184
|
+
"\n [yellow]JIRA requires:[/yellow] JIRA_SERVER, JIRA_EMAIL, JIRA_API_TOKEN"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
return False
|
|
188
|
+
|
|
189
|
+
except Exception as e:
|
|
190
|
+
console.print(f" [red]โ[/red] Configuration test error: {e}")
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
def detect_legacy_config(config_path: Path) -> tuple[bool, dict[str, Any] | None]:
|
|
195
|
+
"""Detect if existing config uses legacy Python module invocation.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
----
|
|
199
|
+
config_path: Path to Codex config.toml file
|
|
200
|
+
|
|
201
|
+
Returns:
|
|
202
|
+
-------
|
|
203
|
+
Tuple of (is_legacy, server_config):
|
|
204
|
+
- is_legacy: True if config uses 'python -m mcp_ticketer.mcp.server'
|
|
205
|
+
- server_config: The legacy server config dict, or None if not legacy
|
|
206
|
+
|
|
207
|
+
"""
|
|
208
|
+
if not config_path.exists():
|
|
209
|
+
return False, None
|
|
210
|
+
|
|
211
|
+
codex_config = load_codex_config(config_path)
|
|
212
|
+
mcp_servers = codex_config.get("mcp_servers", {})
|
|
213
|
+
|
|
214
|
+
if "mcp-ticketer" in mcp_servers:
|
|
215
|
+
server_config = mcp_servers["mcp-ticketer"]
|
|
216
|
+
args = server_config.get("args", [])
|
|
217
|
+
|
|
218
|
+
# Check for legacy pattern: ["-m", "mcp_ticketer.mcp.server", ...]
|
|
219
|
+
if len(args) >= 2 and args[0] == "-m" and "mcp_ticketer.mcp.server" in args[1]:
|
|
220
|
+
return True, server_config
|
|
221
|
+
|
|
222
|
+
return False, None
|
|
223
|
+
|
|
224
|
+
|
|
156
225
|
def remove_codex_mcp(dry_run: bool = False) -> None:
|
|
157
226
|
"""Remove mcp-ticketer from Codex CLI configuration.
|
|
158
227
|
|
|
@@ -160,6 +229,7 @@ def remove_codex_mcp(dry_run: bool = False) -> None:
|
|
|
160
229
|
This will remove mcp-ticketer from the global configuration.
|
|
161
230
|
|
|
162
231
|
Args:
|
|
232
|
+
----
|
|
163
233
|
dry_run: Show what would be removed without making changes
|
|
164
234
|
|
|
165
235
|
"""
|
|
@@ -230,9 +300,11 @@ def configure_codex_mcp(force: bool = False) -> None:
|
|
|
230
300
|
After configuration, you must restart Codex CLI for changes to take effect.
|
|
231
301
|
|
|
232
302
|
Args:
|
|
303
|
+
----
|
|
233
304
|
force: Overwrite existing configuration
|
|
234
305
|
|
|
235
306
|
Raises:
|
|
307
|
+
------
|
|
236
308
|
FileNotFoundError: If Python executable or project config not found
|
|
237
309
|
ValueError: If configuration is invalid
|
|
238
310
|
|
|
@@ -248,7 +320,7 @@ def configure_codex_mcp(force: bool = False) -> None:
|
|
|
248
320
|
"Could not find mcp-ticketer Python executable. "
|
|
249
321
|
"Please ensure mcp-ticketer is installed.\n"
|
|
250
322
|
"Install with: pip install mcp-ticketer or pipx install mcp-ticketer"
|
|
251
|
-
)
|
|
323
|
+
) from e
|
|
252
324
|
|
|
253
325
|
# Step 2: Load project configuration
|
|
254
326
|
console.print("\n[cyan]๐ Reading project configuration...[/cyan]")
|
|
@@ -269,6 +341,26 @@ def configure_codex_mcp(force: bool = False) -> None:
|
|
|
269
341
|
codex_config_path = find_codex_config()
|
|
270
342
|
console.print(f"[dim]Config location: {codex_config_path}[/dim]")
|
|
271
343
|
|
|
344
|
+
# Step 3.5: Check for legacy configuration (DETECTION & MIGRATION)
|
|
345
|
+
is_legacy, legacy_config = detect_legacy_config(codex_config_path)
|
|
346
|
+
if is_legacy:
|
|
347
|
+
console.print("\n[yellow]โ LEGACY CONFIGURATION DETECTED[/yellow]")
|
|
348
|
+
console.print(
|
|
349
|
+
"[yellow]Your current configuration uses the legacy line-delimited JSON server:[/yellow]"
|
|
350
|
+
)
|
|
351
|
+
console.print(f"[dim] Command: {legacy_config.get('command')}[/dim]")
|
|
352
|
+
console.print(f"[dim] Args: {legacy_config.get('args')}[/dim]")
|
|
353
|
+
console.print(
|
|
354
|
+
"\n[red]This legacy server is incompatible with modern MCP clients (Codex, Claude Desktop/Code).[/red]"
|
|
355
|
+
)
|
|
356
|
+
console.print(
|
|
357
|
+
"[red]The legacy server uses line-delimited JSON instead of Content-Length framing.[/red]"
|
|
358
|
+
)
|
|
359
|
+
console.print(
|
|
360
|
+
"\n[cyan]โจ Automatically migrating to modern FastMCP-based server...[/cyan]"
|
|
361
|
+
)
|
|
362
|
+
force = True # Auto-enable force mode for migration
|
|
363
|
+
|
|
272
364
|
# Step 4: Load existing Codex configuration
|
|
273
365
|
codex_config = load_codex_config(codex_config_path)
|
|
274
366
|
|
|
@@ -281,7 +373,9 @@ def configure_codex_mcp(force: bool = False) -> None:
|
|
|
281
373
|
console.print("[dim]Use --force to overwrite existing configuration[/dim]")
|
|
282
374
|
return
|
|
283
375
|
else:
|
|
284
|
-
|
|
376
|
+
if not is_legacy:
|
|
377
|
+
console.print("[yellow]โ Overwriting existing configuration[/yellow]")
|
|
378
|
+
# If is_legacy, we already printed migration message above
|
|
285
379
|
|
|
286
380
|
# Step 6: Create mcp-ticketer server config
|
|
287
381
|
# For global config, include current working directory for context
|
|
@@ -309,12 +403,33 @@ def configure_codex_mcp(force: bool = False) -> None:
|
|
|
309
403
|
console.print(" Server name: mcp-ticketer")
|
|
310
404
|
console.print(f" Adapter: {adapter}")
|
|
311
405
|
console.print(f" Python: {python_path}")
|
|
312
|
-
console.print(" Command:
|
|
406
|
+
console.print(f" Command: {server_config.get('command')}")
|
|
407
|
+
console.print(f" Args: {server_config.get('args')}")
|
|
408
|
+
console.print(" Protocol: Content-Length framing (FastMCP SDK)")
|
|
313
409
|
console.print(" Scope: global (Codex only supports global config)")
|
|
314
410
|
console.print(f" Project path: {project_path}")
|
|
315
|
-
|
|
411
|
+
|
|
412
|
+
# Step 9: Test configuration
|
|
413
|
+
console.print("\n[cyan]๐งช Testing configuration...[/cyan]")
|
|
414
|
+
test_success = _test_configuration(adapter, project_config)
|
|
415
|
+
|
|
416
|
+
if not test_success:
|
|
417
|
+
console.print(
|
|
418
|
+
"[yellow]โ Configuration saved but validation failed. "
|
|
419
|
+
"Please check your credentials and settings.[/yellow]"
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
# Migration success message (if legacy config was detected)
|
|
423
|
+
if is_legacy:
|
|
424
|
+
console.print("\n[green]โ
Migration Complete![/green]")
|
|
425
|
+
console.print(
|
|
426
|
+
"[green]Your configuration has been upgraded from legacy line-delimited JSON[/green]"
|
|
427
|
+
)
|
|
428
|
+
console.print(
|
|
429
|
+
"[green]to modern Content-Length framing (FastMCP SDK).[/green]"
|
|
430
|
+
)
|
|
316
431
|
console.print(
|
|
317
|
-
|
|
432
|
+
"\n[cyan]This fixes MCP connection issues with Codex and other modern clients.[/cyan]"
|
|
318
433
|
)
|
|
319
434
|
|
|
320
435
|
# Next steps
|