mcp-ticketer 0.3.1__py3-none-any.whl → 0.3.2__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.

Files changed (37) hide show
  1. mcp_ticketer/__version__.py +1 -1
  2. mcp_ticketer/adapters/aitrackdown.py +12 -15
  3. mcp_ticketer/adapters/github.py +7 -4
  4. mcp_ticketer/adapters/jira.py +23 -22
  5. mcp_ticketer/adapters/linear/__init__.py +1 -1
  6. mcp_ticketer/adapters/linear/adapter.py +88 -89
  7. mcp_ticketer/adapters/linear/client.py +71 -52
  8. mcp_ticketer/adapters/linear/mappers.py +88 -68
  9. mcp_ticketer/adapters/linear/queries.py +28 -7
  10. mcp_ticketer/adapters/linear/types.py +57 -50
  11. mcp_ticketer/adapters/linear.py +2 -2
  12. mcp_ticketer/cli/adapter_diagnostics.py +86 -51
  13. mcp_ticketer/cli/diagnostics.py +165 -72
  14. mcp_ticketer/cli/linear_commands.py +156 -113
  15. mcp_ticketer/cli/main.py +153 -82
  16. mcp_ticketer/cli/simple_health.py +73 -45
  17. mcp_ticketer/cli/utils.py +15 -10
  18. mcp_ticketer/core/config.py +23 -19
  19. mcp_ticketer/core/env_discovery.py +5 -4
  20. mcp_ticketer/core/env_loader.py +109 -86
  21. mcp_ticketer/core/exceptions.py +20 -18
  22. mcp_ticketer/core/models.py +9 -0
  23. mcp_ticketer/core/project_config.py +1 -1
  24. mcp_ticketer/mcp/server.py +294 -139
  25. mcp_ticketer/queue/health_monitor.py +152 -121
  26. mcp_ticketer/queue/manager.py +11 -4
  27. mcp_ticketer/queue/queue.py +15 -3
  28. mcp_ticketer/queue/run_worker.py +1 -1
  29. mcp_ticketer/queue/ticket_registry.py +190 -132
  30. mcp_ticketer/queue/worker.py +54 -25
  31. {mcp_ticketer-0.3.1.dist-info → mcp_ticketer-0.3.2.dist-info}/METADATA +1 -1
  32. mcp_ticketer-0.3.2.dist-info/RECORD +59 -0
  33. mcp_ticketer-0.3.1.dist-info/RECORD +0 -59
  34. {mcp_ticketer-0.3.1.dist-info → mcp_ticketer-0.3.2.dist-info}/WHEEL +0 -0
  35. {mcp_ticketer-0.3.1.dist-info → mcp_ticketer-0.3.2.dist-info}/entry_points.txt +0 -0
  36. {mcp_ticketer-0.3.1.dist-info → mcp_ticketer-0.3.2.dist-info}/licenses/LICENSE +0 -0
  37. {mcp_ticketer-0.3.1.dist-info → mcp_ticketer-0.3.2.dist-info}/top_level.txt +0 -0
@@ -1,14 +1,10 @@
1
1
  """Adapter diagnostics and configuration validation."""
2
2
 
3
- import os
4
- import sys
5
3
  from pathlib import Path
6
- from typing import Any, Dict, List, Optional, Tuple
4
+ from typing import Any, Dict
7
5
 
8
6
  from rich.console import Console
9
- from rich.panel import Panel
10
7
  from rich.table import Table
11
- from rich.text import Text
12
8
 
13
9
  from ..core import AdapterRegistry
14
10
  from ..core.env_discovery import discover_config
@@ -16,24 +12,27 @@ from ..core.env_discovery import discover_config
16
12
 
17
13
  def diagnose_adapter_configuration(console: Console) -> None:
18
14
  """Diagnose adapter configuration and provide recommendations.
19
-
15
+
20
16
  Args:
21
17
  console: Rich console for output
18
+
22
19
  """
