grane

grane

Enables MCP-compatible agents to run governed, read-only analytics queries against Postgres using predefined metrics and dimensions, with safety checks and provenance on every result.

Category
访问服务器

README

Grane

Governed analytics and controlled exploration for AI agents.

Connect your database, define the business metrics that matter, and give any MCP-compatible agent governed access to those definitions — plus permissioned exploration of everything else.

Self-hosted. Deterministic. Semantic-first, not semantic-only.

Your AI can write SQL. That doesn't mean it knows what Revenue means. Grane tells it which numbers are authoritative and which conclusions are exploratory.


What Grane does

AI agents can already write SQL. But your database does not know your company's approved definitions of Revenue, MRR, Active Customer or ARPU — and letting an LLM invent them produces plausible-looking, wrong numbers.

Grane sits between your database and your agents:

Claude / ChatGPT / Cursor / internal agents
                 |
                 |  MCP
                 v
              GRANE          metrics, dimensions, relationships,
                 |           deterministic compiler, validation,
                 |  SQL      join/grain safety, provenance
                 v
           Your Postgres
  • The agent reasons. Grane enforces truth — and labels exploration. Agents send semantic requests ("revenue by country last month"); Grane resolves the approved definitions, plans the joins, compiles the SQL, and executes it read-only. Permitted raw warehouse columns can be requested as raw_dimensions / raw_metrics without writing SQL.
  • Fan-out safety. Grane knows relationship cardinality and metric grain. Measures across one_to_many joins are pre-aggregated deterministically; queries that would silently multiply rows are refused — including exploratory ones.
  • Refusal is a trust feature. Ask for a metric that isn't defined and Grane returns a structured undefined_metric response with suggestions — it never invents business logic. Raw columns are allowed only when exploration is enabled and the column is not excluded.
  • Three trust levels. governed (approved definitions only), mixed (approved metrics plus raw fields), exploratory (raw warehouse data). Agents must not present exploration as approved business truth.
  • No LLM inside. Grane is deterministic infrastructure. No API keys, no hosted data plane, nothing leaves your environment.

Connect ChatGPT, Claude, Gemini, or any MCP agent

Grane does not need your OpenAI, Anthropic, or Google API keys. You use your own agent subscription or API key on the chat side; Grane sits in the middle and answers governed analytics queries over MCP.

Your agent (ChatGPT / Claude / Gemini / Cursor)  — your LLM keys
        |
        | MCP
        v
Grane  — no LLM keys; metrics + SQL compiler
        |
        | read-only SQL
        v
Your Postgres  — DATABASE_URL

Setup in three steps:

  1. Database — point grane.yml at Postgres with a read-only user; define metrics in YAML; run grane validate.
  2. Grane MCP — run grane serve (HTTP) or let the agent launch grane serve --stdio (local desktop clients).
  3. Agent — register Grane with grane mcp connect <client> (Claude, Cursor, Gemini, VS Code, ChatGPT, Windsurf, Claude Code, or generic), then ask questions in chat.
Agent Typical setup Grane transport
Claude Desktop grane mcp connect claude stdio (local) or HTTPS (remote)
ChatGPT grane mcp connect chatgpt (prints HTTPS steps) HTTPS only — deploy Grane publicly
Gemini CLI grane mcp connect gemini stdio or HTTP
Cursor / VS Code grane mcp connect cursor or vscode stdio or local HTTP

Full walkthrough: docs/connect-an-agent.md

MCP tool reference: docs/mcp-setup.md

Warehouse connections: docs/warehouses.md

Quickstart (with the example database)

npm install -g grane-analytics @duckdb/node-api
git clone https://github.com/Nareik33L/grane.git
cd grane

# DuckDB (no Docker): seeded shop data in example/analytics-duckdb
grane -p example/analytics-duckdb validate
grane -p example/analytics-duckdb query revenue -d country --last 30d

# Or Postgres:
docker compose -f example/docker-compose.yml up -d --wait
grane -p example/analytics validate
grane -p example/analytics query revenue --dimension country --last last_month
grane -p example/analytics query revenue --raw-dimension customers.name --last 30d
grane -p example/analytics mcp doctor --offline --skip-mcp
grane -p example/analytics mcp print-config generic
grane -p example/analytics serve
# MCP  http://localhost:8080/mcp

Install

npm install -g grane-analytics
# or: npx grane-analytics --help

The CLI command is still grane. Requires Node 20+. Warehouse drivers other than Postgres are not installed with the CLI — add only the one you use (see Warehouses below). That keeps a global install free of unrelated SDK deprecation warnings.

Warehouses

Set connection.type in grane.yml. Postgres and Redshift use the bundled pg driver. Other engines need one extra package:

Type Extra install
postgres / redshift (bundled)
mysql npm install mysql2
snowflake npm install snowflake-sdk
bigquery npm install @google-cloud/bigquery
duckdb npm install @duckdb/node-api
clickhouse npm install @clickhouse/client
databricks npm install @databricks/sql

