sourcecode 1.30.30__tar.gz → 1.31.0__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.
Files changed (231) hide show
  1. sourcecode-1.31.0/.continue-here.md +101 -0
  2. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-37df4554.json → sourcecode-1.31.0/.sourcecode-cache/snapshot-0e430c1-37df4554.json +2 -2
  3. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-e9801942.json → sourcecode-1.31.0/.sourcecode-cache/snapshot-0e430c1-e9801942.json +19 -18
  4. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-ee60e0cd.json → sourcecode-1.31.0/.sourcecode-cache/snapshot-0e430c1-ee60e0cd.json +24 -26
  5. {sourcecode-1.30.30 → sourcecode-1.31.0}/PKG-INFO +6 -3
  6. {sourcecode-1.30.30 → sourcecode-1.31.0}/README.md +2 -2
  7. {sourcecode-1.30.30 → sourcecode-1.31.0}/pyproject.toml +5 -1
  8. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/__init__.py +1 -1
  9. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/cli.py +272 -1
  10. sourcecode-1.31.0/src/sourcecode/mcp/__init__.py +5 -0
  11. sourcecode-1.31.0/src/sourcecode/mcp/onboarding/__init__.py +1 -0
  12. sourcecode-1.31.0/src/sourcecode/mcp/onboarding/applier.py +63 -0
  13. sourcecode-1.31.0/src/sourcecode/mcp/onboarding/backup.py +40 -0
  14. sourcecode-1.31.0/src/sourcecode/mcp/onboarding/detector.py +59 -0
  15. sourcecode-1.31.0/src/sourcecode/mcp/onboarding/planner.py +40 -0
  16. sourcecode-1.31.0/src/sourcecode/mcp/runner.py +40 -0
  17. sourcecode-1.31.0/src/sourcecode/mcp/server.py +147 -0
  18. sourcecode-1.31.0/tests/test_mcp_runner.py +65 -0
  19. sourcecode-1.31.0/tests/test_mcp_serve.py +47 -0
  20. sourcecode-1.31.0/tests/test_mcp_tools.py +242 -0
  21. sourcecode-1.30.30/.continue-here.md +0 -150
  22. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-0911b79e.json +0 -3492
  23. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-624321f3.json +0 -11466
  24. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-776b4676.json +0 -367
  25. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-9770fba7.json +0 -374
  26. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-c4e3c102.json +0 -262
  27. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-e8bc5fb4.json +0 -122
  28. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-ee60e0cd.json +0 -328
  29. sourcecode-1.30.30/.sourcecode-cache/snapshot-85d4217-fdd9d3f7.json +0 -514
  30. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-0911b79e.json +0 -3471
  31. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-37df4554.json +0 -262
  32. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-624321f3.json +0 -11389
  33. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-776b4676.json +0 -367
  34. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-9770fba7.json +0 -374
  35. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-c4e3c102.json +0 -262
  36. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-e8bc5fb4.json +0 -122
  37. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-e9801942.json +0 -218
  38. sourcecode-1.30.30/.sourcecode-cache/snapshot-c6e9d39-fdd9d3f7.json +0 -512
  39. {sourcecode-1.30.30 → sourcecode-1.31.0}/.agents/skills/source-command-gsd-join-discord/SKILL.md +0 -0
  40. {sourcecode-1.30.30 → sourcecode-1.31.0}/.agents/skills/source-command-gsd-review-backlog/SKILL.md +0 -0
  41. {sourcecode-1.30.30 → sourcecode-1.31.0}/.agents/skills/source-command-gsd-workstreams/SKILL.md +0 -0
  42. {sourcecode-1.30.30 → sourcecode-1.31.0}/.github/workflows/build-windows.yml +0 -0
  43. {sourcecode-1.30.30 → sourcecode-1.31.0}/.gitignore +0 -0
  44. {sourcecode-1.30.30 → sourcecode-1.31.0}/.ruff.toml +0 -0
  45. {sourcecode-1.30.30 → sourcecode-1.31.0}/CHANGELOG.md +0 -0
  46. {sourcecode-1.30.30 → sourcecode-1.31.0}/CONTRIBUTING.md +0 -0
  47. {sourcecode-1.30.30 → sourcecode-1.31.0}/LICENSE +0 -0
  48. {sourcecode-1.30.30 → sourcecode-1.31.0}/SECURITY.md +0 -0
  49. {sourcecode-1.30.30 → sourcecode-1.31.0}/docs/privacy.md +0 -0
  50. {sourcecode-1.30.30 → sourcecode-1.31.0}/docs/schema.md +0 -0
  51. {sourcecode-1.30.30 → sourcecode-1.31.0}/raw +0 -0
  52. {sourcecode-1.30.30 → sourcecode-1.31.0}/run_cli.py +0 -0
  53. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/adaptive_scanner.py +0 -0
  54. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/architecture_analyzer.py +0 -0
  55. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/architecture_summary.py +0 -0
  56. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/ast_extractor.py +0 -0
  57. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/classifier.py +0 -0
  58. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/code_notes_analyzer.py +0 -0
  59. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/confidence_analyzer.py +0 -0
  60. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/context_scorer.py +0 -0
  61. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/context_summarizer.py +0 -0
  62. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/contract_model.py +0 -0
  63. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/contract_pipeline.py +0 -0
  64. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/coverage_parser.py +0 -0
  65. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/dependency_analyzer.py +0 -0
  66. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/__init__.py +0 -0
  67. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/base.py +0 -0
  68. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/csproj_parser.py +0 -0
  69. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/dart.py +0 -0
  70. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/dotnet.py +0 -0
  71. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/elixir.py +0 -0
  72. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/go.py +0 -0
  73. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/heuristic.py +0 -0
  74. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/hybrid.py +0 -0
  75. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/java.py +0 -0
  76. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/jvm_ext.py +0 -0
  77. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/nodejs.py +0 -0
  78. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/parsers.py +0 -0
  79. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/php.py +0 -0
  80. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/project.py +0 -0
  81. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/python.py +0 -0
  82. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/ruby.py +0 -0
  83. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/rust.py +0 -0
  84. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/systems.py +0 -0
  85. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/terraform.py +0 -0
  86. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/detectors/tooling.py +0 -0
  87. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/doc_analyzer.py +0 -0
  88. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/entrypoint_classifier.py +0 -0
  89. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/env_analyzer.py +0 -0
  90. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/file_classifier.py +0 -0
  91. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/flow_analyzer.py +0 -0
  92. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/git_analyzer.py +0 -0
  93. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/graph_analyzer.py +0 -0
  94. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/metrics_analyzer.py +0 -0
  95. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/pr_comment_renderer.py +0 -0
  96. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/prepare_context.py +0 -0
  97. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/progress.py +0 -0
  98. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/ranking_engine.py +0 -0
  99. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/redactor.py +0 -0
  100. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/relevance_scorer.py +0 -0
  101. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/repo_classifier.py +0 -0
  102. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/repository_ir.py +0 -0
  103. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/runtime_classifier.py +0 -0
  104. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/scanner.py +0 -0
  105. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/schema.py +0 -0
  106. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/semantic_analyzer.py +0 -0
  107. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/serializer.py +0 -0
  108. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/summarizer.py +0 -0
  109. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/telemetry/__init__.py +0 -0
  110. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/telemetry/config.py +0 -0
  111. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/telemetry/consent.py +0 -0
  112. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/telemetry/events.py +0 -0
  113. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/telemetry/filters.py +0 -0
  114. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/telemetry/transport.py +0 -0
  115. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/tree_utils.py +0 -0
  116. {sourcecode-1.30.30 → sourcecode-1.31.0}/src/sourcecode/workspace.py +0 -0
  117. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/__init__.py +0 -0
  118. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/conftest.py +0 -0
  119. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/coverage.xml +0 -0
  120. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/fastapi_app/pyproject.toml +0 -0
  121. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/fastapi_app/src/main.py +0 -0
  122. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/go_service/cmd/api/main.go +0 -0
  123. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/go_service/go.mod +0 -0
  124. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/jacoco.xml +0 -0
  125. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/latin1_sample.java +0 -0
  126. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/latin1_sample_iso.java +0 -0
  127. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/lcov.info +0 -0
  128. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/nextjs_app/app/page.tsx +0 -0
  129. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/nextjs_app/package.json +0 -0
  130. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/nextjs_app/pnpm-lock.yaml +0 -0
  131. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/pnpm_monorepo/apps/web/app/page.tsx +0 -0
  132. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/pnpm_monorepo/apps/web/package.json +0 -0
  133. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/pnpm_monorepo/packages/api/main.py +0 -0
  134. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/pnpm_monorepo/packages/api/pyproject.toml +0 -0
  135. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/pnpm_monorepo/pnpm-workspace.yaml +0 -0
  136. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/pom.xml +0 -0
  137. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/application/service/FindAusenteService.java +0 -0
  138. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/domain/entities/Ausente.java +0 -0
  139. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/ausente/infrastructure/rest/AusenteRestController.java +0 -0
  140. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/application/service/FindAutocoberturasService.java +0 -0
  141. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/domain/entities/Autocoberturas.java +0 -0
  142. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/autocoberturas/infrastructure/rest/AutocoberturasRestController.java +0 -0
  143. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/application/service/FindCalendarioTrabajadorService.java +0 -0
  144. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/domain/entities/CalendarioTrabajador.java +0 -0
  145. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/calendarioTrabajador/infrastructure/rest/CalendarioTrabajadorRestController.java +0 -0
  146. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/application/service/FindDepartamentoService.java +0 -0
  147. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/domain/entities/Departamento.java +0 -0
  148. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/departamento/infrastructure/rest/DepartamentoRestController.java +0 -0
  149. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/application/service/FindEmpleadoService.java +0 -0
  150. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/domain/entities/Empleado.java +0 -0
  151. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/ddd/empleado/infrastructure/rest/EmpleadoRestController.java +0 -0
  152. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/DemoApplication.java +0 -0
  153. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/config/FilterConfig.java +0 -0
  154. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/domain/Health.java +0 -0
  155. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/mapper/HealthMapper.java +0 -0
  156. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/repository/HealthRepository.java +0 -0
  157. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/service/HealthService.java +0 -0
  158. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/HealthRestController.java +0 -0
  159. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/java/com/example/demo/web/NominaRestController.java +0 -0
  160. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application-dev.yml +0 -0
  161. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/resources/application.yml +0 -0
  162. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/fixtures/spring_boot_minimal/src/main/resources/mapper/HealthMapper.xml +0 -0
  163. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_architecture_analyzer.py +0 -0
  164. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_architecture_summary.py +0 -0
  165. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_ast_extractor.py +0 -0
  166. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_block1_reliability.py +0 -0
  167. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_block2_coverage.py +0 -0
  168. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_block5_quality.py +0 -0
  169. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_bug_fixes_v1302.py +0 -0
  170. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_bug_fixes_v16.py +0 -0
  171. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_bug_fixes_v2.py +0 -0
  172. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_classifier.py +0 -0
  173. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_cli.py +0 -0
  174. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_code_notes_analyzer.py +0 -0
  175. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_context_scorer.py +0 -0
  176. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_contract_pipeline.py +0 -0
  177. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_coverage_parser.py +0 -0
  178. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_cross_consistency.py +0 -0
  179. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_dependency_analyzer_node_python.py +0 -0
  180. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_dependency_analyzer_polyglot.py +0 -0
  181. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_dependency_schema.py +0 -0
  182. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detector_dotnet.py +0 -0
  183. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detector_go_rust_java.py +0 -0
  184. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detector_nodejs.py +0 -0
  185. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detector_php_ruby_dart.py +0 -0
  186. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detector_python.py +0 -0
  187. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detector_universal_managed.py +0 -0
  188. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detector_universal_systems.py +0 -0
  189. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_detectors_base.py +0 -0
  190. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_doc_analyzer_jsdom.py +0 -0
  191. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_doc_analyzer_python.py +0 -0
  192. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_encoding_regression.py +0 -0
  193. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_graph_analyzer_polyglot.py +0 -0
  194. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_graph_analyzer_python_node.py +0 -0
  195. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_graph_schema.py +0 -0
  196. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_hybrid_inference.py +0 -0
  197. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration.py +0 -0
  198. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_dependencies.py +0 -0
  199. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_detection.py +0 -0
  200. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_docs.py +0 -0
  201. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_graph_modules.py +0 -0
  202. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_lqn.py +0 -0
  203. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_metrics.py +0 -0
  204. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_multistack.py +0 -0
  205. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_semantics.py +0 -0
  206. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_integration_universal.py +0 -0
  207. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_java_spring_integration.py +0 -0
  208. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_metrics_analyzer.py +0 -0
  209. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_output_ux.py +0 -0
  210. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_packaging.py +0 -0
  211. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_phase1_improvements.py +0 -0
  212. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_pipeline_integrity.py +0 -0
  213. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_real_projects.py +0 -0
  214. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_redactor.py +0 -0
  215. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_repository_ir.py +0 -0
  216. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_scanner.py +0 -0
  217. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_schema.py +0 -0
  218. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_schema_normalization.py +0 -0
  219. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_scoring_calibration.py +0 -0
  220. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_semantic_analyzer_node.py +0 -0
  221. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_semantic_analyzer_python.py +0 -0
  222. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_semantic_import_resolution.py +0 -0
  223. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_semantic_schema.py +0 -0
  224. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_signal_hierarchy.py +0 -0
  225. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_summarizer.py +0 -0
  226. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_surface_honesty.py +0 -0
  227. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_task_differentiation.py +0 -0
  228. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_telemetry.py +0 -0
  229. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_v131_improvements.py +0 -0
  230. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_v1_10_regressions.py +0 -0
  231. {sourcecode-1.30.30 → sourcecode-1.31.0}/tests/test_workspace_analyzer.py +0 -0
