MCP and your data warehouse: where cross-tool joins belong
MCP can run a join across your tools, and on our demo data it did. What it cannot tell you is that the key, the grain and the revenue definition are the ones your business uses. This guide compares three ways to put MCP on a data warehouse, reports one question asked three ways with the figures, and ends with four checks to run on any cross-tool answer.
“Can’t Claude read GA4, HubSpot and Google Ads through MCP and tell us which campaigns made money?” If you are the analyst who got that question, the short version is yes, it can run the join. The part you will be asked about afterwards is harder: was it the right join? A bad join does not announce itself. A wrong total looks exactly like a right one.
Originally published in July 2026. Fully updated in October 2026 with a test on demo data. It replaces the earlier claim that MCP cannot join across tools, which our test did not support.
The short answer
The assistant can ask each tool for its own slice of data. The join is the step that matches rows from different slices, for example matching ad spend to orders by campaign. If that match happens inside the assistant, you see the answer but not how the rows were matched. If it happens in a warehouse, the match is a query you can open and read. There are three common places for it: inside the assistant, working from each tool’s results; in a warehouse MCP server over raw tables; or over Data Marts an analyst has defined and published. The table below compares them.
We asked one question that needs a join across ad spend, sessions and orders, in three setups, three runs each. When the model could see all the data, the answer matched our reference every time. When a row cap cut the data off, the model said so and declined to rank. No setup gave a wrong ranking. The full results come with their limits: one model, one question, clean demo data.
So the useful question is not whether MCP can join. It is whether the key, the grain and the definition of revenue it used are the ones your business uses, and whether you can see which they were. That is what a written model is for. We are OWOX, and we build one, so you should know who is saying this.
What MCP is, in three paragraphs
What MCP is, in three paragraphs
The Model Context Protocol is an open standard for connecting an AI application to outside systems. A system exposes an MCP server with tools the AI can call, such as “run this query”. The AI application opens one connection per server.
Per the MCP specification, each client has a 1:1 relationship with a particular server, and servers should not be able to “see into” other servers. The specification does not define a join between servers. Whatever combining happens, the model does it from the results it holds.

