gramps-evidence-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| GRAMPS_MCP_HOST | No | Host for http transport to listen on (default 127.0.0.1) | |
| GRAMPS_MCP_PORT | No | Port for http transport to listen on (default 8090) | |
| GRAMPS_MCP_CONFIG | No | Path to the TOML config (default ./gramps_mcp.toml, from the working directory) | |
| GRAMPS_MCP_API_URL | Yes | Base URL of gramps-webapi, e.g. http://gramps.example.org:5000 | |
| GRAMPS_MCP_PASSWORD | Yes | Its password | |
| GRAMPS_MCP_USERNAME | Yes | The dedicated MCP user | |
| GRAMPS_MCP_TRANSPORT | No | Transport to use: stdio (default) or http | |
| GRAMPS_MCP_EXPOSE_PRIVATE | No | Override the TOML expose_private flag (default false) |
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 |
|---|---|
| add_personA | Create a new person, optionally with cited birth and/or death events. Use this to add someone to the tree. Good practice: attach the birth event with a citation to the specific record that proves it (a birth or baptism certificate, a census entry), setting the citation's confidence honestly. If you only have a legacy-tree hint with no underlying record, either omit the event or set require_citation=False so it's flagged for follow-up. Returns the new person's handle and gramps_id. |
| add_event_to_personA | Add a dated/placed event (fact) to an existing person. Use for facts beyond birth/death: residence, occupation, census, baptism, immigration, marriage-adjacent events, etc. The event's citation should point at the record establishing the fact. Adding a 'Birth'/'Death' event will set the person's primary birth/death reference if not already set. |
| add_familyA | Create a family linking parents and children, with an optional cited marriage. All members must already exist (create them first with add_person). Creating the family automatically links each person's family/parent-family lists, so you don't need to update the individuals separately. Cite the marriage event to a marriage record where possible. |
| add_sourceA | Create a Source (a body of evidence: a record set, book, certificate, website). In the Gramps evidence model a Source is what you cite through a Citation. Create the source once, then create citations against it for each fact it supports. Optionally link it to a Repository (where the source is held). |
| add_citationA | Create a standalone Citation on a Source (or reuse an existing one). Usually you don't call this directly -- pass a CitationInput to add_person / add_event_to_person / add_family instead, which creates the citation and attaches it to the fact in one step. Use this when you want a reusable citation handle to attach to several facts. |
| add_repositoryA | Create a Repository (an institution or place that holds sources). Repositories sit at the top of the evidence model: Repository -> Source -> Citation -> fact. Create these for archives, libraries, cemeteries, or websites you'll cite sources from. |
| add_noteA | Create a research/general note, optionally attached to an object. Use notes for research logs, reasoning about conflicting evidence, or transcriptions. Attach to a person/event/source by giving target + target_type. |
| attach_mediaA | Attach an image or document to an object -- a new upload, or one already in the tree. With file_path, the bytes are uploaded into the tree's managed media directory (so don't point at files you don't want copied); if that exact file is already present it is reused rather than duplicated. With media_ref, an existing Media object is linked. One image should be ONE Media object, linked from each object it belongs to
and cited once per fact it proves. Uploading the same photograph separately
for the husband and the wife creates duplicates that have to be unpicked
later. The write is verified afterwards: |
| cite_eventA | Attach a citation to an event that ALREADY exists. Use this to source an event you didn't create with an inline citation -- e.g. one added through the Gramps web UI, or an unsourced event surfaced by list_unsourced_facts. The citation is resolved/created (existing handle/id, or an inline source_title + page + confidence) and appended to the event's citation list (no duplicates). Does not change any other event field. |
| update_eventA | Edit an existing event's date, place, and/or description. Only the fields you provide are changed; the rest are left as-is. This does NOT change the event's citations -- use cite_event to add a source. |
| delete_objectA | Permanently delete an object from the tree by handle or gramps_id. DESTRUCTIVE and irreversible. Deleting an object does not clean up references to it, so this can leave dangling references (e.g. deleting a person still referenced by a family, or an event still listed on a person). Prefer deleting leaf objects, and detach references first where possible. |
| tag_objectA | Attach a named Tag to an object, creating the Tag if it doesn't exist yet. Tags are lightweight cross-cutting labels ('Verified', 'Needs review', 'DNA-confirmed'). Matching is by exact name; an existing tag is reused. |
| add_attributeA | Add a typed key/value attribute to an object. Sources and citations use a SrcAttribute; everything else uses an Attribute. The right class is chosen automatically from object_type. |
| add_urlA | Add a web URL to a person, place, or repository. Only these three object types carry a URL list. For sources/citations, record a web address as an attribute (add_attribute) instead. |
| update_urlA | Edit or remove ONE existing URL entry on a person, place, or repository. add_url can only append -- this corrects an entry already there (the classic case: a Find a Grave link filed under the wrong type). The other fields on the object are untouched. |
| set_privateA | Set (or clear) the Gramps private flag on an object. Private records are withheld from bulk output (queries, searches, tree walks, timelines, reports) unless a call passes include_private. |
| update_sourceB | Edit an existing source's title, author, publication info, and/or abbreviation. Only the fields you provide are changed; the rest are left as-is. |
| link_repositoryA | Link an existing source to an existing repository that holds it. Adds a repository reference (with an optional call number) to the source. Both objects must already exist. Duplicate links to the same repository are skipped. |
| add_event_to_familyA | Add a dated/placed event (fact) to an existing family. Use for family-level facts: marriage, divorce, residence, census. The event is added with the 'Family' role. Cite it to the record establishing the fact. |
| add_child_to_familyA | Add an existing person as a child of an existing family. Links the child both ways: a ChildRef is added to the family and the family is added to the child's parent-family list. The child must already exist. Duplicate children are skipped. |
| add_alternate_nameA | Add an alternate (non-primary) name to a person. Use for maiden/married names, aliases, anglicized forms, or nicknames-of-record. The person's primary name is left unchanged. |
| get_personA | Get full detail for one person: name, gender, events (with citation counts), family links, and media count. Direct lookup is allowed even for living/private individuals (this is your own local tool); only bulk/list tools filter them. Use this to inspect someone before adding facts, or to check whether an event is already cited. |
| search_peopleA | Search people by name substring and optional birth-year range. Bulk output: probably-living people (born < 110 years ago with no recorded death) and records marked private are returned as redacted stubs (ids only) unless include_private is set. Fetch a specific person by id with get_person if you need their detail. |
| get_familyA | Get a family: relationship type, parent handles, child handles, event count. |
| get_ancestorsA | Walk a person's ancestors up to N generations (a nested parents tree). Living/private ancestors appear as redacted stubs unless include_private is set. |
| get_descendantsA | Walk a person's descendants up to N generations (a nested children tree). Living/private descendants appear as redacted stubs unless include_private is set. |
| list_unsourced_factsA | Audit: list events that lack a citation or are tagged UNSOURCED. This is the core quality query for a fully-cited tree -- run it to find facts that still need a source. Returns each offending event with its person, type, date, and the reason ('no-citation' or 'tagged-unsourced'). |
| db_statsA | Counts of people, families, events, citations, sources, repositories, places, media, and notes in the tree. A quick health/overview check. |
| list_tagsA | List all tags in the tree with their handle, name, and color. Use to see what labels already exist before tagging (tag_object matches by exact name). |
| get_sourceA | Get a source: title, author, publication info, abbreviation, linked repositories, media/note counts, attributes, and citation count. Use to inspect a source before citing through it or editing it. |
| get_repositoryB | Get a repository: name, type, URLs, address count, and (if available) the number of sources it holds. |
| get_eventA | Get an event: type, date, place handle, description, citation count, and attributes. Use to inspect an event before citing or editing it. |
| query_objectsA | Query any collection with a server-side filter. The workhorse for audits. Use this instead of fetching a collection and filtering it yourself: whole-collection pulls are slow on any real tree, and the filter runs in the database. Typical audit questions it answers directly:
To ask "what cites this source?" use get_backlinks -- a source has no citation_list, because citations point at IT, and reading citation_list on a source reports zero for every source in the tree. Private records and living people come back as redacted stubs. |
| get_backlinksA | List everything that references this object, grouped by type. The right way to ask "is this source actually cited?", "which facts rest on this citation?", or "is it safe to delete this?" -- an object with zero backlinks is orphaned; one with backlinks will leave dangling references if deleted. |
| find_duplicatesA | Find likely-duplicate objects. Reports only -- it never merges anything. Duplicates are not merely untidy: a duplicate SOURCE makes a single-sourced fact look corroborated, which is a false evidentiary claim. But the reverse error is just as real -- an index entry and the register page it indexes are TWO documents and must stay separate. This tool finds candidates; deciding which are truly the same document is yours. Merge with merge_objects. |
| list_object_typesA | The tree's type vocabularies (event types, attribute types, and so on). Check an unfamiliar type string here first: Gramps accepts an unrecognised one as a NEW custom type rather than rejecting it, so a typo permanently enters the tree's vocabulary. |
| get_objectA | Read any object's raw record -- including places, media, notes and citations, which have no shaped getter. Returns the record as stored, which is what you want before editing one. For people and sources the shaped getters (get_person, get_source) are easier to read. |
| update_citationA | Edit a citation's locator, confidence, date, or the source it points at. A page-less citation on a long document is not a locator, and a confidence is a per-instance judgement, not a property of the source class. IMPORTANT: a citation carries ONE confidence, and it belongs to ONE claim. Every fact attached to this citation shares whatever you set here. If the same page supports a second, different claim (a census page proving both "this child appears here" and "these are her parents"), make a SECOND citation on the same source and page -- do not re-grade this one. |
| update_mediaB | Edit a media object's description, date, or path. |
| update_personA | Edit a person's gender, primary name, or privacy flag. Replacing the primary name preserves the old one as an 'Also Known As': a name in the tree came from some record, and dropping it loses the link to whatever document used it. To add a name without replacing the primary one, use add_alternate_name. |
| update_object_fieldsA | Set scalar fields on any object -- the escape hatch for places, notes, repositories and the rest. Only scalar fields are settable. Structural lists (citation_list, event_ref_list, media_list, ...) are refused on purpose: replacing one wholesale is exactly how references get silently dropped. Each has its own tool -- cite_object, detach_object, tag_object, attach_media. |
| update_placeA | Edit a place's type, parent enclosure, name, title, or coordinates. This is the tool update_object_fields deliberately refuses to be: place_type and the enclosure are structural, so they get guard rails here -- the parent must already exist, setting it cannot create an enclosure cycle, and a place holding several dated enclosures (a territory-to-state succession) is refused rather than silently flattened. Aim for every place typed, every non-country place parented, and street addresses on events rather than in the place tree. |
| cite_objectA | Attach a citation to any object that carries one -- not just events. cite_event covers facts; this covers the rest. The important case is the FAMILY, whose citation supports a claim no event makes: that these two people were a couple. Person-level citations are for evidence about the individual as a whole (an identity document) rather than about one dated fact -- prefer citing the specific event where one exists. To cite a parent-child link, use cite_child_link: that is a different claim and needs its own citation. |
| cite_child_linkA | Cite the parent-child link itself, on the family's ChildRef. "This child belongs to these parents" is a DIFFERENT claim from "this child appears in this record", and it needs its own citation object. Reusing the child's existing citation handle makes the link inherit a confidence that was assigned to another claim entirely, so the link displays a confidence its evidence never earned. Note what a ChildRef citation asserts: BOTH sides of the link. A census naming only the mother does not document the father. Where only one parent is evidenced, cite that parent's relationship instead of implying both. |
| unciteA | Detach a citation from an object, deleting it if it is left orphaned. Detaching without deleting is how orphan citations accumulate: the fact the citation supported is gone, but the citation sits in the database still looking like evidence of something. Use this when a citation was attached to the wrong fact, or when a superseded bucket citation is replaced by the real record. |
| merge_objectsA | Merge two objects that are the same thing. Dry-run by default. This uses Gramps' own server-side merge: every reference to Before merging, be sure they really are one thing. Two records OF the same event are two documents: an index entry and the register page it indexes stay separate, and merging them would turn two independent citations into one, silently weakening every fact that rested on both. Conversely, the same census page entered once per household member IS one document, and leaving the duplicates makes single-sourced facts look corroborated. Reversible: the merge is one transaction, so list_transactions + undo_transaction can back it out. |
| detach_objectA | Remove a reference from an object: an event from a person, an image from a source, a tag, a note, a child from a family. The reference is removed; the object itself survives unless delete_if_orphan is set AND nothing else points at it -- which is checked, because deleting something other facts still reference leaves dangling handles behind. |
| add_mediaA | Upload a document as a standalone Media object, reusing an identical file already in the tree. One image, one Media object -- then attach it wherever it belongs with attach_media(media_ref=...) and cite it once per fact it proves. Uploading the same photograph once per person it depicts is the duplicate pattern that later has to be unpicked by hand. |
| ocr_mediaA | Run OCR on a document image, server-side, to locate text within it. A finding aid, not evidence. OCR output is a machine's guess at the writing, and it is at its worst on exactly the handwritten records that matter most. Use it to find WHERE something appears in a long scan; read the image before citing what it says. |
| export_backupA | Write a full-tree export to disk. Take one before any bulk write. Cheap insurance: a few seconds and one file. A bulk write that goes wrong cannot always be undone transaction by transaction; a dump can be re-imported. |
| list_transactionsA | Recent writes to the tree: what changed, when, by which user. Each entry's transaction_id is what undo_transaction takes. Useful for "what did that bulk pass actually do?" and for finding the transaction to reverse when it did the wrong thing. |
| undo_transactionA | Undo a past transaction, after checking whether it can be undone cleanly. A conflict means an object was edited again after this transaction; undoing anyway throws that later edit away. The conflict check is free and runs first, so the default tells you what you are dealing with before anything changes. |
| list_reportsA | List the reports this Gramps instance can generate. Gramps ships a full report engine — Ahnentafel, descendant reports, family group sheets, kinship, fan and relationship charts, statistics, and an end-of-line report that lists exactly where research stops. Each entry names the option keys it accepts; read the defaults with get_report_options before overriding any. |
| get_report_optionsA | Read one report's default options before running it. Reports take a full option dict, not a partial one, so the way to change a single setting is to read these defaults and override that key. |
| run_reportA | Generate a report and return the file it produced. Living people and private records are left out (living_people 0, incl_private false) unless you pass those options or include_private; Gramps' own default includes both. Usually runs in the background, returning a task_id to poll with get_task. |
| list_filter_rulesA | List the filter rules Gramps offers in a namespace. This is the vocabulary that |
| list_custom_filtersA | List the custom filters already saved on this instance. A saved filter can be reused by name from |
| create_filterA | Save a reusable custom filter built from Gramps' own rules. Worth doing for a selection you will run repeatedly — an audit scope, a branch of the tree — because the filter then has a name rather than being retyped each time. |
| delete_filterA | Delete a saved custom filter. Deletes the filter definition only. Nothing in the tree is touched. |
| consolidated_timelineA | Merge several people or families into one chronological timeline. The way to see a household move together through censuses, or to check whether a family's events are mutually consistent. Carries the same citation count and confidence per event as get_timeline, with an uncited_count across the whole set. |
| list_tasksA | List recent background jobs for this tree, newest first. Use when you have lost a task_id, or to see whether anything is still running before starting a write session. |
| get_transactionA | Read one transaction in full, including the objects it changed. list_transactions summarises; this shows what actually moved. Read it before undoing anything. |
| get_placeA | Read one place: name, title, type, enclosure, coordinates and URLs. The |
| get_citationA | Read one citation: page, confidence, date, and its source.
|
| get_noteA | Read one note in full, with its type and what it is attached to. Notes hold the researcher's own reasoning — why a conflict was resolved one way, what a hard-to-read page actually said — so the text comes back whole rather than truncated. |
| get_mediaA | Read one media object: path, mime type, checksum, description, date.
|
| add_placeA | Create a place deliberately, with a type and a parent. Use this instead of letting a place appear as a side effect of naming one in an event. That route produces an untyped, unparented place whose title is the bare string you typed, which is how duplicate hierarchies start. |
| get_factsA | Read the tree's record-holders: oldest at death, youngest parent, most children. Superlatives across a set of people, not statistics about one person. An implausible holder — a father at eight, a death at 130 — is usually a data error, which makes this a quick plausibility check. Living and private people are excluded unless include_private is set. Slow: the server computes it all per call. |
| get_researcherA | Read the researcher details recorded for this tree. These are embedded in every export, so they travel with any GEDCOM or Gramps XML you hand to someone else. Worth checking before sharing one. |
| query_recordsA | Query any collection server-side, with columns, filters and sorting. More capable than It is the only way to filter events by type. GrampsQL cannot: the word
is shadowed, so Returns rows plus a total count and a |
| list_event_typesA | List the event type names this tree uses, with their stored integers. Useful before a |
| add_dna_matchA | Record a DNA match as evidence, cited to the test that found it. Stored as Gramps Web stores a match, so its interface and get_dna_matches read it back. Nothing is written unless the segments parse: unreadable data would otherwise record a match sharing no DNA. A match proves the two share DNA, not how they are related. Record any relationship separately, with its own evidence. |
| get_dna_matchesA | List the DNA matches recorded against a person. Each match reports total shared centiMorgans and the largest single segment — the two figures a relationship estimate actually rests on — plus any common ancestor already identified. DNA evidence works differently from documentary evidence. A match
proves a biological relationship exists; it does not say which one. Shared
cM constrains the possibilities and rarely resolves them, and it says
nothing about the paper trail. |
| get_ydnaA | Report a person's Y-DNA haplogroup, from broadest clade to terminal. Y-DNA follows the direct paternal line only, so it speaks to one thread of a tree and is silent on every other. A shared terminal clade indicates a common paternal ancestor, usually far further back than any record reaches — it corroborates a surname line rather than proving a named link.
|
| parse_dna_segmentsA | Parse pasted shared-segment data into structured segments and totals. Use this to check what a match file actually contains before recording it. Returns each segment plus the total and largest-segment centiMorgans. If nothing parses, |
| get_relationshipA | Work out how two people in the tree are related. Returns the relationship in words plus the generation distance from each
person to their common ancestor. |
| assess_livingA | Ask the server whether a person is probably still alive, and why. The server walks relatives to decide, so it handles people with no dates
of their own — someone undated whose children died a century ago. Use it
before publishing or sharing anything, and use Note this is advisory. Bulk output is filtered by this server's own rule regardless of what this returns. |
| get_timelineA | Build a chronological timeline of someone's life events. Each entry carries their age at the time, how many citations support the
event, and the strongest confidence among them — so a timeline doubles as
a readable audit of where the evidence thins out. |
| event_spanA | Measure the elapsed time between two events. The arithmetic behind most plausibility checks: age at marriage, years between a census and a death, how long a widow waited. Doing this by hand from two formatted date strings is where transcription errors hide. |
| reindex_searchA | Rebuild the full-text search index.
|
| get_taskA | Check whether a background job has finished, and whether it worked. Undo, verification, import and reindex are dispatched to a worker and
answer before the work is done. Poll this until |
| verify_treeA | Run Gramps' own genealogical plausibility checks over the whole tree. This is a different audit from the citation ones. Leave the thresholds alone on a first run; the server's defaults are the conventional ones. Tighten a specific bound when chasing a specific class of error. May run in the background, in which case a task_id comes back — poll it with get_task. |
| consult_referenceA | Consult the legacy GEDCOM reference layer for HINTS (never authoritative). Searches the configured Ancestry/FamilySearch exports and returns, per file, matching individuals and their claimed facts. Crucially, each fact is flagged whether the legacy tree attached a source, with the source text if present -- so you can distinguish 'they cite an actual death certificate' from 'unsourced guess'. These are UNTRUSTED hints: use them to decide what real record to hunt for, then create the fact in the tree citing that record -- do not copy a hint in as a sourced fact. Probably-living people are withheld and counted. |
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 83 tools
Most tools target distinct resources and actions, and descriptions often explicitly distinguish generic from specific tools (e.g. get_object vs get_person, cite_object vs cite_event). However, overlaps remain: query_objects vs query_records, add_media vs attach_media, and list_object_types vs list_event_types could still cause misselection.
The set is overwhelmingly snake_case and action-oriented, with predictable verb_noun names across most CRUD, audit, and lifecycle operations. Minor deviations such as db_stats, event_span, consolidated_timeline, and uncite slightly break the strict verb_noun pattern.
83 tools is far beyond a practical MCP surface for an agent, even for a complex genealogy evidence domain. While many tools are specialized and defensible, the count itself creates excessive selection burden and is an extreme mismatch for efficient tool use.
The surface is very comprehensive, covering people, families, events, sources, citations, repositories, media, places, DNA, reports, filters, transactions, and audits. Minor gaps exist, notably the apparent absence of a generic search_text tool despite reindex_search referencing one, with some operations reachable only through generic escape hatches.