@@ -291,6 +291,11 @@ class TermInfoOutputSchema(Schema):
291291 Meta = fields .Dict (keys = fields .String (), values = fields .String (), required = True )
292292 Tags = fields .List (fields .String (), required = True )
293293 Queries = fields .List (QueryField (), required = False )
294+ # RelatedTools: MCP tools (other than run_query) that are useful for this entity.
295+ # Each entry: {"tool": "<tool_name>", "label": "...", "default_args": {...}}.
296+ # Distinct from Queries because these are not dispatched via run_query — the
297+ # client should call the named tool directly with default_args.
298+ RelatedTools = fields .List (fields .Dict (), required = False )
294299 IsIndividual = fields .Bool (missing = False , required = False )
295300 Images = fields .Dict (keys = fields .String (), values = fields .List (fields .Nested (ImageSchema ()), missing = {}), required = False , allow_none = True )
296301 IsClass = fields .Bool (missing = False , required = False )
@@ -400,6 +405,7 @@ def term_info_parse_object(results, short_form):
400405 termInfo ["SuperTypes" ] = []
401406 termInfo ["Tags" ] = []
402407 termInfo ["Queries" ] = []
408+ termInfo ["RelatedTools" ] = []
403409 termInfo ["IsClass" ] = False
404410 termInfo ["IsIndividual" ] = False
405411 termInfo ["IsTemplate" ] = False
@@ -740,8 +746,9 @@ def term_info_parse_object(results, short_form):
740746
741747 # NeuronsPartHere query - for Class+Anatomy terms (synaptic neuropils, etc.)
742748 # Matches XMI criteria: Class + Synaptic_neuropil, or other anatomical regions
743- if contains_all_tags (termInfo ["SuperTypes" ], ["Class" ]) and (
744- "Synaptic_neuropil" in termInfo ["SuperTypes" ] or
749+ # Excluded for neuron classes: "neurons with some part in <a neuron>" is not a meaningful query
750+ if contains_all_tags (termInfo ["SuperTypes" ], ["Class" ]) and "Neuron" not in termInfo ["SuperTypes" ] and (
751+ "Synaptic_neuropil" in termInfo ["SuperTypes" ] or
745752 "Anatomy" in termInfo ["SuperTypes" ]
746753 ):
747754 q = NeuronsPartHere_to_schema (termInfo ["Name" ], {"short_form" : vfbTerm .term .core .short_form })
@@ -783,9 +790,11 @@ def term_info_parse_object(results, short_form):
783790 q = ComponentsOf_to_schema (termInfo ["Name" ], {"short_form" : vfbTerm .term .core .short_form })
784791 queries .append (q )
785792
786- # PartsOf query - for any Class
793+ # PartsOf query - for any Class except neuron classes
787794 # Matches XMI criteria: Class (any)
788- if contains_all_tags (termInfo ["SuperTypes" ], ["Class" ]):
795+ # Excluded for neuron classes: anatomical sub-parts of a neuron type are not modelled
796+ # in the ontology in a way that makes this query useful at the class level.
797+ if contains_all_tags (termInfo ["SuperTypes" ], ["Class" ]) and "Neuron" not in termInfo ["SuperTypes" ]:
789798 q = PartsOf_to_schema (termInfo ["Name" ], {"short_form" : vfbTerm .term .core .short_form })
790799 queries .append (q )
791800
@@ -941,17 +950,72 @@ def term_info_parse_object(results, short_form):
941950 queries .append (q )
942951 q = UpstreamClassConnectivity_to_schema (termInfo ["Name" ], {"short_form" : vfbTerm .term .core .short_form })
943952 queries .append (q )
944-
953+
954+ # Hierarchy entries — surfaced in RelatedTools, dispatched via the
955+ # get_hierarchy MCP tool rather than run_query.
956+ sf_for_hier = vfbTerm .term .core .short_form
957+ # subclass_of hierarchy is meaningful for cell-type taxonomies.
958+ # Gate: Class + Cell (matches the "Cell"-bounded ancestor filter inside
959+ # get_hierarchy itself).
960+ if termInfo ["SuperTypes" ] and contains_all_tags (termInfo ["SuperTypes" ], ["Class" , "Cell" ]):
961+ termInfo ["RelatedTools" ].append ({
962+ "tool" : "get_hierarchy" ,
963+ "label" : f"Cell-type hierarchy of { termInfo ['Name' ]} " ,
964+ "default_args" : {
965+ "id" : sf_for_hier ,
966+ "relationship" : "subclass_of" ,
967+ "direction" : "both" ,
968+ "max_depth" : 1 ,
969+ },
970+ })
971+ # part_of hierarchy is meaningful for nervous-system regions
972+ # (brain, neuropils, ganglia, tracts), but NOT for cells/neurons or
973+ # non-neural anatomy. Special-case the nervous system root, which lacks
974+ # the "Nervous_system" SuperType because it isn't part_of itself.
975+ is_ns_region = (
976+ termInfo ["SuperTypes" ]
977+ and contains_all_tags (termInfo ["SuperTypes" ], ["Class" , "Nervous_system" ])
978+ and "Cell" not in termInfo ["SuperTypes" ]
979+ )
980+ is_ns_root = sf_for_hier == "FBbt_00005093"
981+ if is_ns_region or is_ns_root :
982+ termInfo ["RelatedTools" ].append ({
983+ "tool" : "get_hierarchy" ,
984+ "label" : f"Region containment hierarchy of { termInfo ['Name' ]} " ,
985+ "default_args" : {
986+ "id" : sf_for_hier ,
987+ "relationship" : "part_of" ,
988+ "direction" : "both" ,
989+ "max_depth" : 1 ,
990+ },
991+ })
992+
945993 # FlyBase stock finder — for Feature terms (FBgn/FBal/FBti/FBtp/FBco/FBst)
946994 sf = vfbTerm .term .core .short_form
947995 if sf .startswith (("FBgn" , "FBal" , "FBti" , "FBtp" , "FBco" , "FBst" )):
948996 q = FindStocks_to_schema (termInfo ["Name" ], {"short_form" : sf })
949997 queries .append (q )
998+ # Also surface the dedicated find_stocks MCP tool, which exposes
999+ # the optional collection_filter parameter (Bloomington, Kyoto,
1000+ # VDRC, etc.) that the run_query/FindStocks path does not.
1001+ termInfo ["RelatedTools" ].append ({
1002+ "tool" : "find_stocks" ,
1003+ "label" : f"Find fly stocks for { termInfo ['Name' ]} (with optional stock-centre filter)" ,
1004+ "default_args" : {"feature_id" : sf },
1005+ })
9501006
9511007 # FlyBase combination publications — for FBco terms
9521008 if sf .startswith ("FBco" ):
9531009 q = FindComboPublications_to_schema (termInfo ["Name" ], {"short_form" : sf })
9541010 queries .append (q )
1011+ # Also surface the dedicated find_combo_publications MCP tool,
1012+ # which returns full per-publication metadata (DOI, PMID, miniref,
1013+ # year) ready for citation rendering.
1014+ termInfo ["RelatedTools" ].append ({
1015+ "tool" : "find_combo_publications" ,
1016+ "label" : f"Find publications for { termInfo ['Name' ]} (with full citation metadata)" ,
1017+ "default_args" : {"fbco_id" : sf },
1018+ })
9551019
9561020 # For individuals that are painted domains of anatomical regions, add parent class queries
9571021 if termInfo ["IsIndividual" ] and termInfo ["Technique" ] and any ('computer' in t .lower () for t in termInfo ["Technique" ]):
0 commit comments