Skip to content

Commit 172d3a6

Browse files
fix(mcp): extend project-not-indexed guard to all query handlers
- Add static helper verify_project_indexed() before handle_get_graph_schema - Replace inline guard in handle_get_architecture with helper call - Apply guard to handle_search_graph, handle_get_graph_schema, handle_trace_call_path, handle_get_code_snippet, handle_query_graph - All five query handlers now return {"error":"project not indexed — run index_repository first"} instead of silently returning empty results Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent c38853f commit 172d3a6

1 file changed

Lines changed: 62 additions & 0 deletions

File tree

src/mcp/mcp.c

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,11 +745,36 @@ static char *handle_list_projects(cbm_mcp_server_t *srv, const char *args) {
745745
return result;
746746
}
747747

748+
/* verify_project_indexed — returns a heap-allocated error JSON string when the
749+
* named project has not been indexed yet, or NULL when the project exists.
750+
* resolve_store uses SQLITE_OPEN_CREATE so store is always non-NULL even for
751+
* unindexed projects; this check catches that silent-empty case.
752+
* Callers that receive a non-NULL return value must free(project) themselves
753+
* before returning the error string. */
754+
static char *verify_project_indexed(cbm_store_t *store, const char *project) {
755+
if (!project) {
756+
return NULL; /* default project — always exists */
757+
}
758+
cbm_project_t proj_check = {0};
759+
if (cbm_store_get_project(store, project, &proj_check) != CBM_STORE_OK) {
760+
return cbm_mcp_text_result(
761+
"{\"error\":\"project not indexed — run index_repository first\"}", true);
762+
}
763+
cbm_project_free_fields(&proj_check);
764+
return NULL;
765+
}
766+
748767
static char *handle_get_graph_schema(cbm_mcp_server_t *srv, const char *args) {
749768
char *project = cbm_mcp_get_string_arg(args, "project");
750769
cbm_store_t *store = resolve_store(srv, project);
751770
REQUIRE_STORE(store, project);
752771

772+
char *not_indexed = verify_project_indexed(store, project);
773+
if (not_indexed) {
774+
free(project);
775+
return not_indexed;
776+
}
777+
753778
cbm_schema_info_t schema = {0};
754779
cbm_store_get_schema(store, project, &schema);
755780

@@ -807,6 +832,13 @@ static char *handle_search_graph(cbm_mcp_server_t *srv, const char *args) {
807832
char *project = cbm_mcp_get_string_arg(args, "project");
808833
cbm_store_t *store = resolve_store(srv, project);
809834
REQUIRE_STORE(store, project);
835+
836+
char *not_indexed = verify_project_indexed(store, project);
837+
if (not_indexed) {
838+
free(project);
839+
return not_indexed;
840+
}
841+
810842
char *label = cbm_mcp_get_string_arg(args, "label");
811843
char *name_pattern = cbm_mcp_get_string_arg(args, "name_pattern");
812844
char *file_pattern = cbm_mcp_get_string_arg(args, "file_pattern");
@@ -882,6 +914,13 @@ static char *handle_query_graph(cbm_mcp_server_t *srv, const char *args) {
882914
return cbm_mcp_text_result("{\"error\":\"no project loaded\"}", true);
883915
}
884916

917+
char *not_indexed = verify_project_indexed(store, project);
918+
if (not_indexed) {
919+
free(project);
920+
free(query);
921+
return not_indexed;
922+
}
923+
885924
cbm_cypher_result_t result = {0};
886925
int rc = cbm_cypher_execute(store, query, project, max_rows, &result);
887926

@@ -1012,6 +1051,13 @@ static char *handle_get_architecture(cbm_mcp_server_t *srv, const char *args) {
10121051
cbm_store_t *store = resolve_store(srv, project);
10131052
REQUIRE_STORE(store, project);
10141053

1054+
char *not_indexed = verify_project_indexed(store, project);
1055+
if (not_indexed) {
1056+
free(project);
1057+
return not_indexed;
1058+
}
1059+
1060+
10151061
cbm_schema_info_t schema = {0};
10161062
cbm_store_get_schema(store, project, &schema);
10171063

@@ -1085,6 +1131,15 @@ static char *handle_trace_call_path(cbm_mcp_server_t *srv, const char *args) {
10851131
free(direction);
10861132
return cbm_mcp_text_result("{\"error\":\"no project loaded\"}", true);
10871133
}
1134+
1135+
char *not_indexed = verify_project_indexed(store, project);
1136+
if (not_indexed) {
1137+
free(func_name);
1138+
free(project);
1139+
free(direction);
1140+
return not_indexed;
1141+
}
1142+
10881143
if (!direction) {
10891144
direction = heap_strdup("both");
10901145
}
@@ -1575,6 +1630,13 @@ static char *handle_get_code_snippet(cbm_mcp_server_t *srv, const char *args) {
15751630
return cbm_mcp_text_result("no project loaded — run index_repository first", true);
15761631
}
15771632

1633+
char *not_indexed = verify_project_indexed(store, project);
1634+
if (not_indexed) {
1635+
free(qn);
1636+
free(project);
1637+
return not_indexed;
1638+
}
1639+
15781640
/* Default to current project (same as all other tools) */
15791641
const char *effective_project = project ? project : srv->current_project;
15801642

0 commit comments

Comments
 (0)