@@ -0,0 +1,101 @@
1
+ # Continue Here — atlas-cli sesión 16
2
+
3
+ **Paused:** 2026-05-20
4
+ **Repo:** `/Users/user/Downloads/atlas-cli`
5
+ **Branch:** master
6
+ **Working tree:** CHANGELOG.md sin commitear (untracked)
7
+
8
+ ---
9
+
10
+ ## Trabajo de esta sesión (ya commiteado)
11
+
12
+ **Commit:** `0e430c1 fix(cli+serializer): BUG-1..5 + IMP-1 — UTF-8 stdout, --exclude parsing, onboard fast scan, angular_version null, lazy_routes_count zero, test_gaps config filter`
13
+
14
+ | ID | Fix | Archivo | Líneas clave |
15
+ |---|---|---|---|
16
+ | BUG-1 | `repo_ir_cmd` usa `stdout.buffer.write(encode("utf-8"))` en vez de `stdout.write()`. `main_entry` llama `stdout.reconfigure(encoding="utf-8")`. UnicodeEncodeError capturado con hint a `--output`. | `cli.py` | ~2367, ~2443 |
17
+ | BUG-2 | `--exclude` añadido a `_OPTIONS_WITH_VALUE` → valor no consumido como repo path. Warning si valor es directorio existente. | `cli.py` | ~173, ~856 |
18
+ | BUG-3 | `onboard --fast` siempre usa `AdaptiveScanner(base_depth=2)`; ya no usa git-index-only (que devolvía solo `.idea/vcs.xml`). | `prepare_context.py` | ~791 |
19
+ | BUG-4 | `deps = {**(pkg.get("dependencies") or {}), ...}` para manejar `null` explícito en package.json. Añade `peerDependencies` como fallback. | `serializer.py` | ~1663 |
20
+ | BUG-5 | Cuenta `loadChildren:` y `loadComponent:` (property syntax modern Angular) en vez del inexistente `loadChildren(`. | `serializer.py` | ~1644 |
21
+ | IMP-1 | `test_gaps` excluye `.eslintrc*`, `karma.conf.js`, `tsconfig*`, `.claude/**`, etc. por defecto. Nuevo flag `--include-config` para override. | `prepare_context.py`, `cli.py` | ~1663, ~1806 |
22
+ | IMP-2 | Stderr warning con workaround exacto cuando se detecta UnicodeEncodeError (BUG-1) o exclude value = directorio (BUG-2). | `cli.py` | ~2373, ~858 |
23
+
24
+ **Tests:** `tests/test_bug_fixes_v2.py` — 14 tests, todos pasan.
25
+ **Suite completa:** 1010 passed, 0 nuevos failures (3 pre-existentes sin tocar).
26
+
27
+ ---
28
+
29
+ ## Primera acción al retomar
30
+
31
+ CHANGELOG.md quedó fuera del commit (untracked). Commitear:
32
+
33
+ ```bash
34
+ cd /Users/user/Downloads/atlas-cli
35
+ git add CHANGELOG.md
36
+ git commit -m "docs: add CHANGELOG.md with BUG-1..5 and IMP-1 entries for v1.30.29
37
+
38
+ Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>"
39
+ ```
40
+
41
+ ---
42
+
43
+ ## Pendientes (heredados de sesión 15, siguen vigentes)
44
+
45
+ 1. **Spring bean wiring graph** — `_build_relations` emite `injects` edges para `@Autowired`. Falta: trazar `@Configuration → @Bean → @Autowired` completo, exponer como `wiring_graph`.
46
+
47
+ 2. **Smoke test en repo spring-boot real:**
48
+ ```bash
49
+ cd ~/Documents/workspace/spring-boot-realworld-example-app
50
+ sourcecode repo-ir . --since HEAD~1 2>/dev/null | python3 -c "
51
+ import json, sys; d=json.load(sys.stdin)
52
+ print('nodes:', len(d['graph']['nodes']))
53
+ print('route_surface:', d.get('route_surface', []))
54
+ print('reverse_graph keys:', len(d.get('reverse_graph', {})))
55
+ "
56
+ ```
57
+
58
+ 3. **Transaction boundary tracking** — `@Transactional` detectado. Falta: emitir `transactional_boundary` edges.
59
+
60
+ 4. **`_diff_routes` para `@RequestMapping` en clase** — class-level mapping change debería propagarse a todos los endpoints del controller.
61
+
62
+ 5. **Tests para el symptom fix (sesión 15)** — validar `--symptom "sesiones"` con mock commits produce ranking diferente al baseline. Cubrir en `tests/test_prepare_context_symptom.py`.
63
+
64
+ 6. **`_FRONTEND_SYMPTOM_MAP`** — añadir "sesiones"/"session" con backend terms `["httpsession", "sessionmanager", "sessionservice", "sessionrepository"]`.
65
+
66
+ ---
67
+
68
+ ## Estado de tests al pausar
69
+
70
+ ```
71
+ 1010 passed, 3 skipped (pre-existing)
72
+ ```
73
+
74
+ Pre-existing failures (no tocar):
75
+ - `tests/test_block2_coverage.py::TestDocAnalyzerLanguageCoverage::test_java_marked_unsupported` — `DocRecord.__init__()` unexpected kwarg `name`
76
+ - `tests/test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile_keeps_declared_versions` — typer version mismatch
77
+ - `tests/test_scoring_calibration.py` — varios score calibration tests
78
+
79
+ ---
80
+
81
+ ## Para retomar
82
+
83
+ ```bash
84
+ cd /Users/user/Downloads/atlas-cli
85
+ git log --oneline -3 # 0e430c1 debe estar arriba
86
+ git status # solo CHANGELOG.md untracked
87
+
88
+ # 1. Commitear CHANGELOG.md (comando arriba)
89
+
90
+ # 2. Verificar suite
91
+ python3 -m pytest tests/ \
92
+ --ignore=tests/test_block2_coverage.py \
93
+ --ignore=tests/test_scoring_calibration.py \
94
+ --deselect=tests/test_dependency_analyzer_node_python.py::test_python_requirements_without_lockfile_keeps_declared_versions \
95
+ -q
96
+ # Expected: 1010 passed, 3 skipped
97
+ ```
98
+
99
+ ---
100
+
101
+ *Pausado 2026-05-20 — gsd:pause-work*
@@ -24,8 +24,8 @@
24
24
  ],
