Skip to content

io.github.cyanheads/paleobiology-mcp-server

by cyanheads · remote · local (npm) · no sign-in to list tools · v0.4.0 · published by GitHub user cyanheads

Search fossil occurrences, taxon ranges, diversity through deep time, and the geologic time scale.

Changes · 1

8 tools: 1 change things and 7 only read.

Scanned Oct 21, 2026

1 check matched something in the tool definitions. No finding is not a safety guarantee. How the checks work.

claude mcp add --transport http paleobiology https://paleobiology.caseyjhand.com/mcp

Findings

Matches of fixed checks, with the text they matched.

1 warn
  • The server marks "paleobiology_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

    Matched text

    annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "paleobiology_dataframe_query" says "query": a word for reading.

    What this check looks for

Tools

Open a tool for its reasons and full description. Descriptions are the publisher's own words, shown as they are.

8 tools

Changes things 1Claude Code: ask
  • paleobiology_dataframe_queryRun a read-only SQL SELECT against occurrence result sets staged on a DataCanvas by paleobiology_search_occurrences.1 finding

    Why it is in this group

    • The name "paleobiology_dataframe_query" says "query": a word for reading.
    • The description's first verb is "run": a word for a change.
    • The input takes a statement or command to run (input.sql), which can change anything it can reach.
    • The server marks it read-only (readOnlyHint: true), but an annotation never lowers a class.

    Findings

    • Warn

      The server marks "paleobiology_dataframe_query" read-only (readOnlyHint: true), and its own name, description or input give the class "write".

      Matched text

      annotations: {"readOnlyHint":true,"idempotentHint":true,"openWorldHint":false}; The name "paleobiology_dataframe_query" says "query": a word for reading.

      What this check looks for
    Description, as the server wrote it
    Run a read-only SQL SELECT against occurrence result sets staged on a DataCanvas by paleobiology_search_occurrences. This is how you analyze a large fossil set without re-fetching it: count occurrences by early_interval, group by formation, country (cc), or accepted_name, or filter by a paleo/modern coordinate range. The classification column is JSON — roll up by rank with json_extract_string(classification, '$.family') (also $.phylum, $.class, $.order, $.genus). Staged rows are occurrences, so collection-only fields such as lithology are not present. Reference tables by the table_name that paleobiology_search_occurrences returned — call paleobiology_dataframe_describe first if you do not know the table or column names. A result too large to return inline comes back as its first rows, with a notice naming the ORDER BY … LIMIT/OFFSET that reads the rest. SELECT only; writes and file-reading functions are rejected.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
