These three rules apply to every VFB question. Re-read them whenever a tool call returns empty or unexpected results.
For any VFB or anatomy ontology ID (VFB_*, FBbt_*), the workflow is always:
search_terms— find the ID (skip if the user already provided one).get_term_info— read theQueriesarray. This lists the validquery_typevalues for this entity.run_query— passidand aquery_typetaken from thatQueriesarray.
DO NOT call run_query with a guessed query_type. If a query_type is not in the entity's Queries array, that query is not available for that entity, and run_query will return an error.
get_term_info also returns a RelatedTools array listing other MCP tools (not run_query) that are useful for this entity. Each entry has:
tool— the MCP tool name to call (e.g.get_hierarchy).label— short human description.default_args— arguments ready to copy into the tool call.
Currently get_term_info surfaces:
get_hierarchy— for cell-type classes (subclass_of) and nervous-system regions (part_of).
FlyBase stocks and split-GAL4 combination publications are NOT RelatedTools — they are run_query query_types (FindStocks for FlyBase feature IDs FBgn/FBal/FBti/FBtp/FBco/FBst, and FindComboPublications for FBco combinations), offered in the Queries array of those terms. Get the FlyBase/FBco ID from resolve_entity / resolve_combination first, then call run_query with that ID and the query_type.
Call the named tool directly with default_args — do not pass these values via run_query.
If run_query returns empty rows or an error:
- The
query_typemay not be supported for this entity → re-check theQueriesarray fromget_term_info. - The entity may have no data for that specific question → try a different
query_typefrom the sameQueriesarray, or try a related entity (e.g. its parent class viaget_hierarchy). - It does NOT mean the answer is unknown to science. It means this MCP call did not return it.
If search_terms returns no good matches:
- Try alternative spellings, synonyms, or a broader term.
- Try with different
filter_types(see the cookbook below).
If the MCP cannot answer, tell the user clearly:
"VFB does not return data for X via [tool]. I tried [list of attempts]. You could try [alternative search strategy]."
DO NOT fabricate any of the following from training data:
- FlyBase IDs (
FBgn,FBal,FBti,FBco,FBst,FBrf) - Anatomy ontology IDs (
FBbt_*) - VFB IDs (
VFB_*) - Driver line names, allele names, or split-GAL4 combination names
- Paper citations, DOIs, or PMIDs
- Connectivity counts, synapse weights, or expression results
Naming a real ID that you have not seen in a tool result this conversation counts as fabrication. If in doubt, say so and ask the user how they would like to proceed.
search_terms runs the search virtualflybrain.org itself runs — the same Solr query, the same filters and boosts, the same final sort — so what you get back is what a user would see on the site. Deprecated terms are already excluded server-side, so you do not need to ask for that.
Unfiltered calls still mix scRNAseq artifacts and unrelated entity types in with what the user wants. Use filter_types from the start. Common recipes:
| User asks about | filter_types |
|---|---|
| Neuron types/classes | ["neuron", "class"] |
| Individual neurons (with images) | ["neuron", "has_image"] |
| Neurons with connectome data | ["neuron", "has_neuron_connectivity"] |
| Brain regions / neuropils | ["anatomy"] |
| Genes | ["gene"] |
| Expression patterns / driver lines | ["expression_pattern"] |
| Datasets | ["dataset"] |
Do not guess type names. There are over 200 of them and they change as data is added. Call list_search_facets — optionally with contains to narrow, e.g. contains: "neuron" — and use what it returns. An unknown name is rejected outright, with suggestions.
Stage filtering — only when the user is specific. VFB covers adult, larval, and embryonic data, and many anatomical FBbt terms are stage-agnostic (the "antennal lobe" class covers all life stages). Do NOT add "adult" by default — you will hide the generic class and any larval/embryonic results.
- Add
"adult"tofilter_typesonly if the user explicitly asks about the adult fly (e.g. "adult Kenyon cells", "in the adult brain"). - Add
"larva"if the user asks about larval anatomy. - If the user does not specify a stage, leave stage filters out and let the user pick from the results.
Other useful options on search_terms:
boost_types: ["has_image", "has_neuron_connectivity"]— soft-ranks the most data-rich entities first without excluding others.demote_types: [...]— the mirror image: sinks matches to the bottom of the ranking without excluding them. Prefer this toexclude_typeswhen you suspect the user might still want the demoted results, just not first. A type listed in bothboost_typesanddemote_typesis treated as boosted.unique: false— one row per matching synonym instead of one per term. Use it when the useful question is "which name matched?", and expect the same ID to repeat. The default (true) gives one row per term.minimize_results: true— limits to top 10 and adds truncation metadata. Use for exploratory searches to avoid filling context with irrelevant matches.auto_fetch_term_info: true— when the query matches one term's name exactly, foldsget_term_infointo the same response, saving a round trip.
Reading the counts. The response reports them separately and they mean different things: returned is how many rows you were given, total is the length of the ranked list they came from, distinct_terms is how many distinct terms matched, and solr_matches is how many terms Solr matched before ranking. Under unique: false the rows are synonyms, so total counts names and can exceed solr_matches, which counts terms — the _note spells that out when it happens. If solr_matches is much larger than candidate_pool, only the top slice was ranked. Never report returned as if it were the number of matches.
The VirtualFlyBrain (VFB) MCP server should be used when users ask questions related to:
- Drosophila melanogaster (fruit fly) brain anatomy and neurobiology
- Neural circuits and connectivity in flies
- Gene expression patterns in the fly brain
- Neuron morphology and classification
- Brain region identification and relationships
- Comparative neuroanatomy across species (fly-focused)
- "What neurons express gene X in the fly brain?"
- "Show me the connectivity of neuron Y"
- "What brain regions are involved in olfactory processing?"
- "Find neurons similar to this morphology"
- "What genes are expressed in the mushroom body?"
- "How does the fly visual system work?"
- Term Information: Detailed metadata about anatomical structures, neurons, genes
- Query Results: Pre-computed analyses like expression domains, connectivity maps
- Search/Autocomplete: Finding relevant VFB entities by name or description
Returns comprehensive metadata about VFB entities:
{
"Name": "IN02A032_T2_L (MANC:23475)",
"Id": "VFB_jrcv0i43",
"SuperTypes": ["Entity", "Individual", "VFB", "Neuron", "Adult", "Anatomy", "Cell"],
"Meta": {
"Name": "[IN02A032_T2_L (MANC:23475)](VFB_jrcv0i43)",
"Description": "",
"Comment": "tracing status-Roughly traced..."
},
"Tags": ["NBLAST", "has_image", "has_neuron_connectivity"],
"Queries": ["SimilarMorphology", "Connectivity", "Expression"],
"Images": {
"VFB_00101567": [{"id": "VFB_jrcv0i43", "label": "IN02A032_T2_L (MANC:23475)", "thumbnail": "...", "nrrd": "...", "obj": "..."}]
},
"IsTemplate": false,
"Publications": ["DOI:10.1101/2020.12.08.417884"],
"Synonyms": ["IN02A032_T2_L", "MANC:23475"]
}Key Fields to Interpret:
- SuperTypes: Classification hierarchy (Neuron, Anatomy, Cell, etc.)
- Tags: Special properties (has_image, has_neuron_connectivity, NBLAST)
- Queries: Available analyses for this entity
- Images: Dictionary keyed by template brain ID, containing image objects with IDs, thumbnails, and 3D data files
- Publications: Scientific references
Returns tabular data from pre-computed analyses:
{
"count": 1,
"count_status": "exact",
"offset": 0,
"limit": 25,
"returned": 1,
"_note": "Image columns (thumbnail) were excluded to reduce size - re-run this query with include_images=true to include them.",
"headers": {
"id": {"title": "ID", "type": "selection_id"},
"name": {"title": "Domain", "type": "markdown"},
"type": {"title": "Type", "type": "text"}
},
"rows": [
{
"id": "VFB_00102141",
"name": "[AOTU on JRC2018Unisex adult brain](https://v2.virtualflybrain.org/...)",
"type": "Expression_pattern"
}
]
}Interpretation:
- count: The TRUE total number of results — may be far larger than the rows returned. Read
count_statusbefore quoting it. - count_status:
exact—countis the true total, quote it freely.row_count— no total was supplied, socountis just how many rows came back.unavailable— the query FAILED upstream andcountis-1. A failed query is not an empty result: never report it as "0", "none" or "no results". Say the query could not be run, and read_note, which explains the failure and the retry. - offset / limit / returned: Paging state. Only the current page (default 25 rows) is returned; to get the next page re-run with
offsetincreased bylimit. - _note: Present when the query failed, when rows were paged, when the result was truncated, and/or when images were excluded — states what happened and how to page further or re-add images (
include_images: true). Read it before summarising. - capped / truncated / warnings: Passed through from VFBquery when present.
truncatedmeans the server holds only the first part of the result set, socountis the true total but the far pages cannot be reached. - Headers / Rows: Column definitions and the current page of data. The
thumbnailcolumn is EXCLUDED by default; passinclude_images: trueto include it.
Runs the website's own search. Parameters:
filter_types: Hard include — results must have ALL specifiedfacets_annotationvalues (AND logic)exclude_types: Hard exclude — results must NOT have any of these typesboost_types: Soft boost — results with these types rank higher without excluding othersdemote_types: Soft demote — results with these types rank lower without being excluded. A type in bothboost_typesanddemote_typesis boostedunique: One row per term (defaulttrue).falsegives one row per matching synonymstart: Page start index (default 0)rows: Rows to return (default 150, max 1000)minimize_results: Return only the top 10, with reduced fields, for a first lookauto_fetch_term_info: When the query matches one term's name exactly, include that term's info
Call list_search_facets for valid type names — do not guess them, and do not rely on any list embedded in documentation, which will drift.
Basic search:
{
"query": "medulla"
}Filtered search (adult neurons with images):
{
"query": "medulla",
"filter_types": ["neuron", "adult", "has_image"]
}One row per synonym, to see which name matched:
{
"query": "Kenyon cell",
"unique": false
}Minimized first look, then paging:
{
"query": "medulla",
"minimize_results": true
}Auto-fetch term info for exact matches:
{
"query": "antennal lobe",
"auto_fetch_term_info": true
}Response:
{
"query": "antennal lobe",
"unique": true,
"start": 0,
"returned": 3,
"total": 438,
"distinct_terms": 438,
"solr_matches": 438,
"candidate_pool": 500,
"_note": "Showing results 0-3 of 438. To see more, re-run with start=3 (same rows).",
"results": [
{
"label": "antennal lobe cPIN (antennal lobe commissural pioneer interneuron)",
"original_label": "antennal lobe commissural pioneer interneuron",
"short_form": "FBbt_00052563",
"id": "http://purl.obolibrary.org/obo/FBbt_00052563",
"facets_annotation": ["Entity", "Class", "Neuron", "Anatomy", "Cell", "Nervous_system", "has_subClass"],
"unique_facets": ["Nervous_system", "Neuron"]
}
],
"term_info": { "Id": "FBbt_00003924", "Name": "antennal lobe" }
}Key Fields:
- short_form: VFB/FlyBase identifier — use this for
get_term_info,run_query, and URLs - label: The site's display form, which is not the plain name. It is either
"name (ID)"or"matched synonym (name)", so it tells you why the row matched - original_label: The plain name. Compare against this, not
label, when checking whether a result is what the user asked for - facets_annotation: Categorisation tags, and the vocabulary the four type filters draw on
- returned / total / distinct_terms / solr_matches: Four different numbers — rows given to you, length of the ranked list, distinct terms matched, and terms Solr matched before ranking. Report the right one;
returnedis never the answer to "how many are there?" - candidate_pool: How many documents Solr was asked for before ranking. If
solr_matchesexceeds it, the list is not exhaustive — narrow the query or addfilter_typesrather than paging to the end - _note: Says what was truncated, collapsed, or approximated. Read it before summarising
- term_info: Present when
auto_fetch_term_infowas set and the query matched one term's name exactly
{
"count": 12,
"total": 233,
"contains": "neuron",
"facets": [{ "name": "Neuron", "docs": 48213 }]
}docs is how many documents carry that facet, which is a useful sanity check: a facet with a handful of documents will not usefully narrow a search. If the response carries a source of "static snapshot bundled with this MCP server", the live vocabulary was unreachable and you are seeing a stale list — a name missing from it may still be valid.
When to use: User asks about fly stocks, driver lines, GAL4 lines, alleles, insertions, or split-GAL4 combinations and wants to find available stocks or resolve names to IDs.
Important: resolve_entity queries FlyBase Chado — for VFB ontology lookups (anatomical terms, neuron class IDs) use search_terms and get_term_info instead.
Important: resolve_entity is for unresolved user text only. Pass the raw query string exactly as written (for example P{VT054895-GAL4.DBD}); do not pass a resolved FlyBase/VFB ID to resolve_entity.
-
Parse input — Identify whether the user provides a name, synonym, or FlyBase ID:
FBgn\d+→ gene ID (userun_querywithquery_typeFindStocks)FBal\d+→ allele ID (userun_querywithquery_typeFindStocks)FBti\d+→ insertion ID (userun_querywithquery_typeFindStocks)FBtp\d+→ transgenic construct ID (userun_querywithquery_typeFindStocks)FBco\d+→ combination ID (userun_querywithquery_typeFindStocks)FBst\d+→ stock ID (userun_querywithquery_typeFindStocks)- A split-GAL4 line name or synonym (e.g.
MB109B,SS04495) → resolve first withresolve_combinationto get its FBco, thenFindStockson the FBco - A VFB split expression pattern (
VFBexp_FBtp…FBtp…or one of its images) → use theFindStocksentry in itsget_term_infoQueriesarray; it is already anchored on the FBco (labelFind fly stocks for <name> (FBco…)) - Any other string → resolve first with
resolve_entity
-
Resolve entity — If user provides a name (not an ID), call
resolve_entitywith the raw unresolved string exactly as written. It uses tiered resolution:- Exact match on feature name
- Synonym match (case-insensitive)
- Broad pattern match (ILIKE)
-
Confirm with user — Critical:
- If match was via SYNONYM or BROAD, show the resolved entity and ask user to confirm before proceeding. Example: "Your search for 'CG9885' matched dpp (FBgn0000490, gene) via synonym. Shall I find stocks for this gene?"
- If multiple matches, show a disambiguation list (name, ID, type) and ask user to choose.
- Wait for user reply — do NOT assume confirmation.
-
Find stocks — Call
run_querywithquery_typeFindStocksandid= the resolved FlyBase feature ID. -
Present results:
- Always start with a query summary block:
Query: - Entity: dpp (FBgn0000490, gene) - Search mode: gene → alleles → stocks - Collection: (all) Results: 45 stocks across 12 alleles from 3 stock centres - ≤30 rows: Show full table
- >30 rows: Show total stock count, allele count, breakdown by stock collection, top 20 rows sorted by collection then allele, note that results are truncated
- Split combinations (FBco): rows carry a
matchcolumn, and only the best tier FlyBase has is returned:Exact combination— the stock carries both hemidrivers. If any exist, no other rows are returned.Hemidriver alone— otherwise, stocks of one hemidriver on its own.Hemidriver in other combination— for a hemidriver with no stock of its own, stocks pairing it with a different hemidriver. Tiers 2 and 3 are chosen per hemidriver, so the two halves can come from different tiers. Say which tier the results are: exact stocks can be ordered as-is, while hemidriver stocks mean the user must cross the two halves to make the split (and a hemidriver from an "other combination" stock must first be separated from its partner). Do not describe hidden tiers as unavailable; they were filtered because a better tier exists.
- For every stock, include FlyBase link:
https://flybase.org/reports/{FBst_ID} - Include entity report link:
https://flybase.org/reports/{feature_id}
- Always start with a query summary block:
-
Follow-up offers:
- "I can filter these to show only stocks from a specific centre (Bloomington, Kyoto, VDRC, etc.)"
- "To see stocks for a specific allele, give me the allele symbol or ID"
- "I can look up the full genotype for any stock listed"
- "I can look up this entity in VFB for anatomical and expression data"
| ID prefix | Query strategy |
|---|---|
| FBgn (gene) | 4-path UNION: direct allele, allele→construct→insertion, allele→associated insertion, regulatory region |
| FBal (allele) | 3-path UNION: direct, construct, associated insertion |
| FBti (insertion) | Direct feature_genotype path |
| FBtp (construct) | Via its insertions, direct genotype membership, and alleles made from it |
| FBco (combination) | Resolve component hemidrivers, run allele paths for each, then keep only the best tier (exact combination → hemidriver alone → hemidriver in other combination) |
| FBst (stock) | Direct stock lookup |
When to use: User asks about publications for a split-GAL4 combination, or asks "what papers describe [combination name]?"
-
Parse input — Accept FBco IDs (e.g.,
FBco0000052), full combination names, or common synonyms (e.g., "MB002B", "SS04495"). -
Resolve combination — If input is not an FBco ID, call
resolve_combinationwith the raw unresolved string exactly as written. Uses tiered resolution: exact name → synonym → broad pattern match. -
Confirm with user — Critical:
- If match was via synonym, show the resolved formal name and FBco ID, ask user to confirm. Example: "Your search for 'MB002B' matched Scer\GAL4[DBD.R14C08]∩Hsap\RELA[AD.R12C11] (FBco0000052) via synonym. Shall I find publications for this combination?"
- If multiple matches, show disambiguation list and ask user to choose.
- Wait for user reply — do NOT assume confirmation.
-
Find publications — Call
run_querywithquery_typeFindComboPublicationsandid= the FBco ID. -
Present results:
- Query summary block:
Query: - Combination: Scer\GAL4[DBD.R14C08]∩Hsap\RELA[AD.R12C11] (FBco0000052) - Synonym used: MB002B Results: 6 publications (2014–2022) - For each publication show:
- Title with year
- Citation (miniref)
- Links (only where identifier exists):
- FlyBase:
https://flybase.org/reports/{FBrf_ID} - DOI:
https://doi.org/{DOI} - PubMed:
https://pubmed.ncbi.nlm.nih.gov/{PMID}/
- FlyBase:
- Include FlyBase report link for the combination:
https://flybase.org/reports/{FBco_ID}
- Query summary block:
-
Follow-up offers:
- "I can fetch the full text of any of these papers via Europe PMC"
- "I can look up detailed metadata (authors, abstract) for any publication"
- "I can search for other combinations that share a component allele"
- "I can look up stocks for this combination"
When to use: User asks about synaptic connections, upstream/downstream partners, connectivity patterns, or where a neuron connects.
DO NOT USE for: Connections between muscles and neurons, or sense organs and neurons.
There are six connectivity query types. Pick the right one using the decision rules below.
Rule 1 — User has an individual neuron ID (starts with VFB_):
- To see all synaptic partners of that neuron → use
run_querywith query_typeNeuronNeuronConnectivityQuery - To see which brain regions that neuron connects to → use
run_querywith query_typeNeuronRegionConnectivityQuery - To see presynaptic inputs with neurotransmitter types → use
run_querywith query_typeNeuronInputsTo - If the user specifically asks for a class-level query (e.g. "what classes connect to neurons like this one?"), first call
get_term_infoon the VFB ID to find its neuron class (FBbt_...ID), then use that class ID with the queries in Rule 2.
Rule 2 — User has a neuron class (starts with FBbt_) or a neuron type name (e.g. "Kenyon cell"):
- To see downstream partner classes → use
run_querywith query_typeDownstreamClassConnectivity(fast, pre-indexed) - To see upstream partner classes → use
run_querywith query_typeUpstreamClassConnectivity(fast, pre-indexed) - To see region connectivity or neurotransmitter inputs for a neuron class → use the instance batch workflow described below
- To filter by both upstream AND downstream class at the same time, or to retrieve results that include data from multiple connectome datasets → use
query_connectivity(slow, live query) - Call
list_connectome_datasetsfirst when you need the available connectome dataset labels/IDs (e.g. to populatequery_connectivity's dataset filters, or to tell the user which connectomes exist).
Instance batch workflow — running individual neuron queries at the class level:
Some queries (NeuronRegionConnectivityQuery, NeuronInputsTo) only work on individual neurons, not classes. To use them for a whole neuron class:
- Get instances of the class:
run_query(id="FBbt_00003686", query_type="ListAllAvailableImages") - Extract the VFB IDs from the results.
- If there are many instances, tell the user how many there are and ask whether to query all of them or a subset.
- Batch-query the instances:
run_query(id=["VFB_xxx", "VFB_yyy", ...], query_type="NeuronRegionConnectivityQuery")
The run_query tool accepts an array of IDs and runs the query on all of them in parallel. Results are returned as a JSON object keyed by "ID::query_type".
Rule 3 — User asks about a brain region (e.g. "What connects to the lobula?"):
- First use
search_termswithfilter_types: ["neuron", "class"]to find neuron classes in that region. - Then apply Rule 2 for the neuron classes found.
Rule 4 — User asks what neurotransmitter a neuron type uses (e.g. "Is Tm9 cholinergic?", "What NT does the moonwalker DN release?"):
- For the data-driven prediction with confidence → use
get_predicted_neurotransmitters(per-instance connectome predictions; aggregated to the class by default,split_by_datasetto compare connectomes,aggregate: falsefor per-neuron rows). - For the curated/established classification (no confidence) → use
get_known_neurotransmitters. - Both take a neuron class name or FBbt ID (covering its subclasses) and report the neurotransmitter as a GO secretion term, so their answers line up. If known-NT is empty, fall back to the prediction. These are the right tools for the NT of a whole type; for a single individual neuron's inputs' NTs, Rule 1's
NeuronInputsTostill applies.
If unsure, start with the run_query options listed in Rules 1–2. They are fast and cached. Only use query_connectivity when dual-end class filtering is specifically needed.
| Query | Input | What it returns | Speed |
|---|---|---|---|
NeuronNeuronConnectivityQuery |
Individual neuron VFB ID | All partner neurons with input/output weights | Fast (cached) |
NeuronRegionConnectivityQuery |
Individual neuron VFB ID | Brain regions with pre/postsynaptic terminal counts | Fast (cached) |
NeuronInputsTo |
Individual neuron VFB ID | Presynaptic partners with neurotransmitter types and weights | Fast (cached) |
DownstreamClassConnectivity |
Neuron class FBbt ID | Downstream partner classes with % connected, avg weight (includes data from all datasets) | Fast (pre-indexed) |
UpstreamClassConnectivity |
Neuron class FBbt ID | Upstream partner classes with % connected, avg weight (includes data from all datasets) | Fast (pre-indexed) |
query_connectivity |
Neuron class names or FBbt IDs | Connections between two neuron classes (includes data from all datasets) | Slow (1–5 min, live) |
get_predicted_neurotransmitters |
Neuron class name or FBbt ID | Predicted NT(s) per class (or per instance), with mean confidence, as GO terms; optional per-dataset split | Live (seconds) |
get_known_neurotransmitters |
Neuron class name or FBbt ID | Curated NT(s) for the class and subclasses, as GO terms (no confidence) | Live (seconds) |
- Get the VFB ID or FBbt ID. If the user gave a name, use
search_termsto find the ID first. - Call
get_term_infoon the ID. Check that the relevant query_type appears in theQueriesarray. If it does not, either the entity does not support that query type, or there are no results for it. - Call
run_querywith the ID and query_type.
Example — individual neuron partners:
run_query(id="VFB_00104glj", query_type="NeuronNeuronConnectivityQuery")
Example — class downstream partners:
run_query(id="FBbt_00003686", query_type="DownstreamClassConnectivity")
Example — neuron region connectivity:
run_query(id="VFB_00104glj", query_type="NeuronRegionConnectivityQuery")
Example — neuron inputs with neurotransmitter types:
run_query(id="VFB_00104glj", query_type="NeuronInputsTo")
-
Check if you really need
query_connectivity. If the user asks about only one direction (e.g. "what is downstream of X?" or "what are the inputs to X?"), useDownstreamClassConnectivityorUpstreamClassConnectivityviarun_queryinstead — they are much faster. Only usequery_connectivitywhen the user specifies both upstream and downstream types. -
Parse the user's request using this table:
User says Action "upstream of X", "inputs to X", "presynaptic to X" Use run_querywithUpstreamClassConnectivityon X."downstream of X", "outputs from X", "postsynaptic to X" Use run_querywithDownstreamClassConnectivityon X."between X and Y", "X to Y connections" Use query_connectivitywithupstream_type= X,downstream_type= Y"summarise by class", "aggregated" Use query_connectivitywithgroup_by_class= true (this option is specific toquery_connectivity)Defaults for
query_connectivity:weight= 5,exclude_dbs= ["hb", "fafb"] -
Validate neuron type names. Use
search_termswithfilter_types: ["neuron", "class"]to check the name is correct. If ambiguous, show candidates and ask user to pick. -
Confirm parameters with the user before running. This query is slow. Show:
I'll query connectivity with these parameters: - Upstream type: transmedullary neuron Tm1 - Downstream type: T3 neuron - Min. weight: 5 - Excluded DBs: hb, fafb - Group by class: No This query may take several minutes. Shall I proceed? -
Execute — Call
query_connectivitywith confirmed parameters.
Reading a paged connectivity result. query_connectivity returns a strongest-first page of limit rows (default 50) plus a summary computed over every connection found, not just the page. Answer from the summary; quote a handful of rows as illustration. A single class at weight=5 can find over 50,000 connections, so the page you see is often a tiny fraction — count is the real total, returned is what you were given, and the _note says so explicitly. Only page with offset if the user asks for specific further rows; if they want the shape of the whole result set, group_by_class=true is the better move.
The summary contains: total connections, the weight column's min/max/total/mean, by_dataset counts, distinct_class_pairs, distinct_upstream_neurons, distinct_downstream_neurons, and top_class_pairs ranked by connection count. That is usually a better answer to "how do these two classes connect?" than any 50 rows would be.
Note that a class label may be several names joined with | — a neuron that is both adult GABAergic neuron and proximal medullary amacrine neuron Pm2 appears as "adult GABAergic neuron|proximal medullary amacrine neuron Pm2". That is one class set, not two classes; when presenting it to a user, the most specific name in the set is usually the one they want.
Performance rules for query_connectivity:
- Always start with the default
weight = 5. There is no universal "good" weight — it varies by cell type. - Single-end queries (only upstream or only downstream set) are slower than both-ends queries because they return more results. If the user only cares about one direction, prefer
DownstreamClassConnectivityorUpstreamClassConnectivityviarun_queryinstead — they are pre-indexed and fast. - Use
group_by_class=truefor faster aggregated results. - Only use
query_connectivitywhen you need both ends filtered by class.
Always start with a query summary:
Query: NeuronNeuronConnectivityQuery for VFB_00104glj
Results: 42 partner neurons (23 upstream, 19 downstream)
Or for query_connectivity:
Query:
- Upstream type: transmedullary neuron Tm1 (FBbt_00003789)
- Downstream type: T3 neuron (FBbt_00003730)
- Min. weight: 5
- Excluded DBs: mc
Results: 7309 connections across 28 upstream neurons → 85 downstream neurons
Result formatting:
- ≤50 rows: Show full table.
- >50 rows: Show top 20 sorted by weight descending. Include summary stats (total connections, unique partners, weight range). Note that results are truncated.
For query_connectivity the summary stats are already computed for you over the full result set — use those figures rather than deriving them from the rows in front of you, which are only a page.
Column guide by query type:
| Query type | Key columns |
|---|---|
NeuronNeuronConnectivityQuery |
partner label, outputs (synapses out), inputs (synapses in), tags |
NeuronRegionConnectivityQuery |
region, presynaptic terminals, postsynaptic terminals |
NeuronInputsTo |
presynaptic neuron name, neurotransmitter type, weight, neuron type |
DownstreamClassConnectivity |
downstream class, total N, connected N, % connected, avg weight |
UpstreamClassConnectivity |
upstream class, total N, connected N, % connected, avg weight |
query_connectivity (per-neuron) |
upstream class, upstream neuron, weight, downstream neuron, downstream class, data source |
query_connectivity (grouped) |
upstream class, downstream class, % connected, pairwise connections, avg weight |
Zero results from query_connectivity — try these relaxation steps in order:
- Lower weight to 1.
- Set
exclude_dbsto[]to include all datasets. - Try
group_by_class=true. - Tell the user what was tried and let them decide.
- "To see full details on any neuron, I can look it up in VFB."
- "To see which brain regions this neuron connects to, I can run a region connectivity query."
- "To find what connects back to this type, I can swap upstream/downstream."
- "To aggregate by neuron class, I can re-run with group_by_class=true."
- "You can view any neuron at
https://v2.virtualflybrain.org/org.geppetto.frontend/geppetto?id={ID}"
When to use: User asks about the structure of a brain region, the types/subtypes of a cell class, or where something fits in the anatomical or cell type hierarchy.
Use the get_hierarchy tool.
| User asks | relationship |
direction |
|---|---|---|
| "What are the parts of the mushroom body?" | part_of |
descendants |
| "What is the mushroom body part of?" | part_of |
ancestors |
| "Where does the mushroom body fit in the brain?" | part_of |
both |
| "What types of Kenyon cell are there?" | subclass_of |
descendants |
| "What class of neuron is the Kenyon cell?" | subclass_of |
ancestors |
| "Show me the Kenyon cell hierarchy" | subclass_of |
both |
Default: Start with max_depth=1 (direct parents/children only). If the user wants more detail, increase it. Use max_depth=-1 with caution — broad terms can have thousands of descendants.
- Descendants are returned as a nested tree for both relationship types (children contain their own children).
- Ancestors are returned as a nested chain for both relationship types.
part_ofancestors are filtered to nervous system terms only (developmental lineage and generic structural terms are excluded).subclass_ofancestors are filtered to FBbt cell types only, stopping at "cell" (cross-ontology and non-cell ancestors are excluded).
Brain region structure:
get_hierarchy(id="FBbt_00005801", relationship="part_of", direction="both", max_depth=1)
Cell type hierarchy:
get_hierarchy(id="FBbt_00003686", relationship="subclass_of", direction="both", max_depth=2)
The response includes:
display— a pre-formatted text tree with large sibling groups shortened. Always present this directly to the user rather than reformatting the JSON.display_full— the same text tree with no shortening. Use this if the user asks to see all terms.
After showing the text tree, offer the user an interactive HTML version they can open in their browser. Construct the URL using this pattern:
https://v3-cached.virtualflybrain.org/get_hierarchy_html?id=<ID>&relationship=<RELATIONSHIP>&direction=<DIRECTION>&max_depth=<DEPTH>
For example: https://v3-cached.virtualflybrain.org/get_hierarchy_html?id=FBbt_00003686&relationship=subclass_of&direction=both&max_depth=2
The HTML page has a collapsible interactive tree with clickable links to VFB for every term.
These patterns apply across all the entity resolution and query tools:
All resolve tools (resolve_entity, resolve_combination) use cascading resolution: exact name → synonym → broad pattern match. These tools expect unresolved user text, not already resolved IDs. Always confirm non-exact matches (SYNONYM/BROAD) with the user before proceeding to further queries.
When multiple matches are returned by any resolve tool, present a numbered list showing name, ID, and type for each match. Ask the user to pick one before continuing.
Always provide appropriate links in results:
- FlyBase reports:
https://flybase.org/reports/{ID}(for FBgn, FBal, FBti, FBco, FBst, FBrf IDs) - VFB browser:
https://v2.virtualflybrain.org/org.geppetto.frontend/geppetto?id={VFB_ID}(for VFB IDs) - DOI:
https://doi.org/{DOI} - PubMed:
https://pubmed.ncbi.nlm.nih.gov/{PMID}/
- If an API call fails, explain the error clearly and suggest alternatives (check spelling, try a FlyBase ID directly, use
search_termsto validate) - If entity not found, suggest broader search or checking spelling
- If connectivity query returns error about unrecognized type, use
search_termsto find the correct neuron class term
The core chain (see Rule 1 at the top) is search → discover → query:
search_terms → get_term_info (read the Queries array) → run_query (with a query_type from that array).
Specific patterns:
resolve_entity→run_querywithquery_typeFindStocksresolve_combination→run_querywithquery_typeFindComboPublicationssearch_terms(find neuron class) →get_term_info→run_querywithDownstreamClassConnectivityorUpstreamClassConnectivitysearch_terms(validate neuron class) →query_connectivity(dual-end class-to-class)search_terms→get_term_info(get VFB ID) →run_querywithNeuronNeuronConnectivityQuery,NeuronRegionConnectivityQuery, orNeuronInputsTosearch_terms(find term) →get_hierarchy(explore structure or taxonomy)
If a chain step returns empty or an error, do not stop — try a different query_type from the Queries array, or a related entity. See Rule 2.
VFB provides multiple types of images:
- Interactive 3D models showing neuron morphology, expression patterns
- Can be viewed in VFB's web interface or downloaded as
.nrrd,.wlz, or.objfiles
- High-resolution confocal images of fly brain sections
- Show actual biological samples with fluorescent markers
- Small preview images (URLs containing
/thumbnail.pngor/thumbnailT.png) - Quick visual identification of brain regions or neuron types
The VFB browser can be opened with specific terms and 3D scenes using URL parameters:
https://v2.virtualflybrain.org/org.geppetto.frontend/geppetto?id=<FOCUS_ID>&i=<IMAGE_ID1>,<IMAGE_ID2>,...
Parameters:
id=— A single VFB ID for the focus term shown in the term info paneli=— A comma-separated list of VFB IDs for images to display together in the 3D viewer
The get_term_info response contains an Images field that is a dictionary keyed by template brain ID:
"Images": {
"VFB_00101567": [{"id": "VFB_00000001", "label": "fru-M-200266", ...}],
"VFB_00017894": [{"id": "VFB_00000001", "label": "fru-M-200266", ...}]
}Each key is a template brain ID (e.g., VFB_00101567 = JRC2018Unisex). The images under each key are registered to that template. Only images registered to the same template will align correctly in the 3D viewer.
- Always put the template ID first in the
i=list to ensure the correct 3D brain coordinate space is loaded - Only combine images registered to the same template — check the
Imagesdictionary keys to determine which template each image belongs to - The
id=parameter sets the focus term — this is typically the entity the user asked about
View a single neuron on its template:
https://v2.virtualflybrain.org/org.geppetto.frontend/geppetto?id=VFB_00000001&i=VFB_00101567,VFB_00000001
VFB_00101567 (JRC2018Unisex template) is listed first in i=, followed by the neuron VFB_00000001. The id=VFB_00000001 sets the focus to the neuron.
View multiple neurons together in 3D:
https://v2.virtualflybrain.org/org.geppetto.frontend/geppetto?id=VFB_00000001&i=VFB_00101567,VFB_00000333,VFB_00000001
Multiple image IDs after the template ID will all be rendered together, provided they are all registered to VFB_00101567.
View just a term's info (no 3D scene):
https://v2.virtualflybrain.org/org.geppetto.frontend/geppetto?id=FBbt_00003624
Omitting the i= parameter opens the term info panel without loading a 3D scene.
A term is a template brain if its SuperTypes array from get_term_info includes "Template". Common templates:
VFB_00101567— JRC2018Unisex (adult brain)
- Use
search_termsto find relevant entities - Use
filter_typesto narrow results by entity type (e.g.,["neuron"],["gene"],["expression_pattern"]) - Use
list_search_facetsto find valid type names instead of guessing them - Use
exclude_typesto remove unwanted result types (deprecated terms are already excluded server-side) - Use
boost_typesto prioritize results with useful data (e.g.,["has_image", "has_neuron_connectivity"]), anddemote_typesto push a type down without hiding it - For large result sets, use
minimize_results: trueto limit to top 10 and reduce context usage - For exact term matches, use
auto_fetch_term_info: trueto get immediate detailed information - Use
startandrowsfor pagination when exploring large result sets - Look for entities with useful Tags (has_image, has_neuron_connectivity)
- Use
get_term_infoon promising IDs - Check SuperTypes for classification
- Look at Tags for available data types
- Use
run_querywith different query_types based on Tags - Common queries: PaintedDomains, SimilarMorphology, Connectivity
- Publications provide scientific context
- Images show visual data
- Related entities can be explored recursively
- Complete Brain Coverage: Unlike partial datasets, VFB covers entire fly brain
- Standardized Templates: All data registered to common brain templates
- Multi-modal Integration: Combines anatomy, gene expression, connectivity
- Large Scale: Tens of thousands of neurons and expression patterns
- Open Access: Freely available for research
- Community Curation: Expert-validated data
- Circuit Analysis: Understanding neural circuits at single-neuron resolution
- Gene Function: Where and when genes are expressed in the brain
- Evolution: Comparing fly brain to other species
- Disease Models: Fly models of human neurological disorders
- Connectomics: Complete wiring diagrams of brain regions
- Confidence Values: Many datasets include confidence scores
- Publication References: Peer-reviewed sources
- Multiple Imaging Modalities: Cross-validation across techniques
- Standard Ontologies: Consistent terminology using the Drosophila anatomy ontology (FBbt) and related ontologies
- Identify the scientific question - Map to VFB capabilities
- Search for relevant terms - Use search_terms to find entities
- Get detailed information - Use get_term_info for context
- Run relevant queries - Use run_query for analyses
- Explain findings - Provide scientific interpretation
- Suggest visualizations - Construct VFB browser URLs to let users view results in 3D (see "Constructing VFB Browser URLs" section)
- Gene expression: Search for gene name with
filter_types: ["gene"]→ get_term_info → run PaintedDomains query - Neuron morphology: Search for neuron type with
filter_types: ["neuron"]→ get_term_info → check for SimilarMorphology - Neurons with images: Search with
filter_types: ["neuron", "has_image"],minimize_results: true(add"adult"or"larva"only if the user specified a stage) - Brain regions: Search for anatomical terms with
filter_types: ["anatomy"]→ explore hierarchical relationships - Connectivity (individual neuron): Search with
filter_types: ["has_neuron_connectivity"]→get_term_info→run_querywithNeuronNeuronConnectivityQuery - Connectivity (neuron class): Search with
filter_types: ["neuron", "class"]→run_querywithDownstreamClassConnectivityorUpstreamClassConnectivity - Connectivity (class-to-class): Search with
filter_types: ["neuron", "class"]→query_connectivity(both upstream and downstream types) - Brain region structure: Search with
filter_types: ["anatomy"]→get_hierarchywithrelationship: "part_of" - Cell type hierarchy: Search with
filter_types: ["neuron", "class"]→get_hierarchywithrelationship: "subclass_of" - Datasets: Search with
filter_types: ["dataset"]to find available datasets - Exact term lookup: Use
auto_fetch_term_info: truefor immediate detailed information on exact matches - Facet names: Call
list_search_facetsrather than guessing type names — there are over 200 and they change
See also: Rules 2 and 3 at the top of this document.
- If
search_termsreturns no good matches, try alternative spellings, synonyms, broader terms, or differentfilter_typesfrom the cookbook. Settingunique: falsecan help here — it shows which synonym matched, which often explains a surprising result. - If
search_termsorquery_connectivityreturns a rejection message, read it: an unknown facet name comes back with suggested alternatives, and a connectivity rejection names the missing or unresolvable parameter. Fix the call from the message rather than retrying it unchanged. - If
run_queryfails or returns empty, callget_term_infoon the ID and pick a differentquery_typefrom theQueriesarray. The error message will list the valid query_types — use them. - If no MCP call answers the question, tell the user clearly what you tried and what you found. Do not fall back to training-data answers (no fabricated FBbt/FBgn/FBst IDs, driver names, citations, or numbers).
- Network timeouts: suggest retrying.
query_connectivityis the only slow tool — others should respond in seconds.
To use the Virtual Fly Brain (VFB) Model Context Protocol (MCP) server with AI on Google Search, connect through the Gemini CLI or a custom Python/Node.js client.
The Gemini web interface does not directly support custom MCP integration. Developer tools are needed to connect the two.
Option 1: Using Gemini CLI
The Gemini CLI allows direct registration of remote MCP servers.
Install the CLI: Ensure Node.js is installed, then run:
npm install -g @google/gemini-cliAdd the VFB Server: Use the add command with the VFB URL.
gemini mcp add vfb https://vfb3-mcp.virtualflybrain.orgVerify & Use: Run the CLI by typing gemini. Check the connection with /mcp. AI on Google Search will then call VFB's neuroanatomy and connectivity tools when questions about Drosophila are asked.
Option 2: Using Python
For application development, use the mcp and google-genai libraries to connect.
Setup: pip install google-genai mcp
Implementation: Use a streamable HTTP transport in JSON response mode (e.g. enableJsonResponse: true) to connect to the VFB URL, list its tools, and pass their schemas to the Gemini model as Function Declarations.
This MCP enables powerful neuroscience research by providing programmatic access to one of the most comprehensive neuroanatomical databases available.