{"slug": "from-plain-english-to-a-live-dashboard-automating-reporting-with-mcp", "title": "From Plain English to a Live Dashboard: Automating Reporting with MCP", "summary": "A developer demonstrates how the Model Context Protocol (MCP) can automate database reporting, allowing users to generate SQL queries from plain-English questions and save them as reusable dashboards. The approach uses a read-only MCP server to keep data safe while grounding AI-generated SQL in the actual schema.", "body_md": "Someone in your Slack asks, \"How many people signed up last week?\" You open a SQL client, write a query you've written a dozen times before, run it, copy the number, and paste it back. A week later, the same question lands in a different channel. Same query, same copy-paste, same five minutes gone.\n\nMultiply that by every \"quick number\" your team asks for — signups, active users, MRR, refunds, top accounts — and reporting quietly becomes a part-time job that nobody signed up for. The knowledge lives in your head and in a folder of `.sql`\n\nfiles nobody else can find.\n\nThe **Model Context Protocol (MCP)** offers a cleaner path. It's an open standard for connecting AI assistants to external systems — including your database — through a consistent, permissioned interface. Instead of the AI guessing at a connection or you pasting credentials into a chat box, an MCP server sits in between and exposes a small set of safe operations: read the schema, run a read-only query, save it, add it to a dashboard. This article walks through that whole loop — plain-English question to living report — and where it can go wrong.\n\nMCP servers expose three kinds of capabilities, and it helps to know which is doing what ([Speakeasy has a clear breakdown](https://www.speakeasy.com/mcp/core-concepts/)):\n\n| Capability | What it is | In a database context |\n|---|---|---|\n| Resources | Read-only data the model can pull in for context | Your table and column definitions — the schema |\n| Tools | Actions the model can invoke | Run a query, save a query, add it to a dashboard |\n| Prompts | Reusable templates for common workflows | \"Build a weekly signups report\" as a repeatable recipe |\n\nThe important part: the AI never touches your database directly. It asks the server for the schema, drafts SQL, and asks the server to run it. Because the query tool is **read-only by design**, a `DELETE`\n\nor `DROP`\n\nthe model dreams up simply gets rejected. The AI explores freely; your data stays intact.\n\nThis is also why schema-awareness matters so much. When the model can read your actual tables and columns as a resource, it stops inventing plausible-but-wrong names like `user.signup_date`\n\nwhen your column is really `users.created_at`\n\n. Grounding the model in the real schema is the single biggest thing that keeps generated SQL honest.\n\nHere's the shape of an interaction. Assume a typical SaaS database with `users`\n\n, `subscriptions`\n\n, and `events`\n\ntables. You type:\n\n\"How many users signed up in the last 7 days, grouped by day?\"\n\nThe assistant fetches the schema, sees `users(id, email, created_at, plan)`\n\n, and produces:\n\n```\nSELECT\n  DATE(created_at) AS signup_day,\n  COUNT(*)         AS signups\nFROM users\nWHERE created_at >= NOW() - INTERVAL '7 days'\nGROUP BY DATE(created_at)\nORDER BY signup_day;\n```\n\nYou didn't specify the column name, the date function, or the grouping. The model inferred them from the schema. That's the difference between an AI that's guessing and one that's reading.\n\nThe generated SQL is a draft, not gospel. The advantage of the read-only setup is that running it to check is completely safe. The result comes back:\n\n| signup_day | signups |\n|---|---|\n| 2026-08-20 | 41 |\n| 2026-08-21 | 38 |\n| 2026-08-22 | 22 |\n| 2026-08-23 | 19 |\n| 2026-08-24 | 54 |\n| 2026-08-25 | 47 |\n| 2026-08-26 | 29 |\n\nGlance at it. Do the weekends dip the way they usually do? Is the total in the right ballpark? A thirty-second sanity check here saves you from confidently reporting a number that's off because \"signup\" quietly meant \"row created, including invited-but-not-activated users.\" More on that trap below.\n\nThis is the step that breaks the treadmill. Once the query is correct, save it with a name and description through the server's save tool:\n\n\"Save that as\n\nWeekly Signups by Day.\"\n\nNow it's a named, reusable report. Next week nobody rewrites it — they ask to run *Weekly Signups by Day* and get fresh numbers against live data. You've turned a throwaway query into an asset the whole team can call by name. This is also where a **prompt** template earns its keep: \"produce a signups report for the last N days\" becomes a recipe you invoke, not SQL you retype.\n\nThe last move is to make the report ambient so people stop asking at all. Add the saved query as a dashboard tile:\n\n\"Add\n\nWeekly Signups by Dayto theGrowthdashboard as a bar chart.\"\n\nChain a few of these together and you've assembled a real reporting surface — signups, activation rate, MRR, churn — entirely from plain-English requests, each one a verified, saved, named query underneath. Managed MCP servers implement exactly this loop; [Draxlr's](https://docs.draxlr.com/docs/mcp-server) is one example that connects over OAuth and is read-only (SELECT only), with tools to list databases, fetch schema, run and save queries, and build dashboards. The pattern is the same regardless of which server you use.\n\nSay you want a small revenue snapshot. You ask for three things in a row.\n\nNew MRR from subscriptions started this month:\n\n```\nSELECT SUM(monthly_amount) AS new_mrr\nFROM subscriptions\nWHERE status = 'active'\n  AND started_at >= DATE_TRUNC('month', NOW());\n```\n\nTop 5 plans by active subscribers:\n\n```\nSELECT plan, COUNT(*) AS subscribers\nFROM subscriptions\nWHERE status = 'active'\nGROUP BY plan\nORDER BY subscribers DESC\nLIMIT 5;\n```\n\nRefunds issued in the last 30 days:\n\n```\nSELECT COUNT(*) AS refunds, SUM(amount) AS refunded_total\nFROM events\nWHERE type = 'refund'\n  AND created_at >= NOW() - INTERVAL '30 days';\n```\n\nSave all three, drop them on a \"Revenue Health\" dashboard, and you've built in five minutes what used to be a recurring manual chore. The AI wrote the SQL; you supplied the judgment about what's worth measuring.\n\n**Treating the first answer as the final answer.** LLMs can produce SQL that runs cleanly but answers a subtly different question than you asked. Always read the query and eyeball the result before you save it or share the number.\n\n**Fuzzy metric definitions.** The word \"active\" can mean logged-in-this-week, has-a-paid-plan, or has-any-event-ever. If your team hasn't agreed on definitions, the AI will pick one for you — and it may not be the one your board is using. Industry write-ups on AI reporting consistently flag [ungoverned metric definitions](https://improvado.io/blog/ai-report-generation) as the top source of \"hallucinated\" analytics: the number is real, but the definition behind it is wrong. Where you can, point the model at a governed view or a semantic layer rather than raw tables, so \"revenue\" means one thing everywhere.\n\n**Granting more access than you need.** The whole security benefit collapses if you connect the AI with a read-write account. Use a read-only role, and prefer a setup where the server enforces SELECT-only regardless of the credential. The AI should be able to *read* everything it's allowed to and *change* nothing.\n\n**No audit trail.** If you can't later see which queries the AI ran, you can't debug a wrong number or satisfy a compliance question. Favor an approach where access is centralized and queries are logged, not scattered across personal database clients.\n\n**Skipping the schema step.** If the model isn't given the real schema, it falls back to guessing table and column names. That's where hallucinated columns come from. Schema-first, always.\n\nThe reporting treadmill isn't a SQL problem — it's a *reuse* problem. You already know how to write the query; the pain is writing it again and again and keeping it somewhere findable. MCP addresses that by putting a safe, schema-aware, read-only interface between the AI and your database, then letting you promote good queries into saved reports and dashboard tiles.\n\nThe loop is small and repeatable: ask in plain English, verify the generated SQL against live data, save the query with a clear name, and pin it to a dashboard. Keep humans in the verification seat, nail down your metric definitions, and never hand the AI more than read access. Do that and \"quick number\" requests stop interrupting your day — they answer themselves.\n\nHow does your team handle recurring reporting today — a folder of saved queries, a BI tool, or a lot of copy-paste? If you've wired an AI assistant to your database through MCP, I'd love to hear what worked and what surprised you. Drop a comment with the setup you're using.\n\n*Sources: MCP core concepts — Speakeasy, What is MCP? A Data Person's Guide to Agentic Analytics — MotherDuck, AI Report Generation guide — Improvado.*", "url": "https://wpnews.pro/news/from-plain-english-to-a-live-dashboard-automating-reporting-with-mcp", "canonical_source": "https://dev.to/vivekdraxlr/from-plain-english-to-a-live-dashboard-automating-reporting-with-mcp-5dl7", "published_at": "2026-08-27 04:00:23+00:00", "updated_at": "2026-08-27 04:18:15.746959+00:00", "lang": "en", "topics": ["developer-tools", "ai-tools", "natural-language-processing"], "entities": ["MCP", "Speakeasy"], "alternates": {"html": "https://wpnews.pro/news/from-plain-english-to-a-live-dashboard-automating-reporting-with-mcp", "markdown": "https://wpnews.pro/news/from-plain-english-to-a-live-dashboard-automating-reporting-with-mcp.md", "text": "https://wpnews.pro/news/from-plain-english-to-a-live-dashboard-automating-reporting-with-mcp.txt", "jsonld": "https://wpnews.pro/news/from-plain-english-to-a-live-dashboard-automating-reporting-with-mcp.jsonld"}}