Skip to content

Commit 55a838a

Browse files
author
Your Name
committed
fix(mcp): wire get_architecture to full store analysis
The get_architecture MCP handler was only returning node/edge label counts (identical to get_graph_schema). The store has a full architecture analysis function cbm_store_get_architecture() that computes languages, hotspots, routes, entry points, packages, clusters, and layers — but it was never called from the MCP handler. Wire all architecture aspects into the response: - languages: file counts per language - hotspots: highest fan-in functions - routes: HTTP route definitions - entry_points: main/handler functions - packages: top-level module groupings - clusters: Louvain community detection results Use strcpy variants for all architecture strings since they're freed by cbm_store_architecture_free before any potential reuse. Tested: cube get_architecture went from 0 for all fields to 10 languages, 10 hotspots, 13 routes, 20 entry points, 15 packages.
1 parent c52469e commit 55a838a

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

src/mcp/mcp.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,12 @@ static char *handle_get_architecture(cbm_mcp_server_t *srv, const char *args) {
11691169
int node_count = cbm_store_count_nodes(store, project);
11701170
int edge_count = cbm_store_count_edges(store, project);
11711171

1172+
/* Call the full architecture analysis */
1173+
cbm_architecture_info_t arch = {0};
1174+
const char *all_aspects[] = {"languages", "hotspots", "routes", "entry_points",
1175+
"packages", "clusters", "layers", "boundaries"};
1176+
cbm_store_get_architecture(store, project, all_aspects, 8, &arch);
1177+
11721178
yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);
11731179
yyjson_mut_val *root = yyjson_mut_obj(doc);
11741180
yyjson_mut_doc_set_root(doc, root);
@@ -1199,6 +1205,105 @@ static char *handle_get_architecture(cbm_mcp_server_t *srv, const char *args) {
11991205
}
12001206
yyjson_mut_obj_add_val(doc, root, "edge_types", types);
12011207

