---
summary: "kingdom, family, and genus on gbif_search_species now scope the search — each name is resolved to a GBIF backbone key and the narrowest is forwarded as higherTaxonKey, the parameter /species/search actually implements."
breaking: false
security: false
---

# 0.7.2 — 2026-08-06

## Fixed

- **`kingdom`, `family`, and `genus` on `gbif_search_species` scope the search.** `/species/search` implements none of the three and ignores a parameter name it does not recognize, so every value returned the unfiltered backbone: `family=Paridae`, `genus=Quercus`, `kingdom=Plantae`, no parameters at all, and an invented `bogusParam=zzz` each answered with the same 46,623,754 names, against 558,589 for the implemented `rank=FAMILY`. Each name is now resolved through `/species/match` and forwarded as `higherTaxonKey` — `family: "Paridae"` returns 641, `genus: "Quercus"` 6,059, `kingdom: "Plantae"` 2,101,916. ([#55](https://github.com/cyanheads/gbif-biodiversity-mcp-server/issues/55))
- **Only the narrowest of the three is sent.** `/species/search` OR-s repeated `higherTaxonKey` values rather than intersecting them — keys 1 and 6 together return 6,534,100, exactly their sum — so a kingdom sent beside a family would widen what the family narrowed. The three nest, so the narrowest is the intersection.
- **`kingdom` supplied beside `family` or `genus` disambiguates that name** rather than scoping on its own, passed to the lookup as GBIF's own `kingdom` parameter: `Prunella` matches nothing alone, the accentor genus 2495070 under Animalia, and the self-heal genus 2926553 under Plantae. It also rejects a contradiction upstream — `Paridae` under Plantae matches nothing.
- **The rank key is forwarded, not `usageKey`,** which is what makes an alternative name land on the taxon it is a synonym of: `Compositae` matches `usageKey` 6070956 with `familyKey` 3065, and `higherTaxonKey=6070956` returns 0 names where 3065 returns 201,100.
- **The returned rank is verified before its key is read.** `/species/match` treats `rank` as a scoring hint rather than a constraint — `Parus major` asked for as a GENUS comes back as a SPECIES and still carries a `genusKey` — and matching is strict, since fuzzy matching shifts a scope onto a taxon nobody named (`Quercus` under kingdom Animalia fuzzy-matches the leafhopper genus *Quernus*).
- **A blank `kingdom`, `family`, or `genus` fails as `invalid_filter`** alongside `q` and `datasetKey`, now that a blank one names no taxon.

## Added

- **`unresolved_taxon_scope`** (`NotFound`) — a `kingdom`, `family`, or `genus` name that reached no backbone taxon at that rank: a misspelling, a lowercase name, a name entered under the wrong rank, or a cross-kingdom name with no `kingdom` beside it.
- **`conflicting_taxon_scope`** (`InvalidParams`) — a `family` and `genus` that each resolved but into different lineages, checked locally against the genus match's own `familyKey` since `/species/match` ignores a `family` hint. The message names the family the genus actually belongs to.
- **`taxonScope`** on the `gbif_search_species` enrichment — which field scoped, the backbone taxon its name resolved to, and that taxon key, on every scoped call.
- **Empty-result notice for a taxon scope paired with `datasetKey`.** GBIF reads a higher-taxon key inside the checklist that key belongs to and the resolved key is always a backbone key, so the pairing matches nothing by construction: `higherTaxonKey=9327` returns the same 641 names with and without the backbone `datasetKey`, and 0 against the 455-name "Checklist of alien birds of Belgium".

## Changed

- **`GbifService.searchSpecies`** takes `higherTaxonKey?: number` in place of `kingdom`, `family`, and `genus`.
- **`README.md`, `docs/design.md` (decision 17 and the endpoint table), the server-level `instructions`, and each field's `.describe()`** state that the three take names, resolve to a key, match exactly at GBIF's own capitalization, and that the narrowest is what scopes.