25
25
  "dependency_summary": {
26
26
  "requested": true,
27
- "total_count": 10,
28
- "direct": 10,
27
+ "total_count": 12,
28
+ "direct": 12,
29
29
  "sources": [
30
30
  "manifest"
31
31
  ]
@@ -33,7 +33,7 @@ stacks:
33
33
  - package_manager:pip
34
34
  - entry:src/sourcecode/cli.py
35
35
  - entry:run_cli.py
36
- - extensions:138
36
+ - extensions:144
37
37
  produced_by: python
38
38
  language_version: null
39
39
  packaging: null
@@ -48,8 +48,9 @@ contracts:
48
48
  - config_cmd() -> None
49
49
  - 'main(ctx: typer.Context, format: str, output: Optional[Pa...'
50
50
  - main_entry() -> None
51
- - 'prepare_context_cmd(task: Optional[str], path: Path, sinc...'
51
+ - mcp_serve() -> None
52
52
  exports:
53
+ - prepare_context_cmd
53
54
  - repo_ir_cmd
54
55
  - telemetry_disable
55
56
  - telemetry_enable
@@ -59,6 +60,20 @@ contracts:
59
60
  deps:
60
61
  - sourcecode
61
62
  - typer
63
+ - path: src/sourcecode/mcp/server.py
64
+ role: entrypoint
65
+ fn:
66
+ - 'agent(path: str, git_context: bool) -> dict'
67
+ - 'compact(path: str, git_context: bool) -> dict'
68
+ - config() -> dict
69
+ - "prepare_context(task: Literal['delta', 'review-pr', 'fix-..."
70
+ - 'repo_ir(path: str) -> dict'
71
+ exports:
72
+ - telemetry
73
+ - version
74
+ deps:
75
+ - mcp
76
+ - sourcecode
62
77
  - path: src/sourcecode/context_scorer.py
63
78
  role: util
64
79
  exports:
@@ -173,29 +188,15 @@ contracts:
173
188
  - TaskContextBuilder
174
189
  - TaskOutput
175
190
  - TaskSpec
176
- - path: src/sourcecode/ranking_engine.py
177
- role: util
178
- fn:
179
- - 'compute_impact_score(runtime_impact: float, dependency_ce...'
180
- - 'resolve_framework_signal(category: str | None) -> float'
181
- - 'resolve_runtime_impact(category: str | None) -> float'
182
- exports:
183
- - k: class
184
- names:
185
- - FileScore
186
- - RankingEngine
187
- - TaskWeights
188
- deps:
189
- - sourcecode
190
191
  contracts_meta:
191
192
  total: 15
192
193
  shown: 15
193
194
  truncated: false
194
195
  summary:
195
196
  files: 15
196
- total: 67
197
+ total: 70
197
198
  methods:
198
- ast: 67
199
+ ast: 70
199
200
  confidence:
200
201
  overall: high
201
202
  stack: high
@@ -42,7 +42,7 @@
42
42
  "package_manager:pip",
43
43
  "entry:src/sourcecode/cli.py",
44
44
  "entry:run_cli.py",
45
- "extensions:137"
45
+ "extensions:144"
46
46
  ],
