Ask the Warehouse MCP Server
Exposes governed dbt Semantic Layer (MetricFlow) metrics and dimensions to MCP clients, with tools to list metrics, list dimensions, and query metric values while enforcing guardrails against raw SQL and undefined fields.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Ask the Warehouse MCP Serverwhat's net spend and small business share by bureau?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
"Ask the Warehouse": Semantic Layer + AI Agent
14 metrics defined once in a dbt semantic layer (MetricFlow) over $6.57B of real federal contract spend. An automated check that dashboard numbers equal the semantic layer to the cent, and catches a planted wrong dashboard. An MCP server that gives an AI agent the metrics and no SQL, with guardrails, scored on a 54-question benchmark with hand-written answers.
Author: Stanley Igwe, Lead Data (Analytics) Engineer · Portfolio Stack: dbt Core · dbt Semantic Layer (MetricFlow 0.213) · MCP (Python SDK 2.x) · Claude (Anthropic SDK) · DuckDB · pytest · GitHub Actions Status: Core build complete on real data. The Claude agent run on the benchmark needs an API key and is the next step. See Roadmap.
Project 12 of my portfolio plan. At a global management consultancy I built governed metrics, plus Power BI data-validation and measure-optimisation models, so every client saw the same numbers. This repo rebuilds the problem on public data. No employer or client data, code or logic is used.
90-second summary
Problem | "Spend" means three different numbers on three dashboards (gross, net, net of credits), and a chatbot over raw tables invents a fourth. Nobody can say which is right. |
What I built | Metrics defined once in MetricFlow. A reconciliation check that every dashboard cell equals the governed metric. An MCP server whose only tools are list metrics, list dimensions and query metrics, behind guardrails that reject undefined metrics, raw columns, SQL in filters and bulk exports. A Claude agent loop over the same tools, and a benchmark whose answers are written in plain SQL, separately from the semantic layer. |
Why it matters | An analyst, a dashboard and an AI assistant get the same answer to "how much did the Park Service spend?", and a wrong dashboard fails CI instead of reaching a board pack. |
Proof | Numbers. Benchmark and dashboard reports in |
Related MCP server: EzBiz Government Contracting MCP Server
Architecture
flowchart LR
P10[(Project 10<br/>USAspending spend lines)] -->|load_spend_lines.py| B[(bronze.spend_lines)]
B -->|dbt| G[(gold: fct_spend_lines<br/>dim_suppliers, time spine)]
G --> SL[[MetricFlow semantic layer<br/>2 semantic models · 14 metrics]]
G --> D[dashboard tables<br/>rpt_dashboard_*]
SL <-->|check_dashboards.py<br/>cell by cell| D
SL --> GR{guardrails}
GR --> MCP[MCP server<br/>list_metrics · list_dimensions · query_metrics]
MCP --> A[Claude agent<br/>or any MCP client]
SL -->|run_eval.py| E[benchmark<br/>vs hand-written SQL]Data
Real: the 41,980 categorised contract actions from project 10 (USAspending.gov, Department of the Interior, federal FY2025, public domain), loaded by ingestion/. CI uses a synthetic fixture with the same columns and vocabulary.
Semantic layer
Metric | Type | Definition |
| simple | Obligations minus de-obligations: the definition of spend |
| simple | New money obligated; money returned (negative) |
| simple | Actions; obligating actions; distinct UEIs |
| ratio | Over obligations where competition / size is recorded |
| ratio | Gross obligations per obligating action |
| derived | −de-obligations / gross obligations |
Dimensions: bureau, category, fiscal quarter, competition status, business size, supplier and parent supplier, and metric_time at day to year grain. The four numerator and denominator helpers make up the rest of the 14.
Guardrails (in agent/semantic_layer.py, checked before anything is compiled)
Only metrics defined in
_semantic.yml; only dimensions MetricFlow lists for those metrics.Filters must be
{{ Dimension('x') }} <op> <literal>joined by and/or. Raw columns, SQL keywords,;, comments and tautologies likeor 1 = 1are rejected.At most 5 metrics, 3 group-bys and 500 rows: it answers questions; it does not export data.
There is no tool that runs SQL. Refusals come back as readable tool errors, so the agent can correct itself.
Numbers
All from the real build (make all) unless marked.
Metric | Value |
Spend lines | 41,980 contract actions, $6.57B net |
dbt build | 25 nodes (7 models, 18 data tests) in 1.9 s, plus 2 semantic models and 14 metrics |
Benchmark, reference requests through the semantic layer | 44/44 answers equal the hand-written SQL |
Benchmark, requests that must be refused | 10/10 refused by the guardrails |
Query latency through MetricFlow | p50 17 ms, p95 26 ms (laptop, DuckDB) |
Dashboard check | 8 dashboard columns, 258 cells, all equal to the cent; the planted legacy dashboard is caught on all 22 of its cells |
Tests ( | 15 pass: guardrail cases, the MCP server over an in-process client, and the agent loop with scripted Claude replies |
Claude agent on the benchmark | not run yet (needs an API key; see Roadmap) |
The planted legacy dashboard makes the two classic mistakes. It shows gross obligations as "spend" (Bureau of Indian Affairs: $408.7M on the dashboard vs $365.7M governed net). And it computes small-business share on net instead of obligated amounts (73.1% vs 72.8%). The check fails CI if it ever stops catching them.
What the reference benchmark proves, and what it doesn't: it shows the metric definitions, the time spine joins, the filters and the guardrails produce the right numbers for 44 realistic questions, and refuse 10 bad requests. It does not yet measure how often an LLM picks the right request. That is make agent-eval, which scores Claude through the same tools against the same answers.
How to run
Requires Python 3.12 (what CI uses) and make, or run the commands in the Makefile by hand.
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
make fixture-all # synthetic fixture: dbt build, benchmark, dashboard check, tests (CI)
make all # real data from ../procurement-spend-cube (build it first)
make mcp # serve the metrics over MCP (stdio), e.g. for Claude Code or Claude Desktop
make agent-eval # Claude agent on the benchmark: needs ANTHROPIC_API_KEY, about 54 short agent runsRoadmap
Scaffold: fixture, staging with key tests, first marts, CI
Define the metrics once (MetricFlow semantic models, 14 metrics) on real USAspending data
Automated test that dashboard numbers equal semantic-layer numbers, with a planted bug it must catch
Expose metrics to an LLM through an MCP server, with no raw-table access and guardrails
Benchmark of 54 questions (44 answerable, 10 to refuse) with hand-written gold SQL; accuracy and latency tracked in CI
Run the Claude agent on the benchmark and report execution accuracy, refusal accuracy, latency and cost per question
Saved queries and a Power BI or Evidence.dev front end reading the same metrics
3-minute Loom walkthrough
Interview topics this project prepares
Semantic layers and metric governance (MetricFlow: measures, ratio and derived metrics, time spines)
Testing BI numbers against a single source of truth
LLM-to-data evaluation: execution accuracy against independent gold answers, refusal accuracy
Guardrails for AI on data, and MCP as the interface
Data and licence
USAspending: U.S. government data, public domain.
Fixture: synthetic, fixed seed,
tests/fixtures/make_fixture.py. It describes no real company or person.Code: MIT (see
LICENSE).
This server cannot be deployed
Maintenance
Related MCP Connectors
US government data as clean JSON for AI agents: SAM.gov contract opportunities, USAspending awards, Grants.gov grants, House STOCK Act trades, and SEC EDGAR filings (Form 4 insider trades, 8-K events, 13F holdings, 13D/G stakes, XBRL fundamentals, 10-K/10-Q sections). 19 read-only tools. Data is as fresh as each source publishes; congressional trades lag up to 45 days and report dollar ranges (House only). Free tier, no card.
See, price, and control every tool call your AI agents make: policy checks, cost, and audit tools.
Search US grants + federal contracts (Grants.gov + SAM.gov) from any LLM.
Access US federal award, recipient, agency, and spending analytics data from USAspending.gov.
Related MCP Servers
- AlicenseNot gradedqualityFmaintenanceEnables AI agents to search and analyze federal government contract opportunities and awards from SAM.gov and USASpending.gov, with tools for contract search, detail, agency spending, and trending sectors.MIT
- FlicenseNot gradedqualityDmaintenanceEnables AI assistants to search federal contracts, analyze agency spending, track competitor wins, and monitor small business set-aside opportunities using SAM.gov, USASpending.gov, and FPDS data.-
- FlicenseNot gradedqualityBmaintenanceExposes a governed semantic layer built on dbt Core and DuckDB, enabling AI agents to query predefined metric definitions for a P&C insurance dataset. Prevents metric hallucination by restricting agents to governed tools and read-only data access.-
- AlicenseBqualityBmaintenanceEnables agents to interact with a governed semantic layer for querying and authoring metrics, providing tools for discovery, planning, validation, and execution of analytics queries.28172 PyPI2Apache 2.0