mcp-ticketer 0.4.8__tar.gz → 0.4.9__tar.gz

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 (292) hide show
  1. {mcp_ticketer-0.4.8/src/mcp_ticketer.egg-info → mcp_ticketer-0.4.9}/PKG-INFO +1 -1
  2. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/pyproject.toml +2 -2
  3. mcp_ticketer-0.4.9/src/mcp_ticketer/__init__.py +27 -0
  4. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/__version__.py +1 -1
  5. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/aitrackdown.py +10 -3
  6. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/github.py +1 -2
  7. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/jira.py +1 -2
  8. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/adapter.py +129 -10
  9. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/client.py +1 -2
  10. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/mappers.py +1 -2
  11. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/adapter_diagnostics.py +2 -4
  12. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/auggie_configure.py +9 -4
  13. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/codex_configure.py +9 -5
  14. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/configure.py +9 -3
  15. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/discover.py +6 -2
  16. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/gemini_configure.py +8 -4
  17. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/main.py +23 -4
  18. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/mcp_configure.py +7 -7
  19. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/__init__.py +1 -2
  20. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/main.py +34 -14
  21. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/server_sdk.py +2 -2
  22. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/__init__.py +9 -7
  23. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/attachment_tools.py +1 -1
  24. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/bulk_tools.py +1 -1
  25. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/comment_tools.py +1 -1
  26. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/hierarchy_tools.py +1 -1
  27. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/pr_tools.py +1 -1
  28. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/search_tools.py +1 -1
  29. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/ticket_tools.py +1 -1
  30. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9/src/mcp_ticketer.egg-info}/PKG-INFO +1 -1
  31. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/SOURCES.txt +2 -0
  32. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_client.py +5 -2
  33. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_mappers.py +7 -3
  34. mcp_ticketer-0.4.9/tests/adapters/linear/test_project_resolution.py +295 -0
  35. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_queries.py +24 -8
  36. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_types.py +11 -9
  37. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_aitrackdown.py +8 -2
  38. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_github.py +1 -2
  39. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_jira_direct.py +1 -2
  40. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_linear_config.py +1 -0
  41. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_linear_native.py +2 -2
  42. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/cli/test_python_detection.py +5 -3
  43. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/conftest.py +8 -2
  44. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_env_discovery.py +6 -3
  45. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_unified_env_loading.py +5 -2
  46. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_complete_ticket_workflow.py +8 -2
  47. mcp_ticketer-0.4.9/tests/e2e/test_mcp_jsonrpc.py +548 -0
  48. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_all_adapters.py +9 -4
  49. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_commenting_functionality.py +1 -2
  50. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_comprehensive.py +8 -2
  51. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_hierarchy_and_workflow.py +8 -2
  52. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_api_usage.py +1 -2
  53. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_codex_config.py +2 -1
  54. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_models.py +8 -2
  55. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_cache_memory.py +6 -2
  56. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_core_exceptions.py +14 -6
  57. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_core_models.py +9 -2
  58. mcp_ticketer-0.4.8/src/mcp_ticketer/__init__.py +0 -18
  59. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175430.json +0 -0
  60. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175768.json +0 -0
  61. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175888.json +0 -0
  62. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175987.json +0 -0
  63. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042176075.json +0 -0
  64. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042176163.json +0 -0
  65. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/tickets/task-20251024141042175062.json +0 -0
  66. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/tickets/task-20251024141042175285.json +0 -0
  67. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.claude.json +0 -0
  68. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.coveragerc +0 -0
  69. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.cursor/mcp.json +0 -0
  70. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.env.example +0 -0
  71. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.github/workflows/docs.yml +0 -0
  72. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.github/workflows/publish.yml +0 -0
  73. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.github/workflows/test.yml +0 -0
  74. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.mcp/config.json +0 -0
  75. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.pre-commit-config.yaml +0 -0
  76. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.python-version +0 -0
  77. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.readthedocs.yaml +0 -0
  78. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CHANGELOG.md +0 -0
  79. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CLAUDE.md +0 -0
  80. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CLI_RESTRUCTURE_REPORT.md +0 -0
  81. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CLI_RESTRUCTURE_TEST_REPORT.md +0 -0
  82. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/LICENSE +0 -0
  83. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/MANIFEST.in +0 -0
  84. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/Makefile +0 -0
  85. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/PATH_TRAVERSAL_SECURITY_TEST_REPORT.md +0 -0
  86. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/README.md +0 -0
  87. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/SECURITY_RESCAN_REPORT.md +0 -0
  88. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/VERIFICATION_v0.4.3.md +0 -0
  89. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/debug_epic_creation.py +0 -0
  90. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/debug_full_flow.py +0 -0
  91. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/debug_worker_epic.py +0 -0
  92. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/ADAPTERS.md +0 -0
  93. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/AI_CLIENT_INTEGRATION.md +0 -0
  94. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/API_REFERENCE.md +0 -0
  95. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/ATTACHMENTS.md +0 -0
  96. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/CONFIGURATION.md +0 -0
  97. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/CONFIG_RESOLUTION_FLOW.md +0 -0
  98. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/DEVELOPER_GUIDE.md +0 -0
  99. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/ENV_DISCOVERY.md +0 -0
  100. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/MCP_INTEGRATION.md +0 -0
  101. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/MIGRATION_GUIDE.md +0 -0
  102. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/PROJECT_CONFIG.md +0 -0
  103. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/PR_INTEGRATION.md +0 -0
  104. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/QUEUE_SYSTEM.md +0 -0
  105. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/QUICK_START.md +0 -0
  106. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/QUICK_START_ENV.md +0 -0
  107. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/README.md +0 -0
  108. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/USER_GUIDE.md +0 -0
  109. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/VERSIONING_AND_BUILD_TRACKING.md +0 -0
  110. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_archive/README.md +0 -0
  111. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/ADAPTERS.md.txt +0 -0
  112. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/API_REFERENCE.md.txt +0 -0
  113. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/CONFIGURATION.md.txt +0 -0
  114. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/DEVELOPER_GUIDE.md.txt +0 -0
  115. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/MCP_INTEGRATION.md.txt +0 -0
  116. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/MIGRATION_GUIDE.md.txt +0 -0
  117. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/USER_GUIDE.md.txt +0 -0
  118. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/adapters/github.md.txt +0 -0
  119. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/adapters.rst.txt +0 -0
  120. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/api.rst.txt +0 -0
  121. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/cli.rst.txt +0 -0
  122. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/development.rst.txt +0 -0
  123. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/examples.rst.txt +0 -0
  124. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/index.rst.txt +0 -0
  125. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/installation.rst.txt +0 -0
  126. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/prd/mcp-ticketer-prd.md.txt +0 -0
  127. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/adapters/github.md +0 -0
  128. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/adapters.rst +0 -0
  129. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/api.rst +0 -0
  130. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/changelogs/CHANGELOG_v0.2.0.md +0 -0
  131. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/changelogs/CHANGELOG_v0.3.0.md +0 -0
  132. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/changelogs/CHANGELOG_v0.3.1.md +0 -0
  133. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/cli.rst +0 -0
  134. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/conf.py +0 -0
  135. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/CODE_STRUCTURE.md +0 -0
  136. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/CONTRIBUTING.md +0 -0
  137. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/RELEASE.md +0 -0
  138. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/RELEASING.md +0 -0
  139. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development.rst +0 -0
  140. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/examples.rst +0 -0
  141. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/guides/BULLETPROOF_TICKET_CREATION_GUIDE.md +0 -0
  142. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/index.rst +0 -0
  143. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/installation.rst +0 -0
  144. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/prd/mcp-ticketer-prd.md +0 -0
  145. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_GUIDE_v0.2.0.md +0 -0
  146. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.2.0.md +0 -0
  147. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.0.md +0 -0
  148. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.1.md +0 -0
  149. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.4.md +0 -0
  150. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.5.md +0 -0
  151. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/RELEASE_v0.1.39_SUMMARY.md +0 -0
  152. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/RELEASE_v0.2.0_SUMMARY.md +0 -0
  153. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/CONFIG_RESOLUTION_FIX.md +0 -0
  154. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/CREDENTIAL_VALIDATION_FIX.md +0 -0
  155. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/DIAGNOSTICS_FEATURE.md +0 -0
  156. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/ENV_DISCOVERY_COMPLETE.md +0 -0
  157. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/FIX_SUMMARY.md +0 -0
  158. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/HIERARCHY_IMPLEMENTATION_SUMMARY.md +0 -0
  159. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/IMPLEMENTATION_SUMMARY.md +0 -0
  160. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/MCP_CONFIGURATION_TEST_REPORT.md +0 -0
  161. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/OPTIMIZATION_SUMMARY.md +0 -0
  162. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/PROJECT_INITIALIZATION_SUMMARY.md +0 -0
  163. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/TEST_COVERAGE_REPORT.md +0 -0
  164. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/TEST_REPORT.md +0 -0
  165. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/TEST_RESULTS_SUMMARY.md +0 -0
  166. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/VERIFICATION_RESULTS.md +0 -0
  167. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/requirements.txt +0 -0
  168. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/CLAUDE_DESKTOP_SETUP.md +0 -0
  169. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/CODEX_INTEGRATION.md +0 -0
  170. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/JIRA_SETUP.md +0 -0
  171. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/LINEAR_SETUP.md +0 -0
  172. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/AUTO_DISCOVERY_BUG_FIX_SUMMARY.md +0 -0
  173. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/BULLETPROOF_IMPROVEMENTS_SUMMARY.md +0 -0
  174. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/COMMAND_SYNONYMS_SUMMARY.md +0 -0
  175. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/COMPREHENSIVE_TESTING_SUMMARY.md +0 -0
  176. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/INTERACTIVE_CLI_SETUP_SUMMARY.md +0 -0
  177. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/LINEAR_ADAPTER_INITIALIZATION_BUG_FIX.md +0 -0
  178. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/MODULE_REFACTORING_ANALYSIS.md +0 -0
  179. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/MODULE_REFACTORING_SUMMARY.md +0 -0
  180. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/PROJECT_CLEANUP_SUMMARY.md +0 -0
  181. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/REFACTORED_ENV_SOLUTION_SUMMARY.md +0 -0
  182. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/mcp-ticketer +0 -0
  183. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/mcp-ticketer-server +0 -0
  184. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/pytest.ini +0 -0
  185. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/requirements-dev.txt +0 -0
  186. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/requirements.txt +0 -0
  187. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/README.md +0 -0
  188. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/install.sh +0 -0
  189. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/manage_version.py +0 -0
  190. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/mcp_server.sh +0 -0
  191. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/test_set_command.sh +0 -0
  192. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/setup.cfg +0 -0
  193. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/setup.py +0 -0
  194. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/__init__.py +0 -0
  195. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/hybrid.py +0 -0
  196. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/__init__.py +0 -0
  197. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/queries.py +0 -0
  198. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/types.py +0 -0
  199. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear.py +0 -0
  200. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cache/__init__.py +0 -0
  201. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cache/memory.py +0 -0
  202. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/__init__.py +0 -0
  203. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/diagnostics.py +0 -0
  204. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/linear_commands.py +0 -0
  205. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/migrate_config.py +0 -0
  206. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/platform_commands.py +0 -0
  207. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/python_detection.py +0 -0
  208. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/queue_commands.py +0 -0
  209. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/simple_health.py +0 -0
  210. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/ticket_commands.py +0 -0
  211. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/utils.py +0 -0
  212. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/adapter.py +0 -0
  213. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/config.py +0 -0
  214. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/env_discovery.py +0 -0
  215. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/env_loader.py +0 -0
  216. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/exceptions.py +0 -0
  217. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/http_client.py +0 -0
  218. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/mappers.py +0 -0
  219. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/models.py +0 -0
  220. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/project_config.py +0 -0
  221. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/registry.py +0 -0
  222. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/__init__.py +0 -0
  223. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/__main__.py +0 -0
  224. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/__init__.py +0 -0
  225. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/__main__.py +0 -0
  226. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/constants.py +0 -0
  227. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/dto.py +0 -0
  228. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/response_builder.py +0 -0
  229. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/py.typed +0 -0
  230. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/__init__.py +0 -0
  231. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/__main__.py +0 -0
  232. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/health_monitor.py +0 -0
  233. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/manager.py +0 -0
  234. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/queue.py +0 -0
  235. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/run_worker.py +0 -0
  236. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/ticket_registry.py +0 -0
  237. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/worker.py +0 -0
  238. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/dependency_links.txt +0 -0
  239. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/entry_points.txt +0 -0
  240. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/not-zip-safe +0 -0
  241. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/requires.txt +0 -0
  242. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/top_level.txt +0 -0
  243. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/test-tickets/tickets/task-20250924002724.json +0 -0
  244. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/test_linear_fixes.py +0 -0
  245. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/test_worker_persistence.py +0 -0
  246. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/README.md +0 -0
  247. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/__init__.py +0 -0
  248. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/__init__.py +0 -0
  249. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_adapter.py +0 -0
  250. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_adapter_validation.py +0 -0
  251. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_aitrackdown_security.py +0 -0
  252. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_github_token.py +0 -0
  253. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_jira.py +0 -0
  254. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_jira_projects.py +0 -0
  255. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_linear.py +0 -0
  256. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/debug_credential_validation.py +0 -0
  257. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_actual_worker_execution.py +0 -0
  258. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_config_resolution.py +0 -0
  259. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_environment_handoff.py +0 -0
  260. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_queue_processing.py +0 -0
  261. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_queue_system.py +0 -0
  262. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_adapter_cache.py +0 -0
  263. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_cli_config.py +0 -0
  264. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_cli_vs_simulation.py +0 -0
  265. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_linear_teams.py +0 -0
  266. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_search.py +0 -0
  267. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_test.py +0 -0
  268. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_worker_adapter.py +0 -0
  269. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_worker_simulation.py +0 -0
  270. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_worker_subprocess.py +0 -0
  271. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_comments_and_attachments.py +0 -0
  272. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_complete_workflow.py +0 -0
  273. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_hierarchy_validation.py +0 -0
  274. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_state_transitions.py +0 -0
  275. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_aitrackdown_commenting.py +0 -0
  276. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_jira_github_adapters.py +0 -0
  277. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_mcp_server_qa.py +0 -0
  278. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_pr_functionality.py +0 -0
  279. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_serve_config.py +0 -0
  280. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_user_assignment.py +0 -0
  281. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/performance/test_optimizations.py +0 -0
  282. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/performance/test_performance.py +0 -0
  283. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/run_comprehensive_tests.py +0 -0
  284. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_base_adapter.py +0 -0
  285. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_basic.py +0 -0
  286. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_comprehensive_qa.py +0 -0
  287. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_error_handling.py +0 -0
  288. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_linear_teams.py +0 -0
  289. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_queue.py +0 -0
  290. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/__init__.py +0 -0
  291. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_core_registry.py +0 -0
  292. {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mcp-ticketer
3
- Version: 0.4.8
3
+ Version: 0.4.9
4
4
  Summary: Universal ticket management interface for AI agents with MCP support
5
5
  Author-email: MCP Ticketer Team <support@mcp-ticketer.io>
6
6
  Maintainer-email: MCP Ticketer Team <support@mcp-ticketer.io>
@@ -152,7 +152,7 @@ extend-exclude = '''
152
152
  '''
153
153
 
154
154
  [tool.ruff]
155
- target-version = "0.4.8"
155
+ target-version = "py310"
156
156
  line-length = 88
157
157
 
158
158
  [tool.ruff.lint]
@@ -180,7 +180,7 @@ ignore = [
180
180
  ]
181
181
 
182
182
  [tool.ruff.lint.per-file-ignores]
183
- "tests/*" = ["S", "D", "T"]
183
+ "tests/*" = ["S", "D", "T", "E402"] # Allow imports after sys.path modifications in tests
184
184
  "**/__init__.py" = ["D", "F401"]
185
185
 
186
186
  [tool.mypy]
@@ -0,0 +1,27 @@
1
+ """MCP Ticketer - Universal ticket management interface."""
2
+
3
+ from .__version__ import (
4
+ __author__,
5
+ __author_email__,
6
+ __copyright__,
7
+ __description__,
8
+ __license__,
9
+ __title__,
10
+ __version__,
11
+ __version_info__,
12
+ get_user_agent,
13
+ get_version,
14
+ )
15
+
16
+ __all__ = [
17
+ "__version__",
18
+ "__version_info__",
19
+ "__title__",
20
+ "__description__",
21
+ "__author__",
22
+ "__author_email__",
23
+ "__license__",
24
+ "__copyright__",
25
+ "get_version",
26
+ "get_user_agent",
27
+ ]
@@ -1,6 +1,6 @@
1
1
  """Version information for mcp-ticketer package."""
2
2
 
3
- __version__ = "0.4.8"
3
+ __version__ = "0.4.9"
4
4
  __version_info__ = tuple(int(part) for part in __version__.split("."))
5
5
 
6
6
  # Package metadata
@@ -8,11 +8,18 @@ from pathlib import Path
8
8
  from typing import Any
9
9
 
10
10
  from ..core.adapter import BaseAdapter
11
+ from ..core.models import (
12
+ Attachment,
13
+ Comment,
14
+ Epic,
15
+ Priority,
16
+ SearchQuery,
17
+ Task,
18
+ TicketState,
19
+ )
20
+ from ..core.registry import AdapterRegistry
11
21
 
12
22
  logger = logging.getLogger(__name__)
13
- from ..core.models import (Attachment, Comment, Epic, Priority, SearchQuery,
14
- Task, TicketState)
15
- from ..core.registry import AdapterRegistry
16
23
 
17
24
  # Import ai-trackdown-pytools when available
18
25
  try:
@@ -9,8 +9,7 @@ import httpx
9
9
 
10
10
  from ..core.adapter import BaseAdapter
11
11
  from ..core.env_loader import load_adapter_config, validate_adapter_config
12
- from ..core.models import (Comment, Epic, Priority, SearchQuery, Task,
13
- TicketState)
12
+ from ..core.models import Comment, Epic, Priority, SearchQuery, Task, TicketState
14
13
  from ..core.registry import AdapterRegistry
15
14
 
16
15
 
@@ -13,8 +13,7 @@ from httpx import AsyncClient, HTTPStatusError, TimeoutException
13
13
 
14
14
  from ..core.adapter import BaseAdapter
15
15
  from ..core.env_loader import load_adapter_config, validate_adapter_config
16
- from ..core.models import (Comment, Epic, Priority, SearchQuery, Task,
17
- TicketState)
16
+ from ..core.models import Comment, Epic, Priority, SearchQuery, Task, TicketState
18
17
  from ..core.registry import AdapterRegistry
19
18
 
20
19
  logger = logging.getLogger(__name__)
@@ -20,15 +20,27 @@ from ...core.adapter import BaseAdapter
20
20
  from ...core.models import Comment, Epic, SearchQuery, Task, TicketState
21
21
  from ...core.registry import AdapterRegistry
22
22
  from .client import LinearGraphQLClient
23
- from .mappers import (build_linear_issue_input,
24
- build_linear_issue_update_input,
25
- map_linear_comment_to_comment, map_linear_issue_to_task,
26
- map_linear_project_to_epic)
27
- from .queries import (ALL_FRAGMENTS, CREATE_ISSUE_MUTATION, LIST_ISSUES_QUERY,
28
- SEARCH_ISSUES_QUERY, UPDATE_ISSUE_MUTATION,
29
- WORKFLOW_STATES_QUERY)
30
- from .types import (LinearStateMapping, build_issue_filter,
31
- get_linear_priority, get_linear_state_type)
23
+ from .mappers import (
24
+ build_linear_issue_input,
25
+ build_linear_issue_update_input,
26
+ map_linear_comment_to_comment,
27
+ map_linear_issue_to_task,
28
+ map_linear_project_to_epic,
29
+ )
30
+ from .queries import (
31
+ ALL_FRAGMENTS,
32
+ CREATE_ISSUE_MUTATION,
33
+ LIST_ISSUES_QUERY,
34
+ SEARCH_ISSUES_QUERY,
35
+ UPDATE_ISSUE_MUTATION,
36
+ WORKFLOW_STATES_QUERY,
37
+ )
38
+ from .types import (
39
+ LinearStateMapping,
40
+ build_issue_filter,
41
+ get_linear_priority,
42
+ get_linear_state_type,
43
+ )
32
44
 
33
45
 
34
46
  class LinearAdapter(BaseAdapter[Task]):
@@ -91,7 +103,10 @@ class LinearAdapter(BaseAdapter[Task]):
91
103
  # Remove environment variable name prefix (e.g., "LINEAR_API_KEY=")
92
104
  if "=" in self.api_key:
93
105
  parts = self.api_key.split("=", 1)
94
- if len(parts) == 2 and parts[0].upper() in ("LINEAR_API_KEY", "API_KEY"):
106
+ if len(parts) == 2 and parts[0].upper() in (
107
+ "LINEAR_API_KEY",
108
+ "API_KEY",
109
+ ):
95
110
  self.api_key = parts[1]
96
111
 
97
112
  # Validate API key format (Linear keys start with "lin_api_")
@@ -197,6 +212,96 @@ class LinearAdapter(BaseAdapter[Task]):
197
212
  except Exception as e:
198
213
  raise ValueError(f"Failed to resolve team '{self.team_key}': {e}")
199
214
 
215
+ async def _resolve_project_id(self, project_identifier: str) -> str | None:
216
+ """Resolve project identifier (slug, name, short ID, or URL) to full UUID.
217
+
218
+ Args:
219
+ project_identifier: Project slug, name, short ID, or URL
220
+
221
+ Returns:
222
+ Full Linear project UUID, or None if not found
223
+
224
+ Raises:
225
+ ValueError: If project lookup fails
226
+
227
+ Examples:
228
+ - "crm-smart-monitoring-system" (slug)
229
+ - "CRM Smart Monitoring System" (name)
230
+ - "f59a41a96c52" (short ID from URL)
231
+ - "https://linear.app/travel-bta/project/crm-smart-monitoring-system-f59a41a96c52/overview" (full URL)
232
+
233
+ """
234
+ if not project_identifier:
235
+ return None
236
+
237
+ # Extract slug/ID from URL if full URL provided
238
+ if project_identifier.startswith("http"):
239
+ # Extract slug-shortid from URL like:
240
+ # https://linear.app/travel-bta/project/crm-smart-monitoring-system-f59a41a96c52/overview
241
+ parts = project_identifier.split("/project/")
242
+ if len(parts) > 1:
243
+ slug_with_id = parts[1].split("/")[
244
+ 0
245
+ ] # Get "crm-smart-monitoring-system-f59a41a96c52"
246
+ project_identifier = slug_with_id
247
+ else:
248
+ raise ValueError(f"Invalid Linear project URL: {project_identifier}")
249
+
250
+ # If it looks like a full UUID already (exactly 36 chars with exactly 4 dashes), return it
251
+ # UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
252
+ if len(project_identifier) == 36 and project_identifier.count("-") == 4:
253
+ return project_identifier
254
+
255
+ # Query all projects and search for matching slug, name, or slugId
256
+ query = """
257
+ query GetProjects {
258
+ projects(first: 100) {
259
+ nodes {
260
+ id
261
+ name
262
+ slugId
263
+ }
264
+ }
265
+ }
266
+ """
267
+
268
+ try:
269
+ result = await self.client.execute_query(query, {})
270
+ projects = result.get("projects", {}).get("nodes", [])
271
+
272
+ # Search for match by slug, slugId, name (case-insensitive)
273
+ project_lower = project_identifier.lower()
274
+ for project in projects:
275
+ # Check if identifier matches slug pattern (extracted from slugId)
276
+ slug_id = project.get("slugId", "")
277
+ if slug_id:
278
+ # slugId format: "crm-smart-monitoring-system-f59a41a96c52"
279
+ # Extract both the slug part and short ID
280
+ if "-" in slug_id:
281
+ parts = slug_id.rsplit(
282
+ "-", 1
283
+ ) # Split from right to get last part
284
+ slug_part = parts[0] # "crm-smart-monitoring-system"
285
+ short_id = parts[1] if len(parts) > 1 else "" # "f59a41a96c52"
286
+
287
+ # Match full slugId, slug part, or short ID
288
+ if (
289
+ slug_id.lower() == project_lower
290
+ or slug_part.lower() == project_lower
291
+ or short_id.lower() == project_lower
292
+ ):
293
+ return project["id"]
294
+
295
+ # Also check exact name match (case-insensitive)
296
+ if project["name"].lower() == project_lower:
297
+ return project["id"]
298
+
299
+ # No match found
300
+ return None
301
+
302
+ except Exception as e:
303
+ raise ValueError(f"Failed to resolve project '{project_identifier}': {e}")
304
+
200
305
  async def _load_workflow_states(self, team_id: str) -> None:
201
306
  """Load and cache workflow states for the team.
202
307
 
@@ -446,6 +551,20 @@ class LinearAdapter(BaseAdapter[Task]):
446
551
  # Remove labelIds if no labels resolved
447
552
  issue_input.pop("labelIds", None)
448
553
 
554
+ # Resolve project ID if parent_epic is provided (supports slug, name, short ID, or URL)
555
+ if task.parent_epic:
556
+ project_id = await self._resolve_project_id(task.parent_epic)
557
+ if project_id:
558
+ issue_input["projectId"] = project_id
559
+ else:
560
+ # Log warning but don't fail - user may have provided invalid project
561
+ logging.getLogger(__name__).warning(
562
+ f"Could not resolve project identifier '{task.parent_epic}' to UUID. "
563
+ "Issue will be created without project assignment."
564
+ )
565
+ # Remove projectId if we couldn't resolve it
566
+ issue_input.pop("projectId", None)
567
+
449
568
  try:
450
569
  result = await self.client.execute_mutation(
451
570
  CREATE_ISSUE_MUTATION, {"input": issue_input}
@@ -16,8 +16,7 @@ except ImportError:
16
16
  HTTPXAsyncTransport = None
17
17
  TransportError = Exception
18
18
 
19
- from ...core.exceptions import (AdapterError, AuthenticationError,
20
- RateLimitError)
19
+ from ...core.exceptions import AdapterError, AuthenticationError, RateLimitError
21
20
 
22
21
 
23
22
  class LinearGraphQLClient:
@@ -6,8 +6,7 @@ from datetime import datetime
6
6
  from typing import Any
7
7
 
8
8
  from ...core.models import Comment, Epic, Priority, Task, TicketState
9
- from .types import (extract_linear_metadata, get_universal_priority,
10
- get_universal_state)
9
+ from .types import extract_linear_metadata, get_universal_priority, get_universal_state
11
10
 
12
11
 
13
12
  def map_linear_issue_to_task(issue_data: dict[str, Any]) -> Task:
@@ -197,8 +197,7 @@ def _test_adapter_instantiation(console: Console) -> None:
197
197
  if primary:
198
198
  adapter_type = primary.adapter_type
199
199
  # Build config from discovery
200
- from ..mcp.server import \
201
- _build_adapter_config_from_env_vars
200
+ from ..mcp.server import _build_adapter_config_from_env_vars
202
201
 
203
202
  config = _build_adapter_config_from_env_vars(adapter_type, {})
204
203
  else:
@@ -385,8 +384,7 @@ def get_adapter_status() -> dict[str, Any]:
385
384
  adapter_type = primary.adapter_type
386
385
  status["configuration_source"] = primary.found_in
387
386
  # Build basic config
388
- from ..mcp.server import \
389
- _build_adapter_config_from_env_vars
387
+ from ..mcp.server import _build_adapter_config_from_env_vars
390
388
 
391
389
  config = _build_adapter_config_from_env_vars(adapter_type, {})
392
390
  else:
@@ -85,6 +85,11 @@ def create_auggie_server_config(
85
85
  Auggie MCP server configuration dict
86
86
 
87
87
  """
88
+ # Get mcp-ticketer CLI command from same directory as Python
89
+ from pathlib import Path
90
+
91
+ python_dir = Path(python_path).parent
92
+ mcp_ticketer_cmd = str(python_dir / "mcp-ticketer")
88
93
  # Get adapter configuration
89
94
  adapter = project_config.get("default_adapter", "aitrackdown")
90
95
  adapters_config = project_config.get("adapters", {})
@@ -134,14 +139,14 @@ def create_auggie_server_config(
134
139
  if "project_key" in adapter_config:
135
140
  env_vars["JIRA_PROJECT_KEY"] = adapter_config["project_key"]
136
141
 
137
- # Use module invocation pattern: python -m mcp_ticketer.mcp.server
138
- args = ["-m", "mcp_ticketer.mcp.server"]
142
+ # Use CLI command: mcp-ticketer mcp
143
+ args = ["mcp"]
139
144
  if project_path:
140
145
  args.append(project_path)
141
146
 
142
147
  # Create server configuration (simpler than Gemini - no timeout/trust)
143
148
  config = {
144
- "command": python_path,
149
+ "command": mcp_ticketer_cmd,
145
150
  "args": args,
146
151
  "env": env_vars,
147
152
  }
@@ -298,7 +303,7 @@ def configure_auggie_mcp(force: bool = False) -> None:
298
303
  console.print(" Server name: mcp-ticketer")
299
304
  console.print(f" Adapter: {adapter}")
300
305
  console.print(f" Python: {python_path}")
301
- console.print(" Command: python -m mcp_ticketer.mcp.server")
306
+ console.print(" Command: mcp-ticketer mcp")
302
307
  console.print(" Scope: Global (affects all projects)")
303
308
  console.print(f" Project path: {project_path}")
304
309
  if "env" in server_config:
@@ -4,11 +4,11 @@ Codex CLI only supports global configuration at ~/.codex/config.toml.
4
4
  Unlike Claude Code and Gemini CLI, there is no project-level configuration support.
5
5
  """
6
6
 
7
- import tomllib
8
7
  from pathlib import Path
9
8
  from typing import Any
10
9
 
11
10
  import tomli_w
11
+ import tomllib
12
12
  from rich.console import Console
13
13
 
14
14
  from .mcp_configure import load_project_config
@@ -87,6 +87,10 @@ def create_codex_server_config(
87
87
  Codex MCP server configuration dict
88
88
 
89
89
  """
90
+ # Get mcp-ticketer CLI command from same directory as Python
91
+ python_dir = Path(python_path).parent
92
+ mcp_ticketer_cmd = str(python_dir / "mcp-ticketer")
93
+
90
94
  # Get adapter configuration
91
95
  adapter = project_config.get("default_adapter", "aitrackdown")
92
96
  adapters_config = project_config.get("adapters", {})
@@ -136,14 +140,14 @@ def create_codex_server_config(
136
140
  if "project_key" in adapter_config:
137
141
  env_vars["JIRA_PROJECT_KEY"] = adapter_config["project_key"]
138
142
 
139
- # Use module invocation pattern: python -m mcp_ticketer.mcp.server
140
- args = ["-m", "mcp_ticketer.mcp.server"]
143
+ # Use CLI command: mcp-ticketer mcp
144
+ args = ["mcp"]
141
145
  if project_path:
142
146
  args.append(project_path)
143
147
 
144
148
  # Create server configuration with Codex-specific structure
145
149
  config: dict[str, Any] = {
146
- "command": python_path,
150
+ "command": mcp_ticketer_cmd,
147
151
  "args": args,
148
152
  "env": env_vars,
149
153
  }
@@ -307,7 +311,7 @@ def configure_codex_mcp(force: bool = False) -> None:
307
311
  console.print(" Server name: mcp-ticketer")
308
312
  console.print(f" Adapter: {adapter}")
309
313
  console.print(f" Python: {python_path}")
310
- console.print(" Command: python -m mcp_ticketer.mcp.server")
314
+ console.print(" Command: mcp-ticketer mcp")
311
315
  console.print(" Scope: global (Codex only supports global config)")
312
316
  console.print(f" Project path: {project_path}")
313
317
  if "env" in server_config:
@@ -8,9 +8,15 @@ from rich.panel import Panel
8
8
  from rich.prompt import Confirm, Prompt
9
9
  from rich.table import Table
10
10
 
11
- from ..core.project_config import (AdapterConfig, AdapterType, ConfigResolver,
12
- ConfigValidator, HybridConfig, SyncStrategy,
13
- TicketerConfig)
11
+ from ..core.project_config import (
12
+ AdapterConfig,
13
+ AdapterType,
14
+ ConfigResolver,
15
+ ConfigValidator,
16
+ HybridConfig,
17
+ SyncStrategy,
18
+ TicketerConfig,
19
+ )
14
20
 
15
21
  console = Console()
16
22
 
@@ -6,8 +6,12 @@ import typer
6
6
  from rich.console import Console
7
7
 
8
8
  from ..core.env_discovery import DiscoveredAdapter, EnvDiscovery
9
- from ..core.project_config import (AdapterConfig, ConfigResolver,
10
- ConfigValidator, TicketerConfig)
9
+ from ..core.project_config import (
10
+ AdapterConfig,
11
+ ConfigResolver,
12
+ ConfigValidator,
13
+ TicketerConfig,
14
+ )
11
15
 
12
16
  console = Console()
13
17
  app = typer.Typer(help="Auto-discover configuration from .env files")
@@ -87,6 +87,10 @@ def create_gemini_server_config(
87
87
  Gemini MCP server configuration dict
88
88
 
89
89
  """
90
+ # Get mcp-ticketer CLI command from same directory as Python
91
+ python_dir = Path(python_path).parent
92
+ mcp_ticketer_cmd = str(python_dir / "mcp-ticketer")
93
+
90
94
  # Get adapter configuration
91
95
  adapter = project_config.get("default_adapter", "aitrackdown")
92
96
  adapters_config = project_config.get("adapters", {})
@@ -136,14 +140,14 @@ def create_gemini_server_config(
136
140
  if "project_key" in adapter_config:
137
141
  env_vars["JIRA_PROJECT_KEY"] = adapter_config["project_key"]
138
142
 
139
- # Use module invocation pattern: python -m mcp_ticketer.mcp.server
140
- args = ["-m", "mcp_ticketer.mcp.server"]
143
+ # Use CLI command: mcp-ticketer mcp
144
+ args = ["mcp"]
141
145
  if project_path:
142
146
  args.append(project_path)
143
147
 
144
148
  # Create server configuration with Gemini-specific options
145
149
  config = {
146
- "command": python_path,
150
+ "command": mcp_ticketer_cmd,
147
151
  "args": args,
148
152
  "env": env_vars,
149
153
  "timeout": 15000, # 15 seconds timeout
@@ -300,7 +304,7 @@ def configure_gemini_mcp(
300
304
  console.print(" Server name: mcp-ticketer")
301
305
  console.print(f" Adapter: {adapter}")
302
306
  console.print(f" Python: {python_path}")
303
- console.print(" Command: python -m mcp_ticketer.mcp.server")
307
+ console.print(" Command: mcp-ticketer mcp")
304
308
  console.print(f" Timeout: {server_config['timeout']}ms")
305
309
  console.print(f" Trust: {server_config['trust']}")
306
310
  if project_path:
@@ -20,8 +20,7 @@ from ..core.models import Comment, SearchQuery
20
20
  from ..queue import Queue, QueueStatus, WorkerManager
21
21
  from ..queue.health_monitor import HealthStatus, QueueHealthMonitor
22
22
  from ..queue.ticket_registry import TicketRegistry
23
- from .configure import (configure_wizard, set_adapter_config,
24
- show_current_config)
23
+ from .configure import configure_wizard, set_adapter_config, show_current_config
25
24
  from .diagnostics import run_diagnostics
26
25
  from .discover import app as discover_app
27
26
  from .migrate_config import migrate_config_command
@@ -1869,9 +1868,29 @@ mcp_app = typer.Typer(
1869
1868
  name="mcp",
1870
1869
  help="Configure MCP integration for AI clients (Claude, Gemini, Codex, Auggie)",
1871
1870
  add_completion=False,
1871
+ invoke_without_command=True,
1872
1872
  )
1873
1873
 
1874
1874
 
1875
+ @mcp_app.callback()
1876
+ def mcp_callback(
1877
+ ctx: typer.Context,
1878
+ project_path: str | None = typer.Argument(
1879
+ None, help="Project directory path (optional - uses cwd if not provided)"
1880
+ ),
1881
+ ):
1882
+ """MCP command group - runs MCP server if no subcommand provided."""
1883
+ if ctx.invoked_subcommand is None:
1884
+ # No subcommand provided, run the serve command
1885
+ # Change to project directory if provided
1886
+ if project_path:
1887
+ import os
1888
+
1889
+ os.chdir(project_path)
1890
+ # Invoke the serve command through context
1891
+ ctx.invoke(mcp_serve, adapter=None, base_path=None)
1892
+
1893
+
1875
1894
  @app.command()
1876
1895
  def install(
1877
1896
  platform: str | None = typer.Argument(
@@ -2211,8 +2230,8 @@ def mcp_serve(
2211
2230
  2. Global: ~/.mcp-ticketer/config.json
2212
2231
  3. Default: aitrackdown adapter with .aitrackdown base path
2213
2232
  """
2214
- from ..mcp.server_sdk import configure_adapter
2215
- from ..mcp.server_sdk import main as sdk_main
2233
+ from ..mcp.server.server_sdk import configure_adapter
2234
+ from ..mcp.server.server_sdk import main as sdk_main
2216
2235
 
2217
2236
  # Load configuration (respects project-specific config in cwd)
2218
2237
  config = load_config()
@@ -161,12 +161,12 @@ def create_mcp_server_config(
161
161
  MCP server configuration dict matching Claude Code stdio pattern
162
162
 
163
163
  """
164
- # Ensure python3 is used (not python)
165
- if python_path.endswith("/python"):
166
- python_path = python_path.replace("/python", "/python3")
164
+ # Get mcp-ticketer CLI command from same directory as Python
165
+ python_dir = Path(python_path).parent
166
+ mcp_ticketer_cmd = str(python_dir / "mcp-ticketer")
167
167
 
168
- # Use module invocation pattern: python -m mcp_ticketer.mcp.server
169
- args = ["-m", "mcp_ticketer.mcp.server"]
168
+ # Use CLI command: mcp-ticketer mcp
169
+ args = ["mcp"]
170
170
 
171
171
  # Add project path if provided
172
172
  if project_path:
@@ -175,7 +175,7 @@ def create_mcp_server_config(
175
175
  # REQUIRED: Add "type": "stdio" for Claude Code compatibility
176
176
  config = {
177
177
  "type": "stdio",
178
- "command": python_path,
178
+ "command": mcp_ticketer_cmd,
179
179
  "args": args,
180
180
  }
181
181
 
@@ -385,7 +385,7 @@ def configure_claude_mcp(global_config: bool = False, force: bool = False) -> No
385
385
  console.print(" Server name: mcp-ticketer")
386
386
  console.print(f" Adapter: {adapter}")
387
387
  console.print(f" Python: {python_path}")
388
- console.print(" Command: python -m mcp_ticketer.mcp.server")
388
+ console.print(" Command: mcp-ticketer mcp")
389
389
  if project_path:
390
390
  console.print(f" Project path: {project_path}")
391
391
  if "env" in server_config:
@@ -1,8 +1,7 @@
1
1
  """Core models and abstractions for MCP Ticketer."""
2
2
 
3
3
  from .adapter import BaseAdapter
4
- from .models import (Attachment, Comment, Epic, Priority, Task, TicketState,
5
- TicketType)
4
+ from .models import Attachment, Comment, Epic, Priority, Task, TicketState, TicketType
6
5
  from .registry import AdapterRegistry
7
6
 
8
7
  __all__ = [
@@ -12,20 +12,40 @@ from dotenv import load_dotenv
12
12
  import mcp_ticketer.adapters # noqa: F401
13
13
 
14
14
  from ...core import AdapterRegistry
15
- from ...core.models import (Comment, Epic, Priority, SearchQuery, Task,
16
- TicketState)
17
- from .constants import (DEFAULT_BASE_PATH, DEFAULT_LIMIT, DEFAULT_MAX_DEPTH,
18
- DEFAULT_OFFSET, ERROR_INTERNAL, ERROR_METHOD_NOT_FOUND,
19
- ERROR_PARSE, JSONRPC_VERSION, MCP_PROTOCOL_VERSION,
20
- MSG_EPIC_NOT_FOUND, MSG_INTERNAL_ERROR,
21
- MSG_MISSING_TICKET_ID, MSG_MISSING_TITLE,
22
- MSG_NO_TICKETS_PROVIDED, MSG_NO_UPDATES_PROVIDED,
23
- MSG_TICKET_NOT_FOUND, MSG_TRANSITION_FAILED,
24
- MSG_UNKNOWN_METHOD, MSG_UNKNOWN_OPERATION,
25
- MSG_UPDATE_FAILED, SERVER_NAME, SERVER_VERSION,
26
- STATUS_COMPLETED, STATUS_ERROR)
27
- from .dto import (CreateEpicRequest, CreateIssueRequest, CreateTaskRequest,
28
- CreateTicketRequest, ReadTicketRequest)
15
+ from ...core.models import Comment, Epic, Priority, SearchQuery, Task, TicketState
16
+ from .constants import (
17
+ DEFAULT_BASE_PATH,
18
+ DEFAULT_LIMIT,
19
+ DEFAULT_MAX_DEPTH,
20
+ DEFAULT_OFFSET,
21
+ ERROR_INTERNAL,
22
+ ERROR_METHOD_NOT_FOUND,
23
+ ERROR_PARSE,
24
+ JSONRPC_VERSION,
25
+ MCP_PROTOCOL_VERSION,
26
+ MSG_EPIC_NOT_FOUND,
27
+ MSG_INTERNAL_ERROR,
28
+ MSG_MISSING_TICKET_ID,
29
+ MSG_MISSING_TITLE,
30
+ MSG_NO_TICKETS_PROVIDED,
31
+ MSG_NO_UPDATES_PROVIDED,
32
+ MSG_TICKET_NOT_FOUND,
33
+ MSG_TRANSITION_FAILED,
34
+ MSG_UNKNOWN_METHOD,
35
+ MSG_UNKNOWN_OPERATION,
36
+ MSG_UPDATE_FAILED,
37
+ SERVER_NAME,
38
+ SERVER_VERSION,
39
+ STATUS_COMPLETED,
40
+ STATUS_ERROR,
41
+ )
42
+ from .dto import (
43
+ CreateEpicRequest,
44
+ CreateIssueRequest,
45
+ CreateTaskRequest,
46
+ CreateTicketRequest,
47
+ ReadTicketRequest,
48
+ )
29
49
  from .response_builder import ResponseBuilder
30
50
 
31
51
  # Load environment variables early (prioritize .env.local)
@@ -14,8 +14,8 @@ from typing import Any
14
14
 
15
15
  from mcp.server.fastmcp import FastMCP
16
16
 
17
- from ..core.adapter import BaseAdapter
18
- from ..core.registry import AdapterRegistry
17
+ from ...core.adapter import BaseAdapter
18
+ from ...core.registry import AdapterRegistry
19
19
 
20
20
  # Initialize FastMCP server
21
21
  mcp = FastMCP("mcp-ticketer")