codrspot-processor-mcp 0.1.4__tar.gz → 0.1.6__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 (106) hide show
  1. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/PKG-INFO +1 -1
  2. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/pyproject.toml +1 -1
  3. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/mcp/server.py +13 -4
  4. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/mcp/tools.py +14 -2
  5. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/scanning/repo_mapper.py +51 -13
  6. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codrspot_processor_mcp.egg-info/PKG-INFO +1 -1
  7. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/LICENSE +0 -0
  8. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/README.md +0 -0
  9. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/setup.cfg +0 -0
  10. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/__init__.py +0 -0
  11. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/__main__.py +0 -0
  12. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/__init__.py +0 -0
  13. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/allowed_scope_cache.py +0 -0
  14. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/api_client/__init__.py +0 -0
  15. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/api_client/lease_client.py +0 -0
  16. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/api_client/net_guard.py +0 -0
  17. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/api_client/promote_client.py +0 -0
  18. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/api_client/reasoning_client.py +0 -0
  19. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/api_client/registry_client.py +0 -0
  20. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/api_client/superkg_client.py +0 -0
  21. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/cli/__init__.py +0 -0
  22. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/cli/init.py +0 -0
  23. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/cli/main.py +0 -0
  24. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/cli/setup.py +0 -0
  25. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/config.py +0 -0
  26. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/git_utils.py +0 -0
  27. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/license/__init__.py +0 -0
  28. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/license/fingerprint.py +0 -0
  29. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/license/jwt_client.py +0 -0
  30. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/license/project_lock.py +0 -0
  31. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/local_registry.py +0 -0
  32. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/manifest/__init__.py +0 -0
  33. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/manifest/credentials.py +0 -0
  34. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/mcp/__init__.py +0 -0
  35. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/mcp/action_monitor.py +0 -0
  36. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/mcp/lifecycle.py +0 -0
  37. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer1_business/project_registry.py +0 -0
  38. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/__init__.py +0 -0
  39. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/__init__.py +0 -0
  40. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/ast_graph.py +0 -0
  41. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/bm25_store.py +0 -0
  42. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/chunking/__init__.py +0 -0
  43. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/chunking/ast_chunker.py +0 -0
  44. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/chunking/languages.py +0 -0
  45. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/embed_worker.py +0 -0
  46. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/embeddings.py +0 -0
  47. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/extract/__init__.py +0 -0
  48. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/extract/compactor.py +0 -0
  49. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/extract/providers/__init__.py +0 -0
  50. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/extract/providers/base.py +0 -0
  51. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/indexer.py +0 -0
  52. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/ppl/__init__.py +0 -0
  53. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/ppl/emitter.py +0 -0
  54. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/ppl/parser.py +0 -0
  55. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/qdrant_store.py +0 -0
  56. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/scanning/__init__.py +0 -0
  57. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/scanning/manifest_scanner.py +0 -0
  58. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/scanning/md_scanner.py +0 -0
  59. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/condensation/session_vector_store.py +0 -0
  60. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/coupling/__init__.py +0 -0
  61. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/coupling/domain.py +0 -0
  62. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/coupling/graph.py +0 -0
  63. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/coupling/layer2_gate.py +0 -0
  64. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/coupling/projector.py +0 -0
  65. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/coupling/resolver.py +0 -0
  66. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/__init__.py +0 -0
  67. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/pipeline/__init__.py +0 -0
  68. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/pipeline/execute_semantic.py +0 -0
  69. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/pipeline/filesystem_reorg.py +0 -0
  70. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/pipeline/patch_generator.py +0 -0
  71. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/pipeline/patch_validator.py +0 -0
  72. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/__init__.py +0 -0
  73. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/anchors.py +0 -0
  74. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/applicability.py +0 -0
  75. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/edit_planner.py +0 -0
  76. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/materializer.py +0 -0
  77. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/merger.py +0 -0
  78. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/ops/__init__.py +0 -0
  79. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/ops/add_import.py +0 -0
  80. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/ops/append_argument.py +0 -0
  81. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/ops/insert_literal.py +0 -0
  82. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/ops/remove_import.py +0 -0
  83. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/ops/remove_statement_unique.py +0 -0
  84. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/ops/rename_symbol_local.py +0 -0
  85. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/region_resolver.py +0 -0
  86. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/synthesizer.py +0 -0
  87. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/target_locator.py +0 -0
  88. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/semantic/validator.py +0 -0
  89. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/snippet/__init__.py +0 -0
  90. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/snippet/assembler.py +0 -0
  91. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/materialization/snippet/loader.py +0 -0
  92. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/retrieval/__init__.py +0 -0
  93. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/retrieval/graph_walk.py +0 -0
  94. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/retrieval/hybrid.py +0 -0
  95. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/retrieval/rerank_worker.py +0 -0
  96. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/retrieval/reranker.py +0 -0
  97. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/watcher/__init__.py +0 -0
  98. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codepreproc_client/layer2_tooling/watcher/fs_watcher.py +0 -0
  99. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codrspot_processor_mcp.egg-info/SOURCES.txt +0 -0
  100. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codrspot_processor_mcp.egg-info/dependency_links.txt +0 -0
  101. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codrspot_processor_mcp.egg-info/entry_points.txt +0 -0
  102. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codrspot_processor_mcp.egg-info/requires.txt +0 -0
  103. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/codrspot_processor_mcp.egg-info/top_level.txt +0 -0
  104. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/contracts/__init__.py +0 -0
  105. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/contracts/dtos.py +0 -0
  106. {codrspot_processor_mcp-0.1.4 → codrspot_processor_mcp-0.1.6}/src/contracts/ir.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codrspot-processor-mcp
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Local MCP server exposing codepreproc's code-context tools to Claude Code
5
5
  Author-email: alexlqi <alexlqi@gmail.com>
