AI Tools
The GASP Standard ships as an MCP server, so Claude, Cursor or any other MCP client can look up the canonical definition of a metric, its formula and the data it needs. Ask it for a definition, a formula, the fields a metric needs or the SQL to compute it against your warehouse.
Quick Start
Install the MCP server with a single command:
Claude Code
claude mcp add gasp-standard -- npx -y gasp-standard-mcp Claude Desktop / Cursor
Add to your MCP config file:
{
"mcpServers": {
"gasp-standard": {
"command": "npx",
"args": ["-y", "gasp-standard-mcp"]
}
}
} Restart your MCP client after adding the config.
The package bundles the standard, so it runs offline. Release notes for each version are in the changelog.
MCP Server
A Model Context Protocol server that serves the whole standard as tools. Claude Code, Claude Desktop or an integration you write yourself can call them for metrics, formulas, relationships and definitions.
Tools
lookup_metric name: string Full metric details: definition, the canonical GASP grammar formula, Operating and Market forms, the Adjusted variant where one exists, benchmarks, signal type, recommended sensitivity tier and access scope, common mistakes, sources and page URL. A name several departments share returns each candidate with its department. Falls back to glossary terms when no metric matches.
lookup_definition term: string Glossary terms such as Signal Type, Sensitivity Tier, Access Scope and Metric Owner: full definition, reference link and page URL.
list_metrics department?: string, signalType?: string List all metrics grouped by department and category, optionally filtered by department or signal type (outcome, leading, efficiency or operational).
get_formula metric: string The canonical formula in the GASP formula grammar, with its unit, Operating and Market forms, named variants and breakdowns, the metrics, fields and datasets each form reads and the enum filters each form applies. Metrics that cannot be computed carry the reason.
get_relationships metric: string Upstream (what drives it) and downstream (what it drives) connections from the GASP relationship graph, for a metric, an entity or a concept. For an entity it also lists every metric whose formula reads the entity's data.
get_data_requirements metric?: string, department?: string, breakdown?: string, dialect?: string Data requirements for a metric or a department dashboard: each field the canonical formula reads with its type and the GASP dataset it comes from, whether the metric needs a staged dataset, reporting grain, source system and example SQL. Pass a breakdown the metric declares for one row per value, or a dialect for the SQL in your warehouse's syntax.
search query: string Whole-word search over metric names, aliases, definitions and formulas, glossary terms and the fields each metric needs. Returns up to 10 results, one per metric or term, with name and alias hits ranked first and each hit's page URL. A misspelling returns the closest names as "Did you mean".
generate_query metric: string, adapter: string, semantic_model?: string, breakdown?: string, dialect?: string
Compile SQL for a metric from its canonical formula and your adapter mapping: one subquery per aggregate, each on the table you mapped to its GASP dataset. The dialect follows your adapter's warehouse (Postgres, Snowflake, BigQuery or Databricks; Postgres SQL also runs on Redshift) unless you pass one. Fields you have not mapped stay as {{field@dataset}} placeholders naming the dataset the column must come from. A breakdown returns one row per value.
validate_mapping adapter: string, semantic_model?: string
Validate a warehouse mapping in either format: a GASP adapter (JSON) or an Apache Ossie mapping document over your semantic model. An adapter is converted on load into an Ossie mapping. The report comes in layers: the schema, the cross-document checks against the GASP ontology, then coverage: unknown fields and datasets, fields mapped to a dataset that lacks them, datasets whose fields point at different tables, every metric scored as fully covered, partially covered or not covered, enum fields mapped without a transform, covered metrics with no declared owner and the next mappings to add. validate_adapter is the same tool under its original name.
compile_model adapter: string, semantic_model?: string, dialect?: string, metrics?: string, department?: string, period_spine?: string, output?: 'model' | 'report'
Compile the GASP metrics your mapping covers into your Apache Ossie semantic model. Same input as validate_mapping; returns your model with a gasp_ metric for every covered formula entry: a direct expression over your datasets and fields where the expression language can state it, else a staged per-period dataset whose source is the compiled SQL over your tables in your warehouse dialect, reading a period spine table you name. Entries with unmapped fields are listed with what they need, and recompiling replaces the earlier additions.
score_drift adapter: string, semantic_model: string, matches?: string, metrics?: string, output?: 'report' | 'json'
Score how far your own metrics drift from the canonical definitions, by result. Each metric in your semantic model is matched to a GASP metric by exact name, by the synonyms in its ai_context or by a pair you pass; near names are listed for review and never scored on a guess. The canonical metric is compiled into your dataset and field names and both run on the GASP synthetic SaaS dataset for six monthly periods, in an in-process Postgres. Where the numbers differ you get both values per period and the likely cause read from the canonical formula: a null on one side (a sum over no rows that is NULL in your SQL and 0 in GASP's), a cohort or opening value the expression cannot state, a filter one side applies, a dataset one side reads or an aggregate with no equal on the other side.
profile_schema schema: string, statistics?: string, organization?: string, output?: 'report' | 'model' | 'json' | 'statistics'
Profile your warehouse schema into a minimal Ossie semantic model, the first step towards a mapping. Pass the rows of information_schema.columns (JSON or CSV), a tables list or CREATE TABLE statements, read through your own warehouse MCP or from a dump, and optionally statistics per column; output: statistics returns the query that gathers them. Every table gets a key, a time field and a kind (snapshot, event, fact or reference) with the evidence and a confidence, plus the relationships the columns imply. What the names cannot settle is listed as a question for you rather than guessed. The model comes back as YAML to pass on as semantic_model.
propose_mapping semantic_model?: string, schema?: string, statistics?: string, organization?: string, output?: 'report' | 'mapping' | 'model' | 'adapter' | 'json'
Propose a GASP mapping from the model profile_schema returned, your own Ossie model or a schema profiled on the way in. Every table is scored against the GASP datasets on its columns, its profiled kind, key and time field and its name; every column of a proposed table against the dataset's fields by name, structural role, a short synonym list, word order and near names, checked against the type and the listed values. A column in cents gets a divide-by-100 transform and values the standard does not use a CASE recode when one is known. High-confidence pairs become an Ossie mapping over the model, ready for validate_mapping; medium ones are listed as candidates with their evidence and what would settle them.
record_decision semantic_model: string, mapping: string, decisions?: string, output?: 'report' | 'mapping' | 'model' | 'json'
Record the decisions people make on a proposed mapping, each named by content with its owner and date: a profiler question answered (the key, the time field, the kind or a datatype, written into the model), a candidate accepted or rejected (a table as a GASP dataset with its columns matched as the proposer would, a column as a GASP field with an optional transform), a metric owner (the slot validate_mapping reads) or a judgement call GASP cannot apply, such as the reporting currency or what date marks churn. Every decision lands in the mapping's GASP extension; a later one on the same subject replaces it. With no decisions it lists what is still open and whether readiness level 2 is reached.
derive_cel adapter: string, currency: string, semantic_model?: string, dialect?: string, first_snapshot?: 'opening' | 'steps', output?: 'report' | 'sql'
SQL that derives CEL Revenue_Event rows from your subscription ledger, by the rules in the CEL. Most billing systems hold subscriptions, not events: the subscription dataset your mapping covers, as snapshots at any cadence or a version history, becomes one event per movement, with the customer's prior_mrr and new_mrr chained so the row identity holds, the event type read from the customer's MRR around the step and the ATL lifecycle tag set. The ledger cannot say what kind of expansion it was, so expansion_classification stays empty for your amendment records to fill. Same mapping input as generate_query, plus the ledger's currency; the dialect comes from the request or your warehouse, and unmapped fields are listed.
generate_checks adapter: string, semantic_model?: string, dialect?: string, window?: number, as_of?: string, results?: string, output?: 'report' | 'sql' | 'json'
The readiness checks the standard states, as SQL over the datasets your mapping covers: CEL row identity, MRR continuity, unique event ids, the three ATL tags, customer identity both ways and freshness per dataset, one statement with one row per check. GASP has no warehouse access, so you run it and paste the rows back as results; the tool then reports pass or fail per check and per metric, each check naming the metrics whose formulas read what it covers. Same mapping input as generate_query.
plan_fixes adapter: string, semantic_model?: string, dialect?: string, results?: string, limit?: number, output?: 'report' | 'json'
The ranked fix list: every unmapped field and every failing check, ordered by Core metrics unlocked, then all metrics unlocked, with an effort class (small, medium, large) shown and used only as a tiebreak. A fix unlocks a metric when it is the last thing between that metric and covered-and-passing. Pass the results from generate_checks to rank data fixes beside mapping gaps.
infer_drivers metric: string, direction: 'up' | 'down', maxDepth?: number Diagnose what could explain an observed metric movement. Walks the graph in reverse and returns ranked upstream candidates with full path and per-step edge classifications. A metric read only as a baseline (at period start, as MRR is in NRR) is listed as a component and the walk stops there. It reasons from the graph's structure and makes no numeric forecast.
explain_path from: string, to: string, maxDepth?: number Enumerate up to five forward edge chains from one metric or node to another, with the edge type and classification (metric_signal, structural, lifecycle, behavioral, assignment or generative) of each step.
coverage_gap metrics: string[] Audit a metric set: one-hop upstream and downstream metrics missing from the set, plus metrics with no path to it. Run it before instrumenting a dashboard.
Use Cases
"What fields and types do I need to track Net Revenue Retention (NRR)?"
Use get_data_requirements to get the exact field schema, types, grain and starter SQL for any metric or department.
"How is Customer Acquisition Cost (CAC) Payback calculated?"
Use get_formula and lookup_metric to get the canonical formula, benchmark ranges and common calculation mistakes to avoid.
"What metrics should my CS team track?"
Use list_metrics to see every metric for a department, then get_data_requirements to plan the implementation.
"Annual Recurring Revenue (ARR) is down this month. Why?"
Use infer_drivers to get a ranked list of upstream candidates whose movement is consistent with the observation, then explain_path to check each link in the chain.
Example Output
What get_data_requirements returns for NRR, with the description, staged and URL lines left out. The table lists each field with the GASP dataset it is read from, one row per pair, as the tool does. The fields, grain and SQL are compiled from the canonical NRR formula. The table names in the SQL are GASP datasets, which generate_query swaps for your own tables.
| Field | Dataset | Type |
|---|---|---|
| customer_id | customer | string |
| customer_id | revenue_event | string |
| customer_id | subscription | string |
| customer_status | customer | string |
| event_date | revenue_event | date |
| event_type | revenue_event | string |
| mrr | subscription | decimal |
| mrr_change | revenue_event | decimal |
| snapshot_date | customer | date |
| snapshot_date | subscription | date |
| subscription_status | subscription | string |
SELECT (CAST((((((SELECT COALESCE(SUM(mrr), 0) FROM subscription WHERE snapshot_date = :period_start AND subscription_status = 'active' AND customer_id IN (SELECT customer_id FROM customer WHERE snapshot_date = :period_start AND customer_status = 'active'))) + ((SELECT COALESCE(SUM(mrr_change), 0) FROM revenue_event WHERE event_date >= :period_start AND event_date <= :period_end AND event_type = 'expansion' AND customer_id IN (SELECT customer_id FROM customer WHERE snapshot_date = :period_start AND customer_status = 'active')))) - ((-(SELECT COALESCE(SUM(mrr_change), 0) FROM revenue_event WHERE event_date >= :period_start AND event_date <= :period_end AND event_type = 'contraction' AND customer_id IN (SELECT customer_id FROM customer WHERE snapshot_date = :period_start AND customer_status = 'active'))))) - ((-(SELECT COALESCE(SUM(mrr_change), 0) FROM revenue_event WHERE event_date >= :period_start AND event_date <= :period_end AND event_type = 'churn' AND customer_id IN (SELECT customer_id FROM customer WHERE snapshot_date = :period_start AND customer_status = 'active'))))) AS DOUBLE PRECISION) / NULLIF(((SELECT COALESCE(SUM(mrr), 0) FROM subscription WHERE snapshot_date = :period_start AND subscription_status = 'active' AND customer_id IN (SELECT customer_id FROM customer WHERE snapshot_date = :period_start AND customer_status = 'active'))), 0)) AS nrr
MCP data at a glance
Knowledge Graph
Underneath the metric pages the GASP Standard is a model of a SaaS business: the metrics, the business entities they measure, the data fields they read and the source systems those fields come from. You can download the model as a Cypher file and import it into Neo4j or any property graph database.
What's in the graph
Node types
The graph contains six types of nodes:
:Metric 65 nodes A metric in the relationship graph, with its definition, canonical formula, department, signal type, level and reporting period.
:Entity 28 nodes A canonical business object such as Customer, Subscription, Opportunity, Ticket, Invoice or Incident (28 in all). A metric points at the entity it tracks with a MEASURES edge.
:Concept 7 nodes An aggregation or classification that sits between entities and metrics, such as Revenue, Bookings, Cohort or Pipeline.
:Dataset 52 nodes A logical table (event, snapshot or fact) with a date field and a key field. The five event tables behind the Commercial Event Ledger also carry their CEL class. Each Field BELONGS_TO a Dataset.
:Field 268 nodes A canonical data field (e.g., customer_id, mrr_start). Your warehouse columns map to these.
:SourceCategory 22 nodes A kind of source system, such as Billing, CRM or Product Analytics, named without a vendor so "Billing" can be Stripe, Chargebee or Zuora.
Metric node properties
Every metric node includes:
| Property | Type | Description |
|---|---|---|
| id | string | Unique identifier (snake_case) |
| name | string | GASP canonical display name |
| department | string | GASP department (Core, Sales, Marketing, ...) |
| signalType | string | outcome, leading, efficiency or operational |
| definition | string | Canonical GASP definition text |
| level | integer | Position in the metric hierarchy (1 is the top) |
| formula | string | Canonical formula in the GASP formula grammar |
| grain | string | Reporting grain (e.g. end-of-month snapshot) |
| frequency | string | How often the metric is refreshed |
| period | string | Reporting period the formula covers |
| url | string | Link to full definition on gaspwiki.com |
Relationship types
21 canonical types used in both the interactive graph (lowercase) and the Cypher file (UPPERCASE). The Cypher file also includes SOURCED_FROM for Field → SourceCategory data lineage edges.
DRIVES A positively influences B. Improving A improves B REDUCES A negatively influences B. A going up causes B to go down PREDICTS A is a leading indicator of B. Changes in A forecast changes in B COMPONENT_OF A is a mathematical input to B's formula MEASURES Metric tracks the state or behaviour of a business entity. "Logo Churn MEASURES Customer" CONVERTS_TO Entity transitions through a funnel stage. Lead → Opportunity → Customer PARENT_OF Hierarchical containment. Parent account contains child accounts BELONGS_TO Entity is a member of a group or classification. Customer belongs to Cohort or Segment OWNS Customer owns Subscription GRANTS Subscription grants License PRICED_BY Determined by a Plan MANAGES Employee manages Customer SERVES Project serves Customer ENGAGES_VIA Customer engages via User SUBMITS Customer submits Ticket REPRESENTED_BY Customer represented by Contact SOURCES Partner sources Opportunity. Campaign sources Lead GENERATES Subscription generates Revenue or Invoice PRODUCES Opportunity produces Bookings or TCV CONTRIBUTES_TO Opportunity contributes to Pipeline INCURS Subscription incurs COGS Import into Neo4j
Download the Cypher file and import it via the Neo4j Browser or cypher-shell:
cat gasp-knowledge-graph.cypher | cypher-shell -u neo4j -p password Or paste the file contents directly into the Neo4j Browser query editor.
Example queries
MATCH (driver)-[:DRIVES|COMPONENT_OF*1..3]->(arr:Metric {id: 'arr'})
RETURN driver.name, driver.department MATCH (churn:Metric {id: 'logo_churn_rate'})-[r]->(affected)
RETURN type(r), affected.name, affected.department MATCH (leading:Metric {signalType: 'leading'})-[:PREDICTS]->(outcome)
RETURN leading.name, outcome.name MATCH (m:Metric)-[:MEASURES]->(e:Entity {id: 'customer'})
RETURN m.name, m.department, m.signalType MATCH (f:Field)-[:SOURCED_FROM]->(s:SourceCategory {id: 'billing'})
RETURN f.id, s.name Apache Ossie export
The standard is also published as Apache Ossie (incubating) files: the ontology, a reference semantic model and the mapping, validated against the upstream Apache Ossie validator in CI. A coverage report lists which metrics the semantic model expresses directly and which need a staged dataset. The downloads page describes each file, the counts and how to run the validator.
Adapter
The GASP Adapter is a JSON mapping file that connects your warehouse columns to the 268 canonical GASP fields. Name the warehouse table behind each GASP dataset and the column for each field, then validate to see which metrics you can compute.
Start from the template and schema below, then run the validate_adapter MCP tool to check your coverage.