A demonstration of prompt-engineered structured tool calling on a model with zero native tool-calling support (Gemma3:4b), wired to a PostgreSQL database via a secure, pre-defined tool layer.
Gemma3:4b, a small open source model, has no native tool-calling support. Ollama returns a 400 error if you attempt it directly.
This project gets around that constraint entirely through prompt design: no fine-tuning, no model modification. The agent reliably emits structured tool calls from plain text output, which are intercepted and parsed by a manual tool loop before being dispatched to the database.
Getting a small model to do this consistently i.e. correct tool selection, correct parameters, correct format -- is the hard part. That's what this project explores.
A café owner can ask questions like:
- "How many sales did we have last week?"
- "What are our most popular tables?"
- "Which days of the week are our busiest?"
And get real answers from a PostgreSQL reservations database without the LLM ever touching the database directly, and without the user writing a single line of SQL.
The LLM has no database access. It can only call named tools defined in tools.yaml, executed by Google's MCP Toolbox against the database. The LLM cannot perform arbitrary SQL. The boundary is enforced by the tool definitions themselves, not by blind trust in the model.
The agent handles the tool loop itself. It calls the toolbox directly via SDK, parses structured tool calls from the model's text output, dispatches them, and injects results back into context. This is a standard agentic loop, not MCP protocol communication.
Token growth is intentionally observable. Every session is logged to logs/sessions.log with per-turn token counts and full tool call results. Prompt tokens grow from ~400 on turn 1 to ~3,300 by turn 8 as tool results accumulate in context. This growth is a documented research outcome, not an oversight.
Three tools are deliberately exposed, enough to demonstrate the agent loop, and measure model behaviour without scope creep:
get-sales-summary— total orders and revenue for a given period (day, week, month, year)get-popular-tables— café tables ranked by reservation count over the last 7 daysget-busiest-days— days of the week ranked by total order revenue
| Component | Role |
|---|---|
| PostgreSQL | Stores café tables, reservations, and sales data |
| Google MCP Toolbox | Executes predefined SQL tool calls against the DB |
| MCP Inspector | Web-based dashboard for testing and debugging tools |
| Docker / Docker Compose | Orchestrates the full stack locally |
| Ollama + Gemma3:4b | Local LLM runtime — no API key required |
git clone https://github.com/BeckerHanne/MCP-Agent-Demo
cd MCP-Agent-Demoollama pull gemma3:4b
ollama servedocker compose up --build -dNavigate to http://localhost:6274 and connect to http://toolbox:5010/mcp using HTTP or SSE transport.
docker exec -it mcp-agent-demo-cafe-app-1 python agent.pyStart with: "What tools are available?" to verify the connection.
docker logs -f mcp-agent-demo-toolbox-1docker compose down # Preserves database state
docker compose down -v # Wipes database for a clean runTool listing occasionally returns JSON. When asked to list available tools, Gemma3:4b sometimes returns a JSON array instead of plain text despite system prompt instructions. This is a known small model behaviour.
Year and month summaries return identical results. All seed data falls within the last 30 days. Gemma occasionally flags this as an error; it is not.
Wednesday is hardcoded as the busiest day via fixed seed dates. Running docker compose down -v reapplies seed data correctly.
Token optimization via result scoping. Currently each tool injects its full result set into the context window on every call, which is the primary driver of prompt token growth. The next step would be to add LIMIT parameters to tools get-popular-tables and get-busiest-days, combined with a post-processing layer in the agent that strips redundant fields before injecting results into context. This would aim to reduce per-turn token consumption without changing the core prompt engineering approach. Implementation note: Google MCP Toolbox requires careful handling of integer parameters.
- Google MCP Toolbox
- Model Context Protocol
- PostgreSQL · Docker · Ollama