6
6
  License: Copyright (c) 2026 alexlqi (alexlqi@gmail.com)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codrspot-processor-mcp"
7
- version = "0.1.4"
7
+ version = "0.1.6"
8
8
  description = "Local MCP server exposing codepreproc's code-context tools to Claude Code"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12,<3.13"
@@ -416,15 +416,24 @@ async def main() -> None:
416
416
  "interfaces, implementations, methods, properties, and relationships. "
417
417
  "For monorepos, auto-detects apps/ (artifacts) and packages/ (reusable modules); "
418
418
  "each direct subfolder of those is treated as a unit, and its src/ directory "
419
- "is the module root. If the layout is not detected, returns needs_clarification=true "
420
- "with questions to answer via artifacts_folder and modules_folder. "
419
+ "is the module root. If the layout instead has multiple sibling top-level app "
420
+ "folders with no shared container (e.g. cemix-api/, cemix-web/, cemix-admin/ "
421
+ "directly at the repo root), pass artifact_units with those folder names instead "
422
+ "of artifacts_folder — each listed folder is treated as its own artifact directly. "
423
+ "If the layout is not detected, returns needs_clarification=true "
424
+ "with questions to answer via artifacts_folder/modules_folder or artifact_units. "
421
425
  "Excludes .git from the scan. "
422
426
  "Stores the result in the knowledge graph and writes repo_map.json to the project root."
423
427
  ),
424
428
  inputSchema=_tool_schema({
425
429
  "project": {"type": ["string", "null"]},
426
- "artifacts_folder": {"type": ["string", "null"], "description": "Top-level folder that contains deployable apps/artifacts (e.g. 'apps')."},
427
- "modules_folder": {"type": ["string", "null"], "description": "Top-level folder that contains reusable shared modules (e.g. 'packages')."},
430
+ "artifacts_folder": {"type": ["string", "null"], "description": "Top-level container folder that contains deployable apps/artifacts (e.g. 'apps'). Mutually exclusive with artifact_units."},
431
+ "modules_folder": {"type": ["string", "null"], "description": "Top-level folder that contains reusable shared modules (e.g. 'packages'). Optional when artifact_units is used."},
432
+ "artifact_units": {
433
+ "type": ["array", "null"],
434
+ "items": {"type": "string"},
435
+ "description": "Explicit list of top-level folder names that are each themselves an artifact/app, for repos with sibling top-level apps instead of a shared container folder (e.g. ['cemix-api', 'cemix-web', 'cemix-admin']). Use instead of artifacts_folder.",
436
+ },
428
437
  }),
