mirror of
https://github.com/PeWu/topola-viewer.git
synced 2026-07-17 17:21:48 +00:00
463 lines
16 KiB
Markdown
463 lines
16 KiB
Markdown
# 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:
|
|
|
|
1. **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.
|
|
2. **The Assistant Adapter (The Bridge):** A singleton instance class
|
|
(`WebMcpBridge`) instantiated once in `App.tsx` and 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.
|
|
3. **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.
|
|
|
|
```mermaid
|
|
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_ancestors` bounded 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`:**
|
|
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {"type": "string"},
|
|
"name": {"type": "string"}
|
|
},
|
|
"required": ["id", "name"]
|
|
}
|
|
```
|
|
|
|
- **`BasicIndi`:**
|
|
|
|
```json
|
|
{
|
|
"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`:**
|
|
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{"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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"type": "object",
|
|
"properties": {
|
|
"id": {"type": "string", "description": "The pointer ID to focus."}
|
|
},
|
|
"required": ["id"]
|
|
}
|
|
```
|
|
- **Response Schema:**
|
|
```json
|
|
{"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:**
|
|
```json
|
|
{
|
|
"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 `BasicIndi` establishing the sequence.
|
|
|
|
### 6. `get_ancestors`
|
|
|
|
Traverses upwards up to bounded ceiling generations.
|
|
|
|
- **Request Schema:**
|
|
```json
|
|
{
|
|
"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:**
|
|
```json
|
|
{
|
|
"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.ts` to avoid
|
|
duplicate hooks.
|
|
- **Relationship Pathfinder:** Topola viewer does not have prebuilt pathfinder
|
|
operators. `find_relationship_path` must 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_indi` must borrow standard
|
|
`buildSearchIndex` from `src/menu/search_index.ts` already 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](../src/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`, and
|
|
`loadedGedcomData`.
|
|
- 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 the
|
|
`navigator.modelContext` array 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.
|
|
|
|
### 2. [NEW] [webmcp_definitions.ts](../src/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](../src/webmcp_types.ts)
|
|
|
|
- **Rationale:** Defines ambient `navigator.modelContext` parameters and
|
|
concrete structural bridge types cleanly.
|
|
|
|
### 4. [Modify] [app.tsx](../src/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.useEffect` hook 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.
|
|
|
|
### 5. [Modify] [gedcom_util.ts](../src/util/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_path` relative footprint.
|
|
- Draft flat array collection algorithms (bounded up to preset depth ceiling)
|
|
for ancestors and descendants generation list.
|
|
|
|
### 6. [Modify] [gedcom_util.spec.ts](../src/util/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_path` with disconnected and
|
|
connected multi relationships.
|
|
- Add test vectors for `get_ancestors` boundary ceilings (e.g., 5 generations)
|
|
and cycles control.
|
|
|
|
### 7. [New] [webmcp.cy.js](../cypress/e2e/webmcp.cy.js)
|
|
|
|
- **Rationale:** Formatted test files acting as automated integration coverage.
|
|
Leverages Cypress stubs for isolated web tools inspection.
|
|
- **Action steps:**
|
|
- Mock `navigator.modelContext` using `cy.visit` on before preset lifecycle
|
|
hooks.
|
|
- Trigger tool actions and check default DOM element shifts in simulated
|
|
Topola frames.
|
|
|
|
## 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_path` with 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_ancestors` and `get_descendants` with generation bounds (e.g.,
|
|
limit = 5) and deep pedigree setups to verify the boundary ceilings and
|
|
internal cycle protection.
|
|
- **Search indexing:** Test `search_indi` to 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.modelContext` can be stubbed using Cypress `onBeforeLoad` hook
|
|
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](../src/util/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](../cypress/e2e/webmcp.cy.js)**
|
|
- **Rationale:** Will act as the dedicated automated integration suite for the
|
|
WebMCP feature. It will stub `navigator.modelContext` to verify correct tool
|
|
registration and that standard execution callbacks successfully sync back
|
|
layout and selection changes inside the Topola visual DOM.
|
|
|
|
## 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.
|