Skip to content

Commit bdebb63

Browse files
jgravelleclaude
andcommitted
v1.108.90 — new tool: get_endpoint_impact (endpoint-centric blast radius)
"What breaks if I change GET /users?" Maps an HTTP endpoint (verb+path, or a handler_symbol_id) to its handler, then fuses get_blast_radius (importers + callers) + rendered views into one read-only answer. - Endpoint resolution unifies existing coverage (no new parsing infra): string- dispatch routes via flow_edges (Django/Express/Flask/Rails) + decorator routes via get_signal_chains gateway classification (Flask/FastAPI/Spring local path), matched verb+path (exact -> suffix). - Standard tier (not core -> core_compact unaffected). Registered across all surfaces: _CANONICAL_TOOL_NAMES, _SNIPPET_TOOL_CATEGORIES, _TOOL_TIER_STANDARD, Tool schema + dispatch, config DEFAULTS tool_tier_bundles (+ template), all_tools. - Known limitation (next phase): FastAPI APIRouter prefix composition + Spring class-level @RequestMapping inheritance unresolved -> those match by local path or via handler_symbol_id. First slice of docs/prd-framework-routes-endpoint-impact.md. New tools/get_endpoint_impact.py + tests/test_endpoint_impact.py (10). Tool count 85->86 full. Full suite 4882 passed. No INDEX_VERSION bump. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 7189258 commit bdebb63

9 files changed

Lines changed: 531 additions & 14 deletions

File tree

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,30 @@
22

33
All notable changes to jcodemunch-mcp are documented here.
44

5+
## [1.108.90] - 2026-06-30 - New tool: get_endpoint_impact (endpoint-centric blast radius)
6+
7+
### Added
8+
9+
- **`get_endpoint_impact`** — "what breaks if I change this HTTP endpoint?" Given
10+
an endpoint (`GET /users` or `/users`, verb optional) or a `handler_symbol_id`,
11+
it resolves the route to its handler and fuses the existing impact primitives
12+
into one read-only answer: importing files + callers (blast radius) and the
13+
templates the handler renders.
14+
- **Unified endpoint resolution** over the route coverage the index already
15+
exposes: string-dispatched routes via `flow_edges` (Django/Express/Flask/Rails)
16+
and decorator-bound routes via the gateway classification `get_signal_chains`
17+
uses (Flask/FastAPI/Spring), matched by verb + path (exact, then suffix). For
18+
prefix-composed FastAPI (`APIRouter(prefix=...)`) or Spring class-level
19+
mappings whose full URL isn't resolved yet, pass `handler_symbol_id`.
20+
21+
Standard tier (alongside `get_blast_radius` / `get_pr_risk_profile`), so
22+
`core_compact` is unaffected. New `tools/get_endpoint_impact.py`; registered in
23+
`server.py`. New `tests/test_endpoint_impact.py` (10). No INDEX_VERSION bump.
24+
25+
> First slice of the framework-routes PRD. Deeper framework path resolution
26+
> (FastAPI prefix chains, Spring class-level mapping inheritance, Nuxt file
27+
> routes) is the follow-on that enriches this same endpoint table.
28+
529
## [1.108.89] - 2026-06-30 - Revert the 1.108.88 Antigravity install target; document correct manual config
630

731
1.108.88 added an `install antigravity` target that wrote to the **wrong**

CLAUDE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# jcodemunch-mcp — Project Brief
22