429
438
  ),
430
439
  types.Tool(
@@ -267,6 +267,7 @@ class GenerateRepoMapInput(BaseModel):
267
267
  project: str | None = None
268
268
  artifacts_folder: str | None = None
269
269
  modules_folder: str | None = None
270
+ artifact_units: list[str] | None = None
270
271
 
271
272
 
272
273
  class KGContextInput(BaseModel):
@@ -1213,6 +1214,7 @@ class CodepreprocTools:
1213
1214
  mapper.build,
1214
1215
  artifacts_folder=payload.artifacts_folder,
1215
1216
  modules_folder=payload.modules_folder,
1217
+ artifact_units=payload.artifact_units,
1216
1218
  )
1217
1219
  except NeedsMonorepoConfig as exc:
1218
1220
  return {
@@ -1234,10 +1236,20 @@ class CodepreprocTools:
1234
1236
  f"Available root directories: {exc.root_dirs}"
1235
1237
  ),
1236
1238
  },
1239
+ {
1240
+ "param": "artifact_units",
1241
+ "question": (
1242
+ "If the deployable apps are sibling top-level folders instead of living "
1243
+ "under one shared container, list them directly (e.g. "
1244
+ f"{exc.root_dirs[:3]}) via artifact_units instead of artifacts_folder."
1245
+ ),
1246
+ },
1237
1247
  ],
1238
1248
  "hint": (
1239
- "Re-invoke generate_repo_map with artifacts_folder and modules_folder set "
1240
- "to the correct directory names."
1249
+ "Re-invoke generate_repo_map with either (artifacts_folder + modules_folder) set "
1250
+ "to the correct container directory names, or artifact_units set to the explicit "
1251
+ "list of top-level folder names that are themselves artifacts (modules_folder is "
1252
+ "still optional in that case)."
1241
1253
  ),
1242
1254
  }
1243
1255
 
@@ -103,15 +103,18 @@ def _detect_monorepo(root: Path) -> tuple[str | None, str | None]:
103
103
  return None, None
104
104
 
105
105
 
106
- def _split_monorepo_path(parts: tuple[str, ...]) -> tuple[str, str]:
106
+ def _split_monorepo_path(parts: tuple[str, ...], offset: int = 1) -> tuple[str, str]:
107
107
  """(unit_name, internal_module_dir) for paths under a monorepo top-folder.
108
108
 
109
- apps/api/src/auth/service.ts → ("api", "auth")
110
- apps/api/src/service.ts → ("api", ".")
111
- apps/api/auth/service.ts → ("api", "auth") # no src/
109
+ offset=1 (default): parts[0] is the container folder (e.g. "apps"), parts[1] is the unit.
110
+ apps/api/src/auth/service.ts → ("api", "auth")
111
+ apps/api/src/service.ts → ("api", ".")
112
+ apps/api/auth/service.ts → ("api", "auth") # no src/
113
+ offset=0: parts[0] is itself the unit (explicit top-level artifact folders, no container).
114
+ cemix-api/src/auth/service.ts → ("cemix-api", "auth")
112
115
  """
113
- unit_name = parts[1]
114
- internal = parts[2:]
116
+ unit_name = parts[offset]
117
+ internal = parts[offset + 1:]
115
118
  if internal and internal[0] == "src":
116
119
  internal = internal[1:]
117
120
  return unit_name, str(Path(*internal[:-1])) if len(internal) > 1 else "."
@@ -134,9 +137,24 @@ class RepoMapper:
134
137
  self,
135
138
  artifacts_folder: str | None = None,
136
139
  modules_folder: str | None = None,
140
+ artifact_units: list[str] | None = None,
137
141
  ) -> dict[str, Any]:
138
- if artifacts_folder and modules_folder:
139
- af, mf = artifacts_folder.strip("/"), modules_folder.strip("/")
142
+ """artifacts_folder/modules_folder: single container folders whose direct
143
+ subfolders are the units (e.g. apps/api, apps/web).
144
+ artifact_units: explicit list of top-level folder names that are themselves
145
+ artifacts, for repos with sibling top-level apps instead of a shared
146
+ container (e.g. ["cemix-api", "cemix-web", "cemix-admin"]).
147
+ """
148
+ mf = modules_folder.strip("/") if modules_folder else None
149
+
150
+ if artifact_units:
151
+ units = frozenset(u.strip("/") for u in artifact_units)
152
+ monorepo_meta: dict[str, Any] = {"artifact_units": sorted(units), "modules_folder": mf}
153
+ file_groups = self._group_files(af=None, mf=mf, artifact_units=units)
154
+ elif artifacts_folder and mf:
155
+ af = artifacts_folder.strip("/")
156
+ monorepo_meta = {"artifacts_folder": af, "modules_folder": mf}
157
+ file_groups = self._group_files(af, mf)
140
158
  else:
141
159
  af, mf = _detect_monorepo(self.project.root)
142
160
  if af is None:
@@ -145,19 +163,25 @@ class RepoMapper:
145
163
  if d.is_dir() and d.name not in _IGNORED_DIRS
146
164
  )
147
165
  raise NeedsMonorepoConfig(root_dirs)
166
+ monorepo_meta = {"artifacts_folder": af, "modules_folder": mf}
167
+ file_groups = self._group_files(af, mf)
148
168
 
149
- file_groups = self._group_files(af, mf)
150
169
  relationships = self._load_relationships()
151
170
 
152
171
  return {
153
172
  "project_id": self.project.project_id,
154
173
  "generated_at": datetime.now(timezone.utc).isoformat(),
155
- "monorepo": {"artifacts_folder": af, "modules_folder": mf},
174
+ "monorepo": monorepo_meta,
156
175
  "_file_groups": file_groups,
157
176
  "_relationships": relationships,
158
177
  }
159
178
 
160
- def _group_files(self, af: str, mf: str) -> list[dict]:
179
+ def _group_files(
180
+ self,
181
+ af: str | None,
182
+ mf: str | None,
183
+ artifact_units: frozenset[str] | None = None,
184
+ ) -> list[dict]:
161
185
  groups: dict[tuple, dict] = {}
162
186
  root = self.project.root
163
187
 
@@ -174,7 +198,21 @@ class RepoMapper:
174
198
  continue
175
199
  parts = rel.parts
176
200
 
177
- if len(parts) >= 3 and parts[0] == af:
201
+ if artifact_units and len(parts) >= 2 and parts[0] in artifact_units:
202
+ unit_name, mod_path = _split_monorepo_path(parts, offset=0)
203
+ key = ("artifact", unit_name, mod_path)
204
+ if key not in groups:
205
+ groups[key] = {
206
+ "context": "artifact",
207
+ "unit_name": unit_name,
208
+ "unit_path": unit_name,
209
+ "module_name": mod_path,
210
+ "module_path": str(Path(parts[0]) / mod_path),
211
+ "file_paths": [],
212
+ }
213
+ groups[key]["file_paths"].append(str(rel))
214
+
215
+ elif af and len(parts) >= 3 and parts[0] == af:
178
216
  unit_name, mod_path = _split_monorepo_path(parts)
179
217
  key = ("artifact", unit_name, mod_path)
180
218
  if key not in groups:
@@ -188,7 +226,7 @@ class RepoMapper:
188
226
  }
189
227
  groups[key]["file_paths"].append(str(rel))
190
228
 
191
- elif len(parts) >= 3 and parts[0] == mf:
229
+ elif mf and len(parts) >= 3 and parts[0] == mf:
192
230
  unit_name, mod_path = _split_monorepo_path(parts)
193
231
  key = ("module", unit_name, mod_path)
194
232
  if key not in groups:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codrspot-processor-mcp
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Local MCP server exposing codepreproc's code-context tools to Claude Code
5
5
  Author-email: alexlqi <alexlqi@gmail.com>
6
6
  License: Copyright (c) 2026 alexlqi (alexlqi@gmail.com)