Connection examples: docs/warehouses.md

Quickstart (your own database)

grane init                 # scaffolds grane.yml, metrics.yml, dimensions.yml, relationships.yml
export DATABASE_URL=postgres://readonly_user:...@host:5432/db
grane discover             # introspect tables, columns, FKs; infer relationships
# ... define entities, metrics, dimensions, relationships ...
grane validate             # the "type checker for analytics"
grane query revenue -d country --last 30d
grane serve                # or: grane serve --stdio

Use a read-only database user. Grane also wraps every query in a READ ONLY transaction with a statement timeout, but the database remains the final security boundary.

Defining metrics

Configuration is code: YAML files, reviewed in pull requests, versioned in Git, edited by you or your coding agent.

# entities: the business objects metrics are counted at (their grain)
entities:
  order:
    table: orders
    primary_key: id

# metrics.yml
metrics:
  revenue:
    description: Net revenue from completed orders
    owner: finance
    entity: order
    type: sum                       # sum | count | count_distinct | avg | min | max | ratio
    sql: ${orders.net_amount}
    time_dimension: ${orders.completed_at}
    unit: GBP
    status: approved                # experimental | approved | deprecated
    synonyms: [sales, net sales]
    filters:
      orders.status: completed

# dimensions.yml
dimensions:
  country:
    entity: customer
    sql: ${customers.country}

# relationships.yml — cardinality powers the join-safety checks
relationships:
  orders_to_customers:
    from: orders.customer_id
    to: customers.id
    type: many_to_one

grane validate checks every reference against the live schema, verifies types, and detects unsafe fan-out before an agent ever runs a query.

The MCP surface

Four tools, deliberately hard to misuse:

Tool Purpose
catalog() Discover metrics, dimensions, entities, synonyms, and (when enabled) explorable warehouse columns
query() Run a Query Model v1 request: resolve → validate → compile → execute → provenance
validate() Dry-run a query without executing it
explain() Inspect definitions, trust level, the join plan and the exact SQL

Agents send analytical intent, not SQL:

{
  "metrics": ["revenue"],
  "dimensions": ["country"],
  "raw_dimensions": ["orders.discount_code"],
  "filters": [{ "field": "customer_type", "operator": "=", "value": "business" }],
  "time": { "from": "2026-07-01", "to": "2026-07-31", "grain": "month" },
  "order": [{ "field": "revenue", "direction": "desc" }],
  "limit": 100
}

Every result carries a trust level and provenance:

{
  "trust": "mixed",
  "governed": ["revenue"],
  "ungoverned": ["orders.discount_code"],
  "warning": "orders.discount_code is not defined in the Grane semantic model",
  "provenance": {
    "query_id": "q_1faea438cc34",
    "trust": "mixed",
    "query_model": "v1",
    "metrics": { "revenue": { "definition_version": "a82cf1d3" } },
    "generated_sql": "SELECT ...",
    "executed_at": "2026-08-25T12:00:00Z"
  }
}

See docs/connect-an-agent.md for ChatGPT, Claude, Gemini, Cursor, and grane mcp connect. See docs/mcp-setup.md for MCP tool reference and config file formats.

The trust contract

Grane is semantic-first, not semantic-only. A company should not have to model its entire warehouse before agents can investigate. Define Revenue, MRR, Customers; let agents explore discount_code or device_type when policy allows. Grane still compiles the SQL — agents never get unrestricted SQL by default.

trust Meaning
governed Every field came through an approved Grane definition. Present as business truth.
mixed Approved metrics combined with permitted raw warehouse fields. A strong lead, not an approved conclusion.
exploratory Raw warehouse data only. Investigation, not governed analytics.

Enable exploration in grane.yml:

exploration:
  enabled: true
  schemas:
    - public
  exclude:
    - users.password_hash
    - customers.ssn

Set enabled: false to refuse every raw column. Excluded columns are never queryable. The database credentials used by Grane should remain read-only.

When a raw field is repeatedly useful:

grane usage                          # orders.discount_code used in 47 analyses
grane promote orders.discount_code   # writes a governed dimension to dimensions.yml

When Grane returns trust: governed, it guarantees that every metric and dimension was explicitly defined in the semantic model, every join was known and cardinality-safe, no business logic was invented by an LLM, the SQL is inspectable, and the exact definition versions are identified. If Grane cannot safely resolve the requested meaning, it refuses instead.

What Grane is not

No dashboards, no chart builder, no built-in chatbot, no hosted data plane, no required LLM API key. Agents own presentation; Grane owns analytics truth — and always says which numbers are governed and which are exploratory.

Development

npm install
npm run test:unit                                        # no database needed
docker compose -f example/docker-compose.yml up -d --wait
npm test                                                 # unit + integration

V0.1 supports Postgres. The connector interface will open up to other databases (MySQL, ClickHouse, DuckDB, Snowflake, ...) as demand appears.

License

Apache-2.0

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选