Tool Graph Mesh
At the heart of ToolPilot is a Memgraph-powered property graph containing 491+ developer tools and thousands of relationships. Unlike a flat database, the graph captures how tools relate to each other — compatibility, alternatives, ecosystems, and more.
Why a Graph?
Developer tools don’t exist in isolation. A testing framework depends on a language runtime, pairs naturally with a build tool, and competes with alternatives. Relational databases struggle to express these multi-hop, many-to-many relationships efficiently. A property graph makes traversals like “find tools that work well with Prisma and are written in TypeScript” a single Cypher query instead of a cascade of JOINs.
Graph vs. Keyword Search
Node Types
The graph contains five node types, each serving a distinct role in the tool ecosystem:
🔧 Tool Primary node
Represents a developer tool, library, or framework. This is the central entity in the graph — every other node type connects back to Tool nodes.
nameShort identifier (e.g., “prisma”)full_nameGitHub-style owner/repo (e.g., “prisma/prisma”)descriptionOne-line summary of what the tool doeslanguagePrimary programming languagecategoryFunctional category (e.g., “ORM”, “Testing”)starsGitHub star counthealth_scoreMaintenance score (0–100)maintenance_scoreDetailed maintenance metriccreated_atWhen the tool was first indexedupdated_atLast data refresh timestampdocs_urlLink to official documentation📂 Category
Functional grouping like ORM, Testing Framework, CSS Framework, or Build Tool.
Properties: name, slug, tool_count
💬 Language
Programming language or runtime. Tools connect here via WRITTEN_IN edges.
Properties: name, slug
📜 License
Software license type (MIT, Apache-2.0, GPL-3.0, etc.).
Properties: name, spdx_id
💻 Platform
Target platform or runtime environment (Node.js, Browser, Docker, etc.).
Properties: name, slug
Edge Types
Edges encode the relationships between nodes. Each edge type carries semantic meaning, and most have properties like weight that influence search ranking.
| Edge | Direction | Meaning | Properties |
|---|---|---|---|
RELATED_TO | Tool → Tool | Tools that work well together, weighted by co-usage frequency | weight (0–1), type, created_at, last_reinforced |
BELONGS_TO | Tool → Category | Functional category membership | weight (0–1), created_at |
WRITTEN_IN | Tool → Language | Primary programming language of the tool | created_at |
LICENSED_AS | Tool → License | Software license the tool is distributed under | created_at |
ALTERNATIVE_TO | Tool → Tool | Competing or substitute tools that solve the same problem | weight (0–1), created_at, last_reinforced |
DEPENDS_ON | Tool → Tool | Runtime or build-time dependency relationship | weight (0–1), type, created_at |
Graph Visualization
Here’s a simplified view of how tool nodes connect through different edge types in the graph:
┌─────────────┐ RELATED_TO ┌─────────────┐
│ Prisma │──── (w: 0.82) ───▶│ Drizzle │
│ ★ 41.2k │ │ ★ 26.8k │
│ health: 92 │ │ health: 88 │
└──────┬───────┘ └──────┬──────┘
│ │
WRITTEN_IN WRITTEN_IN
│ │
▼ ▼
┌─────────────┐ ┌──────────────┐
│ TypeScript │ │ TypeScript │
└─────────────┘ └──────────────┘
│
BELONGS_TO
│
▼
┌─────────────┐ ALTERNATIVE_TO ┌──────────────┐
│ ORM │ │ Knex.js │
└─────────────┘ └──────────────┘Querying the Graph
Under the hood, ToolPilot uses Cypher queries (via the Bolt protocol) to traverse the graph. The search pipeline builds these queries automatically, but here’s what a typical relationship traversal looks like:
1// Find tools related to "prisma" with relationship strength
2MATCH (t:Tool {name: "prisma"})-[r:RELATED_TO]->(related:Tool)
3WHERE r.weight > 0.5
4RETURN related.name, related.health_score, r.weight
5ORDER BY r.weight DESC
6LIMIT 10
Edge Properties
The most important edge property is weight, a float between 0 and 1 that represents relationship strength. Weights are influenced by:
- Co-usage frequency — how often tools appear together in real projects
- GitHub co-occurrence — package.json, requirements.txt, and similar manifest analysis
- Agent feedback — success/failure reports from
report_outcome - Temporal decay — weights decrease over time without reinforcement (see Edge Decay)
Other properties include created_at (when the edge was first established) and last_reinforced (when the weight was last boosted by new evidence).