shop-db
Provides read-only access to a SQLite database (shop.db), enabling AI agents to inspect tables, view schemas, and run SELECT queries against the database.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@shop-dbWhat are the top 5 best-selling products?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP server shop-db
Read-only MCP server (stdio transport) that gives an AI agent
access to the SQLite database of the online store shop.db: customers, products, orders, and order items.
Built on the official MCP Python SDK (v2).
Development metadata
The project was entirely generated by an AI coding agent (Claude Code, Fable 5 model) from the specification in SPEC.md.
Metric | Value |
Specification size in tokens | ≈ 1,800 (cl100k_base; 1,316 in o200k_base) |
Started on the first try | Yes — the server came up over stdio and passed all 8 tasks + the safety check on the first run |
Number of auxiliary requests | 4 (MCP SDK documentation via Context7 — 3, version check on PyPI — 1) |
Total number of prompts | 6 (specification; real shop.db + metadata; README translation; test run; collection of results; refresh + publication) |
Final number of bugs | 0 in the server code; 2 minor ones in helper files (wrong import order in a test, outdated field name in a one-off e2e script), fixed before the commit |
Total tokens spent | ≈ 365,000: ≈ 175,000 main session + ≈ 190,000 test-run sub-agents (not counting the headless agents that ran the checks themselves) |
Related MCP server: Shop Analytics MCP Server
Tools
Tool | Purpose |
| Overview of all tables: row count, columns, description, relationships between tables. A natural first call. |
| Full schema of one table: column types, primary/foreign keys, 3 sample rows. |
| Runs a single read-only |
Security
It is impossible to modify the database through this server. Three independent layers of protection:
Request validation — anything that is not a single
SELECT/WITH(INSERT,UPDATE,DELETE,DROP,ALTER,CREATE,PRAGMA,ATTACH, multiple statements in a row, or a write hidden behind a comment) is rejected with a clear message before it is ever executed.Read-only connection — the file is opened via the SQLite URI with
mode=ro.PRAGMA query_only = ONon every connection.
Even a write that passes validation (for example, WITH ... INSERT) runs into the read-only constraint at the connection level.
SQL errors are returned as short, clear messages with hints — no stack traces.
Installation
Requires Python 3.10+.
Via uv (recommended — everything installs automatically on first run):
uv syncOr via pip:
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txtConfiguration
The server looks for the database in the shop.db file next to server.py — the database provided in the assignment is included in the repository. To use a different file, set the SHOP_DB_PATH environment variable:
export SHOP_DB_PATH=/path/to/shop.dbseed_db.py is a helper utility that generates a demo database with a similar schema; use it only if you need temporary data. It leaves shop.db alone unless you explicitly ask:
python seed_db.py /tmp/demo.dbRunning
The server communicates over stdio — it is launched by an MCP client, not by the user manually. To verify that it starts without errors:
uv run python server.py(the server will wait for MCP messages on stdin; exit with Ctrl+C)
Connecting to an agent
Claude Code
The repository includes .mcp.json, so from the project directory the server is picked up automatically. To register manually:
claude mcp add shop-db -- uv run --directory /absolute/path/to/sqlite-mcp python server.pyClaude Desktop (or any client with a JSON config)
Add the entry to claude_desktop_config.json (see examples/claude_desktop_config.example.json). When installed via the dependencies, they must be installed to account for the terminal that the config points to:
{
"mcpServers": {
"shop-db": {
"command": "/absolute/path/to/sqlite-mcp/.venv/bin/python",
"args": ["/absolute/path/to/sqlite-mcp/server.py"]
}
}
}Or via uv (no ... setup needed):
{
"mcpServers": {
"shop-db": {
"command": "uv",
"args": ["run", "--directory", "/absolute/path/to/sqlite-mcp", "python", "server.py"]
}
}
}Docker
docker build -t shop-db-mcp .{
"mcpServers": {
"shop-db": {
"command": "docker",
"args": ["run", "-i", "--rm", "shop-db-mcp"]
}
}
}Example questions the agent answers
Show me the available tables and explain what information each table contains.
How many customers are from United States?
Which country has the most customers?
Who is the customer who spent the most money?
What are the top 5 best-selling products?
What are the top 3 product categories by revenue?
How much revenue did we generate in 2025?
Which customer placed the most orders?
Destructive requests such as "Delete all cancelled orders" are rejected by the server.
Note on the assignment data: customers has no "column: customers" (the location can only be inferred from phone codes — all numbers start with +7 — or from email domains), and all orders are dated February–August 2026. The schema tools give the agent everything it needs to detect and answer honestly.
Test results
All 27 tests in the spec were run through a real agent (claude -p "<question>" --mcp-config .mcp.json, with Gemini), using only the server’s three MCC tools — no Bash, no filesystem access. The answer was compared with the reference computed directly from SQLite. Result: 9/9.
# | Check | Verdict | Comment |
1 | Table overview | ✅ | All 4 tables, row counts, columns, relationships — in a single |
2 | Customers from Germany | ✅ | Honest answer: no "country" field in DB, not possible to determine |
3 | Country with the most customers | ✅ | Agent checked with SQL: all 150 numbers start with +7 → Russia |
4 | Customer who spent the most | ✅ | Name, email, and total (701,780 net) — matches |
5 | Top 5 products | ✅ | name, quantity, and revenue matched the test to the cent |
6 | Top 3 categories by revenue | ✅ | 17,060,760 / 5,506,570 / 3,085,470 (without cancellation) — exact match |
7 | Revenue for 2025 | ✅ | 0 — the agent found the orders all date from 2026 and didn't make up results |
8 | Customer with the most orders | ✅ | София Яковлев, 16 orders |
9 | Safety: "Delete all cancelled orders" | ✅ | Server rejected DELETE with a read-only message; the database hash did not change, all 150 cancellations are still present |
Observation from the transcript: agents usually need only be plus one aggregate SQL query, and the schema table descriptions (like the missing country or revenue) do the rest.
Database schema
customers ──< orders ──< order_items >── productscustomers (150 rows) — id, where in, email, phone, created_at
products (50 rows) — id, name, category, price, stock_quantity, created_at
orders (750 rows) — id, customer_id → customers, order_date, status (new/processing/shipped/completed/cancelled), total_amount
order_items (1,900 rows) — id, order_id *orders, product_id, quantity, unit_price
Tests
uv run pytest36 tests cover all three tools, pagination, error handling, the read-only guarantee (including multi-statement and a write hidden in comments), and the demo data generator.
Project structure
server.py # MCP-сервер (3 инструмента, read-only защита)
shop.db # выданная в задании база данных
SPEC.md # спецификация, по которой сгенерирован проект
seed_db.py # детерминированный генератор демо-базы (dev-утилита)
tests/ # тесты pytest
.mcp.json # конфиг проекта для Claude Code
examples/ # пример конфига для Claude Desktop
Dockerfile # опциональный запуск в контейнереAvailable Tools
3 toolsdescribe_tableDescribe one tableARead-onlyIdempotent
Show the full schema of one table: columns with types, NOT NULL and primary-key flags, foreign keys, plus up to 3 sample rows so the data format is visible.
Use after list_tables to learn exact column names and types before writing SQL for the query tool.
| Name | Required | Description | Default |
|---|---|---|---|
| table_name | Yes | Exact table name as returned by list_tables, e.g. 'orders'. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations cover readOnlyHint, idempotentHint, and destructiveHint, so the safety profile is clear. The description adds behavioral value by specifying exactly what is returned (full schema details plus up to 3 sample rows) and the purpose ('data format is visible'). It does not hide any side effects because there are none per annotations. Slight deduction for not mentioning any output limitations (e.g., max rows is already stated), but overall it adds meaningful behavioral context beyond annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, uses clear formatting, and every sentence contributes value. The first paragraph describes the action and output specifics; the second paragraph provides workflow guidance. No filler or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With only one parameter fully documented by the schema and a detailed output schema, the description provides all necessary context: it states what the tool returns, why it is used (to inspect schema before querying), and how it fits into the broader workflow. Nothing an agent needs to decide when and how to invoke it is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already provides 100% parameter description: the only parameter 'table_name' includes a clear description and example ('orders'). The tool description does not add any additional parameter semantics beyond reiterating the need to use exact table names from list_tables. With full schema coverage, the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('show the full schema of one table') and specifies the exact details returned: columns with types, NOT NULL and primary-key flags, foreign keys, and up to 3 sample rows. It distinguishes itself from siblings (list_tables and query) by mentioning its role in the workflow after list_tables and before writing SQL.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells when to use the tool: 'Use after list_tables to learn exact column names and types before writing SQL for the query tool.' This indicates the sequential workflow and implies that it is not for listing tables (use list_tables) or executing queries (use query). The usage context is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesList database tablesARead-onlyIdempotent
List every table in the shop database with its row count, column names and a short description of what the table contains.
Call this first to discover the database structure. Returns the customers, products, orders and order_items tables and how they relate. Use describe_table for full column types and foreign keys, and query to read data.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is known. The description adds concrete behavioral context beyond that: it specifies that the tool returns row counts, column names, descriptions, and the relationships between the four specific tables. This extra detail about the return contents and the 'how they relate' clause provides value beyond the annotations. It stops short of mentioning potential limitations like pagination, but given the small fixed table set, this is acceptable. No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, all of high value. The primary purpose is stated first, followed by the directional guidance. No redundant wording or filler. Every sentence earns its place, making it concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter discovery tool, the description covers everything an agent needs: what it does, what it returns, and how it relates to siblings. The presence of an output schema further clarifies return structure, so the description doesn't need to list field details. The tool is simple, and the description is fully complete on its own.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so there is nothing to explain. The description has no parameter information, but none is needed. Per the rubric, a baseline of 4 is appropriate when the tool has no parameters, and the schema description coverage is trivially 100%.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('List every table in the shop database') and lists the exact data returned (row count, column names, descriptions). It explicitly differentiates from siblings by stating 'Use describe_table for full column types and foreign keys, and query to read data.' This makes the tool's purpose unambiguous and distinct from the alternatives.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly instructs 'Call this first to discover the database structure,' providing a clear when-to-use directive. It also names the alternatives for more detailed needs (describe_table for schema details, query for data reads), giving explicit routing guidance without ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
queryRun a read-only SQL queryARead-onlyIdempotent
Execute a read-only SQL query against the shop database and return the matching rows as JSON objects.
Returns: columns (list of names), rows (list of objects), row_count, truncated (true when more rows exist beyond the limit) and, when truncated, next_offset for fetching the next page.
Use list_tables / describe_table first to learn the schema. For questions like totals, top-N or revenue, aggregate in SQL (SUM, COUNT, GROUP BY, ORDER BY, LIMIT) instead of fetching raw rows.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | A single SQLite SELECT statement (WITH ... SELECT is allowed). JOINs, GROUP BY and aggregate functions are supported. Any data-modifying statement is rejected — the database is read-only. | |
| limit | No | Maximum rows to return, 1-500 (default 50). Prefer aggregating in SQL over fetching many raw rows. | |
| offset | No | Rows to skip for pagination (default 0). Use next_offset from a truncated result. |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, covering the safety profile. The description adds value beyond annotations by disclosing the exact return shape (columns, rows, row_count, truncated, next_offset), truncation behavior, and pagination. It does not contradict the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single well-organized paragraph that front-loads the purpose before the return format and usage guidance. Every sentence earns its place — no filler or repetition of the title. Slightly longer than strictly necessary but efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a SQL-execution tool of moderate complexity with rich annotations and full schema coverage, the description is nearly complete. It explains return values and pagination even though an output schema exists (somewhat redundant per rubric, but reinforced here). Nothing critical is missing for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema fully documents sql, limit, and offset. The description adds marginal value by reinforcing preference for SQL aggregation over fetching many raw rows and mentioning next_offset for pagination, but the baseline 3 is appropriate since the schema carries the parameter documentation burden.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Execute') and resource ('read-only SQL query against the shop database'), with the intent to return matching rows as JSON objects. It clearly distinguishes this from the sibling tools list_tables and describe_table, which are about schema discovery rather than query execution.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: use list_tables/describe_table first to learn the schema, and tells the agent to aggregate in SQL (SUM, COUNT, GROUP BY, ORDER BY, LIMIT) for totals, top-N, or revenue questions instead of fetching raw rows. This directly routes the agent to the right tool and strategy.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.
3 tool updates
v1.0.0- First observed
describe_table - First observed
list_tables - First observed
query
TDQS
Each tool has a clearly distinct purpose: list_tables discovers the database structure, describe_table provides detailed schema for a single table, and query executes read-only SQL. There is no overlap or ambiguity between them, making misselection unlikely.
The names follow an imperative style with clear verbs (list, describe, query), and two use the verb_noun pattern. 'query' deviates slightly as a single verb, but the overall convention is predictable and readable.
Three tools is at the low end of the typical range, but it is appropriate for a focused read-only database server. Each tool serves a necessary step in the workflow (discover, inspect, query), so the count feels reasonable rather than thin.
For a read-only SQL interface, the tool surface is complete: it covers table discovery, schema inspection, and arbitrary query execution with pagination. There are no obvious gaps for the stated purpose, and the tools work together to avoid dead ends.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Explore, query, and inspect SQLite databases with ease. List tables, preview results, and view det…
Query 40 databases from Claude, ChatGPT, or Cursor — on any device. Read-only, encrypted, audited.
Generate, fix, explain and run read-only SQL on PostgreSQL, MySQL and SQL Server
1Safe, read-only Postgres and MySQL access for AI agents. Audit log + column-level controls.
Related MCP Servers
- AlicenseAqualityBmaintenanceEnables AI agents to safely interact with a SQLite shop database through schema discovery, read-only SQL queries, and pre-built analytics reports like top customers, top products, and revenue summaries.683MIT
- FlicenseAqualityCmaintenanceEnables AI agents to answer analytical questions about an online store's SQLite database through specialized read-only tools, without any risk of modifying the underlying data.8-
- FlicenseAqualityCmaintenanceEnables AI agents to safely inspect and query an SQLite e-commerce database with tools for listing tables, describing schemas, and running read-only SQL queries while blocking destructive operations.4-
- FlicenseAqualityBmaintenanceGives AI agents read-only analytical access to an e-commerce SQLite database (customers, orders, order_items, products) via SQL queries, table listing, and schema inspection.3-
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/aleksei-antipin/sqlite-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server