Skip to main content
Glama
dhandashreya

mcp-data-agent

by dhandashreya
README.md
# MCP Data Agent

[![CI](https://github.com/dhandashreya/mcp-data-agent/actions/workflows/ci.yml/badge.svg)](https://github.com/dhandashreya/mcp-data-agent/actions/workflows/ci.yml)
![License](https://img.shields.io/badge/license-MIT-blue.svg)

A real Model Context Protocol (MCP) server exposing data-analyst tools over a
sales database, plus an LLM agent (Gemini) that discovers those tools at
runtime and decides which to call to answer a question — the actual point of
MCP being that the tool definitions live on the server, not hardcoded into
the agent.

## Why this is a real MCP implementation, not a mock

- [`src/mcp_server.py`](src/mcp_server.py) is a genuine MCP server, built on
  the official `mcp` Python SDK, exposing 4 tools (`list_tables`,
  `run_sql_query`, `get_column_stats`, `plot_bar_chart`) over the standard
  stdio transport.
- [`src/smoke_test_client.py`](src/smoke_test_client.py) is a protocol-level
  test with **no LLM involved at all** — it launches the server as a real
  subprocess, connects over stdio, calls `list_tools()`, and calls
  `run_sql_query` through the actual MCP wire protocol. This is what proves
  the server works, independent of whether the agent on top of it works.
- [`src/mcp_client_agent.py`](src/mcp_client_agent.py) is the agent: it lists
  the server's tools, converts their JSON schemas directly into Gemini
  function declarations (`parameters_json_schema=tool.input_schema` — no
  manual schema translation), and runs the standard tool-calling loop: ask
  the model → execute any requested tool call via the real MCP session →
  feed the result back → repeat until the model gives a final answer.

## Requires Python 3.10+

The `mcp` package doesn't support Python 3.9. If your default `python` is
older, use `py -3.12` (or whichever 3.10+ interpreter you have) for every
command below.

## Pipeline

```bash
pip install -r requirements.txt
python src/generate_data.py          # -> data/sales.db (3,000 synthetic orders)
python src/smoke_test_client.py      # protocol-only sanity check, no LLM
python src/mcp_client_agent.py "Which category has the highest revenue?"
```

Without `GEMINI_API_KEY` set, `mcp_client_agent.py` runs a **manual fallback**:
it lists the tools discovered from the live server and calls one directly,
so the MCP plumbing is demonstrable with zero API keys. With a key (copy
`.env.example` to `.env`), it runs the full agent loop.

## Tests

`tests/test_pipeline.py` calls the server's tool functions directly (schema
introspection, SQL rejection of non-SELECT statements, stats), and — the
real proof this is a working MCP implementation — runs
`smoke_test_client.py`, which launches the server as an actual subprocess
and talks to it over the real stdio protocol. No API key needed, so this
runs in CI on every push, on Python 3.12.

```bash
pip install -r requirements.txt pytest
pytest tests/ -v
```

## Tools exposed by the server

| Tool | Purpose |
|---|---|
| `list_tables` | Schema introspection |
| `run_sql_query` | Read-only SQL — rejects anything that isn't a `SELECT` before it reaches the database |
| `get_column_stats` | Summary stats for `quantity`, `unit_price`, or `revenue` |
| `plot_bar_chart` | Aggregates by region/category and saves a PNG |

## Verified vs. not independently verified

- **Verified**: the MCP server and protocol wiring (tool discovery, tool
  execution over stdio) — `smoke_test_client.py` runs it end to end with no
  LLM in the loop, and the manual fallback path in `mcp_client_agent.py`
  exercises the same real protocol.
- **Implemented against the current `google-genai` SDK, not run against a
  live key in this environment**: the Gemini tool-calling loop itself. The
  function-declaration and function-response types were checked directly
  against the installed SDK, but the actual multi-turn call requires an API
  key this environment doesn't have. Run it with your own `GEMINI_API_KEY`
  to exercise that path.

## Project structure

```
data/     generated sales.db
src/      mcp_server, smoke_test_client, mcp_client_agent, generate_data
reports/  charts saved by plot_bar_chart
```

## Stack

Python 3.12 · `mcp` (official Model Context Protocol SDK) · `google-genai` ·
SQLite · matplotlib

## License

MIT — see [LICENSE](LICENSE).