Skip to main content
Glama

family.ancestry

Private family trees for your family. What you'd use Ancestry for, without the subscription, and without your family's history becoming someone else's product. Open source (MIT).

https://family.ancestry, a name on the Moshpit network. The desktop app, the CLI and the MCP server reach it by themselves; a browser needs one setting.

  • Trees you build together: editors add and fix, viewers look. Invite by email or by link: paste a whole list (a To: line, a spreadsheet column, Aunt Rose <rose@example.com>), 20 at a time, 500 on the Family plan.

  • Join the family as yourself. Right after you add someone, the page quietly offers to invite them; they join as that person and keep their own profile up to date, even as a viewer. A pasted name that matches someone in the tree invites them as that person; everyone else picks themselves ("Which one is you?") or adds themselves when they join, then adds a photo. A profile is only ever claimed by the email address the invite went to: signing in with an emailed link is the proof.

  • Local: businesses recommended by people you know. Your family, neighbors and friends say who they use (the plumber, the dentist, the bakery) and why; you see the picks of your connections and tree-mates, ranked by how many vouch for a place and how close they are to you. No strangers' reviews, nothing paid to the top. See Local.

  • Network (add-on, free for everyone): family, friends, neighbors and business contacts with every detail you keep (emails, phones, addresses, birthdays, links, notes), vCard import/export, and a private Inbox. See Network.

  • People with dates, places, notes and stories, photos, and a life timeline.

  • Every kind of family. Partners (married, partners, or boyfriend / girlfriend) plus children (birth, adopted, step, foster), the GEDCOM way. Add a brother or sister directly: full (even when nobody knows the parents), half through a chosen parent, adopted, foster, or step through a step-parent. Add a grandparent when the parent between is unknown (an "Unknown" parent holds the place). And bonds that are not descent: raised by, guardian, godparent, caregiver, chosen family, neighbor, so grandparents who raised you are both. All of it round-trips through GEDCOM (PEDI, ASSO/RELA).

  • Pets (Family plan): the dogs, cats and horses that were family too, with owners, photos and stories. They never appear as anyone's parent or child, nor in GEDCOM.

  • Pedigree (3–6 generations, Ahnentafel numbers) and descendant charts.

  • "How are we related?" in words: first cousin once removed, mother-in-law, half-sister, stepbrother, adoptive mother, grandfather (by adoption). Only a marriage makes an in-law: a daughter's boyfriend is daughter's boyfriend.

  • Sources and citations, so you know where every fact came from.

  • GEDCOM 5.5.1 import and export. Bring your tree from Ancestry, FamilySearch, MyHeritage, Gramps or RootsMagic, and take it with you. Exports can hide living people.

  • Family photo album, free: every photo in the tree on one page (/t/:tree/photos), and albums ("Christmas 1985") that any verified member adds to, viewers included. Pick a whole batch at once; the page sends them one by one and shrinks anything over 8 MB. Tag who is in a photo and it shows on their page too.

  • Family businesses, free: "Ettinger Plumbing" as its own entry, with its founders, owners, partners, investors and employees (titles and years), founded/closed dates, place, website, notes and photos. On each person's page and in search; never in a pedigree or descendant chart. GEDCOM carries them as a custom _BUS record.

  • Sign in with an emailed link (which is also sign-up) or a passkey. No passwords.

Every surface

Web + phone (PWA)

https://family.ancestry, "Install app" from the browser menu

Desktop

macOS / Windows / Linux builds on the releases page

CLI

bun add -g familyancestry, then ancestry login

TUI

ancestry tui

MCP

claude mcp add ancestry -- ancestry mcp

API

JSON under /api/v1, Authorization: Bearer fa_...

CLI