47
47
  "produced_by": "python",
48
48
  "language_version": null,
@@ -61,9 +61,10 @@
61
61
  "config_cmd() -> None",
62
62
  "main(ctx: typer.Context, format: str, output: Optional[Pa...",
63
63
  "main_entry() -> None",
64
- "prepare_context_cmd(task: Optional[str], path: Path, sinc..."
64
+ "mcp_serve() -> None"
65
65
  ],
66
66
  "exports": [
67
+ "prepare_context_cmd",
67
68
  "repo_ir_cmd",
68
69
  "telemetry_disable",
69
70
  "telemetry_enable",
@@ -76,6 +77,25 @@
76
77
  "typer"
77
78
  ]
78
79
  },
80
+ {
81
+ "path": "src/sourcecode/mcp/server.py",
82
+ "role": "entrypoint",
83
+ "fn": [
84
+ "agent(path: str, git_context: bool) -> dict",
85
+ "compact(path: str, git_context: bool) -> dict",
86
+ "config() -> dict",
87
+ "prepare_context(task: Literal['delta', 'review-pr', 'fix-...",
88
+ "repo_ir(path: str) -> dict"
89
+ ],
90
+ "exports": [
91
+ "telemetry",
92
+ "version"
93
+ ],
94
+ "deps": [
95
+ "mcp",
96
+ "sourcecode"
97
+ ]
98
+ },
79
99
  {
80
100
  "path": "src/sourcecode/context_scorer.py",
81
101
  "role": "util",
@@ -262,28 +282,6 @@
262
282
  ]
