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.
- {mcp_ticketer-0.4.8/src/mcp_ticketer.egg-info → mcp_ticketer-0.4.9}/PKG-INFO +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/pyproject.toml +2 -2
- mcp_ticketer-0.4.9/src/mcp_ticketer/__init__.py +27 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/__version__.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/aitrackdown.py +10 -3
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/github.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/jira.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/adapter.py +129 -10
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/client.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/mappers.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/adapter_diagnostics.py +2 -4
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/auggie_configure.py +9 -4
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/codex_configure.py +9 -5
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/configure.py +9 -3
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/discover.py +6 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/gemini_configure.py +8 -4
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/main.py +23 -4
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/mcp_configure.py +7 -7
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/__init__.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/main.py +34 -14
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/server_sdk.py +2 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/__init__.py +9 -7
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/attachment_tools.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/bulk_tools.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/comment_tools.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/hierarchy_tools.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/pr_tools.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/search_tools.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/tools/ticket_tools.py +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9/src/mcp_ticketer.egg-info}/PKG-INFO +1 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/SOURCES.txt +2 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_client.py +5 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_mappers.py +7 -3
- mcp_ticketer-0.4.9/tests/adapters/linear/test_project_resolution.py +295 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_queries.py +24 -8
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_types.py +11 -9
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_aitrackdown.py +8 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_github.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_jira_direct.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_linear_config.py +1 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_linear_native.py +2 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/cli/test_python_detection.py +5 -3
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/conftest.py +8 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_env_discovery.py +6 -3
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_unified_env_loading.py +5 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_complete_ticket_workflow.py +8 -2
- mcp_ticketer-0.4.9/tests/e2e/test_mcp_jsonrpc.py +548 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_all_adapters.py +9 -4
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_commenting_functionality.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_comprehensive.py +8 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_hierarchy_and_workflow.py +8 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_api_usage.py +1 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_codex_config.py +2 -1
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_models.py +8 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_cache_memory.py +6 -2
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_core_exceptions.py +14 -6
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_core_models.py +9 -2
- mcp_ticketer-0.4.8/src/mcp_ticketer/__init__.py +0 -18
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175430.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175768.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175888.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042175987.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042176075.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/comments/comment-20251024141042176163.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/tickets/task-20251024141042175062.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.aitrackdown-test/tickets/task-20251024141042175285.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.claude.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.coveragerc +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.cursor/mcp.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.env.example +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.github/workflows/docs.yml +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.github/workflows/publish.yml +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.github/workflows/test.yml +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.mcp/config.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.pre-commit-config.yaml +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.python-version +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/.readthedocs.yaml +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CHANGELOG.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CLAUDE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CLI_RESTRUCTURE_REPORT.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/CLI_RESTRUCTURE_TEST_REPORT.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/LICENSE +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/MANIFEST.in +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/Makefile +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/PATH_TRAVERSAL_SECURITY_TEST_REPORT.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/README.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/SECURITY_RESCAN_REPORT.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/VERIFICATION_v0.4.3.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/debug_epic_creation.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/debug_full_flow.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/debug_worker_epic.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/ADAPTERS.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/AI_CLIENT_INTEGRATION.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/API_REFERENCE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/ATTACHMENTS.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/CONFIGURATION.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/CONFIG_RESOLUTION_FLOW.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/DEVELOPER_GUIDE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/ENV_DISCOVERY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/MCP_INTEGRATION.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/MIGRATION_GUIDE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/PROJECT_CONFIG.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/PR_INTEGRATION.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/QUEUE_SYSTEM.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/QUICK_START.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/QUICK_START_ENV.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/README.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/USER_GUIDE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/VERSIONING_AND_BUILD_TRACKING.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_archive/README.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/ADAPTERS.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/API_REFERENCE.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/CONFIGURATION.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/DEVELOPER_GUIDE.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/MCP_INTEGRATION.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/MIGRATION_GUIDE.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/USER_GUIDE.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/adapters/github.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/adapters.rst.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/api.rst.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/cli.rst.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/development.rst.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/examples.rst.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/index.rst.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/installation.rst.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/_build/_sources/prd/mcp-ticketer-prd.md.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/adapters/github.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/adapters.rst +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/api.rst +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/changelogs/CHANGELOG_v0.2.0.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/changelogs/CHANGELOG_v0.3.0.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/changelogs/CHANGELOG_v0.3.1.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/cli.rst +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/conf.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/CODE_STRUCTURE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/CONTRIBUTING.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/RELEASE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development/RELEASING.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/development.rst +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/examples.rst +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/guides/BULLETPROOF_TICKET_CREATION_GUIDE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/index.rst +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/installation.rst +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/prd/mcp-ticketer-prd.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_GUIDE_v0.2.0.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.2.0.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.0.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.1.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.4.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/PUBLICATION_SUCCESS_v0.3.5.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/RELEASE_v0.1.39_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/releases/RELEASE_v0.2.0_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/CONFIG_RESOLUTION_FIX.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/CREDENTIAL_VALIDATION_FIX.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/DIAGNOSTICS_FEATURE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/ENV_DISCOVERY_COMPLETE.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/FIX_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/HIERARCHY_IMPLEMENTATION_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/IMPLEMENTATION_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/MCP_CONFIGURATION_TEST_REPORT.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/OPTIMIZATION_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/PROJECT_INITIALIZATION_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/TEST_COVERAGE_REPORT.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/TEST_REPORT.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/TEST_RESULTS_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/reports/VERIFICATION_RESULTS.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/requirements.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/CLAUDE_DESKTOP_SETUP.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/CODEX_INTEGRATION.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/JIRA_SETUP.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/setup/LINEAR_SETUP.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/AUTO_DISCOVERY_BUG_FIX_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/BULLETPROOF_IMPROVEMENTS_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/COMMAND_SYNONYMS_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/COMPREHENSIVE_TESTING_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/INTERACTIVE_CLI_SETUP_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/LINEAR_ADAPTER_INITIALIZATION_BUG_FIX.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/MODULE_REFACTORING_ANALYSIS.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/MODULE_REFACTORING_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/PROJECT_CLEANUP_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/docs/summaries/REFACTORED_ENV_SOLUTION_SUMMARY.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/mcp-ticketer +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/mcp-ticketer-server +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/pytest.ini +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/requirements-dev.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/requirements.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/README.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/install.sh +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/manage_version.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/mcp_server.sh +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/scripts/test_set_command.sh +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/setup.cfg +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/setup.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/hybrid.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/queries.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear/types.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/adapters/linear.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cache/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cache/memory.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/diagnostics.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/linear_commands.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/migrate_config.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/platform_commands.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/python_detection.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/queue_commands.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/simple_health.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/ticket_commands.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/cli/utils.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/adapter.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/config.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/env_discovery.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/env_loader.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/exceptions.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/http_client.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/mappers.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/models.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/project_config.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/core/registry.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/__main__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/__main__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/constants.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/dto.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/mcp/server/response_builder.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/py.typed +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/__main__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/health_monitor.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/manager.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/queue.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/run_worker.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/ticket_registry.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer/queue/worker.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/dependency_links.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/entry_points.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/not-zip-safe +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/requires.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/src/mcp_ticketer.egg-info/top_level.txt +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/test-tickets/tickets/task-20250924002724.json +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/test_linear_fixes.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/test_worker_persistence.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/README.md +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_adapter.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/linear/test_adapter_validation.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_aitrackdown_security.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_github_token.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_jira.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_jira_projects.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/adapters/test_linear.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/debug_credential_validation.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_actual_worker_execution.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_config_resolution.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_environment_handoff.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_queue_processing.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/core/test_queue_system.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_adapter_cache.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_cli_config.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_cli_vs_simulation.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_linear_teams.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_search.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_test.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_worker_adapter.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_worker_simulation.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/debug/debug_worker_subprocess.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_comments_and_attachments.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_complete_workflow.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_hierarchy_validation.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/e2e/test_state_transitions.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_aitrackdown_commenting.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_jira_github_adapters.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_mcp_server_qa.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_pr_functionality.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_serve_config.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/integration/test_user_assignment.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/performance/test_optimizations.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/performance/test_performance.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/run_comprehensive_tests.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_base_adapter.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_basic.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_comprehensive_qa.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_error_handling.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_linear_teams.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/test_queue.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/__init__.py +0 -0
- {mcp_ticketer-0.4.8 → mcp_ticketer-0.4.9}/tests/unit/test_core_registry.py +0 -0
- {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.
|
|
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 = "
|
|
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
|
+
]
|
|
@@ -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
|
|
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
|
|
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 (
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
from .
|
|
31
|
-
|
|
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 (
|
|
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
|
|
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
|
|
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
|
|
138
|
-
args = ["
|
|
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":
|
|
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:
|
|
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
|
|
140
|
-
args = ["
|
|
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":
|
|
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:
|
|
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 (
|
|
12
|
-
|
|
13
|
-
|
|
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 (
|
|
10
|
-
|
|
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
|
|
140
|
-
args = ["
|
|
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":
|
|
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:
|
|
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
|
|
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
|
-
#
|
|
165
|
-
|
|
166
|
-
|
|
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
|
|
169
|
-
args = ["
|
|
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":
|
|
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:
|
|
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
|
|
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
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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
|
|
18
|
-
from
|
|
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")
|