Only reads 7Claude Code: allow
  • paleobiology_dataframe_describeList the tables and their columns staged on a DataCanvas by paleobiology_search_occurrences.No findings

    Why it is in this group

    • The name "paleobiology_dataframe_describe" says "describe": a word for reading.
    Description, as the server wrote it
    List the tables and their columns staged on a DataCanvas by paleobiology_search_occurrences. Call this before paleobiology_dataframe_query to discover the exact table_name and column names to reference in SQL.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: false
  • paleobiology_get_diversityCompute a diversity / origination / extinction curve for a clade across geologic time, binned by period, epoch, or age — answers "plot dinosaur genus diversity across the Mesozoic.…No findings

    Why it is in this group

    • The name "paleobiology_get_diversity" says "get": a word for reading.
    Description, as the server wrote it
    Compute a diversity / origination / extinction curve for a clade across geologic time, binned by period, epoch, or age — answers "plot dinosaur genus diversity across the Mesozoic." Pass a clade-inclusive base_name (or base_id, the same clade by resolved taxon id — exactly one of the two) and bound the span by a named interval (e.g. "Mesozoic") or a max_ma/min_ma range; choose what to count (genera, species, or families) and the bin resolution. The full bin set returns inline — a diversity series is a bounded set of geologic intervals — so you read the curve, the turnover, and the per-bin origination/extinction directly. Counts reflect SAMPLED diversity, biased by collection effort and rock availability, not true past diversity.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true
  • paleobiology_get_referencesResolve PBDB reference_no values — the source publication on every paleobiology_search_occurrences and paleobiology_search_collections row — to full citations with authors, year, t…No findings

    Why it is in this group

    • The name "paleobiology_get_references" says "get": a word for reading.
    Description, as the server wrote it
    Resolve PBDB reference_no values — the source publication on every paleobiology_search_occurrences and paleobiology_search_collections row — to full citations with authors, year, title, publication, volume, pages, and DOI. Pass the ids from a page of rows in one call: the first 25 distinct ids are resolved and any beyond that come back in remaining_reference_nos for a follow-up call. Ids PBDB has no reference for are listed in not_found. Results keep the order the ids were given.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true
  • paleobiology_get_taxonResolve a taxon by name (e.g.No findings

    Why it is in this group

    • The name "paleobiology_get_taxon" says "get": a word for reading.
    Description, as the server wrote it
    Resolve a taxon by name (e.g. "Tyrannosaurus") or by integer taxon_no to its accepted name, rank, higher classification, immediate parent, fossil occurrence count, and first/last appearance (FAD/LAD) range in millions of years — "when did this clade exist, and what is it." Run this first to resolve a name into the accepted name and taxon_no, then pass that id as base_id to paleobiology_search_occurrences, paleobiology_get_diversity, or paleobiology_search_collections for a clade-inclusive filter that carries no name ambiguity (the same id also appears as accepted_no on occurrence rows). Set show_children to also list immediate child taxa. PBDB taxonomy is opinionated and can differ from GBIF's backbone, so the accepted name may differ from the name you searched.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true
  • paleobiology_list_intervalsLook up the geologic time scale — eons, eras, periods, epochs, and ages with their absolute-age boundaries in millions of years (Ma) and nesting.No findings

    Why it is in this group

    • The name "paleobiology_list_intervals" says "list": a word for reading.
    Description, as the server wrote it
    Look up the geologic time scale — eons, eras, periods, epochs, and ages with their absolute-age boundaries in millions of years (Ma) and nesting. This is the reference that grounds every temporal filter on the other tools and translates a named interval like "Late Cretaceous" to its 100.5–66.0 Ma boundaries (and back). Filter by a name substring, a Ma range (overlap match), and/or a level; call with no filters to browse the full scale. Browsing and every name on the bundled ICS international-scale snapshot are answered offline. A name the snapshot does not carry — the sub-stage and regional names that occurrence and collection rows report, such as "Late Maastrichtian" or "Lancian" — costs one PBDB lookup across its other time scales; the response names which source answered and which scale the interval belongs to.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true
  • paleobiology_search_collectionsFind fossil collections (localities) by area and geologic time — "what has been dug up here, and from what rock." Each locality returns its location, age (named interval and Ma), f…No findings

    Why it is in this group

    • The name "paleobiology_search_collections" says "search": a word for reading.
    Description, as the server wrote it
    Find fossil collections (localities) by area and geologic time — "what has been dug up here, and from what rock." Each locality returns its location, age (named interval and Ma), formation and strata, lithology, depositional environment, and the count of co-occurring fossils. Filter by a clade-inclusive base_name (or base_id, the same clade by resolved taxon id), a named interval or max_ma/min_ma range, a lng/lat bounding box, a formation or lithology name, and/or an environment. Results page inline via limit/offset (the response discloses when more remain). Take a collection_no from a row and pass it — or the same bbox+interval — to paleobiology_search_occurrences to see the actual fauna found together.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true
  • paleobiology_search_occurrencesSearch fossil occurrences filtered by taxon, geologic time, geography, and depositional environment — the flagship.No findings

    Why it is in this group

    • The name "paleobiology_search_occurrences" says "search": a word for reading.
    Description, as the server wrote it
    Search fossil occurrences filtered by taxon, geologic time, geography, and depositional environment — the flagship. Use base_name for a clade and all its descendants (what "Tyrannosaurus occurrences" usually means), base_id for that same clade by resolved taxon id, or taxon_name for an exact taxon. Bound the age by a named interval (e.g. "Maastrichtian") or a max_ma/min_ma range, and/or a lng/lat bounding box; scope to a single locality with collection_no (take it from a paleobiology_search_collections row). At least one filter is required — taxon, time, place, environment, or collection_no. Every row carries two distinct coordinate systems — modern lng/lat (where the rock is today) and paleo lng/lat (where the landmass sat at deposition) — plus the formation, age interval, and higher classification (phylum through genus); never plot a deep-time occurrence on a modern coastline. Resolve a name with paleobiology_get_taxon first if unsure. Broad queries return many rows: an inline preview answers the immediate question. When this deployment has DataCanvas enabled, a set that outgrows the inline preview stages on a canvas (canvas_id + table_name, returned only then): list its columns with paleobiology_dataframe_describe, then run SQL with paleobiology_dataframe_query (count by interval, group by formation/country, map by region). The response reports how many occurrences matched in total, which rows this page covers, and the offset that reaches the next page — page through the whole match set with limit/offset.

    Annotations the server declares

    • readOnlyHint: true
    • idempotentHint: true
    • openWorldHint: true

This is not a safety rating, and no finding is not a safety guarantee. The groups and findings come from fixed checks of the tool definitions the server returned on the date shown, not from its code or what it does when called. How the checks work.

Install

Pinned to version 0.4.0. Values in angle brackets are yours to fill in.

claude mcp add --transport http paleobiology https://paleobiology.caseyjhand.com/mcp

Run in a terminal.

Claude Code permissions

Allow the reads, ask before a change, deny the deletes. Paste into .claude/settings.json.

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__paleobiology__paleobiology_search_occurrences",
      "mcp__paleobiology__paleobiology_get_taxon",
      "mcp__paleobiology__paleobiology_get_diversity",
      "mcp__paleobiology__paleobiology_list_intervals",
      "mcp__paleobiology__paleobiology_search_collections",
      "mcp__paleobiology__paleobiology_get_references",
      "mcp__paleobiology__paleobiology_dataframe_describe"
    ],
    "ask": [
      "mcp__paleobiology__paleobiology_dataframe_query"
    ],
    "deny": []
  }
}

Tools that only read are allowed, tools that change things ask first, tools that delete or cancel are denied. It assumes the server is installed as paleobiology. Review it before you use it.