Hands-on learning and demo material: you run a small Olympic data stack in Docker, expose it through Google MCP Toolbox for Databases, then drive the same tools from a Python agent (OpenRouter) and a demo notebook—so you can see the same ideas in the UI, in logs, and in code.
From the repo root:
docker compose up --buildThat brings up PostgreSQL and MongoDB, runs a one-shot seed (downloads public CSV slices from Hugging Face, loads both databases, then exits), and starts Toolbox on http://127.0.0.1:5050 (host 5050 → container 5000). Copy .env.example to .env if you want local overrides.
Detached (no log stream on your terminal): use docker compose up --build -d. Containers keep running in the background; follow logs only when you want, e.g. docker compose logs -f toolbox or docker compose logs -f for all services. docker compose ps shows status.
- Postgres:
localhost:5432— default user / password / database:olympics. - MongoDB:
localhost:27017— databaseolympics. - Toolbox: set
TOOLBOX_BASE_URL=http://127.0.0.1:5050for Python (adjust if you change the published port indocker-compose.yml).
Re-seeding is skipped if data already exists. Clean slate: docker compose down -v then docker compose up --build again.
With the stack up and seeded:
bash scripts/tests/test_databases.shFor a full reset plus sample queries: bash scripts/tests/verify_stack.sh.
Python 3.12+ recommended. From the repo root, create a virtual environment, activate it (so the next steps use this interpreter), and install the project in editable mode so import mcp_tutorial works like any other package (no PYTHONPATH):
python3.12 -m venv .venv
# macOS / Linux:
source .venv/bin/activate
# Windows cmd: .venv\Scripts\activate.bat
# Windows PowerShell: .venv\Scripts\Activate.ps1
pip install -U pip
pip install -e .That reads dependencies from pyproject.toml and registers the mcp_tutorial package in editable mode.
For Jupyter later, register a kernel from this same venv, e.g.
python -m ipykernel install --user --name=mcp-tutorial --display-name="MCP tutorial".
Leave the venv activated (same shell, or point your IDE terminal at it) for steps 4 and 5.
With the venv from step 3 still active, set OPENROUTER_API_KEY (see .env.example) if you have not already, then:
python scripts/run_agent_demo.pyThis runs two cross-database questions against OpenRouter with Toolbox’s combined toolset. Watch INFO lines for when each chat request and each tool starts and finishes—handy if something feels slow.
Open notebooks/demo_mcp_toolbox.ipynb with the same venv as the Jupyter kernel (step 3), Docker still running (step 1), and OPENROUTER_API_KEY set (e.g. in repo-root .env). Run cells in order from the top.
That notebook is the teaching path alongside the CLI demo:
- Compose + YAML — short explanation of how Toolbox is wired in
docker-compose.ymland how merged files undertoolbox/config/tools/define tools and thecombinedtoolset. - Tool-calling loop in cells — imports, mapping Toolbox tools to OpenAI
tools=, OpenRouter client, one completion at a time, then a full loop—implemented in the notebook as small steps (same ideas asrun_chat_with_toolsinmcp_tutorial.agent, not a re-export of that function). - Two cross-database runs — Example A (relational facts first, bios second) and Example B (biography search first, Postgres cross-check). Prompts for A/B are defined next to those cells; Example B uses a notebook-only simplified prompt (one random sport phrase, no hit-index nudge). The terminal demo still uses
mcp_tutorial.prompts/build_prompt_b()for its second prompt.
For a quicker notebook that only calls run_chat_with_tools, see notebooks/simple_tool_calls.ipynb.
| Piece | Role |
|---|---|
pyproject.toml |
Declares the installable mcp_tutorial package (under src/mcp_tutorial/) and its dependencies. |
docker-compose.yml |
Postgres, Mongo, seed, Toolbox (inline comments describe each service). |
toolbox/config/tools/ |
Merged YAML: sources, SQL/Mongo tools, toolsets (combined, postgres_only, mongo_only), prompts. Numbered filenames set merge order. |
src/mcp_tutorial/ |
Tutorial package mcp_tutorial: run_chat_with_tools, Settings. Installed with pip install -e . in step 3. |
scripts/run_agent_demo.py |
Terminal walkthrough of two prompts. |
notebooks/demo_mcp_toolbox.ipynb |
Demo notebook: Compose/YAML context, step-by-step OpenRouter + Toolbox loop in cells, two cross-database examples. |
notebooks/simple_tool_calls.ipynb |
Minimal notebook: loads settings and calls run_chat_with_tools for the same two prompts. |
scripts/seed_databases.py |
Logic the seed container uses to fill the DBs. |
db/postgres/, db/mongo/ |
Schema and init helpers for the containers. |
Data (high level): Postgres holds core Olympic tables (countries, games, athletes, events); Mongo holds biography-style text and wide event rows—both fed from the public dataset SVeldman/126-years-olympic-results during seed.
Toolbox in the browser: http://127.0.0.1:5050/ui — try tools and parameters by hand. MCP (Streamable HTTP): http://127.0.0.1:5050/mcp — e.g. MCP Inspector quickstart (npx @modelcontextprotocol/inspector). Python uses the base URL only (no /mcp suffix).
Cross-database prompts the repo is built around: relational slice (medals, NOC, year, optional sport fragment) then Mongo biographies by athlete_id; or Mongo text search on biographies then Postgres checks for the same athlete.
Other OpenAI-compatible APIs: set OPENROUTER_BASE_URL and OPENROUTER_MODEL instead of OpenRouter defaults (see .env.example).
After edits to scripts/seed_databases.py, rebuild the seed image when re-running seed: docker compose run --build --rm seed.
Official docs: MCP Toolbox for Databases (architecture and features) | Toolbox YAML configuration | MCP quickstart | Python toolbox-core SDK (sync usage) | OpenRouter API | OpenAI function calling (tools) | OpenAI Python library.