mcp-data-agent
MCP Data Agent
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.pyis a genuine MCP server, built on the officialmcpPython SDK, exposing 4 tools (list_tables,run_sql_query,get_column_stats,plot_bar_chart) over the standard stdio transport.src/smoke_test_client.pyis a protocol-level test with no LLM involved at all — it launches the server as a real subprocess, connects over stdio, callslist_tools(), and callsrun_sql_querythrough 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.pyis 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
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.
pip install -r requirements.txt pytest
pytest tests/ -vTools exposed by the server
Tool | Purpose |
| Schema introspection |
| Read-only SQL — rejects anything that isn't a |
| Summary stats for |
| 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.pyruns it end to end with no LLM in the loop, and the manual fallback path inmcp_client_agent.pyexercises the same real protocol.Implemented against the current
google-genaiSDK, 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 ownGEMINI_API_KEYto 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_chartStack
Python 3.12 · mcp (official Model Context Protocol SDK) · google-genai ·
SQLite · matplotlib
License
MIT — see LICENSE.