263
283
  }
264
284
  ]
265
- },
266
- {
267
- "path": "src/sourcecode/ranking_engine.py",
268
- "role": "util",
269
- "fn": [
270
- "compute_impact_score(runtime_impact: float, dependency_ce...",
271
- "resolve_framework_signal(category: str | None) -> float",
272
- "resolve_runtime_impact(category: str | None) -> float"
273
- ],
274
- "exports": [
275
- {
276
- "k": "class",
277
- "names": [
278
- "FileScore",
279
- "RankingEngine",
280
- "TaskWeights"
281
- ]
282
- }
283
- ],
284
- "deps": [
285
- "sourcecode"
286
- ]
287
285
  }
288
286
  ],
289
287
  "contracts_meta": {
@@ -293,9 +291,9 @@
293
291
  },
294
292
  "summary": {
295
293
  "files": 15,
296
- "total": 67,
294
+ "total": 70,
297
295
  "methods": {
298
- "ast": 67
296
+ "ast": 70
299
297
  }
300
298
  },
301
299
  "confidence": {
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sourcecode
3
- Version: 1.30.30
3
+ Version: 1.31.0
4
4
  Summary: Deterministic codebase context for AI coding agents
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -212,16 +212,19 @@ Requires-Dist: tree-sitter-javascript>=0.21; extra == 'ast'
212
212
  Requires-Dist: tree-sitter-typescript>=0.21; extra == 'ast'
213
213
  Requires-Dist: tree-sitter>=0.21; extra == 'ast'
214
214
  Provides-Extra: dev
215
+ Requires-Dist: mcp>=1.0.0; extra == 'dev'
215
216
  Requires-Dist: mypy>=1.10; extra == 'dev'
216
217
  Requires-Dist: pytest>=8; extra == 'dev'
217
218
  Requires-Dist: ruff>=0.15; extra == 'dev'
219
+ Provides-Extra: mcp
220
+ Requires-Dist: mcp>=1.0.0; extra == 'mcp'
218
221
  Description-Content-Type: text/markdown
219
222
 
220
223
  # sourcecode
221
224
 
222
225
  **Deterministic, behavior-aware codebase context for AI agents and PR review.**
223
226
 
224
- ![Version](https://img.shields.io/badge/version-1.30.30-blue)
227
+ ![Version](https://img.shields.io/badge/version-1.31.0-blue)
225
228
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
226
229
 
227
230
  ---
@@ -257,7 +260,7 @@ pipx install sourcecode
257
260
 
258
261
  ```bash
259
262
  sourcecode version
260
- # sourcecode 1.30.30
263
+ # sourcecode 1.31.0
261
264
  ```
262
265
 
263
266
  ---
@@ -2,7 +2,7 @@
2
2
 
3
3
  **Deterministic, behavior-aware codebase context for AI agents and PR review.**
4
4
 
5
- ![Version](https://img.shields.io/badge/version-1.30.30-blue)
5
+ ![Version](https://img.shields.io/badge/version-1.31.0-blue)
6
6
  ![Python](https://img.shields.io/badge/python-3.10%2B-green)
7
7
 
8
8
  ---
@@ -38,7 +38,7 @@ pipx install sourcecode
38
38
 
39
39
  ```bash
40
40
  sourcecode version
41
- # sourcecode 1.30.30
41
+ # sourcecode 1.31.0
42
42
  ```
43
43
 
44
44
  ---
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "sourcecode"
7
- version = "1.30.30"
7
+ version = "1.31.0"
8
8
  description = "Deterministic codebase context for AI coding agents"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -39,12 +39,16 @@ dev = [
39
39
  "pytest>=8",
40
40
  "ruff>=0.15",
41
41
  "mypy>=1.10",
42
+ "mcp>=1.0.0",
42
43
  ]
43
44
  ast = [
44
45
  "tree-sitter>=0.21",
45
46
  "tree-sitter-typescript>=0.21",
46
47
  "tree-sitter-javascript>=0.21",
47
48
  ]
49
+ mcp = [
50
+ "mcp>=1.0.0",
51
+ ]
48
52
 
49
53
  [[tool.mypy.overrides]]
50
54
  module = ["tree_sitter", "tree_sitter_typescript", "tree_sitter_javascript"]
@@ -1,3 +1,3 @@
1
1
  """sourcecode — Deterministic codebase context maps for AI coding agents."""
2
2
 
3
- __version__ = "1.30.30"
3
+ __version__ = "1.31.0"
@@ -154,6 +154,10 @@ Compressed AI-ready context for Java/Spring enterprise codebases.
154
154
 
155
155
  [bold]Subcommands:[/bold]
156
156
  prepare-context TASK [PATH] [dim]# task-specific context (onboard, delta, fix-bug, ...)[/dim]
157
+ mcp init [dim]# setup MCP integration (Claude Desktop, Cursor)[/dim]
158
+ mcp status [dim]# show MCP integration status[/dim]
159
+ mcp remove [dim]# remove MCP integration safely[/dim]
160
+ mcp serve [dim]# start MCP server for AI agent integration[/dim]
157
161
  telemetry status|enable|disable
158
162
  version
159
163
  """
@@ -161,7 +165,7 @@ Compressed AI-ready context for Java/Spring enterprise codebases.
161
165
  # Known subcommand names — tokens matching these are routed as subcommands,
162
166
  # not consumed as a repository path.
163
167
  _SUBCOMMANDS: frozenset[str] = frozenset(
164
- {"telemetry", "prepare-context", "version", "config", "analyze", "repo-ir"}
168
+ {"telemetry", "prepare-context", "version", "config", "analyze", "repo-ir", "mcp"}
165
169
  )
166
170
 
167
171
  # Mutable container holding the path extracted by _preprocess_argv().
@@ -300,6 +304,9 @@ except Exception:
300
304
  telemetry_app = typer.Typer(help="Manage anonymous telemetry (opt-in).", rich_markup_mode="rich")
301
305
  app.add_typer(telemetry_app, name="telemetry")
302
306
 
307
+ mcp_app = typer.Typer(help="MCP integration: setup, status, serve, remove.", rich_markup_mode="rich")
308
+ app.add_typer(mcp_app, name="mcp")
309
+
303
310
 
304
311
  def _maybe_ask_consent() -> None:
305
312
  """Show first-run consent prompt once, on interactive TTYs only."""
@@ -317,6 +324,26 @@ def _maybe_ask_consent() -> None:
317
324
  pass
318
325
 
319
326
 
327
+ def _maybe_show_mcp_hint() -> None:
328
+ """Show MCP integration hint once after first install, on TTY only."""
329
+ import sys as _sys
330
+ try:
331
+ if not _sys.stderr.isatty():
332
+ return
333
+ from sourcecode.telemetry.config import _CONFIG_FILE, _load, _save
334
+ data = _load()
335
+ if data.get("mcp", {}).get("hint_shown"):
336
+ return
337
+ typer.echo("", err=True)
338
+ typer.echo(" MCP integration available:", err=True)
339
+ typer.echo(" → sourcecode mcp init", err=True)
340
+ typer.echo("", err=True)
341
+ data.setdefault("mcp", {})["hint_shown"] = True
342
+ _save(data)
343
+ except Exception:
344
+ pass
345
+
346
+
320
347
  def _active_flags(
321
348
  dependencies: bool, graph_modules: bool, docs: bool, full_metrics: bool,
322
349
  semantics: bool, architecture: bool, git_context: bool, env_map: bool,
@@ -616,6 +643,7 @@ def main(
616
643
  # First-run consent (skip for telemetry/version/config subcommands)
617
644
  if ctx.invoked_subcommand not in ("telemetry", "version", "config"):
618
645
  _maybe_ask_consent()
646
+ _maybe_show_mcp_hint()
619
647
 
620
648
  # When a subcommand is invoked, skip the main analysis.
621
649
  if ctx.invoked_subcommand is not None:
@@ -2432,6 +2460,249 @@ def analyze_cmd(
2432
2460
  raise typer.Exit(code=1)
2433
2461
 
2434
2462
 
2463
+ # ── MCP server ────────────────────────────────────────────────────────────────
2464
+
2465
+ @mcp_app.command("serve")
2466
+ def mcp_serve() -> None:
2467
+ """Start the MCP server on stdio for AI agent integration.
2468
+
2469
+ \b
2470
+ Requires the 'mcp' extra:
2471
+ pip install sourcecode[mcp]
2472
+
2473
+ \b
2474
+ Configure in your MCP client (e.g. Claude Desktop):
2475
+ {
2476
+ "sourcecode": {
2477
+ "command": "sourcecode",
2478
+ "args": ["mcp", "serve"]
2479
+ }
2480
+ }
2481
+ """
2482
+ import logging
2483
+ import sys as _sys
2484
+
2485
+ logging.basicConfig(
2486
+ stream=_sys.stderr,
2487
+ level=logging.INFO,
2488
+ format="[sourcecode-mcp] %(levelname)s %(message)s",
2489
+ )
2490
+ try:
2491
+ from sourcecode.mcp.server import mcp as _mcp
2492
+ except ImportError:
2493
+ typer.echo(
2494
+ "MCP support not available. Install with:\n"
2495
+ " pip install sourcecode[mcp]",
2496
+ err=True,
2497
+ )
2498
+ raise typer.Exit(code=1)
2499
+
2500
+ log = logging.getLogger(__name__)
2501
+ log.info("sourcecode-mcp starting (stdio transport)")
2502
+ try:
2503
+ _mcp.run()
2504
+ except KeyboardInterrupt:
2505
+ log.info("sourcecode-mcp stopped")
2506
+ except Exception as exc:
2507
+ log.critical("sourcecode-mcp fatal error: %s", exc, exc_info=True)
2508
+ raise typer.Exit(code=1)
2509
+
2510
+
2511
+ # ── MCP onboarding ────────────────────────────────────────────────────────────
2512
+
2513
+ @mcp_app.command("init")
2514
+ def mcp_init(
2515
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt."),
2516
+ ) -> None:
2517
+ """Setup MCP integration for Claude Desktop, Cursor, and other clients.
2518
+
2519
+ \b
2520
+ Detects installed MCP clients, backs up their config files, and safely
2521
+ inserts the sourcecode server entry. Fully idempotent — safe to re-run.
2522
+ """
2523
+ from sourcecode.mcp.onboarding.detector import detect_clients
2524
+ from sourcecode.mcp.onboarding.planner import build_install_plan
2525
+ from sourcecode.mcp.onboarding import backup, applier
2526
+
2527
+ typer.echo("Detecting MCP clients...")
2528
+ typer.echo("")
2529
+
2530
+ clients = detect_clients()
2531
+ if not clients:
2532
+ typer.echo("No MCP clients found on this system.")
2533
+ typer.echo("")
2534
+ typer.echo("Manual setup — add to your MCP client config:")
2535
+ typer.echo(' "sourcecode": {"command": "sourcecode", "args": ["mcp", "serve"]}')
2536
+ raise typer.Exit(code=0)
2537
+
2538
+ # Show detection results
2539
+ for client in clients:
2540
+ mark = "✓" if client.app_installed else "○"
2541
+ note = "" if client.app_installed else " (not found)"
2542
+ typer.echo(f" {mark} {client.name:<18} {client.config_path}{note}")
2543
+ typer.echo("")
2544
+
2545
+ # Build plan
2546
+ plan = build_install_plan(clients)
2547
+ actionable = [a for a in plan if a.client.app_installed and not a.already_installed]
2548
+ already_done = [a for a in plan if a.client.app_installed and a.already_installed]
2549
+
2550
+ if already_done and not actionable:
2551
+ typer.echo("Already configured:")
2552
+ for a in already_done:
2553
+ typer.echo(f" ✓ {a.client.name} {a.client.config_path}")
2554
+ typer.echo("")
2555
+ typer.echo("Nothing to do. Remove: sourcecode mcp remove")
2556
+ raise typer.Exit(code=0)
2557
+
2558
+ if already_done:
2559
+ typer.echo("Already configured:")
2560
+ for a in already_done:
2561
+ typer.echo(f" ✓ {a.client.name} {a.client.config_path}")
2562
+ typer.echo("")
2563
+
2564
+ # Show plan for actionable items
2565
+ typer.echo("This will:")
2566
+ for a in actionable:
2567
+ verb = "Create " if a.will_create_file else "Modify "
2568
+ typer.echo(f" {verb} {a.client.config_path}")
2569
+ typer.echo(f" Backup → ~/.config/sourcecode/mcp-backups/")
2570
+ typer.echo("")
2571
+
2572
+ if not yes:
2573
+ confirmed = typer.confirm("Proceed?", default=False)
2574
+ if not confirmed:
2575
+ typer.echo("Aborted.")
2576
+ raise typer.Exit(code=0)
2577
+ typer.echo("")
2578
+
2579
+ # Apply
2580
+ errors: list[str] = []
2581
+ for a in actionable:
2582
+ try:
2583
+ config = applier.read_config(a.client.config_path)
2584
+ if a.client.config_path.exists():
2585
+ bak = backup.create(a.client.config_path)
2586
+ typer.echo(f" ✓ Backup {bak}")
2587
+ updated = applier.apply_entry(config)
2588
+ applier.write_config(a.client.config_path, updated)
2589
+ if not applier.validate(a.client.config_path):
2590
+ errors.append(f"{a.client.name}: JSON validation failed after write")
2591
+ continue
2592
+ typer.echo(f" ✓ Updated {a.client.config_path}")
2593
+ except Exception as exc:
2594
+ errors.append(f"{a.client.name}: {exc}")
2595
+
2596
+ typer.echo("")
2597
+
2598
+ if errors:
2599
+ for err in errors:
2600
+ typer.echo(f" ✗ {err}", err=True)
2601
+ raise typer.Exit(code=1)
2602
+
2603
+ typer.echo("MCP integration active.")
2604
+ typer.echo("")
2605
+
2606
+ restart_needed = [a.client.name for a in actionable if not a.will_create_file]
2607
+ if restart_needed:
2608
+ typer.echo(f" Restart {', '.join(restart_needed)} to apply changes.")
2609
+ typer.echo(" Remove: sourcecode mcp remove")
2610
+
2611
+
2612
+ @mcp_app.command("status")
2613
+ def mcp_status() -> None:
2614
+ """Show MCP integration status for all detected clients."""
2615
+ from sourcecode.mcp.onboarding.detector import detect_clients
2616
+ from sourcecode.mcp.onboarding import applier
2617
+
2618
+ clients = detect_clients()
2619
+ typer.echo("MCP Integration Status")
2620
+ typer.echo("")
2621
+
2622
+ if not clients:
2623
+ typer.echo(" No MCP clients detected on this system.")
2624
+ raise typer.Exit(code=0)
2625
+
2626
+ for client in clients:
2627
+ if not client.app_installed:
2628
+ typer.echo(f" ○ {client.name:<18} not found")
2629
+ continue
2630
+ config = applier.read_config(client.config_path)
2631
+ if applier.is_installed(config):
2632
+ typer.echo(f" ✓ {client.name:<18} configured {client.config_path}")
2633
+ else:
2634
+ typer.echo(f" ✗ {client.name:<18} not configured")
2635
+ typer.echo("")
2636
+ typer.echo(" Setup: sourcecode mcp init")
2637
+ typer.echo(" Remove: sourcecode mcp remove")
2638
+
2639
+
2640
+ @mcp_app.command("remove")
2641
+ def mcp_remove(
2642
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation prompt."),
2643
+ ) -> None:
2644
+ """Remove sourcecode MCP integration from all configured clients.
2645
+
2646
+ \b
2647
+ Backs up config files before modifying. Restores from backup when available,
2648
+ otherwise removes the sourcecode entry while preserving all other config.
2649
+ """
2650
+ from sourcecode.mcp.onboarding.detector import detect_clients
2651
+ from sourcecode.mcp.onboarding.planner import build_remove_plan
2652
+ from sourcecode.mcp.onboarding import backup, applier
2653
+
2654
+ clients = detect_clients()
2655
+ plan = build_remove_plan(clients)
2656
+ installed = [a for a in plan if a.already_installed]
2657
+
2658
+ if not installed:
2659
+ typer.echo("sourcecode MCP integration not found in any client config.")
2660
+ typer.echo(" Setup: sourcecode mcp init")
2661
+ raise typer.Exit(code=0)
2662
+
2663
+ typer.echo("Remove sourcecode MCP integration from:")
2664
+ typer.echo("")
2665
+ for a in installed:
2666
+ typer.echo(f" {a.client.name} {a.client.config_path}")
2667
+ bak = backup.latest(a.client.config_path)
2668
+ if bak:
2669
+ typer.echo(f" Backup available: {bak}")
2670
+ typer.echo("")
2671
+
2672
+ if not yes:
2673
+ confirmed = typer.confirm("Proceed?", default=False)
2674
+ if not confirmed:
2675
+ typer.echo("Aborted.")
2676
+ raise typer.Exit(code=0)
2677
+ typer.echo("")
2678
+
2679
+ errors: list[str] = []
2680
+ for a in installed:
2681
+ try:
2682
+ bak = backup.create(a.client.config_path)
2683
+ typer.echo(f" ✓ Backup {bak}")
2684
+ config = applier.read_config(a.client.config_path)
2685
+ updated = applier.remove_entry(config)
2686
+ applier.write_config(a.client.config_path, updated)
2687
+ if not applier.validate(a.client.config_path):
2688
+ errors.append(f"{a.client.name}: JSON validation failed — restoring backup")
2689
+ backup.restore(bak, a.client.config_path)
2690
+ continue
2691
+ typer.echo(f" ✓ Updated {a.client.config_path}")
2692
+ except Exception as exc:
2693
+ errors.append(f"{a.client.name}: {exc}")
2694
+
2695
+ typer.echo("")
2696
+
2697
+ if errors:
2698
+ for err in errors:
2699
+ typer.echo(f" ✗ {err}", err=True)
2700
+ raise typer.Exit(code=1)
2701
+
2702
+ typer.echo("MCP integration removed.")
2703
+ typer.echo(" Re-add: sourcecode mcp init")
2704
+
2705
+
2435
2706
  # ── Entry point ───────────────────────────────────────────────────────────────
2436
2707
 
2437
2708
  def main_entry() -> None:
@@ -0,0 +1,5 @@
1
+ """MCP server integration for sourcecode CLI.
2
+
3
+ Exposes all CLI capabilities as MCP tools callable by AI agents.
4
+ Install the 'mcp' extra to enable: pip install sourcecode[mcp]
5
+ """
@@ -0,0 +1 @@
1
+ """MCP client onboarding: detect, plan, apply, backup, remove."""