23
- console.print("\n[bold blue]🔍 MCP Ticketer Adapter Configuration Diagnostics[/bold blue]\n")
20
+ console.print(
21
+ "\n[bold blue]🔍 MCP Ticketer Adapter Configuration Diagnostics[/bold blue]\n"
22
+ )
24
23
 
25
24
  # 1. Check .env files
26
25
  _check_env_files(console)
27
-
26
+
28
27
  # 2. Check configuration files
29
28
  _check_configuration_files(console)
30
-
29
+
31
30
  # 3. Check adapter discovery
32
31
  _check_adapter_discovery(console)
33
-
32
+
34
33
  # 4. Test adapter instantiation
35
34
  _test_adapter_instantiation(console)
36
-
35
+
37
36
  # 5. Provide recommendations
38
37
  _provide_recommendations(console)
39
38
 
@@ -44,6 +43,7 @@ def _check_env_files(console: Console) -> None:
44
43
 
45
44
  # Load .env files
46
45
  from ..mcp.server import _load_env_configuration
46
+
47
47
  env_config = _load_env_configuration()
48
48
 
49
49
  # Check for .env files
@@ -60,10 +60,10 @@ def _check_env_files(console: Console) -> None:
60
60
  try:
61
61
  # Count variables in file
62
62
  var_count = 0
63
- with open(env_path, 'r') as f:
63
+ with open(env_path) as f:
64
64
  for line in f:
65
65
  line = line.strip()
66
- if line and not line.startswith('#') and '=' in line:
66
+ if line and not line.startswith("#") and "=" in line:
67
67
  var_count += 1
68
68
 
69
69
  status = "✅ Found"
@@ -81,11 +81,15 @@ def _check_env_files(console: Console) -> None:
81
81
 
82
82
  # Show discovered configuration
83
83
  if env_config:
84
- console.print(f"\n[green]✅ Discovered adapter: {env_config['adapter_type']}[/green]")
85
- config_keys = list(env_config['adapter_config'].keys())
84
+ console.print(
85
+ f"\n[green]✅ Discovered adapter: {env_config['adapter_type']}[/green]"
86
+ )
87
+ config_keys = list(env_config["adapter_config"].keys())
86
88
  console.print(f"[dim]Configuration keys: {config_keys}[/dim]")
87
89
  else:
88
- console.print("\n[yellow]⚠️ No adapter configuration found in .env files[/yellow]")
90
+ console.print(
91
+ "\n[yellow]⚠️ No adapter configuration found in .env files[/yellow]"
92
+ )
89
93
 
90
94
  console.print()
91
95
 
@@ -93,20 +97,20 @@ def _check_env_files(console: Console) -> None:
93
97
  def _check_configuration_files(console: Console) -> None:
94
98
  """Check configuration files."""
95
99
  console.print("[bold]2. Configuration Files[/bold]")
96
-
100
+
97
101
  config_files = [
98
102
  (".env.local", "Local environment file (highest priority)"),
99
103
  (".env", "Environment file"),
100
104
  (".mcp-ticketer/config.json", "Project configuration"),
101
105
  (str(Path.home() / ".mcp-ticketer" / "config.json"), "Global configuration"),
102
106
  ]
103
-
107
+
104
108
  table = Table(show_header=True, header_style="bold magenta")
105
109
  table.add_column("File", style="cyan")
106
110
  table.add_column("Description", style="white")
107
111
  table.add_column("Status", style="green")
108
112
  table.add_column("Size", style="yellow")
109
-
113
+
110
114
  for file_path, description in config_files:
111
115
  path = Path(file_path)
112
116
  if path.exists():
@@ -120,9 +124,9 @@ def _check_configuration_files(console: Console) -> None:
120
124
  else:
121
125
  status = "❌ Missing"
122
126
  size_str = "N/A"
123
-
127
+
124
128
  table.add_row(str(path), description, status, size_str)
125
-
129
+
126
130
  console.print(table)
127
131
  console.print()
128
132
 
@@ -130,35 +134,34 @@ def _check_configuration_files(console: Console) -> None:
130
134
  def _check_adapter_discovery(console: Console) -> None:
