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.

Files changed (111) hide show
  1. mcp_ticketer/__init__.py +10 -10
  2. mcp_ticketer/__version__.py +3 -3
  3. mcp_ticketer/adapters/__init__.py +2 -0
  4. mcp_ticketer/adapters/aitrackdown.py +394 -9
  5. mcp_ticketer/adapters/asana/__init__.py +15 -0
  6. mcp_ticketer/adapters/asana/adapter.py +1416 -0
  7. mcp_ticketer/adapters/asana/client.py +292 -0
  8. mcp_ticketer/adapters/asana/mappers.py +348 -0
  9. mcp_ticketer/adapters/asana/types.py +146 -0
  10. mcp_ticketer/adapters/github.py +836 -105
  11. mcp_ticketer/adapters/hybrid.py +47 -5
  12. mcp_ticketer/adapters/jira.py +772 -1
  13. mcp_ticketer/adapters/linear/adapter.py +2293 -108
  14. mcp_ticketer/adapters/linear/client.py +146 -12
  15. mcp_ticketer/adapters/linear/mappers.py +105 -11
  16. mcp_ticketer/adapters/linear/queries.py +168 -1
  17. mcp_ticketer/adapters/linear/types.py +80 -4
  18. mcp_ticketer/analysis/__init__.py +56 -0
  19. mcp_ticketer/analysis/dependency_graph.py +255 -0
  20. mcp_ticketer/analysis/health_assessment.py +304 -0
  21. mcp_ticketer/analysis/orphaned.py +218 -0
  22. mcp_ticketer/analysis/project_status.py +594 -0
  23. mcp_ticketer/analysis/similarity.py +224 -0
  24. mcp_ticketer/analysis/staleness.py +266 -0
  25. mcp_ticketer/automation/__init__.py +11 -0
  26. mcp_ticketer/automation/project_updates.py +378 -0
  27. mcp_ticketer/cache/memory.py +3 -3
  28. mcp_ticketer/cli/adapter_diagnostics.py +4 -2
  29. mcp_ticketer/cli/auggie_configure.py +18 -6
  30. mcp_ticketer/cli/codex_configure.py +175 -60
  31. mcp_ticketer/cli/configure.py +884 -146
  32. mcp_ticketer/cli/cursor_configure.py +314 -0
  33. mcp_ticketer/cli/diagnostics.py +31 -28
  34. mcp_ticketer/cli/discover.py +293 -21
  35. mcp_ticketer/cli/gemini_configure.py +18 -6
  36. mcp_ticketer/cli/init_command.py +880 -0
  37. mcp_ticketer/cli/instruction_commands.py +435 -0
  38. mcp_ticketer/cli/linear_commands.py +99 -15
  39. mcp_ticketer/cli/main.py +109 -2055
  40. mcp_ticketer/cli/mcp_configure.py +673 -99
  41. mcp_ticketer/cli/mcp_server_commands.py +415 -0
  42. mcp_ticketer/cli/migrate_config.py +12 -8
  43. mcp_ticketer/cli/platform_commands.py +6 -6
  44. mcp_ticketer/cli/platform_detection.py +477 -0
  45. mcp_ticketer/cli/platform_installer.py +536 -0
  46. mcp_ticketer/cli/project_update_commands.py +350 -0
  47. mcp_ticketer/cli/queue_commands.py +15 -15
  48. mcp_ticketer/cli/setup_command.py +639 -0
  49. mcp_ticketer/cli/simple_health.py +13 -11
  50. mcp_ticketer/cli/ticket_commands.py +277 -36
  51. mcp_ticketer/cli/update_checker.py +313 -0
  52. mcp_ticketer/cli/utils.py +45 -41
  53. mcp_ticketer/core/__init__.py +35 -1
  54. mcp_ticketer/core/adapter.py +170 -5
  55. mcp_ticketer/core/config.py +38 -31
  56. mcp_ticketer/core/env_discovery.py +33 -3
  57. mcp_ticketer/core/env_loader.py +7 -6
  58. mcp_ticketer/core/exceptions.py +10 -4
  59. mcp_ticketer/core/http_client.py +10 -10
  60. mcp_ticketer/core/instructions.py +405 -0
  61. mcp_ticketer/core/label_manager.py +732 -0
  62. mcp_ticketer/core/mappers.py +32 -20
  63. mcp_ticketer/core/models.py +136 -1
  64. mcp_ticketer/core/onepassword_secrets.py +379 -0
  65. mcp_ticketer/core/priority_matcher.py +463 -0
  66. mcp_ticketer/core/project_config.py +148 -14
  67. mcp_ticketer/core/registry.py +1 -1
  68. mcp_ticketer/core/session_state.py +171 -0
  69. mcp_ticketer/core/state_matcher.py +592 -0
  70. mcp_ticketer/core/url_parser.py +425 -0
  71. mcp_ticketer/core/validators.py +69 -0
  72. mcp_ticketer/defaults/ticket_instructions.md +644 -0
  73. mcp_ticketer/mcp/__init__.py +2 -2
  74. mcp_ticketer/mcp/server/__init__.py +2 -2
  75. mcp_ticketer/mcp/server/diagnostic_helper.py +175 -0
  76. mcp_ticketer/mcp/server/main.py +187 -93
  77. mcp_ticketer/mcp/server/routing.py +655 -0
  78. mcp_ticketer/mcp/server/server_sdk.py +58 -0
  79. mcp_ticketer/mcp/server/tools/__init__.py +37 -9
  80. mcp_ticketer/mcp/server/tools/analysis_tools.py +854 -0
  81. mcp_ticketer/mcp/server/tools/attachment_tools.py +65 -20
  82. mcp_ticketer/mcp/server/tools/bulk_tools.py +259 -202
  83. mcp_ticketer/mcp/server/tools/comment_tools.py +74 -12
  84. mcp_ticketer/mcp/server/tools/config_tools.py +1429 -0
  85. mcp_ticketer/mcp/server/tools/diagnostic_tools.py +211 -0
  86. mcp_ticketer/mcp/server/tools/hierarchy_tools.py +878 -319
  87. mcp_ticketer/mcp/server/tools/instruction_tools.py +295 -0
  88. mcp_ticketer/mcp/server/tools/label_tools.py +942 -0
  89. mcp_ticketer/mcp/server/tools/pr_tools.py +3 -7
  90. mcp_ticketer/mcp/server/tools/project_status_tools.py +158 -0
  91. mcp_ticketer/mcp/server/tools/project_update_tools.py +473 -0
  92. mcp_ticketer/mcp/server/tools/search_tools.py +180 -97
  93. mcp_ticketer/mcp/server/tools/session_tools.py +308 -0
  94. mcp_ticketer/mcp/server/tools/ticket_tools.py +1182 -82
  95. mcp_ticketer/mcp/server/tools/user_ticket_tools.py +364 -0
  96. mcp_ticketer/queue/health_monitor.py +1 -0
  97. mcp_ticketer/queue/manager.py +4 -4
  98. mcp_ticketer/queue/queue.py +3 -3
  99. mcp_ticketer/queue/run_worker.py +1 -1
  100. mcp_ticketer/queue/ticket_registry.py +2 -2
  101. mcp_ticketer/queue/worker.py +15 -13
  102. mcp_ticketer/utils/__init__.py +5 -0
  103. mcp_ticketer/utils/token_utils.py +246 -0
  104. mcp_ticketer-2.0.1.dist-info/METADATA +1366 -0
  105. mcp_ticketer-2.0.1.dist-info/RECORD +122 -0
  106. mcp_ticketer-0.4.11.dist-info/METADATA +0 -496
  107. mcp_ticketer-0.4.11.dist-info/RECORD +0 -77
  108. {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/WHEEL +0 -0
  109. {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/entry_points.txt +0 -0
  110. {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/licenses/LICENSE +0 -0
  111. {mcp_ticketer-0.4.11.dist-info → mcp_ticketer-2.0.1.dist-info}/top_level.txt +0 -0
@@ -73,6 +73,9 @@ class HybridAdapter(BaseAdapter):
73
73
 
74
74
  def _get_state_mapping(self) -> dict[TicketState, str]:
75
75
  """Get state mapping from primary adapter."""
76
+ # Type narrowing: primary_adapter_name is validated in __init__
77
+ if self.primary_adapter_name is None:
78
+ raise ValueError("Primary adapter name is not set")
76
79
  primary = self.adapters[self.primary_adapter_name]
77
80
  return primary._get_state_mapping()
78
81
 
@@ -163,8 +166,11 @@ class HybridAdapter(BaseAdapter):
163
166
  Created ticket with universal ID
164
167
 
165
168
  """
169
+ if self.primary_adapter_name is None:
170
+ raise ValueError("Primary adapter name is not set")
171
+
166
172
  universal_id = self._generate_universal_id()
167
- results = []
173
+ results: list[tuple[str, Task | Epic]] = []
168
174
 
169
175
  # Create in primary adapter first
170
176
  primary = self.adapters[self.primary_adapter_name]
@@ -236,6 +242,9 @@ class HybridAdapter(BaseAdapter):
236
242
  Ticket if found, None otherwise
237
243
 
238
244
  """
245
+ if self.primary_adapter_name is None:
246
+ raise ValueError("Primary adapter name is not set")
247
+
239
248
  # Check if this is a universal ID
240
249
  if ticket_id.startswith("hybrid-"):
241
250
  # Get primary adapter ticket ID
@@ -266,7 +275,10 @@ class HybridAdapter(BaseAdapter):
266
275
  Updated ticket from primary adapter
267
276
 
268
277
  """
269
- universal_id = ticket_id
278
+ if self.primary_adapter_name is None:
279
+ raise ValueError("Primary adapter name is not set")
280
+
281
+ universal_id: str | None = ticket_id
270
282
  if not ticket_id.startswith("hybrid-"):
271
283
  # Try to find universal ID by searching mapping
272
284
  universal_id = self._find_universal_id(ticket_id)
@@ -279,6 +291,9 @@ class HybridAdapter(BaseAdapter):
279
291
  # Update in all adapters
280
292
  results = []
281
293
  for adapter_name, adapter in self.adapters.items():
294
+ if universal_id is None:
295
+ logger.warning(f"No universal ID available for ticket: {ticket_id}")
296
+ continue
282
297
  adapter_ticket_id = self._get_adapter_ticket_id(universal_id, adapter_name)
283
298
  if not adapter_ticket_id:
284
299
  logger.warning(f"No ticket ID for adapter {adapter_name}")
@@ -325,7 +340,10 @@ class HybridAdapter(BaseAdapter):
325
340
  True if deleted from at least one adapter
326
341
 
327
342
  """
328
- universal_id = ticket_id
343
+ if self.primary_adapter_name is None:
344
+ raise ValueError("Primary adapter name is not set")
345
+
346
+ universal_id: str | None = ticket_id
329
347
  if not ticket_id.startswith("hybrid-"):
330
348
  universal_id = self._find_universal_id(ticket_id)
331
349
  if not universal_id:
@@ -336,6 +354,9 @@ class HybridAdapter(BaseAdapter):
336
354
  # Delete from all adapters
337
355
  success_count = 0
338
356
  for adapter_name, adapter in self.adapters.items():
357
+ if universal_id is None:
358
+ logger.warning(f"No universal ID available for ticket: {ticket_id}")
359
+ continue
339
360
  adapter_ticket_id = self._get_adapter_ticket_id(universal_id, adapter_name)
340
361
  if not adapter_ticket_id:
341
362
  continue
@@ -372,6 +393,8 @@ class HybridAdapter(BaseAdapter):
372
393
  List of tickets from primary adapter
373
394
 
374
395
  """
396
+ if self.primary_adapter_name is None:
397
+ raise ValueError("Primary adapter name is not set")
375
398
  primary = self.adapters[self.primary_adapter_name]
376
399
  return await primary.list(limit, offset, filters)
377
400
 
@@ -385,6 +408,8 @@ class HybridAdapter(BaseAdapter):
385
408
  List of tickets matching search criteria
386
409
 
387
410
  """
411
+ if self.primary_adapter_name is None:
412
+ raise ValueError("Primary adapter name is not set")
388
413
  primary = self.adapters[self.primary_adapter_name]
389
414
  return await primary.search(query)
390
415
 
@@ -401,7 +426,10 @@ class HybridAdapter(BaseAdapter):
401
426
  Updated ticket from primary adapter
402
427
 
403
428
  """
404
- universal_id = ticket_id
429
+ if self.primary_adapter_name is None:
430
+ raise ValueError("Primary adapter name is not set")
431
+
432
+ universal_id: str | None = ticket_id
405
433
  if not ticket_id.startswith("hybrid-"):
406
434
  universal_id = self._find_universal_id(ticket_id)
407
435
  if not universal_id:
@@ -412,6 +440,9 @@ class HybridAdapter(BaseAdapter):
412
440
  # Transition in all adapters
413
441
  results = []
414
442
  for adapter_name, adapter in self.adapters.items():
443
+ if universal_id is None:
444
+ logger.warning(f"No universal ID available for ticket: {ticket_id}")
445
+ continue
415
446
  adapter_ticket_id = self._get_adapter_ticket_id(universal_id, adapter_name)
416
447
  if not adapter_ticket_id:
417
448
  continue
@@ -446,7 +477,10 @@ class HybridAdapter(BaseAdapter):
446
477
  Created comment from primary adapter
447
478
 
448
479
  """
449
- universal_id = comment.ticket_id
480
+ if self.primary_adapter_name is None:
481
+ raise ValueError("Primary adapter name is not set")
482
+
483
+ universal_id: str | None = comment.ticket_id
450
484
  if not comment.ticket_id.startswith("hybrid-"):
451
485
  universal_id = self._find_universal_id(comment.ticket_id)
452
486
  if not universal_id:
@@ -457,6 +491,11 @@ class HybridAdapter(BaseAdapter):
457
491
  # Add comment to all adapters
458
492
  results = []
459
493
  for adapter_name, adapter in self.adapters.items():
494
+ if universal_id is None:
495
+ logger.warning(
496
+ f"No universal ID available for ticket: {comment.ticket_id}"
497
+ )
498
+ continue
460
499
  adapter_ticket_id = self._get_adapter_ticket_id(universal_id, adapter_name)
461
500
  if not adapter_ticket_id:
462
501
  continue
@@ -501,6 +540,9 @@ class HybridAdapter(BaseAdapter):
501
540
  List of comments from primary adapter
502
541
 
503
542
  """
543
+ if self.primary_adapter_name is None:
544
+ raise ValueError("Primary adapter name is not set")
545
+
504
546
  if ticket_id.startswith("hybrid-"):
505
547
  # Get primary adapter ticket ID
506
548
  primary_id = self._get_adapter_ticket_id(