familysearch-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| FS_TIMEOUT | No | HTTP timeout in seconds. Default 60. | 60 |
| FS_ENV_FILE | No | The env file to read these settings from, and to re-read a refreshed token from. Default: the nearest .env from the working directory upward. | |
| FS_CLIENT_ID | No | Your registered application's client id, reported by auth_status. | |
| FS_ENVIRONMENT | No | production (default) or integration for the FamilySearch sandbox. | production |
| FS_ACCESS_TOKEN | No | Bearer token from your application's OAuth flow. |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
| experimental | {} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| search_placesA | Look up a place in the FamilySearch gazetteer. Resolves a bare place name to its full jurisdictional form and coordinates, which is what a properly-formed place record needs. Each result carries a place id you can pass to get_place or get_place_jurisdictions. If the place name comes from a record with a date on it, prefer search_places_at_date: jurisdictions change, and the modern answer is often the wrong one. Works without credentials. |
| search_places_at_dateA | Resolve a place as it existed in a particular year. Jurisdictions are not stable. Counties are created, split, renamed and abolished, so a record naming a county that no longer exists is ordinary rather than an error. Filing that record under the modern county that now covers the ground is a common mistake, and an invisible one: the place name still looks plausible, but it sends the next search to the wrong courthouse and the wrong record set. Give it the name as the record spells it and the year of the record. Each result carries the span over which that jurisdiction existed, so you can see whether it was the right one at the time. Works without credentials. |
| get_placeA | Read one place: its jurisdictional chain, type, coordinates and dates. The dates are the ones that matter for research. A place description records the span over which that jurisdiction existed, so you can check whether the county a record names was the county in being on the date the record was made. Works without credentials. |
| get_place_jurisdictionsA | Walk a place's containment chain upward to the country. This is what turns "Kaskaskia" into "Kaskaskia, Randolph, Illinois, United States". The chain is returned innermost first, each level carrying its own id, type and the span over which it existed, so you can see at which level the naming changed. Works without credentials. |
| search_recordsA | Search historical records by name, events, relatives, type or collection. Beyond a person's own name and dates, two kinds of criteria matter: Relationship criteria. Searching for a man by his wife's or his father's name is how you find him when his own name was misindexed, mis-spelled or abbreviated to an initial. An indexer who mangled "Chesebrough" often got the wife's "Mary" right. Scoping. Restricting to a record type or a single collection turns a search of the whole archive into a search of one register, which is what you want once you know which register should hold the entry. Pass at least one name. Everything else narrows. Requires an access token. |
| get_recordA | Read one indexed record in full. A search returns a persona: one person's summary of what a record said. This returns the record, which is more: every person named on it, and the indexed fields behind each of them, labelled with the box on the original form each value was read from. The fields are where a search summary loses things -- the informant, the witness, the enumerator's spelling, the age that contradicts the birth year. This is still the index, not the document. Use get_record_image to reach what was actually written. Requires an access token. |
| get_record_imageA | Find the document image an indexed record was taken from. The persona is somebody's reading of the record. The image is the record. Indexers mis-read hands, skip columns, normalise spellings and guess at ages, so anything that matters should be checked against the film. Returns whatever the record offers as a route to the image: image and waypoint links, and the digital film (DGS) and image numbers indexed against it. Many records carry no image link at all, in which case this says so rather than inventing one -- a great deal of the archive was indexed from microfilm that has never been published, and the answer is then to read the citation and order the film. Requires an access token. |
| search_collectionsA | Find a record collection, so a search can be scoped to one. A collection is one register, census or index -- "Connecticut Church Records, 1630-1920" rather than the whole archive. Once you know which collection should hold an entry, scoping search_records to its id turns a fishing expedition into a lookup, and turns a nil result into something that means anything. Each result carries a coverage statement: which record types, which place, which years. Read it. A collection covering 1850 to 1900 cannot answer a question about 1840, and the difference between "no record exists" and "I searched a collection that could not contain it" is the whole of the reasoning. FamilySearch offers no search over the catalogue, so this walks it and matches your words against the titles. The catalogue runs to thousands of collections and the API pages it in blocks of roughly ninety, so this makes several calls the first time; the result is cached. Works without a token. |
| get_collectionA | Read one record collection: what it covers, and how much of it there is. Worth reading before trusting a nil result. The counts say how many records, people and images the collection holds, and a collection whose image count is far below its record count was indexed from film that was largely never published. Works without a token. |
| get_personA | Read one person from the FamilySearch shared tree. Returns names, sex and facts. Use it to find records: get_person_sources on the same id is usually the next call, because it leads out of the tree towards a document. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_person_relativesA | Read a tree person's parents, spouses, children and siblings. One call for the whole immediate family, which is what you need to judge whether a profile is the person you are looking for. A family that does not fit -- a child born before the marriage, a wife with the wrong surname, parents twenty years too young -- is the usual first sign of a conflation of two same-named people. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_ancestryA | Walk a tree person's pedigree back through the generations. Each person carries an Ahnentafel position: 1 is the person asked about, 2 and 3 their father and mother, 4 to 7 their grandparents, and so on -- so a flat list reads as a tree, and a gap is visible as a missing number. The further back a pedigree runs the less of it is sourced. Lines beyond about five generations are frequently copied rather than researched, and a long unbroken pedigree is a reason for more suspicion rather than less. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_descendancyA | Walk a tree person's descendants forward through the generations. Useful for the sideways search: when a person's own record cannot be found, a descendant's obituary, probate or pension file often names him. Living descendants are withheld and come back marked as restricted. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_person_sourcesA | Read the sources attached to a tree person. This is the most useful thing in the tree, because it is the way out of it. Each attached source carries a citation and usually an ark pointing at an indexed record, so a profile that seemed unsupported becomes a list of documents to read. Each source also carries what it is said to support -- Name, Birth, Death -- which distinguishes "this person has sources" from "this person's death date has a source". A profile with ten sources, none of which touch the fact you care about, has told you nothing about it. A profile with no sources at all is not evidence of anything. It is somebody's assertion, and should be treated as one. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_person_memoriesA | Read the photographs and documents attached to a tree person. Memories are uploads: a headstone photograph, a scanned letter, a family Bible page, a typed story. Some are primary documents worth citing; others are a relative's recollection written down eighty years later. What each one is depends entirely on what was uploaded, so look before relying on it. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_person_changesA | Read the change log of a tree profile: who edited it, when and why. This is how you judge what you are looking at. A profile assembled in one sitting last month by one contributor is a different kind of claim from one built over years by several. A name or a parent that changed recently, with no reason given, is where a conflation of two same-named people usually enters. Each entry carries the contributor, the timestamp, what changed and any reason they typed. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_matchesA | Read FamilySearch's own candidate matches for a tree person. With collection 'tree' these are profiles the system thinks may be the same person -- the duplicates behind most conflations, and the reason a person appears twice with two different sets of parents. With collection 'records' they are indexed records that may belong to this person, which is a lead towards a document. These are the system's guesses, scored by its own confidence. A high score is a reason to look, never a reason to conclude. Record matches are restricted in production to applications FamilySearch has certified; an uncertified one gets a refusal here rather than results. The FamilySearch shared tree is community-edited: anyone can change this profile, and conflations of two same-named people are common. What this returns is a hint about where to look, not evidence. Follow it to an underlying record and cite that instead. Requires an access token. |
| get_place_childrenA | List the places directly inside a jurisdiction. The downward walk, complementing get_place_jurisdictions' upward one. Use it to find the right sub-jurisdiction when a record names a town you cannot place, or to see what a county contained at the time. Works without a token. |
| browse_waypointsA | Browse a collection's structure — its volumes, date ranges and films. The way to reach a page the index never covered. Indexing is incomplete across most of the archive, so a record you cannot find by searching may still be sitting on an image you can browse to: collection, then volume or date range, then film, then pages. Works without a token. Pass a collection_id to start, then a waypoint_id from the children to descend. |
| get_records_on_imageA | List every record indexed from one image. The reverse of get_record_image. A passenger manifest page carries thirty people and a census page forty; finding one of them tells you where the others are. Use it to pick up a household, or to check whether the person you want was indexed at all from a page you are already reading. Requires an access token. |
| get_collection_fieldsA | Decode the field codes a collection's indexed records use. An indexed record labels its values with codes rather than words —
Works without a token. |
| get_image_linksA | Resolve a document image to its actual, fetchable URLs. A record read does not carry image links; the image resource does, and
this is it. Returns the storage node, the deep-zoom descriptor, thumbnails
at several sizes, and Also returns the neighbouring pages. A pension file or a passenger manifest runs to many images, and the entry you want is often not the one the index pointed at. |
| get_film_imageA | Reach a page image by film and image number instead of by ark. Citations often name a film and an image rather than an ark — those are
the Checks the thumbnail first and says plainly whether the image exists, so a wrong film or image number is a clear answer rather than a URL that fails later. The thumbnail is readable without a token; the full page needs one. |
| download_imageA | Download a document image to a local file so it can be read. This is the step that turns a citation into evidence. The image is written to disk rather than returned inline: a full page scan runs to megabytes, which is not something to push through a tool result. Only FamilySearch image URLs are fetched, because the request carries your access token. Images are copyrighted or access-restricted in some collections. Treat a downloaded file as a working copy for reading, not as something to redistribute. |
| auth_statusA | Report whether credentials are configured, and what is missing. With a token configured, also asks FamilySearch whether it is still
accepted ( This server ships no client id. Production access needs your own registered FamilySearch application; see docs/AUTH.md. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
No prompts | |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
No resources | |
TDQS
Scored across 25 tools
Most tools target clearly distinct resources and actions (records, places, collections, tree persons, images). The main overlap is the four image-access tools (get_record_image, get_image_links, get_film_image, download_image), which an agent could confuse despite the descriptions clarifying their different steps.
All names use lowercase snake_case, and almost all follow a verb_noun pattern (get_record, search_places, download_image). The few deviations, such as auth_status, are common and readable rather than inconsistent.
25 tools is heavy for this surface, though the domain is broad enough that most tools are not redundant. The count sits at the borderline where density starts to make tool selection harder for an agent.
The set covers record search/read, place resolution, collections, image retrieval, and many tree-person read operations. However, it lacks a way to discover tree persons by name or otherwise find their IDs, which blocks or complicates tree workflows before any get_person_* tool can be used.