The short version
- The Model Context Protocol (MCP) is an open standard that lets an AI assistant use outside tools and data: it can look things up and take actions, instead of only answering from what it was trained on.
- An assistant connects to an MCP server. A warehouse's MCP server gives it a handful of tools: list the databases, read the schema, run a query.
- Remote servers sign you in with OAuth, so you approve access on a consent screen and never hand over a password or paste a key into a chat.
- On DuckHouse the connection is read-only unless you say otherwise. That stops an assistant from changing your data, but it does not limit what it can read.
Pondside now has a warehouse with a clean layer of named views on top. Anyone who knows a little SQL can answer almost any question about the business in a minute. Most people at Pondside do not know any SQL. They know how to ask.
This part is about the bridge between the two: how an AI assistant such as Claude goes from a question typed in English to a query run against your data, and back to an answer. The bridge has a name, the Model Context Protocol, and once you see how it works you will know what it can do, what it cannot, and what to watch.
Before MCP: the copy-and-paste era
For the first couple of years of chat assistants, using one on your own business data went like this. Export a CSV from Square. Export another from Shopify. Drag both into the chat window, ask your question, and hope the files were recent, complete and small enough to fit. Next week, do it all again.
It worked, after a fashion, and it had three problems that never went away:
- The data was always stale. The assistant knew whatever you pasted, as of the moment you exported it.
- It did not scale. A year of café payments is around fifty thousand rows. Pasting that into a chat is slow at best, and an assistant reading it row by row is the wrong tool for adding it up.
- Every connection was custom. Each AI product that wanted to reach a database, a calendar or a code repository needed its own integration with each one. N apps times M systems is a lot of glue.
The better shape was obvious: let the assistant ask the system for exactly what it needs, when it needs it, and let the system do the heavy lifting. A warehouse can add up fifty thousand rows in milliseconds. The assistant only needs to know how to ask, and to read the three rows that come back.
What the Model Context Protocol is
The Model Context Protocol is an open standard for connecting AI applications to outside systems. Anthropic published it on November 25, 2024, and it spread quickly: OpenAI added MCP support to its Agents SDK in March 2025, Microsoft announced MCP support for Windows in May, and Google Cloud previewed managed MCP servers for its own services that December. On December 9, 2025, Anthropic donated MCP to the Agentic AI Foundation, a fund under the Linux Foundation co-founded with Block and OpenAI, so the standard is no longer one company's project.
The project's own documentation puts it in one line: “Think of MCP like a USB-C port for AI applications.” One shape of plug, many devices. A system that speaks MCP once can be used by every assistant that speaks it too, which turns N times M integrations into N plus M.
The assistant does not get your data. It gets a way to ask for it, one question at a time.
Hosts, clients and servers
MCP has three roles, and the names are worth learning because every setup screen uses them.
- Host
- The AI application you actually use: Claude on the web, on your desktop or on your phone, an IDE such as Cursor, or a command-line agent. It holds the model and the conversation.
- Client
- A small piece inside the host that keeps one connection to one server. A host with three servers configured runs three clients.
- Server
- A program that offers tools to clients, each with a name, a description and the inputs it takes. DuckHouse runs one; so do calendars, code hosts, CRMs and many other services.
Local and remote servers
A server can run in one of two places. A local server is a program on your own computer that the host starts itself, and the two talk over the program's standard input and output (stdio). That suits anything that should stay on your machine, such as your files. A remote server lives on the internet and is reached over HTTPS, using the transport the spec calls Streamable HTTP: each message is an HTTP request to a single endpoint.
For a warehouse you want to question from anywhere, remote is the only kind that makes sense. A local server would tie you to the laptop it runs on, and a phone app has nowhere to run one. DuckHouse's server is remote, at one address: https://duckhouse.co/api/mcp. There is nothing to install or host.
Tools, resources and prompts
A server can offer three kinds of thing. Most of the value, for data, is in the first.
- Tools
- Functions the model can call, such as “run this query”. Each declares its inputs as a JSON schema, so the model knows exactly what to send.
- Resources
- Content the host can read and put in front of the model, such as a file or a document, addressed by a URI.
- Prompts
- Ready-made instructions a server offers, which a person picks from a menu, such as “summarize this week”.
DuckHouse offers tools only. A warehouse is too big to hand over as a resource, and the questions are too varied for a fixed menu of prompts. What a model needs is the ability to look around and then ask precisely, and these are the tools that give it that:
| Tool | What it does |
|---|---|
list_databases | Lists your databases and whether each is running. |
get_database | One database, including its status. |
describe_schema | Every table and view, with its columns and their types. |
query | Runs one DuckDB SQL statement and returns the rows. |
list_organizations | The organizations this connection can work in, and which one is current. |
switch_organization | Moves the connection to another of your organizations. |
list_engines | The kinds of database that can be created. |
create_database | Creates a new database. Needs full access. |
When a host connects, the server also hands over a short note of instructions. DuckHouse's tells the model to call list_databases, then describe_schema, before writing any SQL. That one sentence is most of the reason assistants get warehouse questions right the first time: they look before they leap. The MCP documentation lists every tool and what it needs.
Signing in without handing over a password
A remote server needs to know who is asking. The old answer was an API key: a long secret you copy from one place and paste into another. That still works for scripts, but for a person it is clumsy, and pasting a secret into an app is exactly the habit you do not want to build.
MCP's answer is OAuth, the same “Sign in with…” dance you already know from logging into one app with another. Here is how it goes with DuckHouse, from the person's side:
- You give the assistant the server's address, and nothing else.
- The first time it connects, the server answers “sign in first” and tells the host where. The host opens DuckHouse in your browser.
- You sign in and see a consent screen naming the application that is asking. You choose which organization it may use and whether it may only read, or also write, and you approve.
- The host receives a short-lived token and uses it from then on. You never typed a password into the assistant, and there is no key to copy, store or rotate.
Under the hood that is the authorization-code flow with PKCE. DuckHouse's access tokens last an hour, and the refresh tokens that renew them rotate every time they are used and expire after 30 days of disuse. Under Settings → Profile → Connected applications you can switch a connection between read and full access, move it to another organization, or disconnect it, which ends every token it holds at once.
Anything without a person and a browser nearby, such as a nightly script or an agent on a server, uses an organization API key instead. The docs show both.
One question, traced end to end
Here is everything that happens when someone at Pondside, connected through Claude, asks: How did each channel do in September?
First, it finds the database. The model calls list_databases and gets back Pondside's warehouse, its id and that it is running.
Then it reads the map. describe_schema returns every table and view with its columns and types. Underneath, that is one query against the warehouse's own catalog. Here it is, narrowed to the view that matters for this question:
SELECT c.table_schema, c.table_name, t.table_type,
c.column_name, c.data_type, c.is_nullable
FROM information_schema.columns c
JOIN information_schema.tables t
USING (table_catalog, table_schema, table_name)
WHERE c.table_catalog = current_database()
AND c.table_schema = 'marts'
AND c.table_name = 'daily_sales'
ORDER BY c.ordinal_position;Result, 4 rows
| table_schema | table_name | table_type | column_name | data_type | is_nullable |
|---|---|---|---|---|---|
| marts | daily_sales | VIEW | day | DATE | YES |
| marts | daily_sales | VIEW | channel | VARCHAR | YES |
| marts | daily_sales | VIEW | orders | BIGINT | YES |
| marts | daily_sales | VIEW | revenue | DECIMAL(38,2) | YES |
The model sees the same thing as JSON. From names alone it can tell that marts.daily_sales has one row per day per channel, with orders and revenue: exactly the shape this question needs.
Then it asks. The model writes the SQL and calls query:
SELECT channel, sum(orders) AS orders, round(sum(revenue)) AS revenue
FROM marts.daily_sales
WHERE day BETWEEN DATE '2026-09-01' AND DATE '2026-09-30'
GROUP BY channel
ORDER BY revenue DESC;Result, 3 rows
| channel | orders | revenue |
|---|---|---|
| cafe | 5,028 | 49,120 |
| web | 730 | 23,844 |
| subscription | 687 | 15,152 |
Finally, it answers, in English: the café brought in about $49,100 from 5,028 orders, the web shop about $23,800 from 730, and Pond Club about $15,200 from 687 subscription payments. A good assistant offers the obvious follow-up (how does that compare with August, or with last September?) and, asked, shows the SQL it ran.
Notice what did not happen. Nobody exported anything. The model never saw ninety-four thousand café payments. It saw a list of tables, a few column names and three rows, and the warehouse did the arithmetic it is built for. The answer is as fresh as the last sync, not the last export.
The safety model
Letting software run SQL against your business data deserves a careful look at the guard rails. These are DuckHouse's, and each one is enforced by the server rather than by asking the model nicely:
- Read-only by default. The
querytool refuses anything but a plain query unless the call asks for writes, and asking only works on a connection you granted full access. The SQL is parsed before it is sent: writes,COPY,ATTACH, settings changes and a second statement hidden after a semicolon are all refused. On a read connection, no prompt can make it write. - Results are capped at 500 rows. An assistant that asks for a whole table gets the first 500, is told the result was cut, and is nudged to aggregate instead. That protects its context, and your patience.
- No tool deletes a database. Deleting is permanent, so it is left to a person in the dashboard.
- Errors come back as text. A typo in the model's SQL returns DuckDB's error message, which it reads and fixes on the next try, rather than a dead end.
- You always see who is asking. The consent screen names the application and where the authorization will be delivered. Tokens are short-lived, and disconnecting revokes them immediately.
Why your names matter to a model
Go back to the trace. The model chose the right table without being told, because it was called marts.daily_sales and had columns called day, channel, orders and revenue. Point the same assistant at the raw sync tables and it has to work out on its own that Square's amounts are in cents, that Shopify keeps test orders, that a cancelled order still has a total and that the café's clock is not UTC. It might. It might not, and you would not know which from the answer.
That is why part five spent so long on naming and on a thin layer of clean views. Every decision made there once, in SQL, is a decision the model never has to guess at. A well-modeled warehouse is the single biggest thing you can do to make an assistant's answers right, more than any choice of model or any clever prompt. The rule of thumb is simple: if a new colleague could find the answer from the table and column names alone, so can a model.
Now the payoff. Everything in this part works the same whether the host is a laptop or a phone, because the server is remote and the sign-in is a consent screen rather than a config file. In part eight, Pondside's owner connects once on the web, puts the laptop away, and asks the warehouse those three questions from part one, standing at a farmers' market stall.
Further reading
- What is the Model Context Protocol? — the project’s own introduction
- The MCP specification — roles, tools, resources, prompts and transports
- Introducing the Model Context Protocol — Anthropic, November 2024
- Donating MCP and establishing the Agentic AI Foundation — Anthropic, December 2025
- Official MCP support for Google services — Google Cloud, December 2025
- DuckHouse MCP documentation — every client’s setup, the tools and the safety model