16 KiB
WebMCP Interface Design
The Problem
Exploring large genealogy charts can be overwhelming and time-consuming because users have to manually search, click, and scroll through hundreds of interconnected family branches just to find simple answers. To make this experience intuitive and modern, we are adding an interactive AI layer that acts as a research copilot directly inside the browser. This will allow users to effortlessly ask questions like "how is John related to Mary" or command the map to focus on specific relatives using simple natural conversation. Ultimately, this makes genealogy research accessible to everyone, letting users engage with their ancestry without wrestling with complex navigation controls.
System Architecture (How it works)
To make this feature work, we bridge three simple components together to let the map and the Assistant communicate smoothly:
- The Visual Chart (Topola core): This is what you see on your screen. It draws the family members, sets up transitions, and tracks who you are currently looking at.
- The Assistant Adapter (The Bridge): A singleton instance class (
WebMcpBridge) instantiated once inApp.tsxand running in the background. It acts as a continuous translator, giving the assistant access to read and move the active user chart while preventing disconnected side variables and state memory leaks. - The AI Command Registry (WebMCP): The external plug that allows the browser AI to issue predefined commands (such as "Focus on Sarah" or "Get direct descendants") to the Assistant Adapter.
graph LR
User["User on Screen"] <--> Chart["Visual Chart (Topola viewer)"]
Chart <--> Bridge["Assistant Adapter Bridge"]
Bridge <--> Assistant["AI Browser Assistant"]
This setup lets the AI control the tree smoothly without rebuilding the viewer from scratch. It behaves much like a second pair of hands working beside you on the same controls.
Rejected Alternatives (Design Guardrails)
To ensure consistent development and avoid repeating past defaults, here are the alternate designs considered but discarded during early setup:
- Pushing real-time events for layout clicks: We evaluated building a reactive push model that constantly updates the AI on every user click in real-time. We rejected this in favor of passive standard queries (
get_selected_person()) because constant pushes can confuse the assistant and bloat the UI event stream. - A single combined Focus & Details tool: We considered having one command perform both view manipulation and metadata inspection. We split these into isolated fetch commands (
inspect_indi) and camera viewport shifts (focus_indi) so reading relatives stays fast and doesn't accidentally jerk the user's screen viewpoint. - Relying solely on recursive tool loops for deep trees: Initially, direct single-node queries were considered enough for relationships. We rejected leaving the AI to fetch single nodes repeatedly in favor of generational acceleration commands (
get_ancestorsbounded to 5 generations ceiling) to protect interactive performance latency. - Internal fuzzy date parser algorithms: We decided against writing standard regex parser logic for partial or approximate genealogy records (e.g.,
"ABT 1750","BEFORE 1800"). Instead, raw in-flight text string dumps allow standard conversational LLMs to contextualize approximation by themselves. - Module-scoped global state variables: Rejected in favor of a single static bridge instance (Singleton pattern) initialized inside the React application frame. This prevents loose standard closures and allows isolated updates for new file uploads.
- Custom synchronous DOM events for state queries: Considered dispatching events from tools and capturing them inside React components. Rejected due to overhead constraints and event emitter latency.
Exposed MCP Tools
To enable smooth AI communication, the following tools are exposed to the LLM. Returned individual details are structured into three level tiers:
IndiReference:
{
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" }
},
"required": ["id", "name"]
}
BasicIndi:
{
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"birth": {
"type": "object",
"properties": {
"date": { "type": "string" },
"place": { "type": "string" }
}
},
"death": {
"type": "object",
"properties": {
"date": { "type": "string" },
"place": { "type": "string" }
}
},
"mother": { "$ref": "#/definitions/IndiReference" },
"father": { "$ref": "#/definitions/IndiReference" }
},
"required": ["id", "name"]
}
FullIndi:
{
"type": "object",
"properties": {
"id": { "type": "string" },
"name": { "type": "string" },
"birth": {
"type": "object",
"properties": {
"date": { "type": "string" },
"place": { "type": "string" }
}
},
"death": {
"type": "object",
"properties": {
"date": { "type": "string" },
"place": { "type": "string" }
}
},
"mother": { "$ref": "#/definitions/BasicIndi" },
"father": { "$ref": "#/definitions/BasicIndi" },
"children": {
"type": "array",
"items": { "$ref": "#/definitions/BasicIndi" }
},
"spouses": {
"type": "array",
"items": {
"type": "object",
"properties": {
"spouse": { "$ref": "#/definitions/BasicIndi" },
"marriage": {
"type": "object",
"properties": {
"date": { "type": "string" },
"place": { "type": "string" }
}
}
},
"required": ["spouse"]
}
}
},
"required": ["id", "name"]
}
1. get_selected_person
Returns the individual currently selected in the browser viewport. This corresponds to the person displayed in the side panel, which is not necessarily the focused person.
- Request Schema:
{ "type": "object", "properties": {} } - Response Schema:
FullIndi
2. search_indi
Searches the genealogy index for individuals by name. Returns at most 20 results to maintain fast performance and reasonable payload sizes.
- Request Schema:
{ "type": "object", "properties": { "query": { "type": "string", "description": "The name of the person to search for." } }, "required": ["query"] } - Response Schema: Array of
BasicIndi(maximum 20 items).
3. inspect_indi
Fetches isolated detailed information for a specific individual by ID pointer.
- Request Schema:
{ "type": "object", "properties": { "id": { "type": "string", "description": "The pointer ID of the individual." } }, "required": ["id"] } - Response Schema:
FullIndi
4. focus_indi
Instructs the Topola viewer camera view to center on and focus a specific relative node. This will also update the side panel to show the focused person.
Note
Changing focus prompts a full redesign layout sweep to center that person. This creates high UX layout jitter if the assistant uses it repetitively.
- Request Schema:
{ "type": "object", "properties": { "id": { "type": "string", "description": "The pointer ID to focus." } }, "required": ["id"] } - Response Schema:
{ "type": "object", "properties": { "status": { "type": "string" } } }
5. find_relationship_path
Traverses the internal graph model to find relative step paths between two individuals. The following links should be traversed: parent, child, spouse, sibling.
- Request Schema:
{ "type": "object", "properties": { "source": { "type": "string", "description": "Start individual ID pointer" }, "target": { "type": "string", "description": "End individual ID pointer" } }, "required": ["source", "target"] } - Response Schema: Array of
BasicIndiestablishing the sequence.
6. get_ancestors
Traverses upwards up to bounded ceiling generations.
- Request Schema:
{ "type": "object", "properties": { "id": { "type": "string", "description": "Target individual ID" }, "generations": { "type": "number", "description": "Depth bound" } }, "required": ["id"] } - Response Schema: Array of
BasicIndi
7. get_descendants
Traverses downwards up to bounded ceiling generations.
- Request Schema:
{ "type": "object", "properties": { "id": { "type": "string", "description": "Target individual ID" }, "generations": { "type": "number", "description": "Depth bound" } }, "required": ["id"] } - Response Schema: Array of
BasicIndi
Constraints and Assumptions
- Family Structure Assumptions: The WebMCP integration assumes simplified family structures (e.g., single set of biological parents per individual). Multiple marriages are fully supported, consistent with the core Topola Viewer app design.
- Privacy Boundaries: The WebMCP tools must strictly follow the privacy constraints of the Topola Viewer. For instance, private profiles (such as WikiTree restricted profiles) must be filtered and hidden from the AI assistant and its tool responses.
- Cycle Protection: All graph traversal algorithms (e.g., finding ancestors and descendants) must implement internal cycle protection (e.g., tracking visited node pointers) to avoid endless iteration loops caused by standard pedigree collapse.
- Legacy Replacement: WebMCP tool creation must strictly overwrite and replace the existing tools previously defined in
src/webmcp.tsto avoid duplicate hooks. - Relationship Pathfinder: Topola viewer does not have prebuilt pathfinder operators.
find_relationship_pathmust be manually implemented from scratch using a standard Breadth-First Search (BFS) algorithm traversing parent, child, spouse, and sibling links. - Index searching reuse: The tool
search_indimust borrow standardbuildSearchIndexfromsrc/menu/search_index.tsalready powering the top search UI instead of deploying newly written independent fuzzy match loops. - Data Format Standards: WebMCP tool integration consumes Topola's pre-parsed core JSON formats (
JsonGedcomData,JsonIndi) instead of low-level raw GEDCOM pointer lines to enforce implementation consistency and operational efficiency.
Detailed Implementation Plan
This section lists the exact files to be created or modified to execute this design successfully.
1. [Modify] webmcp.ts
- Rationale: Serves as the core integration plug for the experimental WebMCP browser assistant setup and standard operational in-memory state cache.
- Action steps:
- Define isolated state stores for current
selection,detailIndi, andloadedGedcomData. - Refactor current custom callbacks to register the complete tools collection blueprint (
search_indi,inspect_indi,focus_indi,get_ancestors,get_descendants,find_relationship_path) into thenavigator.modelContextarray hook. - Expose default standard state setters for Topola view adapter.
- Implement conversion and response helpers (
toMcpResponse,textMcpResponse,toBasicIndi,toFullIndi) to standardise in-transit JSON streams.
- Define isolated state stores for current
2. [NEW] webmcp_definitions.ts
- Rationale: Keeps standard LLM tool definition blueprints separate from the execution bridge to avoid bloat and single interface monolithic designs.
3. [NEW] webmcp_types.ts
- Rationale: Defines ambient
navigator.modelContextparameters and concrete structural bridge types cleanly.
4. [Modify] app.tsx
- Rationale: The top-level state component for Topola Viewer. It holds the interactive chart state and needs standard side effect hooks to update the WebMCP context on active selections.
- Action steps:
- Initialize WebMCP Bridge securely using
useState(() => new WebMcpBridge())avoiding loose disconnected singleton memory leaks. - Add standard
React.useEffecthook to monitor active viewport selection changes and feed them into the WebMCP in-transit state. - Expose selection and inspection callbacks handlers to the bridge hook preset.
- Initialize WebMCP Bridge securely using
5. [Modify] gedcom_util.ts
- Rationale: Handles core conversion formulas from raw gedcom pointers to JSON objects. Houses newly proposed BFS algorithms avoiding visual rendering components dependency.
- Action steps:
- Implement standard Breadth-First Search (BFS) method for isolated
find_relationship_pathrelative footprint. - Draft flat array collection algorithms (bounded up to preset depth ceiling) for ancestors and descendants generation list.
- Implement standard Breadth-First Search (BFS) method for isolated
6. [Modify] gedcom_util.spec.ts
- Rationale: Standard isolated unit test suite. It must accommodate boundary tests for newly added generic algorithms.
- Action steps:
- Add unit test cases for
find_relationship_pathwith disconnected and connected multi relationships. - Add test vectors for
get_ancestorsboundary ceilings (e.g., 5 generations) and cycles control.
- Add unit test cases for
7. [New] webmcp.cy.js
- Rationale: Formatted test files acting as automated integration coverage. Leverages Cypress stubs for isolated web tools inspection.
- Action steps:
- Mock
navigator.modelContextusingcy.visiton before preset lifecycle hooks. - Trigger tool actions and check default DOM element shifts in simulated Topola frames.
- Mock
Testing Strategy
To ensure the robustness and correctness of the WebMCP integration, we will employ a multi-tiered testing approach spanning unit, integration, and manual end-to-end tests.
Unit Tests
- Graph Traversal Algorithms:
- Test
find_relationship_pathwith multiple scenarios:- Direct descendants (e.g., Parent to Child).
- Sibling and cousin relationships.
- Pedigree collapse (cycles in the family tree).
- Unrelated individuals (should return an empty list or appropriate error).
- Test
get_ancestorsandget_descendantswith generation bounds (e.g., limit = 5) and deep pedigree setups to verify the boundary ceilings and internal cycle protection.
- Test
- Search indexing: Test
search_indito verify it delegates correctly to the core search index and correctly limits the size of the response payload to at most 20 items.
Integration Tests
- Standard UI integration tests are implemented using Cypress.
- The
navigator.modelContextcan be stubbed using CypressonBeforeLoadhook to verify standard registration callbacks on application setup frame. - The integration suite tests:
- Core tool callbacks correctly transition the React internal viewport selection.
- Application changes in selected person correctly propagate into in-transit operational state without rendering glitches.
Manual Verification
- Because interactive tools are bound to the experimental WebMCP protocol, manual verification can be accelerated using the Model Context Tool Inspector Chrome Extension. This grants operational developers a dashboard panel to trigger and fire tools independently inside standard dev viewports.
Files Created or Modified for Testing
- [Modify] gedcom_util.spec.ts
- Rationale: Contains existing unit tests for GEDCOM data structures. It will be extended to verify the newly introduced relationship finding and bounded graph traversal algorithms without visual overhead.
- [New] webmcp.cy.js
- Rationale: Will act as the dedicated automated integration suite for the WebMCP feature. It will stub
navigator.modelContextto verify correct tool registration and that standard execution callbacks successfully sync back layout and selection changes inside the Topola visual DOM.
- Rationale: Will act as the dedicated automated integration suite for the WebMCP feature. It will stub
Future Considerations
- AI Canvas & Camera controls: Exposing interactive UI commands such as canvas zoom and shifting the chart views (e.g., hourglass, donatso) could be added in future increments as additional tool blueprints.