1208+
/* Languages */
1209+
if (arch.language_count > 0) {
1210+
yyjson_mut_val *langs = yyjson_mut_arr(doc);
1211+
for (int i = 0; i < arch.language_count; i++) {
1212+
yyjson_mut_val *item = yyjson_mut_obj(doc);
1213+
yyjson_mut_obj_add_strcpy(doc, item, "language",
1214+
arch.languages[i].language ? arch.languages[i].language : "");
1215+
yyjson_mut_obj_add_int(doc, item, "files", arch.languages[i].file_count);
1216+
yyjson_mut_arr_add_val(langs, item);
1217+
}
1218+
yyjson_mut_obj_add_val(doc, root, "languages", langs);
1219+
}
1220+
1221+
/* Hotspots (high fan-in functions) */
1222+
if (arch.hotspot_count > 0) {
1223+
yyjson_mut_val *spots = yyjson_mut_arr(doc);
1224+
for (int i = 0; i < arch.hotspot_count; i++) {
1225+
yyjson_mut_val *item = yyjson_mut_obj(doc);
1226+
yyjson_mut_obj_add_strcpy(doc, item, "name",
1227+
arch.hotspots[i].name ? arch.hotspots[i].name : "");
1228+
yyjson_mut_obj_add_strcpy(
1229+
doc, item, "qualified_name",
1230+
arch.hotspots[i].qualified_name ? arch.hotspots[i].qualified_name : "");
1231+
yyjson_mut_obj_add_int(doc, item, "fan_in", arch.hotspots[i].fan_in);
1232+
yyjson_mut_arr_add_val(spots, item);
1233+
}
1234+
yyjson_mut_obj_add_val(doc, root, "hotspots", spots);
1235+
}
1236+
1237+
/* Routes */
1238+
if (arch.route_count > 0) {
1239+
yyjson_mut_val *routes_arr = yyjson_mut_arr(doc);
1240+
for (int i = 0; i < arch.route_count; i++) {
1241+
yyjson_mut_val *item = yyjson_mut_obj(doc);
1242+
yyjson_mut_obj_add_strcpy(doc, item, "method",
1243+
arch.routes[i].method ? arch.routes[i].method : "");
1244+
yyjson_mut_obj_add_strcpy(doc, item, "path",
1245+
arch.routes[i].path ? arch.routes[i].path : "");
1246+
yyjson_mut_obj_add_strcpy(doc, item, "handler",
1247+
arch.routes[i].handler ? arch.routes[i].handler : "");
1248+
yyjson_mut_arr_add_val(routes_arr, item);
1249+
}
1250+
yyjson_mut_obj_add_val(doc, root, "routes", routes_arr);
1251+
}
1252+
1253+
/* Entry points */
1254+
if (arch.entry_point_count > 0) {
1255+
yyjson_mut_val *eps = yyjson_mut_arr(doc);
1256+
for (int i = 0; i < arch.entry_point_count; i++) {
1257+
yyjson_mut_val *item = yyjson_mut_obj(doc);
1258+
yyjson_mut_obj_add_strcpy(doc, item, "name",
1259+
arch.entry_points[i].name ? arch.entry_points[i].name : "");
1260+
yyjson_mut_obj_add_strcpy(
1261+
doc, item, "qualified_name",
1262+
arch.entry_points[i].qualified_name ? arch.entry_points[i].qualified_name : "");
1263+
yyjson_mut_obj_add_strcpy(doc, item, "file",
1264+
arch.entry_points[i].file ? arch.entry_points[i].file : "");
1265+
yyjson_mut_arr_add_val(eps, item);
1266+
}
1267+
yyjson_mut_obj_add_val(doc, root, "entry_points", eps);
1268+
}
1269+
1270+
/* Packages */
1271+
if (arch.package_count > 0) {
1272+
yyjson_mut_val *pkgs = yyjson_mut_arr(doc);
1273+
for (int i = 0; i < arch.package_count; i++) {
1274+
yyjson_mut_val *item = yyjson_mut_obj(doc);
1275+
yyjson_mut_obj_add_strcpy(doc, item, "name",
1276+
arch.packages[i].name ? arch.packages[i].name : "");
1277+
yyjson_mut_obj_add_int(doc, item, "node_count", arch.packages[i].node_count);
1278+
yyjson_mut_obj_add_int(doc, item, "fan_in", arch.packages[i].fan_in);
1279+
yyjson_mut_obj_add_int(doc, item, "fan_out", arch.packages[i].fan_out);
1280+
yyjson_mut_arr_add_val(pkgs, item);
1281+
}
1282+
yyjson_mut_obj_add_val(doc, root, "packages", pkgs);
1283+
}
1284+
1285+
/* Clusters */
1286+
if (arch.cluster_count > 0) {
1287+
yyjson_mut_val *cls = yyjson_mut_arr(doc);
1288+
for (int i = 0; i < arch.cluster_count; i++) {
1289+
yyjson_mut_val *item = yyjson_mut_obj(doc);
1290+
yyjson_mut_obj_add_int(doc, item, "id", arch.clusters[i].id);
1291+
yyjson_mut_obj_add_strcpy(doc, item, "label",
1292+
arch.clusters[i].label ? arch.clusters[i].label : "");
1293+
yyjson_mut_obj_add_int(doc, item, "members", arch.clusters[i].members);
1294+
yyjson_mut_obj_add_real(doc, item, "cohesion", arch.clusters[i].cohesion);
1295+
if (arch.clusters[i].top_node_count > 0) {
1296+
yyjson_mut_val *tn = yyjson_mut_arr(doc);
1297+
for (int j = 0; j < arch.clusters[i].top_node_count; j++) {
1298+
yyjson_mut_arr_add_strcpy(doc, tn, arch.clusters[i].top_nodes[j]);
1299+
}
1300+
yyjson_mut_obj_add_val(doc, item, "top_nodes", tn);
1301+
}
1302+
yyjson_mut_arr_add_val(cls, item);
1303+
}
1304+
yyjson_mut_obj_add_val(doc, root, "clusters", cls);
1305+
}
1306+
12021307
/* Relationship patterns */
12031308
if (schema.rel_pattern_count > 0) {
12041309
yyjson_mut_val *pats = yyjson_mut_arr(doc);
@@ -1210,6 +1315,7 @@ static char *handle_get_architecture(cbm_mcp_server_t *srv, const char *args) {
12101315

12111316
char *json = yy_doc_to_str(doc);
12121317
yyjson_mut_doc_free(doc);
1318+
cbm_store_architecture_free(&arch);
12131319
cbm_store_schema_free(&schema);
12141320
free(project);
12151321

0 commit comments

Comments
 (0)