279279 },
280280 "execution" : {"taskSupport" : "forbidden" },
281281 },
282+ {
283+ "name" : "sin_simone_mcp_graphify_query" ,
284+ "title" : "Graphify Query" ,
285+ "description" : "Ask a question about a codebase using its knowledge graph (graphify BFS traversal)." ,
286+ "inputSchema" : {
287+ "$schema" : _JSON_SCHEMA_2020_12 ,
288+ "type" : "object" ,
289+ "properties" : {
290+ "query" : {"type" : "string" , "description" : "Natural language question about the codebase" },
291+ "root" : {"type" : "string" , "description" : "Workspace root path" },
292+ "budget" : {"type" : "integer" , "description" : "Max output tokens (default 2000)" },
293+ },
294+ "required" : ["query" , "root" ],
295+ },
296+ "outputSchema" : {
297+ "$schema" : _JSON_SCHEMA_2020_12 ,
298+ "type" : "object" ,
299+ "properties" : {
300+ "ok" : {"type" : "boolean" },
301+ "output" : {"type" : "string" },
302+ "error" : {"type" : "string" },
303+ },
304+ },
305+ "annotations" : {
306+ "readOnlyHint" : True ,
307+ "destructiveHint" : False ,
308+ "idempotentHint" : True ,
309+ "openWorldHint" : True ,
310+ },
311+ "execution" : {"taskSupport" : "forbidden" },
312+ },
313+ {
314+ "name" : "sin_simone_mcp_graphify_update" ,
315+ "title" : "Graphify Update" ,
316+ "description" : "Re-extract code files and update the knowledge graph for a workspace." ,
317+ "inputSchema" : {
318+ "$schema" : _JSON_SCHEMA_2020_12 ,
319+ "type" : "object" ,
320+ "properties" : {
321+ "root" : {"type" : "string" , "description" : "Workspace root path" },
322+ },
323+ "required" : ["root" ],
324+ },
325+ "outputSchema" : {
326+ "$schema" : _JSON_SCHEMA_2020_12 ,
327+ "type" : "object" ,
328+ "properties" : {
329+ "ok" : {"type" : "boolean" },
330+ "output" : {"type" : "string" },
331+ "error" : {"type" : "string" },
332+ },
333+ },
334+ "annotations" : {
335+ "readOnlyHint" : False ,
336+ "destructiveHint" : True ,
337+ "idempotentHint" : False ,
338+ "openWorldHint" : True ,
339+ },
340+ "execution" : {"taskSupport" : "forbidden" },
341+ },
342+ {
343+ "name" : "sin_simone_mcp_graphify_explain" ,
344+ "title" : "Graphify Explain" ,
345+ "description" : "Plain-language explanation of a graph node and its neighbors in a codebase." ,
346+ "inputSchema" : {
347+ "$schema" : _JSON_SCHEMA_2020_12 ,
348+ "type" : "object" ,
349+ "properties" : {
350+ "node" : {"type" : "string" , "description" : "Node name or label to explain" },
351+ "root" : {"type" : "string" , "description" : "Workspace root path" },
352+ },
353+ "required" : ["node" , "root" ],
354+ },
355+ "outputSchema" : {
356+ "$schema" : _JSON_SCHEMA_2020_12 ,
357+ "type" : "object" ,
358+ "properties" : {
359+ "ok" : {"type" : "boolean" },
360+ "output" : {"type" : "string" },
361+ "error" : {"type" : "string" },
362+ },
363+ },
364+ "annotations" : {
365+ "readOnlyHint" : True ,
366+ "destructiveHint" : False ,
367+ "idempotentHint" : True ,
368+ "openWorldHint" : True ,
369+ },
370+ "execution" : {"taskSupport" : "forbidden" },
371+ },
372+ {
373+ "name" : "sin_simone_mcp_graphify_path" ,
374+ "title" : "Graphify Path" ,
375+ "description" : "Find the shortest path between two nodes in the codebase knowledge graph." ,
376+ "inputSchema" : {
377+ "$schema" : _JSON_SCHEMA_2020_12 ,
378+ "type" : "object" ,
379+ "properties" : {
380+ "source" : {"type" : "string" , "description" : "Source node name" },
381+ "target" : {"type" : "string" , "description" : "Target node name" },
382+ "root" : {"type" : "string" , "description" : "Workspace root path" },
383+ },
384+ "required" : ["source" , "target" , "root" ],
385+ },
386+ "outputSchema" : {
387+ "$schema" : _JSON_SCHEMA_2020_12 ,
388+ "type" : "object" ,
389+ "properties" : {
390+ "ok" : {"type" : "boolean" },
391+ "output" : {"type" : "string" },
392+ "error" : {"type" : "string" },
393+ },
394+ },
395+ "annotations" : {
396+ "readOnlyHint" : True ,
397+ "destructiveHint" : False ,
398+ "idempotentHint" : True ,
399+ "openWorldHint" : True ,
400+ },
401+ "execution" : {"taskSupport" : "forbidden" },
402+ },
282403]
283404CAPABILITIES = [tool ["name" ] for tool in TOOL_DEFINITIONS ] + [
405+ "graphify" ,
284406 "memory.hybrid" ,
285407 "transport.streamable_http" ,
286408 "auth.oauth2.1" ,
@@ -316,6 +438,10 @@ def build_agent_card(base_url: str) -> dict[str, Any]:
316438 {"id" : "sin_simone_mcp_memory_query" , "name" : "Memory Query" },
317439 {"id" : "sin_simone_mcp_find_references" , "name" : "Find References" },
318440 {"id" : "sin_simone_mcp_project_overview" , "name" : "Project Overview" },
441+ {"id" : "sin_simone_mcp_graphify_query" , "name" : "Graphify Query" },
442+ {"id" : "sin_simone_mcp_graphify_update" , "name" : "Graphify Update" },
443+ {"id" : "sin_simone_mcp_graphify_explain" , "name" : "Graphify Explain" },
444+ {"id" : "sin_simone_mcp_graphify_path" , "name" : "Graphify Path" },
319445 ],
320446 "defaultInputModes" : ["application/json" , "text/plain" ],
321447 "defaultOutputModes" : ["application/json" , "text/plain" ],
@@ -765,7 +891,7 @@ def get_project_overview(payload: dict[str, Any]) -> dict[str, Any]:
765891 suffix = path .suffix or "[none]"
766892 counts [suffix ] = counts .get (suffix , 0 ) + 1
767893 top_extensions = sorted (counts .items (), key = lambda item : (- item [1 ], item [0 ]))[:10 ]
768- return {
894+ result : dict [ str , Any ] = {
769895 "ok" : True ,
770896 "root" : str (root ),
771897 "fileCount" : file_count ,
@@ -774,15 +900,52 @@ def get_project_overview(payload: dict[str, Any]) -> dict[str, Any]:
774900 for extension , count in top_extensions
775901 ],
776902 }
903+ graph_summary = _graphify_summary_impl (str (root ))
904+ if graph_summary .get ("has_graph" ):
905+ result ["graphify" ] = graph_summary
906+ return result
777907
778908
779909from .hybrid_memory import query_hybrid_memory as _query_hybrid_memory_impl # noqa: E402
910+ from .graphify_service import ( # noqa: E402
911+ graphify_query as _graphify_query_impl ,
912+ graphify_update as _graphify_update_impl ,
913+ graphify_explain as _graphify_explain_impl ,
914+ graphify_path as _graphify_path_impl ,
915+ graphify_summary as _graphify_summary_impl ,
916+ graphify_available as _graphify_available_impl ,
917+ )
780918
781919
782920def query_hybrid_memory (payload : dict [str , Any ]) -> dict [str , Any ]:
783921 return _query_hybrid_memory_impl (payload )
784922
785923
924+ def _graphify_query (payload : dict [str , Any ]) -> dict [str , Any ]:
925+ question = str (payload .get ("query" ) or "" ).strip ()
926+ root = str (payload .get ("root" ) or _workspace_root (None ))
927+ budget = int (payload .get ("budget" , 2000 ))
928+ return _graphify_query_impl (question , root , budget = budget )
929+
930+
931+ def _graphify_update (payload : dict [str , Any ]) -> dict [str , Any ]:
932+ root = str (payload .get ("root" ) or _workspace_root (None ))
933+ return _graphify_update_impl (root )
934+
935+
936+ def _graphify_explain (payload : dict [str , Any ]) -> dict [str , Any ]:
937+ node = str (payload .get ("node" ) or "" ).strip ()
938+ root = str (payload .get ("root" ) or _workspace_root (None ))
939+ return _graphify_explain_impl (node , root )
940+
941+
942+ def _graphify_path (payload : dict [str , Any ]) -> dict [str , Any ]:
943+ source = str (payload .get ("source" ) or "" ).strip ()
944+ target = str (payload .get ("target" ) or "" ).strip ()
945+ root = str (payload .get ("root" ) or _workspace_root (None ))
946+ return _graphify_path_impl (source , target , root )
947+
948+
786949_SYNC_ACTIONS = frozenset ({
787950 "sin_simone_mcp_symbol_search" ,
788951 "sin_simone_mcp_find_references" ,
@@ -791,6 +954,10 @@ def query_hybrid_memory(payload: dict[str, Any]) -> dict[str, Any]:
791954 "sin_simone_mcp_project_overview" ,
792955 "sin_simone_mcp_health" ,
793956 "sin_simone_mcp_insert_after" ,
957+ "sin_simone_mcp_graphify_query" ,
958+ "sin_simone_mcp_graphify_update" ,
959+ "sin_simone_mcp_graphify_explain" ,
960+ "sin_simone_mcp_graphify_path" ,
794961})
795962
796963
@@ -809,6 +976,10 @@ async def execute_simone_action(payload: dict[str, Any]) -> dict[str, Any]:
809976 "sin_simone_mcp_memory_query" ,
810977 "sin_simone_mcp_find_references" ,
811978 "sin_simone_mcp_project_overview" ,
979+ "sin_simone_mcp_graphify_query" ,
980+ "sin_simone_mcp_graphify_update" ,
981+ "sin_simone_mcp_graphify_explain" ,
982+ "sin_simone_mcp_graphify_path" ,
812983 ],
813984 }
814985 if action in {"simone.mcp.health" , "sin.simone.mcp.health" , "sin_simone_mcp_health" }:
@@ -840,6 +1011,14 @@ def _execute_sync_action(action: str, payload: dict[str, Any]) -> dict[str, Any]
8401011 return query_hybrid_memory (payload )
8411012 if action == "sin_simone_mcp_insert_after" :
8421013 return insert_after_symbol (payload )
1014+ if action == "sin_simone_mcp_graphify_query" :
1015+ return _graphify_query (payload )
1016+ if action == "sin_simone_mcp_graphify_update" :
1017+ return _graphify_update (payload )
1018+ if action == "sin_simone_mcp_graphify_explain" :
1019+ return _graphify_explain (payload )
1020+ if action == "sin_simone_mcp_graphify_path" :
1021+ return _graphify_path (payload )
8431022 return {"ok" : False , "error" : "unknown_action" , "action" : action }
8441023
8451024
0 commit comments