33
## Current State
4+
- **Version:** 1.108.90 — New tool **`get_endpoint_impact`** (endpoint-centric blast radius; first slice of the framework-routes PRD `docs/prd-framework-routes-endpoint-impact.md`). "What breaks if I change `GET /users`?" Maps an endpoint (verb+path, or a `handler_symbol_id`) to its handler, then fuses `get_blast_radius` (importers + callers) + rendered views into one read-only answer. **Endpoint resolution unifies two existing sources** (no new parsing infra): string-dispatch routes via `flow_edges.resolve_flow_edges(kinds=("route",))` (Django/Express/Flask/Rails) + decorator routes via `get_signal_chains._classify_gateway`/`_extract_label` (Flask/FastAPI/Spring local path), matched verb+path (exact→suffix). New `tools/get_endpoint_impact.py` (`_collect_endpoints`/`_match_endpoints`/`_impact_for_handler`); **standard tier** (not core → core_compact unchanged). Registered across all surfaces: `_CANONICAL_TOOL_NAMES`, `_SNIPPET_TOOL_CATEGORIES`, `_TOOL_TIER_STANDARD`, the `Tool()` schema + dispatch in `server.py`, and `config.py` `all_tools`. KNOWN LIMITATION (next phase): FastAPI `APIRouter(prefix=)`/`include_router` composition + Spring class-level `@RequestMapping` inheritance not resolved → those routes only match by local path or via `handler_symbol_id`. Investigation correction to the PRD: FastAPI is decorator-based (already a gateway), so its real gap is prefix-path composition, NOT a new flow_edges shape — that's why the tool (which works on existing coverage) was the right first slice, not "FastAPI first." New `tests/test_endpoint_impact.py` (10). NO INDEX_VERSION bump. Clean-room from the GitNexus review (see memory `reference_competitor_gitnexus`).
45
- **Version:** 1.108.89 — Revert the 1.108.88 `install antigravity` target; document the correct manual config instead. 1.108.88 wrote to the WRONG paths (`~/.gemini/settings.json` + `~/.gemini/antigravity/skills/`, lifted from a competitor README) so it never configured Antigravity. **Authoritative paths (Google docs + our own `reference_antigravity_integration` memory):** Antigravity (2.0/IDE/CLI) loads MCP servers from the shared HOME-level **`~/.gemini/config/mcp_config.json`** (`mcpServers` key); shared skills in `~/.gemini/skills/` (CLI-only `~/.gemini/antigravity-cli/skills/`). This release deletes `cli/antigravity.py`, restores `cli/skills.py`+`cli/init.py`+`server.py` to 1.108.87 shape, removes `tests/test_antigravity_install.py`, and adds a copy-paste `mcp_config.json` block to README "Works with". **#307 was already CLOSED 2026-05-23** (manual config documented/working); a first-class installer stays DEFERRED (demand threshold ~5 reports, `feedback_demand_driven_installer_support`). Lesson: reconcile our own hands-on memory before trusting a competitor's README; verify config paths against the live contract. NO INDEX_VERSION bump.
56
- **Versions 1.108.85–1.108.87** (all 2026-06-30): **.85** install-mechanism-aware `watch` hint (`watch_extra_install_command()` → pipx inject / uv tool install / uvx --with) + migration-warning de-spam (`_MIGRATION_SCHEMA_WARNED` warn-once per repo) — #357 follow-up @zakblacki. **.86** `watch-all` prints a steady-state line (Ctrl+C / `watch-install`) + per-repo "Now watching … (idle until you edit a file)" so the post-index silence isn't read as a hang. **.87** License v1.1: non-commercial use/copy/modify stay free but redistribution narrowed (no registry republish, no rename/rebrand, no false-authorship, no name/marks) — response to the AnimAIOS `animamunch` PyPI fork; see memory `project_animamunch_fork`.
67
- **Version:** 1.108.84 — Install-mechanism-aware `upgrade` (#357, reported by @zakblacki on a pipx install). `jcodemunch-mcp upgrade` ran `sys.executable -m pip install -U` blindly; pipx/uv venvs ship NO `pip` module → `No module named pip`, pip exited non-zero, and the command **bailed before refreshing hooks**. Compounding it: the startup version-drift warning (`server.py`) told the user to run `jcodemunch-mcp upgrade` to clear the stale-hook nag — the exact pip-less-failing command — so it never cleared. Fix (rewrote `cli/upgrade.py`): new `detect_install_mechanism()` (path/env heuristic, no subprocess) → `(mechanism, upgrade_command)` for pip/pipx/uv/uvx/venv. `_pip_available()` gates the in-process `pip install -U`: present → runs as before (a genuine pip *failure* now refreshes hooks anyway + preserves the non-zero rc, was: skip-and-bail); **absent → does NOT shell out to a foreign package manager** (honors jjg's stated "detect then tell, don't guess-and-run" stance from the issue thread), prints the exact command (`pipx upgrade` / `uv tool upgrade`), and refreshes hooks in-process via `init --hooks` (pip-free, stamps `last_init_version.txt` so the nag clears). The nag warning now leads with `init --hooks`. NO INDEX_VERSION bump. New `tests/test_v1_108_84.py` (11). Files: `cli/upgrade.py` (rewrite), `server.py` (warning text). Side issues answered in #357 reply (not bugs): `.pack/nodejs` migration warning = stale starter-pack index; `find_dead_code` `framework_warning` inflated dead-code % on a Node project because its entry-point heuristic looks for `main.py`/`app.py` (pass `entry_point_patterns` or reindex); real-time freshness = `watch-all`. See [[project_jmunch_console]].
@@ -84,7 +85,7 @@
8485
- **INDEX_VERSION:** 16
8586
- **Tests:** 4432 passed, 10 skipped (1.108.25 — full count varies by optional-dep availability)
8687
- **Python:** >=3.10
87-
- **Tool count:** 85 in `full` (front door hidden; +1 v1.108.69 `get_delivery_metrics`); `tool_surface=counter` exposes a 3-tool front door (`order`/`menu`/`route`) instead
88+
- **Tool count:** 86 in `full` (front door hidden; +1 v1.108.69 `get_delivery_metrics`, +1 v1.108.90 `get_endpoint_impact`); `tool_surface=counter` exposes a 3-tool front door (`order`/`menu`/`route`) instead
8889

8990
## Key Files
9091
```
@@ -162,6 +163,7 @@ src/jcodemunch_mcp/
162163
assemble_task_context.py # assemble_task_context: task-aware single-call context orchestrator. Auto-classifies the task into one of six intents (explore/debug/refactor/extend/audit/review) via keyword scoring, auto-extracts anchor symbol names from the task, runs the intent-appropriate sub-tool sequence (digest + hotspots + tectonic for explore; anchor + callers + callees + blast + runtime for debug; anchor + rename_safe + delete_safe + implementations + similar for refactor; anchor + implementations + similar + decorators for extend; anchor + risk + blast + dead_code + untested for audit; changed + blast + risk + similar_changed for review), packs results into a single source-attributed capsule under token_budget. Each entry tagged with stage + source_tool. Intent classification is explainable (returns intent_keywords_matched + intent_confidence). Caller can override intent and include to force specific stages.
163164
get_tectonic_map.py # get_tectonic_map: logical module topology via 3-signal fusion (structural+behavioral+temporal) + label propagation
164165
get_signal_chains.py # get_signal_chains: entry-point-to-leaf pathway discovery; traces how HTTP/CLI/task/event signals propagate through the call graph; discovery + lookup modes. v1.108.58: include_flow_edges param consumes flow_edges.py — string-dispatched handlers become http gateways, rendered templates attach as a per-chain `views` list
166+
get_endpoint_impact.py # (v1.108.90) Endpoint-centric impact: "what breaks if I change GET /users?" _collect_endpoints unifies flow_edges route edges (string-dispatch) + get_signal_chains decorator gateways (Flask/FastAPI/Spring local path) into one endpoint table; _match_endpoints (verb+path exact→suffix); _impact_for_handler fuses get_blast_radius (importers+callers) + render→view edges. Read-only, standard tier. handler_symbol_id bypasses URL resolution for prefixed routes. First slice of docs/prd-framework-routes-endpoint-impact.md; FastAPI prefix / Spring class-mapping composition is the follow-on
165167
flow_edges.py # (v1.108.58) Language-agnostic framework flow-edge resolver. resolve_flow_edges(index, store, owner, name, kinds=("route","render")) emits typed edges the AST call graph misses: route→handler (Django path/re_path/url, Express/Fastify/Koa .get(p,h), Flask add_url_rule view_func=, Rails to:"ctrl#action") resolved to symbols via the import graph; render→view (render/render_template/res.render/view string templates) resolved to the template file when indexed. Shape-keyed (one resolver, not per-framework plugins); reuses _ContentCache/_symbol_body/build_symbols_by_file/resolve_specifier. Pure read path, no reindex. Decorator-bound handlers NOT re-emitted (they already surface as gateways)
166168
render_diagram.py # render_diagram: universal Mermaid renderer; auto-detects source tool, picks optimal diagram type (flowchart/sequence), encodes metadata as visual signals; 3 themes, smart pruning; optional `open_in_viewer` (config-gated, spawns mmd-viewer)
167169
mermaid_viewer.py # mmd-viewer spawn helper for render_diagram; resolve_viewer_path/open_diagram/cleanup_temp_dir; jcm- prefix for safe cleanup; config-gated via render_diagram_viewer_enabled + mermaid_viewer_path

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ The point: jCodeMunch is structured retrieval *with* an orchestration layer over
279279

280280
### Structural queries native tools can't answer
281281

282-
`find_importers` tells you what imports a file. `get_blast_radius` tells you what breaks if you change a symbol, with depth-weighted risk scores and optional source snippets. `get_class_hierarchy` traverses inheritance chains. `get_call_hierarchy` traces callers and callees N levels deep using AST-derived call graphs, with optional LSP-enriched dispatch resolution for interface/trait method calls. `find_dead_code` finds symbols and files unreachable from any entry point. `get_untested_symbols` finds functions with no evidence of test-file reachability — the intersection of import-graph analysis and test-file detection. `get_changed_symbols` maps a git diff to the exact symbols that were added, modified, or removed. `get_symbol_importance` ranks your codebase by architectural centrality using PageRank on the import graph. `get_hotspots` surfaces the riskiest code by combining complexity with git churn. `get_dependency_cycles` detects circular imports. `get_coupling_metrics` measures module coupling and instability. `get_tectonic_map` discovers the logical module topology by fusing three coupling signals (imports, shared references, git co-churn) — revealing hidden module boundaries, misplaced files, and god-module risk without any configuration. `get_signal_chains` traces how external signals (HTTP requests, CLI commands, scheduled tasks, events) propagate through the codebase via the call graph — discovery mode maps all entry-point-to-leaf pathways and reports orphan symbols, lookup mode tells you which user-facing chains a specific symbol participates in (e.g. "validate_email sits on POST /api/users and cli:import-users"). These are not "faster grep" — they are questions grep cannot answer at all.
282+
`find_importers` tells you what imports a file. `get_blast_radius` tells you what breaks if you change a symbol, with depth-weighted risk scores and optional source snippets. `get_class_hierarchy` traverses inheritance chains. `get_call_hierarchy` traces callers and callees N levels deep using AST-derived call graphs, with optional LSP-enriched dispatch resolution for interface/trait method calls. `find_dead_code` finds symbols and files unreachable from any entry point. `get_untested_symbols` finds functions with no evidence of test-file reachability — the intersection of import-graph analysis and test-file detection. `get_changed_symbols` maps a git diff to the exact symbols that were added, modified, or removed. `get_symbol_importance` ranks your codebase by architectural centrality using PageRank on the import graph. `get_hotspots` surfaces the riskiest code by combining complexity with git churn. `get_dependency_cycles` detects circular imports. `get_coupling_metrics` measures module coupling and instability. `get_tectonic_map` discovers the logical module topology by fusing three coupling signals (imports, shared references, git co-churn) — revealing hidden module boundaries, misplaced files, and god-module risk without any configuration. `get_signal_chains` traces how external signals (HTTP requests, CLI commands, scheduled tasks, events) propagate through the codebase via the call graph — discovery mode maps all entry-point-to-leaf pathways and reports orphan symbols, lookup mode tells you which user-facing chains a specific symbol participates in (e.g. "validate_email sits on POST /api/users and cli:import-users"). `get_endpoint_impact` answers the endpoint-shaped version of "what breaks if I change X": give it an HTTP endpoint (`GET /users`) or a handler symbol and it resolves the route to its handler — across string-dispatch (Django/Express/Flask/Rails) and decorator routes (Flask/FastAPI/Spring) — then fuses the blast radius (importing files + callers) with the templates that handler renders, in one read-only call mapping a URL to everything a change to it would touch. These are not "faster grep" — they are questions grep cannot answer at all.
283283

284284
### Agent config hygiene
285285

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "jcodemunch-mcp"
3-
version = "1.108.89"
3+
version = "1.108.90"
44
description = "Token-efficient MCP server for source code exploration via tree-sitter AST parsing"
55
readme = "README.md"
66
requires-python = ">=3.10"

src/jcodemunch_mcp/config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,7 @@ def apply_adaptive_languages(source_root: str, detected: set[str]) -> bool:
323323
"find_implementations",
324324
"get_impact_preview", "get_changed_symbols",
325325
"get_symbol_diff", "get_symbol_provenance",
326-
"get_pr_risk_profile", "get_symbol_complexity",
326+
"get_pr_risk_profile", "get_endpoint_impact", "get_symbol_complexity",
327327
"get_churn_rate", "get_delivery_metrics", "get_hotspots",
328328
"get_symbol_importance", "get_repo_map", "find_dead_code",
329329
"get_dead_code_v2", "get_untested_symbols", "find_similar_symbols",
@@ -1740,6 +1740,7 @@ def generate_template() -> str:
17401740
"get_file_risk",
17411741
"get_file_tree",
17421742
"get_hotspots",
1743+
"get_endpoint_impact",
17431744
"get_impact_preview",
17441745
"get_layer_violations",
17451746
"get_pr_risk_profile",
@@ -2002,7 +2003,7 @@ def generate_template() -> str:
20022003
"find_implementations",
20032004
"get_impact_preview", "get_changed_symbols",
20042005
"get_symbol_diff", "get_symbol_provenance",
2005-
"get_pr_risk_profile", "get_symbol_complexity",
2006+
"get_pr_risk_profile", "get_endpoint_impact", "get_symbol_complexity",
20062007
"get_churn_rate", "get_delivery_metrics", "get_hotspots",
20072008
"get_symbol_importance", "get_repo_map", "find_dead_code",
20082009
"get_dead_code_v2", "get_untested_symbols", "find_similar_symbols",

0 commit comments

Comments
 (0)