OWOX Data Marts
See your first report built in real time. 15 minutes.
- Connect your data warehouse
- Pick your metrics
- Get a live Google Sheets report
In the time it takes to write a ticket. Then imagine never writing that ticket again.
Book a DemoWe'll use your actual use case
What one tool’s MCP server answers well
What one tool’s MCP server answers well
Ask a single tool a single-tool question and MCP does what you would expect: yesterday’s sessions from GA4, last quarter’s closed deals from your CRM, today’s spend on one platform. There is no pipeline to build and no export to schedule, and the answer is as fresh as the tool.
This is where MCP replaces the “can you pull something for me” messages, and where there is nothing to join.
Three ways to put MCP on a data warehouse
Three ways to put MCP on a data warehouse
The question changes when the answer needs two systems. These are the three setups we tested, and the three places a join can live. Which warehouse? Yours, the one your data is already in. OWOX Data Marts works on five: Google BigQuery, Snowflake, AWS Redshift, AWS Athena and Databricks.
Each setup answers the same four questions, in plain words:
- Per-tool servers. The model gets one result from each tool and matches the rows itself. The key it matched on is its own choice. Revenue means whatever the tool’s field is called. You can open the chat and the files it read. Each tool’s server sets its own cap on how many rows come back.
- Warehouse MCP on raw tables. The model writes the SQL that matches the rows, and picks its own meaning of revenue. You can open the SQL it ran in the warehouse’s job history. The server’s row cap applies.
- MCP over published Data Marts. An analyst has written down how the tables relate (the technical word is a declared relationship) and what revenue means, once. The assistant asks for fields, filters and totals. You can open the Data Mart definition and the record of each query.
“Grain” below means one row per what: one row per day per campaign for spend, one row per order for revenue.
The warehouse setup deserves a fair word. Google runs an MCP server for BigQuery with two query tools, execute_sql and execute_sql_readonly; it limits results to 3,000 rows and cancels queries after three minutes by default, per Google’s documentation (read October 2026). Setup, roles and the bugs you will hit are in BigQuery MCP for Claude, and AI analytics on BigQuery compares it with the other two on who writes the SQL. If your warehouse is not BigQuery, read your vendor’s own MCP page for its limits; we only checked Google’s.
OWOX’s MCP server lets the assistant ask for fields, filters and aggregations from published Data Marts, and the queries run in your warehouse. This page shows how an assistant connects.
Where a cross-tool number can go wrong
Where a cross-tool number can go wrong
The old version of this page said cross-tool joins fail because there is no shared key. On our demo shop that is false. In a check we ran before the test, the seven paid source and medium labels in the ad data matched the sessions data exactly, and 13 campaign names matched exactly. Source, medium and campaign line up. What can still go wrong is four other things.
Name collisions. The campaign “brand awareness - us” runs on both Facebook and TikTok. Join on campaign alone and the two merge into one row with spend of 8,677.16 and a ratio of 4.87. TikTok’s campaign, which ranks fourth on its own at 5.41, drops out of the top five, and “search - brand keywords” takes its place.
Grain (one row per what). Ad spend is one row per day per campaign. Orders are one row per order. The wrong-grain query joins one row per order to the daily spend rows, so each day’s spend is counted once per order. Totals stop reconciling: 30,702.80 instead of 47,524.81, and one campaign shows a ratio of 683.37.
Definition. “Net revenue” has to mean something. In our reference it is the shop’s own: the net amount on order lines, completed orders only. A model that sums gross revenue produces a clean, wrong table.
Truncation. A row cap can cut one source off partway through. Whatever is joined afterwards covers only the part that arrived.
All four are cheap to fix once someone has decided the key, the grain and the definition, and expensive to find afterwards. All of these figures come from hand-written SQL, run once with no model involved. The correct version aggregates both sides to source, medium and campaign before joining.
What we measured
The question, fixed for every run: “Which campaigns returned the most net revenue per dollar of ad spend in Q3 2026, excluding Reddit? Top five, with the figures.” Reddit is excluded because a known gap in our ad-spend Data Mart would otherwise be mistaken for a join result. The reference answer, from hand-written SQL:
| Campaign (platform) | Spend | Net revenue | Net revenue per $1 |
|---|---|---|---|
| pmax - brand catchall (Google) | 60.89 | 635.53 | 10.44 |
| performance max - all products (Google) | 2,155.73 | 13,639.15 | 6.33 |
| brand search - exact (Bing) | 3,557.34 | 21,174.16 | 5.95 |
| brand awareness - us (TikTok) | 2,518.59 | 13,625.48 | 5.41 |
| conversions - warm audience (TikTok) | 3,503.78 | 18,932.70 | 5.40 |
Three setups, three runs each, one model, a fresh session per run. Counts, not rates:
| Setup | Top five matched the reference | What it said about its own answer | What it needed from the user |
|---|---|---|---|
| Per-tool results: three files, each capped at 3,000 rows | 0 of 3 | 3 of 3 noticed the sessions file stopped on 3 July and declined to rank | Re-pull sessions in smaller date ranges |
| BigQuery MCP on raw views | 3 of 3 | 3 of 3 said net revenue means completed orders only | Nothing |
| OWOX Data Marts MCP | 3 of 3 | 3 of 3 said the division was their own arithmetic, and that LinkedIn and X spend could not be matched to campaigns | Nothing |
Two details matter. In the per-tool setup, 1 of 3 runs also showed a table for 1 to 3 July only, labelled as not a Q3 answer. And the control question, “How many employees did we have at the end of Q3 2026?”, was declined correctly in all three setups, each time saying what the data did hold.
What this shows is narrow. A current model joined correctly when it had the data, and said so plainly when it did not. It also shows what the setups cost. The per-tool runs took 12 to 15 tool calls each and ended with a request to the user. The warehouse run needed four SQL statements; the Data Marts run needed 9 to 11 calls per run (counting loading the tools), one or two of the query calls of which returned output too large to use.
So what does the written data model add, when raw tables also scored 3 of 3? The raw-views run chose its own definitions, and it showed them: it said net revenue means completed orders only. The Data Marts run used the definition written in the Data Mart. A model that chooses a definition can choose differently next week, which is the pattern in our AI-trust guide. What the Data Marts setup cannot do is also outside this test: HubSpot deals, offline conversions and messy UTM tags were not tested, so the first check on your own data is to count the distinct campaign names across your sources and see which repeat.
Four checks before you trust a cross-tool answer
Four checks before you trust a cross-tool answer
Apply these to any answer that combines two tools, whoever or whatever produced it:
- Which key joined the sources, and is it stated? Platform plus campaign is not the same as campaign.
- At what grain were they joined? Daily spend and per-order revenue need aggregating to a common level first.
- Whose definition of revenue? Net or gross, with or without cancelled orders, and does the answer say which led?
- Can you open the calculation? The SQL, the Data Mart definition or the query record. An answer from chat memory leaves nothing to open.
A spreadsheet join by hand needs the same four checks, with no record of what you did. For a number leadership will repeat, move the join into the warehouse and deliver the result to the sheet from there.
Best practices for MCP on a warehouse
Best practices for MCP on a warehouse
- Use a read-only identity. Google’s server has
execute_sql_readonlyfor this, which allows only read operations. - Give it a narrow scope: a dataset of views you are willing to defend, not the raw tables behind them.
- Treat row caps as data loss. A cap of 3,000 rows is a cut, and a client may not mark it. Aggregate before returning rows.
- Keep the join and the definition written down, in SQL or a model, not in a prompt.
For what a benchmark score does and does not tell you, see text-to-SQL accuracy. For the rollout in order, see governed MCP analytics.
Start with one question
Pick the cross-source question your team is asked most, often campaign performance against revenue. Write down its key, its grain and its definition, and build one Data Mart that answers it, with joinable Data Marts for the relationships. Then let people ask it through MCP.
OWOX Data Marts positions on zero hallucinations, meaning the assistant reads a data model the analyst owns and does not write free-form SQL against your tables. That lowers the risk and is not a 100% guarantee: in our runs the assistant still did its own division and still chose which Data Mart to read, which is why the four checks apply to every answer. If you want to try it, OWOX Data Marts is where we built it.
How we tested this
Run on 14 October 2026 on OWOX’s demo shop, Q3 2026 (1 July to 30 September), with Claude as the model and a fresh sub-agent session per run. The protocol was written before the first run and not changed after.
- Setup A is a simulation. Three CSV files served as isolated tool results, capped at 3,000 rows each: ad spend by day (1,500 rows), the first 3,000 of 78,700 Q3 session rows with no truncation marker, and 1,942 orders with gross and net revenue. They are not real GA4 or HubSpot MCP servers. A real server may mark truncation explicitly, which would make this setup easier.
- Setup B used Google’s BigQuery MCP, read-only, on the demo’s raw views, with no instructions beyond the question.
- Setup C used OWOX Data Marts MCP on the demo project’s Data Marts. Nothing was created or changed in the project during the runs. Afterwards we checked Run History in the app: each of the 11 query calls made by the three runs has an entry showing the executed SQL, the source table, the row count, a
truncatedflag and when the source tables were last updated. 7 of the 11 are marked truncated because they stopped at the row limit the run set. This is one demo project; no screenshot yet. - Limits: one model, one question, three runs per setup, one clean dataset. This is not a benchmark, and it does not say how often any setup is wrong on your data.
- Reference: the reference answer and both wrong variants were computed once with hand-written SQL and no model.
Turn your data into decisions.
Governed data marts give you the clean foundation ML needs to actually work.
- No AI hallucinations
- Analyst-governed definitions
- Every number traces to SQL
Frequently Asked Questions
Is MCP safe for enterprise analytics data?
MCP is a way to connect an AI application to a tool, so safety depends on what the connection can read and who is signed in. Use a read-only identity and a narrow dataset. The separate risk is accuracy: when the join happens inside the assistant, you cannot always see which key, grain and definition of revenue it used. The article lists four checks to run on any cross-tool answer.
What is a Data Mart and how does it reduce wrong answers?
A Data Mart is a dataset an analyst has defined and published in your warehouse, with the relationships between tables and the meaning of each metric written down once. When an assistant asks for fields, filters and totals from it, the join follows that written definition instead of being chosen anew each time. That lowers the risk of a wrong answer. It is not a 100% guarantee: in our test the assistant still did its own division and chose which Data Mart to read.
Can Claude combine data from several MCP servers, and what decides whether the answer is right?
Yes. In our test (one model, one question, demo data, three runs per setup) it joined correctly whenever it could see all the data. What decides the answer is the join key, the grain, the revenue definition and whether a row cap cut a source off. When the cap cut the data off in our per-tool setup, all three runs said so and declined to rank.
What is the difference between MCP and a data pipeline?
MCP provides real-time read access to individual tools without extracting, transforming, or storing data. A data pipeline (ETL/ELT) extracts data from multiple sources, transforms it with defined join logic, and loads it into a warehouse where cross-source queries are possible. MCP replaces the access layer but not the transformation or join logic that pipelines provide.
How does MCP connect to analytics tools like GA4?
MCP (Model Context Protocol) is an open standard for connecting an AI application to outside systems. A GA4 MCP server exposes analytics data as tools the AI can call, and the application keeps one connection per server. That suits single-tool questions. Combining two tools happens in the assistant, from the results it holds, because the MCP specification does not define a join between servers.
How often is a cross-source answer wrong?
In our run, 0 of 6 warehouse-based answers were wrong and 0 of 3 per-tool answers produced a ranking. That is nine runs on one model and one question, not a rate.
Can MCP replace a data warehouse for analytics?
For a single-tool question you may not need a warehouse. For a number leadership repeats, keep one. MCP gives you the door to each tool. A warehouse gives the join, the definition of revenue and the history somewhere you can open and check. For that number, write the join down.
How do I use MCP with a data warehouse?
Connect a warehouse MCP server with a read-only identity and a narrow dataset, or publish Data Marts and connect over MCP. Google's BigQuery server caps results at 3,000 rows and 3 minutes. Check the four things listed in the article against any answer.
Which data warehouse should I use with MCP?
The one your data is already in. OWOX Data Marts supports Google BigQuery, Snowflake, AWS Redshift, AWS Athena and Databricks.
What are best practices for using MCP with a data warehouse?
Use a read-only identity, a dataset of views, treat row caps as data loss, keep the join and the definition written down, and check against a number you trust.