131
135
  """Check adapter discovery from configuration."""
132
136
  console.print("[bold]3. Adapter Discovery[/bold]")
133
-
137
+
134
138
  try:
135
139
  # Discover configuration
136
140
  discovered = discover_config(Path.cwd())
137
-
141
+
138
142
  if discovered and discovered.adapters:
139
143
  primary = discovered.get_primary_adapter()
140
-
144
+
141
145
  table = Table(show_header=True, header_style="bold magenta")
142
146
  table.add_column("Adapter", style="cyan")
143
147
  table.add_column("Confidence", style="white")
144
148
  table.add_column("Source", style="green")
145
149
  table.add_column("Status", style="yellow")
146
-
150
+
147
151
  for adapter_info in discovered.adapters:
148
152
  confidence = f"{adapter_info.confidence:.0%}"
149
153
  status = "✅ Primary" if adapter_info == primary else "⚪ Available"
150
-
154
+
151
155
  table.add_row(
152
- adapter_info.adapter_type,
153
- confidence,
154
- adapter_info.found_in,
155
- status
156
+ adapter_info.adapter_type, confidence, adapter_info.found_in, status
156
157
  )
157
-
158
+
158
159
  console.print(table)
159
-
160
+
160
161
  if primary:
161
- console.print(f"\n[green]✅ Primary adapter detected: {primary.adapter_type}[/green]")
162
+ console.print(
163
+ f"\n[green]✅ Primary adapter detected: {primary.adapter_type}[/green]"
164
+ )
162
165
  console.print(f"[dim]Source: {primary.found_in}[/dim]")
163
166
  console.print(f"[dim]Confidence: {primary.confidence:.0%}[/dim]")
164
167
  else:
@@ -166,10 +169,10 @@ def _check_adapter_discovery(console: Console) -> None:
166
169
  else:
167
170
  console.print("[red]❌ No adapters discovered[/red]")
168
171
  console.print("[dim]This usually means no credentials are configured[/dim]")
169
-
172
+
170
173
  except Exception as e:
171
174
  console.print(f"[red]❌ Error during discovery: {e}[/red]")
172
-
175
+
173
176
  console.print()
174
177
 
175
178
 
@@ -179,6 +182,7 @@ def _test_adapter_instantiation(console: Console) -> None:
179
182
 
180
183
  # Determine which adapter to test from .env files
181
184
  from ..mcp.server import _load_env_configuration
185
+
182
186
  env_config = _load_env_configuration()
183
187
 
184
188
  if env_config:
@@ -194,6 +198,7 @@ def _test_adapter_instantiation(console: Console) -> None:
194
198
  adapter_type = primary.adapter_type
195
199
  # Build config from discovery
196
200
  from ..mcp.server import _build_adapter_config_from_env_vars
201
+
197
202
  config = _build_adapter_config_from_env_vars(adapter_type, {})
198
203
  else:
199
204
  adapter_type = "aitrackdown"
@@ -212,16 +217,20 @@ def _test_adapter_instantiation(console: Console) -> None:
212
217
  # Try to instantiate adapter
213
218
  adapter = AdapterRegistry.get_adapter(adapter_type, config)
214
219
 
215
- console.print(f"[green]✅ Adapter instantiated successfully: {adapter.__class__.__name__}[/green]")
220
+ console.print(
221
+ f"[green]✅ Adapter instantiated successfully: {adapter.__class__.__name__}[/green]"
222
+ )
216
223
 
217
224
  # Test basic functionality
218
- if hasattr(adapter, 'validate_credentials'):
225
+ if hasattr(adapter, "validate_credentials"):
219
226
  try:
220
227
  is_valid, error_msg = adapter.validate_credentials()
221
228
  if is_valid:
222
229
  console.print("[green]✅ Credentials validation passed[/green]")
223
230
  else:
224
- console.print(f"[red]❌ Credentials validation failed: {error_msg}[/red]")
231
+ console.print(
232
+ f"[red]❌ Credentials validation failed: {error_msg}[/red]"
233
+ )
225
234
  except Exception as e:
