Orders DB MCP Server

Orders DB MCP Server

Enables natural language querying of a customer and orders database through read-only MCP tools for finding customers, listing orders, and generating revenue summaries.

Category
Visit Server

README

Orders DB — MCP server

"Which customers spent more than $500 last quarter?"

That question takes someone on your team about twenty minutes: open the admin panel, filter, export, pivot, read the number back. It gets asked every week, usually by the person least equipped to run the query.

This is what removing that looks like. An MCP server sits between Claude and your database, and the question gets answered in about four seconds — from your real data, not from the model guessing.

Claude answering a revenue question through the MCP server


What it does

Three read-only tools over a small customer and orders database:

Tool What it answers
find_customer Who is this person or company, and what are they worth to us?
list_orders What transactions happened in this window, filtered how I want?
revenue_summary What are the totals, grouped by month, plan, product, country, or customer?

The database here is generated sample data. In a client engagement this points at the real system instead — Postgres, an internal REST API, a SaaS admin backend — and the tools get named after the questions that team actually asks.

Asking it who the high-value customers were, and watching it pick the tool, run the query, and total the results:

Claude identifying high-value customers through the MCP server

Why it is built this way

An MCP server is infrastructure. Most of the work is the part nobody sees until something breaks:

  • The connection is opened read-only. A bug in a tool cannot write to customer data. This is enforced at the SQLite layer, not by convention.
  • Every query is parameterised. No string interpolation into SQL. A customer named Robert'); DROP TABLE is just a customer.
  • Results are capped at 100 rows, and the cap announces itself. A model asking for "all orders" should not pull 200,000 rows into a context window and blow the budget.
  • Bad input comes back as readable text. group_by="quarter" returns a message listing the valid options, so Claude can correct itself and retry instead of failing the conversation.
  • Logging goes to stderr. stdout carries the MCP protocol; writing to it breaks the transport. This is the single most common way a first MCP server fails silently.

Try it

Requires Python 3.10 or newer.

python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
.venv/bin/python seed_db.py        # creates demo.db: 40 customers, ~210 orders
.venv/bin/python smoke_test.py     # verifies the server over the MCP protocol

Calling the venv binaries by path instead of activating the environment is deliberate: it works identically on every shell and cannot be forgotten halfway through a session. If python3 -m venv fails, install the package Debian splits out — sudo apt install python3.12-venv.

The virtual environment is not optional on Debian, Ubuntu, and recent macOS builds: those ship an externally managed Python and pip install refuses to touch it (PEP 668). Do not reach for --break-system-packages to get around it — that is how you end up debugging someone's broken system Python later.

Expected output:

Connected. Tools exposed: find_customer, list_orders, revenue_summary

[ok   ] find_customer({'query': 'Cobalt'}) -> 2 customer(s) matched 'Cobalt':
[ok   ] revenue_summary(...) -> Completed revenue by plan, 2026-01-01 to 2026-06-30:
[ok   ] list_orders(...) -> 18 order(s) between 2026-06-01 and 2026-06-30:
[error] revenue_summary({... 'group_by': 'quarter'}) -> group_by must be one of
        month, plan, product, country, customer, got 'quarter'.

That last line is not a failure. It is the error path working: invalid input returns a message the model can act on.

Connect it to Claude Desktop

Add this to your claude_desktop_config.json. Both paths must be absolute, and command must point at the Python inside your virtual environment — not the system python3, which does not have the SDK installed:

{
  "mcpServers": {
    "orders-db": {
      "command": "/absolute/path/to/mcp-demo/.venv/bin/python",
      "args": ["/absolute/path/to/mcp-demo/server.py"]
    }
  }
}

realpath .venv/bin/python prints the exact path to use.

On WSL: Claude Desktop runs on Windows and cannot resolve a /mnt/... path, so pointing command straight at the Linux Python fails with no error message. Bridge through wsl.exe instead — Windows launches WSL, WSL launches the right Python:

{
  "mcpServers": {
    "orders-db": {
      "command": "wsl.exe",
      "args": [
        "-e",
        "/mnt/d/path/to/mcp-demo/.venv/bin/python",
        "/mnt/d/path/to/mcp-demo/server.py"
      ]
    }
  }
}

This is the second most common way a first MCP server fails: the config points at a Python that cannot import mcp, the process dies during startup, and the client shows the server as unavailable with no explanation. If a server will not connect, run the command and args from that config by hand in a terminal — the import error shows up immediately.

  • macOS — ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows — %APPDATA%\Claude\claude_desktop_config.json

Restart Claude Desktop. The three tools appear in the tools menu.

The same server works with Claude Code, Cursor, and any other MCP client — that is the point of the protocol being open.

When it will not connect

Three failure modes, all of which are silent. The client shows the server as unavailable and nothing explains why.

1. The config is not where you think it is (Windows). The official Windows installer uses MSIX packaging, which runs the app in a container with a virtualised filesystem. The app reads its config from inside that container, not from %APPDATA%\Claude\. The "Edit Config" button in Developer settings can open the non-virtualised path — a different file from the one actually loaded. The real path:

%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json

The package identifier can differ. Find it with:

Get-ChildItem "$env:LOCALAPPDATA\Packages" -Filter "Claude*" | Select-Object Name

2. The JSON is invalid. One missing comma and the entire file is discarded — every server, not just the broken entry. mcpServers belongs at the top level, as a sibling of the other root keys, not nested inside one of them. Validate before restarting:

Get-Content <config path> -Raw | ConvertFrom-Json | Select-Object -ExpandProperty mcpServers

3. The command points at the wrong Python. Whatever ends up executing has to be the venv Python. python3 on its own starts an interpreter without the SDK, the process dies during startup, and the client reports the server as unavailable.

To isolate which of the three it is, run the command and args from your config by hand in a terminal. If the server prints its startup log and then hangs waiting on stdin, it works and the problem is the config. If it throws, the error is right there.

Questions worth asking it

Which customers spent more than $500 last quarter?
Show me revenue by plan for the first half of 2026.
What does Cobalt Systems buy from us, and how much are they worth?
Compare March and April revenue, and tell me what drove the difference.
Which product line brings in the most money?

The last two are the interesting ones. They need more than one tool call and some reasoning on top of the results — which is the whole reason to hand Claude a tool instead of writing a dashboard.

Files

server.py       the MCP server: three tools, ~230 lines
seed_db.py      generates the sample database, deterministic seed
smoke_test.py   client that speaks the protocol, verifies tools and errors

Built by Bryan Mena Suárez — Kubernetes and cloud infrastructure engineer, CKA certified, previously Azure Kubernetes escalation at Microsoft. Available for MCP server and AI automation work.

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured