Skip to main content
Glama
Band-Aid

Pendo Ontology MCP Server

by Band-Aid
README.md
# pendo-ontology-mcp

**A semantic ontology layer for Pendo, as an MCP server.** Pairs with the [Pendo MCP server](https://www.pendo.io): Pendo MCP is the *data plane* (live entities, usage, retention, funnels); this server is the *meaning plane* — the business concepts, definitions, entity relationships, causes, and playbooks your workspace has agreed on.

## Why

LLM agents querying product analytics fail in a characteristic way: they don't know what your objects *mean*. Feature and segment names encode tribal knowledge, business terms like "activation" have workspace-specific definitions that live in people's heads, and the relationships between objects and business goals are written down nowhere — so agents ask endless follow-ups and produce confidently wrong answers.

This server is the place where that meaning gets written down — and it's designed so the LLM itself does most of the writing. The flywheel:

```
you ask questions → the model learns what you care about
  → it proposes/records concepts here (you review)
    → every future question is grounded in your definitions
      → answers get sharper → you ask more
```

The ontology store is a single portable JSON file: diffable, version-controllable, and an organizational asset that survives model swaps and agent rewrites.

## What it is (and isn't)

- A **typed JSON graph**, not RDF/OWL. Its consumers are an LLM context window and a human reviewer.
- **Query-language agnostic.** Concepts carry a prose `measurementHint` ("weekly cohort retention over the measured features"), not query templates. The agent turns hints into concrete Pendo MCP calls (`entityUsageTimeSeries`, `cohortRetentionCurve`, …).
- **No LLM calls inside the server.** The client model is the intelligence; this server contributes deterministic guarantees (stable ids, phrase-match floors, coverage gaps) and durable storage.

## Data model

```
STRUCTURAL (synced/pushed, rebuildable)        SEMANTIC (the asset)
─────────────────────────────────────          ─────────────────────────────
EntityNode                                     Concept
  id: "feature:<pendoId>"  ← stable              name, definition
  kind: feature|page|segment|                    measurementHint (prose)
        productArea|trackEvent|object            measures: [entity ids]
  pendoId  ← valid directly in Pendo tools       causes[]  (+ questionTemplate)
  name, appId?, url?, groupId?                   actions[] (+ questionTemplate)
                                                 tags[], source
```

Stable ids mean concept links survive full re-syncs. Entities deleted upstream leave dangling references that are ignored, never destroyed — a later sync may bring them back.

## Install

```bash
git clone <this repo> && cd pendo-ontology-mcp
npm install && npm run build
```

### Claude Code

```bash
claude mcp add pendo-ontology -- node /path/to/pendo-ontology-mcp/dist/index.js
```

### Claude Desktop (`claude_desktop_config.json`)

```json
{
  "mcpServers": {
    "pendo-ontology": {
      "command": "node",
      "args": ["/path/to/pendo-ontology-mcp/dist/index.js"],
      "env": {
        "ONTOLOGY_STORE_PATH": "/path/to/team/ontology.json"
      }
    }
  }
}
```

### Environment

| Variable | Default | Purpose |
|---|---|---|
| `ONTOLOGY_STORE_PATH` | `~/.pendo-ontology/ontology.json` | Where the ontology lives. Point at a repo file to share with your team. |
| `PENDO_INTEGRATION_KEY` | — | Enables the optional `sync_from_pendo` direct REST sync. Not needed when pairing with Pendo MCP. |
| `PENDO_API_BASE` | `https://app.pendo.io/api/v1` | Override for EU/other regions. |

## Tools

| Tool | Purpose |
|---|---|
| `get_product_map` | Overview: entity counts + every concept (definition, measurement hint, measured entities with pendoIds, causes, actions). Call first. |
| `lookup_ontology` | Search entities & concepts by name. Product areas expand into member features. |
| `get_entity_catalogue` | Full registered catalogue, features grouped by area — for picking measure links. |
| `upsert_concept` | Create/update a concept. `autoLink: true` adds deterministic phrase-matched entities. |
| `delete_concept` | Remove a concept (cause links to it are scrubbed). |
| `suggest_links` | Deterministic phrase-match candidates for a problem statement — the precision floor under the model's own semantic picks. |
| `list_coverage_gaps` | Entities no concept measures yet. Join with Pendo MCP usage data to rank concept candidates. |
| `ingest_pendo_payload` | **The easy sync path**: pass a RAW Pendo MCP tool result (`listCountables`, `listProductAreas`, `segmentList`, …) verbatim — array, wrapper object, or JSON string — and it's normalized and merged. Per-item evidence (`elementPathRules` → feature, `url` → page, kind-named wrapper keys) beats the `kind` hint. |
| `register_entities` | Structured push with explicit kinds (merge or replace). Use when you've already reshaped the data. |
| `sync_from_pendo` | Optional direct REST sync (needs `PENDO_INTEGRATION_KEY`). |

**Resource:** `ontology://digest` — a markdown digest of the whole ontology, ready to be pulled into context.

## The pairing workflow (with Pendo MCP)

1. **Seed the structure** — ask Claude:
   > "List my product areas and features via Pendo, then register them in the ontology."

   Claude calls Pendo MCP (`listProductAreas`, `listCountables`, `segmentList`) and pipes each raw result straight into `ingest_pendo_payload` — no reshaping, no Pendo API key. (Alternatives: `register_entities` for pre-shaped data, or `PENDO_INTEGRATION_KEY` + `sync_from_pendo` for direct REST sync.)

2. **Define what matters** — ask:
   > "Define a concept 'Activation': accounts that used ≥3 core features in week 1. Map the entities it measures."

   Claude drafts the concept, picks semantically-related entities from `get_entity_catalogue` (plus the `suggest_links` floor), and saves with `upsert_concept`.

3. **Let usage drive coverage** — ask:
   > "What high-usage entities aren't covered by any concept?"

   Claude joins `list_coverage_gaps` with Pendo MCP usage (`entityUsage`) and proposes new concepts from the gaps.

4. **Ask grounded questions** — from now on:
   > "How is Activation trending?"

   Claude reads the concept (definition + `measurementHint` + measure pendoIds) and goes straight to the right Pendo MCP calls — no follow-up questions, no guessed IDs, your definition every time.

## Design notes

- **Phrase-matching is the floor, not the ceiling.** Single-token name matching measured 119 false positives for "agent" in a real workspace; two-word phrases stay precise but can't see semantics. The model does the semantic mapping; `suggest_links`/`autoLink` guarantee the obvious matches are never missed.
- **Ontologies don't work on day 1.** Meaning is distilled from use — questions asked, usage observed, definitions clarified. Start with structure + one or two concepts; let the flywheel run.
- **Errors are results.** Lookups return notes, not exceptions; a miss tells the model exactly which fallback to take.

## License

MIT

TDQS

A4.3/5.0

Scored across 11 tools

Disambiguation4/5

Most tools have clearly distinct purposes, but get_concept and lookup_ontology both return full concept details, and the three entity ingestion methods (register_entities, ingest_pendo_payload, sync_from_pendo) could confuse agents despite clear descriptions. Overall, the boundaries are well-defined.

Naming Consistency5/5

All tool names follow a consistent verb_noun snake_case pattern (list_, get_, lookup_, upsert_, delete_, suggest_, register_, ingest_, sync_). The naming is predictable and makes the action and resource clear.

Tool Count5/5

With 11 tools, the server is well-scoped for ontology management. Each tool covers a distinct aspect (concepts, entities, links, ingestion, discovery) without redundancy or bloat.

Completeness5/5

The tool set provides comprehensive coverage: concept CRUD (upsert_concept, delete_concept, get_concept), ontology overview/search (get_product_map, lookup_ontology), entity cataloging and registration (get_entity_catalogue, register_entities, ingest_pendo_payload, sync_from_pendo), link suggestions (suggest_links), and gap analysis (list_coverage_gaps). No obvious dead ends.

Maintenance

ActivitySlowing
ResponsivenessNo issues