226
235
  console.print(f"[yellow]⚠️ Credentials validation error: {e}[/yellow]")
227
236
 
@@ -230,16 +239,24 @@ def _test_adapter_instantiation(console: Console) -> None:
230
239
 
231
240
  # Provide specific guidance based on adapter type
232
241
  if adapter_type == "linear":
233
- console.print("\n[yellow]Linear adapter requires in .env/.env.local:[/yellow]")
242
+ console.print(
243
+ "\n[yellow]Linear adapter requires in .env/.env.local:[/yellow]"
244
+ )
234
245
  console.print("• LINEAR_API_KEY=your_api_key")
235
- console.print("• LINEAR_TEAM_ID=your_team_id (or LINEAR_TEAM_KEY=your_team_key)")
246
+ console.print(
247
+ "• LINEAR_TEAM_ID=your_team_id (or LINEAR_TEAM_KEY=your_team_key)"
248
+ )
236
249
  elif adapter_type == "github":
237
- console.print("\n[yellow]GitHub adapter requires in .env/.env.local:[/yellow]")
250
+ console.print(
251
+ "\n[yellow]GitHub adapter requires in .env/.env.local:[/yellow]"
252
+ )
238
253
  console.print("• GITHUB_TOKEN=your_token")
239
254
  console.print("• GITHUB_OWNER=your_username")
240
255
  console.print("• GITHUB_REPO=your_repository")
241
256
  elif adapter_type == "jira":
242
- console.print("\n[yellow]JIRA adapter requires in .env/.env.local:[/yellow]")
257
+ console.print(
258
+ "\n[yellow]JIRA adapter requires in .env/.env.local:[/yellow]"
259
+ )
243
260
  console.print("• JIRA_SERVER=your_server_url")
244
261
  console.print("• JIRA_EMAIL=your_email")
245
262
  console.print("• JIRA_API_TOKEN=your_token")
@@ -253,6 +270,7 @@ def _provide_recommendations(console: Console) -> None:
253
270
 
254
271
  # Check .env configuration
255
272
  from ..mcp.server import _load_env_configuration
273
+
256
274
  env_config = _load_env_configuration()
257
275
 
258
276
  recommendations = []
@@ -273,7 +291,9 @@ def _provide_recommendations(console: Console) -> None:
273
291
  if not config.get("api_key"):
274
292
  recommendations.append("Add LINEAR_API_KEY to .env file")
275
293
  if not config.get("team_id") and not config.get("team_key"):
276
- recommendations.append("Add LINEAR_TEAM_ID or LINEAR_TEAM_KEY to .env file")
294
+ recommendations.append(
295
+ "Add LINEAR_TEAM_ID or LINEAR_TEAM_KEY to .env file"
296
+ )
277
297
 
278
298
  elif adapter_type == "github":
279
299
  missing = []
@@ -284,7 +304,9 @@ def _provide_recommendations(console: Console) -> None:
284
304
  if not config.get("repo"):
285
305
  missing.append("GITHUB_REPO")
286
306
  if missing:
287
- recommendations.append(f"Add missing GitHub variables to .env: {', '.join(missing)}")
307
+ recommendations.append(
308
+ f"Add missing GitHub variables to .env: {', '.join(missing)}"
309
+ )
288
310
 
289
311
  elif adapter_type == "jira":
290
312
  missing = []
@@ -295,7 +317,9 @@ def _provide_recommendations(console: Console) -> None:
295
317
  if not config.get("api_token"):
296
318
  missing.append("JIRA_API_TOKEN")
297
319
  if missing:
298
- recommendations.append(f"Add missing JIRA variables to .env: {', '.join(missing)}")
320
+ recommendations.append(
321
+ f"Add missing JIRA variables to .env: {', '.join(missing)}"
322
+ )
299
323
 
300
324
  if recommendations:
301
325
  for i, rec in enumerate(recommendations, 1):
@@ -305,8 +329,12 @@ def _provide_recommendations(console: Console) -> None:
305
329
 
