Talk to Your Database from Excel - Postgres, DuckDB - via Claude in Excel with MCP
Published: February 21, 2026
I have put up a public MCP server that lets you run SQL queries against two live databases - right from Claude in Excel. No setup, no credentials, no installs. Just connect and ask.
The server sits on top of two cricket databases - about 2 million rows of ball-by-ball data. One on Postgres (Supabase) with ODI records. One on DuckDB with T20 records. Both covering 2013 to 2025.
Each row is a single delivery in a match. So you have the batsman, bowler, runs off bat, extras (wides, no-balls, byes, legbyes), wicket type, player dismissed, venue, batting team, bowling team, innings, season, match date. Ball-by-ball level detail for every ODI and T20 match over 12 years.
You can ask things like "top 20 strikers by total runs, matches, overs faced and run rate per match and per over" Claude figures out the SQL, hits the database, brings back results right into Excel.
You open Claude in Excel, go to Settings > Connectors > Custom Connectors, paste the MCP URL, give it a name, save. Come back to the chat and start asking. That's it.
I have also put up a sample spreadsheet with data pulled from this server and charts built on top of it - link in resources below.
How does the agent know what the data is
This is an important practical point. When Claude connects to the MCP server, how does it know what tables exist, what columns mean, what the data looks like?
In this case I have added a detailed docstring as part of the MCP tool description itself. So when Claude connects, it gets the table name, all column names, data semantics (what each field means), counting rules (the ball field is an over.ball identifier, not a sequential count - overs can have more than 6 deliveries due to wides and no-balls), how runs work (runs_off_bat vs extras), how to check for wickets (both wicket_type and other_wicket_type), player name search tips (use LIKE wildcards with surnames), season format quirks (can be '2023' or '2023/24'). Plus an example query to get it started.
This is enough for a single-table cricket dataset. The agent picks it up and writes correct SQL most of the time without needing additional guidance.
But in real life production setups - where you have 10s or 100s of tables with business logic, complex joins, calculated fields - this docstring approach is not enough. You need a proper semantic layer. That means business definitions for every table and column, relationship mappings between tables, golden queries for common business questions (pre-validated SQL that you know gives correct results), and rules for things like "revenue means net revenue not gross" or "active customer means at least one transaction in last 90 days."
That semantic layer itself becomes a whole operation to build and maintain. How detailed should it be, how do you feed the right context for each query without bloating the prompt, how do you keep it updated as the schema changes. I have built this for client projects and it is real work.
For this public demo server though, the docstring approach works well. Simple schema, clear data semantics, and the agent gets it right.
How it works under the hood
It is a FastAPI server. For Postgres, the connection goes through asyncpg with a connection pool. For DuckDB, it runs through a read-only embedded connection. Both are exposed as API endpoints - /api/query/postgres and /api/query/duckdb. These endpoints are then mounted as an MCP server using Tadata's FastAPI-MCP package. So any MCP-compatible client can connect - Claude in Excel, Claude Code, Claude Desktop, or anything else that speaks MCP.
The server supports two response formats. JSON is the default. TSV is the compact option - uses shortened column headers and is about 70% smaller, which matters when you are working within AI context windows.
Where it stumbles and what I have done about it
If you have read my earlier post on Claude in Excel with MCP, you know the pattern. Claude in Excel has a tendency to pull everything at one shot and then try to write it all to Excel at once. It basically thinks it is Claude Code - dumps the entire result set into its context window, tries to write thousands of cells in one go, then chokes up and collapses.
For this database server I have handled it from the backend itself. Responses are capped at 1,000 rows. If your query returns more, it truncates to the first 1,000 rows and sends back a truncation flag so you know the result is not complete. It does not throw an error - you still get data, just capped.
The assumption is this: if you are querying from Claude in Excel, you are pulling summaries, aggregations, filtered record sets - not dumping a million rows into a spreadsheet. A query like "top 20 run scorers by season" returns 20 rows. "Match summary for all T20s in 2024" might return a few hundred. That is the sweet spot for this setup.
If you need bulk data extraction - full table dumps, millions of rows - this is not the right tool. Use Claude Code or a direct database connection for that.
Even within the 1,000 row cap, if you are pulling 500+ records, you might want to tell Claude to write data in chunks rather than all at once. Something like "pull the data and write it in batches of 100 rows." Otherwise it can still struggle with the writing-to-cells part. The data pull itself is fine - it is the writing to Excel where it gets clumsy with larger sets.
For most analytical queries though - top scorers, averages by team, match summaries, bowling figures, strike rates - results are typically a few dozen rows. That works cleanly with no issues.
A standard test query
Here is the query I use to test the setup:
"Show top 20 strikers by total runs off the bat, matches and overs played and run rate per match and per over. Share that as separate tables. Add a few insightful charts for each."
This is a good test because it requires the agent to write multiple SQL queries (aggregations, computed columns like run rate), create separate result tables in Excel, and then build charts. It exercises the full pipeline - understanding the data, writing correct SQL, presenting results, and visualization. Try this one when you connect - it works reliably.
Avoid queries with specific player name searches as a first test. Name matching can be dicey - some players have initials, some have full first names, some have multiple spellings. Use the LIKE wildcard approach (WHERE striker LIKE '%Kohli%') rather than exact name matches until you know how names are stored.
Security
This is a public server, kept open deliberately for people to try. So I have not put OAuth or role-based access control on it. But the safety basics are all there:
- The Postgres user itself is read-only at the database level
- Every connection sets default_transaction_read_only = on
- DuckDB opens in read_only mode with external access disabled
- SQL validation blocks INSERT, DROP, ALTER, CREATE, COPY, LOAD, ATTACH and about 20 other dangerous keywords - checked as whole words to avoid false positives
- Only SELECT, SHOW, DESCRIBE, EXPLAIN, WITH queries are allowed
- Query timeouts on both databases (30 seconds default)
- Rate limiting at 60 queries per hour per IP
- Row cap at 1,000 rows per query (truncated with flag, not errored)
If you need proper access control - MCP does support OAuth, and Claude's custom connector settings have fields for OAuth Client ID and Client Secret. So in theory you can set up proper authentication with an identity provider like Auth0, add role-based access, control who sees what data. I have not implemented it on this server because it is a public demo. And to be honest, I have not tested the OAuth flow end to end with Claude in Excel yet - there have been some reported issues with OAuth in custom connectors, so this is something I will test and cover separately. For my client work currently, I handle access control with token-based auth at the API level.
On MCP security - the usual reminder
Don't connect to random MCP servers. You are basically running somebody else's code. You never know what an unknown MCP endpoint is doing with your queries or your data.
This server is fully documented with source code on GitHub. You can read every line of the Python code - it is a single file, about 550 lines. If you don't trust using my endpoint directly, clone the repo, inspect it, and deploy on your own infrastructure. Or just test it with the public endpoint first since it is read-only anyway.
Source code and how to replicate
The full source code is on GitHub as a public repo. The README has setup instructions - clone, install, add your Postgres connection string, run. The repo includes the DuckDB file with T20 data ready to go.
It is a single Python file. FastAPI, asyncpg, duckdb, fastapi-mcp, slowapi for rate limiting. Clean and simple - you can read and understand the whole thing in one sitting.
Resources
- Documentation page
- MCP Endpoint: https://db-mcp.tigzig.com/mcp
- API Docs (Swagger)
- Source Code on GitHub
- Sample spreadsheet with charts
Previous posts on Claude in Excel and MCP:
- Power User Guide to Claude in Excel & PowerPoint - 26 Working Tips
- Claude in Excel with MCP Connector - Talk to Your Backends from Inside Excel
- Claude in Excel - Nifty50 Return Distribution Analysis
- Claude in Excel built a 50-chart India Macroeconomic Dashboard from RBI data
- Claude in Excel just one-shotted an XGBoost response model