gasp-standard-mcp 1.14.2 → 1.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/index.js +1 -1
- package/build/loader.d.ts +2 -2
- package/build/loader.js +8 -6
- package/build/standard-data.json +1 -1
- package/build/standard-version.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -33,7 +33,7 @@ Restart your MCP client after adding the config.
|
|
|
33
33
|
|
|
34
34
|
| Tool | Description |
|
|
35
35
|
|------|-------------|
|
|
36
|
-
| `lookup_metric` | Full record for one metric: department, category, signal type, definition, formulas as written, the canonical formula with unit, forms, variants and breakdowns, benchmarks, validation rules, common mistakes, sources, aliases, the entities it measures, operating and market forms, the recommended sensitivity tier and access scope and the page URL. Matches exactly, ignoring case: formula id, graph node id, name with or without its abbreviation, abbreviation, graph label, alias or slug, with the full record preferred over a cross-reference stub. A name two departments define (
|
|
36
|
+
| `lookup_metric` | Full record for one metric: department, category, signal type, definition, formulas as written, the canonical formula with unit, forms, variants and breakdowns, benchmarks, validation rules, common mistakes, sources, aliases, the entities it measures, operating and market forms, the recommended sensitivity tier and access scope and the page URL. Matches exactly, ignoring case: formula id, graph node id, name with or without its abbreviation, abbreviation, graph label, alias or slug, with the full record preferred over a cross-reference stub. A name two departments define (Activation Rate) lists each candidate with department, formula id and URL; prefix the department ("Product Activation Rate") or pass the formula id. A glossary term returns its definition and a miss returns close names (misspellings included) |
|
|
37
37
|
| `lookup_definition` | Glossary term lookup (e.g. Signal Type, Sensitivity Tier, Access Scope, Metric Owner, CEL): full definition, section, canonical or reference link, where it is used and page URL. Matches the term, its slug or either part of "Term (Abbreviation)" exactly; a metric name points to `lookup_metric` and a miss returns close terms |
|
|
38
38
|
| `list_metrics` | Metric names grouped by department and category, optionally filtered by department (case-insensitive, spaces or hyphens; an unknown name returns close names and the department list) and signal type (`outcome`, `leading`, `efficiency`, `operational`, primary or secondary). The Core tier is the Core department |
|
|
39
39
|
| `get_formula` | Canonical formula in the GASP formula grammar, with unit, O/M forms, named variants, breakdowns (field, bucket and total mode), notes, input metrics with role and polarity, the fields and datasets the formula and each form read and the enum filters each form applies (CAC-O reads `cost_function in (gtm, implementation, onboarding)`, CAC-M `cost_function = gtm`), then the formula as written in the standard. Metrics that cannot be computed carry the reason |
|
|
@@ -50,7 +50,7 @@ The traversal tools (`infer_drivers`, `explain_path`, `coverage_gap`) return pat
|
|
|
50
50
|
|
|
51
51
|
## Data
|
|
52
52
|
|
|
53
|
-
Version 1.
|
|
53
|
+
Version 1.15.0.
|
|
54
54
|
|
|
55
55
|
- 301 metrics across 13 departments
|
|
56
56
|
- 93 glossary definitions (80 SaaS domain + 13 GASP framework)
|
package/build/index.js
CHANGED
|
@@ -129,7 +129,7 @@ function notAMetric(name, resolved) {
|
|
|
129
129
|
return `No metric is named "${name}".${suggestMatches(data, name)}`;
|
|
130
130
|
}
|
|
131
131
|
// --- Tool 1: lookup_metric ---
|
|
132
|
-
server.tool("lookup_metric", "The full record of one GASP Standard metric: department, category, signal type, page URL, definition, the formulas as written, the canonical GASP grammar formula (unit, forms, variants, breakdowns, fields and datasets), benchmarks, validation rules, common mistakes, sources, aliases, the entities it measures, operating and market forms, any adjusted variant and the recommended sensitivity tier and access scope. The name must match exactly, ignoring case: formula id, graph node id, full name, name without its abbreviation, abbreviation, graph label, alias or slug. A name several departments use (e.g. '
|
|
132
|
+
server.tool("lookup_metric", "The full record of one GASP Standard metric: department, category, signal type, page URL, definition, the formulas as written, the canonical GASP grammar formula (unit, forms, variants, breakdowns, fields and datasets), benchmarks, validation rules, common mistakes, sources, aliases, the entities it measures, operating and market forms, any adjusted variant and the recommended sensitivity tier and access scope. The name must match exactly, ignoring case: formula id, graph node id, full name, name without its abbreviation, abbreviation, graph label, alias or slug. A name several departments use (e.g. 'Activation Rate') returns each candidate with department, formula id and URL; prefix the department ('Product Activation Rate') or pass the formula id. A glossary term (e.g. 'Signal Type') returns its definition and a miss returns close names to retry with. Use get_formula for the formula alone and search when you do not know the name.", { name: z.string().describe("Exact metric name, abbreviation, alias, slug or formula id, case-insensitive (e.g. 'MRR', 'Net Revenue Retention', 'CAC Payback', 'product_activation_rate'). Prefix the department to pick between metrics that share a name.") }, async ({ name }) => {
|
|
133
133
|
const resolved = resolveMetric(data, name);
|
|
134
134
|
if (resolved.kind === "ambiguous") {
|
|
135
135
|
return { content: [{ type: "text", text: formatAmbiguous(data, name, resolved.candidates) }] };
|
package/build/loader.d.ts
CHANGED
|
@@ -73,13 +73,13 @@ export type Resolved = {
|
|
|
73
73
|
};
|
|
74
74
|
/**
|
|
75
75
|
* Exact matches only, never a substring guess. Five tiers, first hit wins:
|
|
76
|
-
* 1. the formula id or graph node id as typed ("
|
|
76
|
+
* 1. the formula id or graph node id as typed ("product_activation_rate",
|
|
77
77
|
* "nps"): unique keys, so never ambiguous;
|
|
78
78
|
* 2. a name: the full name, the name without its abbreviation, the
|
|
79
79
|
* abbreviation, or the label of the metric's graph node;
|
|
80
80
|
* 3. an alias;
|
|
81
81
|
* 4. the slug;
|
|
82
|
-
* 5. the formula id with spaces for underscores ("
|
|
82
|
+
* 5. the formula id with spaces for underscores ("Product Activation Rate").
|
|
83
83
|
* Non-stub metrics are tried through every tier first, then as a name
|
|
84
84
|
* qualified by department; a cross-reference stub answers only when no full
|
|
85
85
|
* record matches. Two full records matching in the same tier are ambiguous.
|
package/build/loader.js
CHANGED
|
@@ -343,9 +343,11 @@ export function metricFormulaId(data, metric) {
|
|
|
343
343
|
let bare = metric.slug.replace(/-/g, "_").replace(/^(\d+)_day_/, "day_$1_");
|
|
344
344
|
if (/^\d/.test(bare))
|
|
345
345
|
bare = `n_${bare}`;
|
|
346
|
-
//
|
|
347
|
-
//
|
|
348
|
-
// the
|
|
346
|
+
// A metric is qualified by department when its bare id would be shared: two
|
|
347
|
+
// departments defining metrics under one heading (no heading is shared today,
|
|
348
|
+
// the rule stays as a guard), or a bare id that is another metric's graph node
|
|
349
|
+
// (Product's "Activation Rate" against the Onboarding node activation_rate,
|
|
350
|
+
// hence product_activation_rate). The node owner keeps the bare id.
|
|
349
351
|
const rivals = data.metrics.filter((m) => m !== metric && !isMetricStub(m) && m.slug === metric.slug);
|
|
350
352
|
const nodeOwner = data.nodes.some((n) => n.id === bare) || rivals.some((m) => metricNodeId(data, m) === bare);
|
|
351
353
|
if (rivals.length === 0 && !nodeOwner)
|
|
@@ -503,13 +505,13 @@ function namedBy(data, q) {
|
|
|
503
505
|
}
|
|
504
506
|
/**
|
|
505
507
|
* Exact matches only, never a substring guess. Five tiers, first hit wins:
|
|
506
|
-
* 1. the formula id or graph node id as typed ("
|
|
508
|
+
* 1. the formula id or graph node id as typed ("product_activation_rate",
|
|
507
509
|
* "nps"): unique keys, so never ambiguous;
|
|
508
510
|
* 2. a name: the full name, the name without its abbreviation, the
|
|
509
511
|
* abbreviation, or the label of the metric's graph node;
|
|
510
512
|
* 3. an alias;
|
|
511
513
|
* 4. the slug;
|
|
512
|
-
* 5. the formula id with spaces for underscores ("
|
|
514
|
+
* 5. the formula id with spaces for underscores ("Product Activation Rate").
|
|
513
515
|
* Non-stub metrics are tried through every tier first, then as a name
|
|
514
516
|
* qualified by department; a cross-reference stub answers only when no full
|
|
515
517
|
* record matches. Two full records matching in the same tier are ambiguous.
|
|
@@ -536,7 +538,7 @@ export function resolveMetric(data, name) {
|
|
|
536
538
|
if (hits.length > 1)
|
|
537
539
|
return { kind: "ambiguous", candidates: hits };
|
|
538
540
|
}
|
|
539
|
-
// A name qualified by its department: "
|
|
541
|
+
// A name qualified by its department: "Product Activation Rate", "Activation Rate (Product)"
|
|
540
542
|
for (const dept of new Set(full.map((m) => m.department))) {
|
|
541
543
|
const d = dept.toLowerCase();
|
|
542
544
|
const rest = q.startsWith(d + " ") ? q.slice(d.length + 1) : q.endsWith(` (${d})`) ? q.slice(0, -(d.length + 3)) : null;
|