Vela MCP Server
Enables governed, agent-agnostic data exploration by allowing users to ask natural language questions through MCP-compatible agents, executing safe, permission-scoped queries against data sources and returning interactive charts.
README
Vela
Governed, agent-agnostic data exploration over MCP Apps. Ask a question in natural language through your company's approved agent — Vela runs a safe, permission-scoped query and returns an interactive chart right inside the chat.
One build, every agent. Because Vela is a standard MCP server, the same setup works in Claude Code, Claude Desktop, ChatGPT, Codex, VS Code — anything that speaks MCP.
business user ──▶ company's agent ──▶ Vela MCP server ──▶ your data source
"revenue by · semantic layer (Postgres / DuckDB
region last · row-level security / CSV / Parquet)
month" · PII masking
· read-only + audit
◀──────── interactive chart in chat ◀────────
Demo

Charts are auto-selected from the shape of the query and rendered interactively (type switcher top-right). See them yourself with no host needed:
npm run build:ui && open dist/ui/preview.html
Why
Text-to-SQL demos are easy. What stops them reaching production is everything around the query: who is allowed to see which rows, what "revenue" actually means, keeping PII out of the model, and proving what ran. Vela puts that governance in the server and hands business users a chat box.
- Semantic layer — the agent can only reference metrics/dimensions an admin defined. It never writes raw SQL, so it can't hallucinate joins or scan whole tables.
- Row-level security — filters are injected based on the caller's role, taken from the trusted session (never a tool argument the model could forge).
- PII masking — sensitive columns are hashed unless the caller's role is explicitly allowed to see them.
- Read-only + audit — every query runs read-only and is logged (who, what spec, row count, duration).
- Charts in chat — results render as an interactive chart via MCP Apps, not a wall of numbers.
Quickstart
npm install
npm run smoke # exercises the engine against the bundled sample data
npm start # builds the UI and starts the MCP server (stdio)
npm run smoke prints a checklist proving chart selection, row-level security, PII masking, and the semantic boundary all work against examples/data/orders.csv — no database required.
See the charts
npm run build:ui
open dist/ui/preview.html # standalone preview of the chart types, no host needed
Connect it to an agent
Add Vela as an MCP server (Claude Desktop / Claude Code shown; any MCP host is similar):
{
"mcpServers": {
"vela": {
"command": "npx",
"args": ["tsx", "/absolute/path/to/vela-mcp/src/server.ts"],
"env": {
"VELA_SEMANTIC": "/absolute/path/to/your/semantic.yaml",
"VELA_ROLE": "sales_west",
"VELA_AUDIT_LOG": "/var/log/vela-audit.jsonl"
}
}
}
}
Then ask: "What was revenue by region last month?" — the agent calls list_metrics, then explore, and a chart appears in the conversation.
Just trying it out? Omit
VELA_SEMANTICandVELA_ROLEto run against the bundled sample data asviewer— no database or config needed. The server anchors to its own install directory, so it works no matter which directory the host launches it from.
Two transports: local (stdio) and remote/browser (HTTP)
The config above uses stdio — local hosts (Claude Desktop, VS Code, Goose, Codex, Cursor) spawn Vela as a subprocess. Browser and hosted clients (claude.ai custom connectors, ChatGPT) can't launch a local process; they connect to a URL. Run Vela over Streamable HTTP for those:
npm run start:http # listens on :3000/mcp (set VELA_HTTP_PORT to change)
For a quick browser test, expose it with a tunnel and register the public URL (https://<host>/mcp) as a custom connector in your client's settings:
npx cloudflared tunnel --url http://localhost:3000 # or: ngrok http 3000
⚠️ The HTTP endpoint has no built-in auth. For anything beyond local testing, put it behind an authenticating proxy and derive the role from the authenticated identity — never trust a client-supplied role.
The semantic layer (the one file an admin writes)
sources:
- name: sales_db
adapter: postgres
dsnEnv: SALES_DB_DSN # secrets come from env, never this file
models:
- name: orders
source: sales_db
table: public.orders
dimensions:
- { name: region, column: region, type: string }
- { name: ordered, column: ordered_at, type: time }
- { name: customer, column: email, type: string }
measures:
- { name: revenue, sql: "sum(amount)", type: number }
- { name: order_count, sql: "count(*)", type: number }
access:
pii_mask:
- { column: email, unmask: [admin] } # hashed for everyone else
row_filters:
- { role: sales_west, where: "region = 'WEST'" }
Business users never see this. They just chat.
Tools exposed to the agent
| Tool | Purpose |
|---|---|
list_metrics |
What the current caller (by role) may explore — masked columns and active row filters are flagged. |
explore |
Submit a structured query spec (metrics, dimensions, filters, time grain) → get a chart. No raw SQL crosses this boundary. |
The explore query spec:
{
"model": "orders",
"measures": ["revenue"],
"dimensions": ["region"],
"filters": [{ "dimension": "ordered", "op": "last", "value": "30d" }],
"timeGrain": "day",
"limit": 1000
}
Chart auto-selection
Vela picks a chart from the shape of the result, the way an analyst would (the user can switch types in the UI):
| Result shape | Chart |
|---|---|
| single measure, no dimension | KPI card |
| a time dimension | line (2nd categorical dim → series) |
| two measures + a label | scatter |
| one categorical dimension | bar |
| two categorical dimensions | grouped bar |
Host support
Vela has two layers that light up independently:
- Tool execution — works today, everywhere. Any MCP host (Claude Desktop, claude.ai, Claude Code, Codex, VS Code, Cursor, …) can call
list_metrics/exploreand get a governed, permission-scoped answer over stdio or HTTP. This is the core value and it works now. - Interactive chart rendering — needs a GUI host with MCP Apps UI support. The in-chat chart is a MCP Apps widget (shipped Jan 2026); support is still rolling out. Terminal/CLI hosts can't render HTML widgets at all — the chart target is graphical hosts (desktop apps, web, IDE webviews). Vela's UI is spec-correct and standalone-verified (see the demo above); it renders as soon as a host executes MCP Apps widgets — no code change on Vela's side.
Architecture
src/
semantic/ schema + loader + compiler (spec → parameterized SQL)
adapters/ duckdb, postgres, behind one interface
guards/ read-only / single-SELECT enforcement
chart/ shape → chart-type selection
audit/ append-only JSONL trail
ui/ render.ts (pure SVG renderer) + chart.ts (MCP App wiring)
engine.ts the governed core (no MCP dependency — unit-testable)
runtime.ts shared setup + MCP server factory (tools/resources)
server.ts stdio entrypoint (local hosts)
http.ts Streamable HTTP entrypoint (remote / browser hosts)
The engine is independent of MCP, so all the safety logic is exercised directly by scripts/smoke.ts. scripts/mcp-check.ts drives the real server as an MCP client.
Security model
- The caller's role comes from the session (
VELA_ROLEfor local/stdio; an authenticated identity in a real deployment) — an agent cannot escalate its own permissions via tool arguments. - Every compiled statement is asserted to be a single read-only SELECT before it runs; user-supplied values are always parameterized.
- Postgres queries additionally run inside a
READ ONLYtransaction. - Secrets live in environment variables, never in the semantic file.
Roadmap
Vela is open core (Apache-2.0). The safety-critical pieces live in the OSS core so self-hosting is genuinely production-safe. Planned:
- More adapters (BigQuery, Snowflake, MySQL) on the same interface
- Import metrics from existing semantic layers (dbt / Cube)
- SSO/SCIM identity, fine-grained policy, and centralized audit (enterprise)
License
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.