306
330
  # Show .env file examples
307
331
  console.print("\n[bold].env File Examples:[/bold]")
308
- console.print("• Linear: [cyan]echo 'MCP_TICKETER_ADAPTER=linear\\nLINEAR_API_KEY=your_key\\nLINEAR_TEAM_ID=your_team' > .env.local[/cyan]")
309
- console.print("• GitHub: [cyan]echo 'MCP_TICKETER_ADAPTER=github\\nGITHUB_TOKEN=your_token\\nGITHUB_OWNER=user\\nGITHUB_REPO=repo' > .env.local[/cyan]")
332
+ console.print(
333
+ "• Linear: [cyan]echo 'MCP_TICKETER_ADAPTER=linear\\nLINEAR_API_KEY=your_key\\nLINEAR_TEAM_ID=your_team' > .env.local[/cyan]"
334
+ )
335
+ console.print(
336
+ "• GitHub: [cyan]echo 'MCP_TICKETER_ADAPTER=github\\nGITHUB_TOKEN=your_token\\nGITHUB_OWNER=user\\nGITHUB_REPO=repo' > .env.local[/cyan]"
337
+ )
310
338
 
311
339
  console.print("\n[bold]Quick Setup Commands:[/bold]")
312
340
  console.print("• For Linear: [cyan]mcp-ticketer init linear[/cyan]")
@@ -316,7 +344,9 @@ def _provide_recommendations(console: Console) -> None:
316
344
 
317
345
  console.print("\n[bold]Test Configuration:[/bold]")
318
346
  console.print("• Run diagnostics: [cyan]mcp-ticketer diagnose[/cyan]")
319
- console.print("• Test ticket creation: [cyan]mcp-ticketer create 'Test ticket'[/cyan]")
347
+ console.print(
348
+ "• Test ticket creation: [cyan]mcp-ticketer create 'Test ticket'[/cyan]"
349
+ )
320
350
  console.print("• List tickets: [cyan]mcp-ticketer list[/cyan]")
321
351
 
322
352
 
@@ -325,18 +355,20 @@ def get_adapter_status() -> Dict[str, Any]:
325
355
 
326
356
  Returns:
327
357
  Dictionary with adapter status information
358
+
328
359
  """
329
360
  status = {
330
361
  "adapter_type": None,
331
362
  "configuration_source": None,
332
363
  "credentials_valid": False,
333
364
  "error_message": None,
334
- "recommendations": []
365
+ "recommendations": [],
335
366
  }
336
367
 
337
368
  try:
338
369
  # Check .env files first
339
370
  from ..mcp.server import _load_env_configuration
371
+
340
372
  env_config = _load_env_configuration()
341
373
 
342
374
  if env_config:
@@ -353,6 +385,7 @@ def get_adapter_status() -> Dict[str, Any]:
353
385
  status["configuration_source"] = primary.found_in
354
386
  # Build basic config
355
387
  from ..mcp.server import _build_adapter_config_from_env_vars
388
+
356
389
  config = _build_adapter_config_from_env_vars(adapter_type, {})
357
390
  else:
358
391
  adapter_type = "aitrackdown"
@@ -369,7 +402,7 @@ def get_adapter_status() -> Dict[str, Any]:
369
402
  adapter = AdapterRegistry.get_adapter(adapter_type, config)
370
403
 
371
404
  # Test credentials if possible
372
- if hasattr(adapter, 'validate_credentials'):
405
+ if hasattr(adapter, "validate_credentials"):
373
406
  is_valid, error_msg = adapter.validate_credentials()
374
407
  status["credentials_valid"] = is_valid
375
408
  if not is_valid:
@@ -379,6 +412,8 @@ def get_adapter_status() -> Dict[str, Any]:
379
412
 
380
413
  except Exception as e:
381
414
  status["error_message"] = str(e)
382
- status["recommendations"].append("Check .env file configuration and credentials")
415
+ status["recommendations"].append(
416
+ "Check .env file configuration and credentials"
417
+ )
383
418
 
384
419
  return status