ancestry login                       # browser sign-in (auth code + PKCE); or --token fa_...
ancestry import ~/Downloads/tree.ged # into a new tree, which becomes your default
ancestry people ettinger             # search
ancestry show "Johann Ettinger"
ancestry add --given Lily --surname Ettinger --born 2015 --living --child-of "Robert Ettinger"
ancestry add --given Sam --sibling-of Lily --sibling half --via Robert
ancestry add --given Rose --grandparent-of Lily --raised   # parents unknown: an "Unknown" parent goes between
ancestry bond Lily godparent "Aunt Karen"
ancestry pet Lily Rex --species Dog       # Family plan
ancestry plan                             # ancestry plan buy --chain USDC_POL
ancestry claim "Lily Ettinger"            # this is me
ancestry business add "Ettinger Plumbing" --category Plumbing --founded 1952 --place Sacramento --founder Karl
ancestry business role "Ettinger Plumbing" Robert owner --title "Master plumber" --from 1971 --to 1990
ancestry businesses plumbing              # ancestry business "Ettinger Plumbing" shows its people
ancestry business link "Ettinger Plumbing" "Ettinger office"   # to one of your contacts (or --create)
ancestry search ettinger                  # people and businesses
ancestry upload ~/Pictures/xmas85/*.jpg --album "Christmas 1985" --of Rose
ancestry albums                           # ancestry photos --album "Christmas 1985"
ancestry local plumber                    # who the people you know use
ancestry local add "Joe's Plumbing" --category Plumber --town Sacramento --note "Came on a Sunday"
ancestry pedigree Robert -g 4
ancestry descendants Johann
ancestry relate Robert Anna          # Anna Ettinger is Robert Ettinger's aunt.
ancestry export --privacy -o family.ged
ancestry invite rose@example.com --as "Rose Ettinger"   # she joins as Rose, keeps her own profile
ancestry invite a@example.com b@example.com --role editor --note "Help with Grandpa's side"
ancestry invite --file family-emails.txt  # any pasted list; --file - reads stdin
ancestry contact add --name "Dr. Patel" --circle business --relationship "our dentist" --phone "555 0142"
ancestry contact add --name "Pat Lee" --email pat@example.com --circle friends --connect   # add a friend + ask to connect
ancestry contact add --person "Kurt Rademacher" --email kurt@example.com --connect     # someone in your tree, into your network
ancestry contacts import ~/phone.vcf --circle family
ancestry connect "Aunt Rose"         # one email; if she says yes, you can message
ancestry inbox
ancestry message "Aunt Rose" "Are you coming Sunday?"

--json on any command prints JSON. ANCESTRY_URL points every client at another server (your own, or http://127.0.0.1:8792).

MCP tools

list_trees, search_people, get_person, add_person, update_person, link_relative (parent, partner, child, sibling, grandparent), add_bond, add_pet, family_plan, search_businesses, get_business, add_business, update_business, add_business_role, remove_business_role, link_business_contact, list_albums, list_photos, create_album, add_photo, update_photo, local_recommendations, recommend_business, add_event, pedigree, descendants, relationship, export_gedcom, import_gedcom, invite_to_tree, tree_members, and for the network list_contacts, get_contact, add_contact, add_person_to_network, update_contact, connect_contact, inbox, read_conversation, send_message. The assistant acts as you: it sees the trees you see, and changes only the ones you can edit.

API

GET /api/v1/me

you and your trees

GET/POST /api/v1/trees

list / create ({name})

GET /api/v1/trees/:tree/people?q=

list or search

POST /api/v1/trees/:tree/people

add ({given, surname, ..., relative_of?, as?: parent|partner|child|sibling|grandparent, relation?, sibling?: full|half|adopted|foster|step, via?, raised?, existing_id?})

POST /api/v1/trees/:tree/people/:id/bonds, DELETE .../bonds/:bond

a bond ({kind: raised_by|guardian|godparent|caregiver|chosen_family, other_id or person fields, note?})

POST /api/v1/trees/:tree/pets

a pet ({owner_id(s), given, species?}); 402 without the Family plan

GET /api/v1/trees/:tree/plan, POST .../plan/checkout

the Family plan; start a payment ({chain})

POST /api/v1/trees/:tree/claim

this is me ({person_id}) or add me (person fields)

GET/PATCH/DELETE /api/v1/trees/:tree/people/:id

one person, with parents, siblings (and their kind), partners, children, bonds, pets, events, sources, photos

POST /api/v1/trees/:tree/people/:id/events

add a life event

GET /api/v1/trees/:tree/pedigree/:id?generations=4

ancestors

GET /api/v1/trees/:tree/descendants/:id?generations=3

descendants

GET /api/v1/trees/:tree/relate?a=&b=

relationship in words, and the path

POST /api/v1/trees/:tree/import

GEDCOM text body

GET /api/v1/trees/:tree/export?privacy=1

GEDCOM

GET /api/v1/trees/:tree/members

members, with the person each one is

GET/POST /api/v1/trees/:tree/invites, DELETE .../invites/:id

pending invites; invite ({emails, role?, person_id?, note?}; no emails = a link)

GET/POST /api/v1/trees/:tree/businesses?q=

businesses: list or search / add ({name, category?, founded?, closed?, place?, website?, notes?, people?: [{person_id, role, title?, start_date?, end_date?}]})

GET/PATCH/DELETE /api/v1/trees/:tree/businesses/:id

one business, with its people, photos and your own linked contact

POST /api/v1/trees/:tree/businesses/:id/people, DELETE .../business-roles/:role

someone's role ({person_id or given+surname, role: founder|owner|partner|investor|officer|manager|employee|apprentice|other, title?, start_date?, end_date?, note?})

POST /api/v1/trees/:tree/businesses/:id/contact

link one of your Network contacts ({contact_id}, null unlinks, {create: true} adds it); private to you

GET /api/v1/trees/:tree/search?q=

people and businesses at once

GET/POST /api/v1/trees/:tree/albums, GET/PATCH/DELETE .../albums/:id

photo albums ({title, description?, cover_id?}); an album's GET carries its photos

GET /api/v1/trees/:tree/photos?album=&before=

photos, newest first

POST /api/v1/trees/:tree/photos

add photos: multipart file (up to 20) or JSON {filename, data_base64}, with caption?, album_id? or album_title?, person_id?

GET/PATCH/DELETE /api/v1/trees/:tree/photos/:id

one photo ({caption?, person_id?, album_id?})

GET /api/v1/local?q=&category=, POST /api/v1/local, DELETE /api/v1/local/:id

recommendations from people you know; recommend ({name, category, town?, phone?, website?, note?} or {contact_id})

GET/POST /api/v1/contacts?q=&circle=

your network: list / add ({connect: true, note_to_them?} also asks them to connect)

POST /api/v1/trees/:tree/people/:person/contact

someone in the tree into your network ({circle?, email?, relationship?, connect?, note?}); one contact per person

GET/PATCH/DELETE /api/v1/contacts/:id

one contact

POST /api/v1/contacts/:id/connect

ask them to connect ({note?})

POST /api/v1/contacts/import?circle=, GET /api/v1/contacts.vcf

vCard in and out

GET /api/v1/inbox, GET/POST /api/v1/inbox/:user

conversations; read / send ({body})

Related MCP server: FamilySearch MCP Server

Family plan

One payment per tree, once, for good: $49 (FAMILY_PLAN_USD), in crypto through CoinPay. It covers the whole family: pets, pasting up to 500 invites at a time, and no daily invitation limit for anyone in the tree (a 2,000/day ceiling only stops runaway scripts). Everything else stays free. Trees owned by an ADMIN_EMAILS account are on the plan without paying.

The server needs COINPAY_API_KEY, COINPAY_BUSINESS_ID and COINPAY_WEBHOOK_SECRET, with the business's webhook pointed at /webhooks/coinpay. A payment is written down before the buyer leaves; the signed webhook settles it, and only a payment we started can mark a tree paid. COINPAY_CHAINS limits checkout to chains the business holds wallets for.

Businesses

src/business.ts. A business is its own table, not a person, so no bloodline walk (pedigree, descendants, relationships, siblings) can reach one, and it is free on every tree. Roles: founder, owner, partner, investor, officer, manager, employee, apprentice, other, each with an optional title, years and note; one person can hold several. A member may link a business to one of their own Network contacts; contacts stay private, so each member sees only their own link.

In GEDCOM a business is a custom 0 @B1@ _BUS record (NAME, TYPE, _FOUNDED/_CLOSED with DATE, PLAC, WWW, NOTE, and _ROLE @I..@ with TYPE, TITL, _FROM, _TO, NOTE) that other programs skip. Each role is also an OCCU on the person ("Founder, Ettinger Plumbing", DATE FROM .. TO ..) marked 2 _BUS @B1@, so other programs still show it; our import skips a marked OCCU and rebuilds the role from _BUS, so a round trip never doubles anything. A privacy export keeps the business and leaves out what living people did.

Photo album

src/album.ts. Photos stay in the one SQLite file (media, now with album_id and uploaded_by); albums is a table of its own. Verified member = any member of the tree (owner, editor, viewer) who signed in with their own email; a pit.world-only account has a placeholder @pit.invalid address, so it can look but not add until it signs in with an email. The uploader and the tree's editors may caption, retag, move or delete a photo; whoever started an album and the editors may rename or delete it (photos stay). Files are judged by their bytes (JPEG, PNG, GIF, WebP, AVIF), 8 MB each, 500 a day per person.

family.tree is ours too: any request whose Host is in ANCESTRY_REDIRECT_HOSTS (default family.tree on the official site) gets a 301 to the same path on family.ancestry, or on family.ancestry.pit.world when it came through the relay.

Local

src/local.ts. A recommendation snapshots the business (name, category, town, phone, website, a line on why) when you share it; your contacts themselves stay private. You see your own picks and those of everyone you are connected with or share a tree with, grouped by phone, then website, then name and town. Score = sum of how close each recommender is to you: family and neighbors 3, friends and tree-mates 2, other connections 1 (your own circle for them decides). Blocks hide both ways.

Ads

Pages carry one crawlproof unit: a fluid text link in the footer everywhere, and a 300×250 on Local and Network. It is a cross-origin frame (/api/ads/frame), so the CSP gains one frame-src and nothing else: no ad script, no cookie. CRAWLPROOF_AD_SLOT sets the slot; off removes the units.

Network

An add-on with its own tables and routes (src/network*.ts), included free with every account. Anything we ever charge for is covered by a Profullstack Power Key.

It is for people who know each other, and the rules are in the code, not just the copy:

  • Contacts are private to whoever saved them. No public profiles, no follower counts, no "people you may know", no directory to browse.

  • You can message someone only if you both said yes to connecting, or you share a tree. One person at a time; there is no broadcast.

  • Joining a tree from someone's invite connects you with them, as family.

  • Every living person's page has Add to my network (circle, email, and "email them to connect" in one step); after that it says In my network. The Add form on /network has the same "email them to connect" box, so adding a friend and inviting them is one step.

  • Either side can block; a block ends the conversation both ways and is never revealed.

  • Per sender: 40 invitations (tree or connect) a day (no limit for a family on the Family plan), 120 messages an hour. A new message emails the recipient once per unread run, not once per message.

Running it

bun install
bun src/server.ts            # http://127.0.0.1:8792, data in ~/.local/share/family-ancestry

env

PORT (8792), HOST (127.0.0.1)

where it listens

ANCESTRY_SITE

the public URL, used in links and for passkeys (default https://family.ancestry)

ANCESTRY_DATA_DIR

where family.db lives (everything, photos included, is in that one SQLite file)

RESEND_API_KEY, MAIL_FROM

sign-in and invite mail; without a key, links are printed to the log

Production is dev2: /opt/family.ancestry, bin/install.sh (OpenInstall) runs it as the systemd unit family-ancestry; secrets in /root/.local/share/family-ancestry/app.env from the vault profullstack/family-ancestry--prod. Every merge to main deploys.

nginx serves family.ancestry on 80 and 443 (no redirect; see the seo.rank notes on why Moshpit names serve both) and proxies to 8792. The certificate is signed by the Moshpit registry and renewed by moshpit-renew-riotcoder.timer, because the name belongs to the riotcoder account and its certificates live in /etc/ssl/moshpit-riotcoder.

License

MIT

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to search FamilySearch's Family Tree, view person details, explore ancestors and descendants, and search historical records using browser session authentication.
    10 npm
    4
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Lets an AI assistant do everything you would do on Ancestry.com by hand: search records, read and edit trees (people, facts, sources, citations, notes, tags, media), review hints, attach records, look at DNA matches, and read or send messages.
    13
    1
    MIT