shop
상점의 읽기 전용 MCP 서버
기존 온라인 쇼핑몰 SQLite 데이터베이스(data/shop.db)를 위한 stdio 기반 Python MCP 서버입니다. 파일은 읽기 전용으로만 열리며, 데이터를 변경하는 SQL은 거부되어 실행되지 않습니다.
설치
Python 3.11+:
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"Related MCP server: Shop SQLite MCP
실행
프로젝트 루트에서 실행합니다 (기본 DB 경로는 ./data/shop.db):
python -m shop_mcp
# или
shop-mcp다른 DB 경로:
SHOP_DB_PATH=~/my/test-mcp-db/data/shop.db python -m shop_mcp프로세스는 MCP를 통해 stdin/stdout으로 통신합니다. MCP 클라이언트가 연결되기 전까지는 이 터미널에 명령을 입력하지 마세요.
Cursor에서 MCP 설정
mcpServers 항목을 추가하세요 (Cursor Settings → MCP 또는 프로젝트의 .cursor/mcp.json). 전송 방식은 stdio입니다.
예시에서 ~/my/test-mcp-db는 이 저장소입니다. SHOP_DB_PATH는 서버가 직접 해석합니다 (~ → 홈 디렉터리). Cursor가 command / cwd에서 ~를 해석하지 않으면 해당 필드에 /Users/<вы>/my/test-mcp-db/...를 지정하세요.
로컬 (venv)
{
"mcpServers": {
"shop": {
"command": "~/my/test-mcp-db/.venv/bin/python",
"args": ["-m", "shop_mcp"],
"cwd": "~/my/test-mcp-db",
"env": {
"SHOP_DB_PATH": "~/my/test-mcp-db/data/shop.db"
}
}
}
}pip install -e . 이후 콘솔 스크립트가 더 편리하다면:
{
"mcpServers": {
"shop": {
"command": "~/my/test-mcp-db/.venv/bin/shop-mcp",
"cwd": "~/my/test-mcp-db",
"env": {
"SHOP_DB_PATH": "~/my/test-mcp-db/data/shop.db"
}
}
}
}Docker
이미지를 한 번 빌드합니다:
docker build -t shop-mcp .{
"mcpServers": {
"shop": {
"command": "docker",
"args": [
"run",
"-i",
"--rm",
"-v",
"~/my/test-mcp-db/data/shop.db:/data/shop.db:ro",
"-e",
"SHOP_DB_PATH=/data/shop.db",
"shop-mcp"
]
}
}
}-i 플래그는 stdio 연결을 유지하는 데 필수입니다. shop.db만 마운트하고, 컨테이너가 호스트의 파일을 덮어쓰면 안 됩니다.
도구
도구 | 용도 |
| 사용자 테이블과 역할에 대한 간단한 설명 ( |
| 실제 컬럼, 타입, PK/FK |
| 단일 |
| 수동 SQL 없이 연간 평점과 매출 |
금액, 수량, 매출은 order_items.quantity * order_items.unit_price로 계산됩니다. cancelled 상태의 주문은 제외됩니다. 달력 연도는 strftime('%Y', orders.order_date)에서 가져옵니다.
안전
SQLite URI
file:<abs>?mode=ro주석은 제거되고, 쿼리 체인(
SELECT 1; DELETE ...)은 거부됩니다.INSERT / UPDATE / DELETE / DROP / ALTER / CREATE / ATTACH / PRAGMA / … → '허용되지 않음' 명시적 오류
SQLite 구문 오류와 알 수 없는 컬럼은 구조화된 형태로 반환되며, 프로세스는 종료되지 않습니다.
평가 참고 사항
customers에는country컬럼이 없습니다. 이 내용은describe_table로 확인할 수 있습니다. 지리 정보를 임의로 만들어내면 안 됩니다.SELECT country FROM customers는 SQLite 오류를 반환합니다.현재 덤프의 주문 날짜는 2026년입니다. 2025년 매출은 0일 수 있습니다. 이것은 올바른 결과이지 필터가 고장 난 것이 아닙니다.
테스트
pytest테스트는 data/shop.db를 임시 파일로 복사하고, 거부된 쓰기 작업 후에도 복사본의 해시가 변하지 않는지 확인합니다.
처리된 요청 예시

Available Tools
4 toolsdescribe_tableA
Describe columns, types, primary keys, and foreign keys for one table.
Use before writing joins. Returns actual SQLite metadata only — never fabricates fields such as country. Parameters: table (name from list_tables). Returns {table, columns: [{name, type, primary_key, ...}], foreign_keys}.
| Name | Required | Description | Default |
|---|---|---|---|
| table | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden of behavioral disclosure. It adds an important guarantee: 'Returns actual SQLite metadata only — never fabricates fields such as country', which communicates trustworthiness and avoids hallucinated results. It also describes the return shape. It does not explicitly state that the operation is read-only, but 'returns metadata' strongly conveys that.
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 and front-loaded: purpose first, then when to use it, then parameter provenance, then output shape. Every sentence earns its place, with no filler or repeated structural information beyond what is useful.
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?
The tool is simple (one string parameter, an output schema exists, no annotations), and the description gives enough to invoke it correctly: what it returns, where the parameter value comes from, and why to use it before joins. It could add explicit note about error behavior for invalid table names, but that is not essential for a straightforward describe/metadata tool.
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 schema provides only a type string and a title 'table', so the description adds crucial meaning: table is 'the name from list_tables'. This tells the agent where valid values come from, effectively linking describe_table to list_tables. That is exactly the kind of semantic enrichment the schema lacks.
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 uses a specific verb ('Describe') and precise resources (columns, types, primary keys, foreign keys) for 'one table', clearly distinguishing it from list_tables (listing) and execute_readonly_sql (querying). The phrase 'one table' prevents confusion with table-listing siblings, and the mention of metadata-only output further clarifies its exact scope.
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 says 'Use before writing joins', which gives a clear context and timing for using this tool. It also states that the table name should come from list_tables, effectively providing a prerequisite. However, it does not explicitly name alternatives or say when not to use this tool (e.g., when listing tables or running arbitrary SQL).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
execute_readonly_sqlA
Run a single read-only SQL statement against shop.db.
Allowed: one SELECT, WITH (CTE), or EXPLAIN. Writes and DDL (INSERT, UPDATE, DELETE, REPLACE, DROP, ALTER, CREATE, TRUNCATE, ATTACH, VACUUM, REINDEX, PRAGMA) are rejected with an explicit not-allowed error. Stacked statements (semicolons) are rejected. Prefer shop_analytics for rankings and yearly revenue.
Pagination: default limit 100, maximum 1000 (error if exceeded), offset default 0. Returns {columns, rows, truncated, row_count, next_offset} or {error, sqlite_error?}. The database is opened read-only; refused mutations leave the file unchanged.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | ||
| limit | No | ||
| offset | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so thoroughly: it discloses that the database is opened read-only, that refused mutations leave the file unchanged, states that stacked statements are rejected, and explains pagination defaults and the response format. This goes well beyond what the schema or annotations alone would reveal.
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 dense but structured: it front-loads the primary action, then lists allowed/rejected statements, pagination behavior, and return contract. Every sentence contributes a distinct constraint with no filler.
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 3-parameter tool with an output schema and no annotations, the description covers the SQL grammar constraints, safety guarantees, pagination limits, error behaviors, and guidance for choosing a sibling tool. Nothing essential to correctly invoking 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?
Schema description coverage is 0%, so the description compensates by defining the 'sql' parameter in terms of allowed statement types and by providing concrete limits for 'limit' (default 100, max 1000) and 'offset' (default 0). All three parameters gain usable meaning.
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 opens with an exact verb and resource: 'Run a single read-only SQL statement against shop.db.' It further specifies the allowed statement forms (SELECT, WITH/CTE, EXPLAIN) and explicitly distinguishes itself from the shop_analytics sibling for rankings/revenue, making the tool's purpose unambiguous.
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 says to 'Prefer shop_analytics for rankings and yearly revenue,' naming an alternative and the scenario where it should be used. It also sets clear boundaries for this tool by enumerating what is allowed (read-only SELECT, WITH, EXPLAIN) and rejecting writes/DDL and stacked statements.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_tablesA
List user tables in shop.db with a one-line purpose for each.
Use this first to discover the real schema. Internal SQLite tables such as sqlite_sequence are omitted. Does not invent columns (customers has no country). Returns {tables: [{name, purpose}, ...]}.
| 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?
With no annotations present, the description carries the behavioral burden well: it mentions internal SQLite tables are omitted and that columns are not invented. This guards against false expectations, though it does not address side effects or access requirements, which are minor for a read-only listing tool.
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?
Each sentence earns its place: purpose, usage timing, exclusions, anti-invention behavior, and return shape. The description is front-loaded and compact.
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 zero-parameter listing tool with an output schema, this description is complete. It tells the agent when to use it, what it will not include, and what the response looks like.
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 detailed parameter descriptions are unnecessary. The description usefully documents the output contract instead: a table list of names and purposes.
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 names a specific verb and resource: 'List user tables in shop.db', and clarifies the output is a one-line purpose per table. It also differentiates itself by explicitly targeting user tables rather than internal ones, which separates it from schema/query tools.
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?
'Use this first to discover the real schema' gives a clear and explicit usage signal. It does not, however, explicitly state when it should not be used or name alternatives like describe_table or execute_readonly_sql.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
shop_analyticsA
Shop aggregations without hand-written SQL.
Operations: top_customers_by_spend (name, email, total_amount; default limit 5), customer_most_orders (name, email, order_count), top_products (product_name, units_sold, revenue; default limit 5), top_categories (category, revenue; default limit 3), revenue_by_year (requires year). Spend/units/revenue use quantity * unit_price and exclude cancelled orders. Year is taken from order_date.
| Name | Required | Description | Default |
|---|---|---|---|
| year | No | ||
| limit | No | ||
| operation | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations present, the description carries the full behavioral burden. It reveals important behavior beyond a naive reading: spend, units, and revenue are computed as quantity * unit_price, cancelled orders are excluded, and year is taken from order_date. It also implies a read-only aggregation nature, though it doesn't explicitly state side-effect safety, cancellation behavior, or error conditions.
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, structured, and front-loaded with the main purpose. It lists operations in a scannable format, then adds only the necessary computation caveats. Every sentence carries substantive information with no filler.
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?
Given an output schema exists, the description doesn't need to formally define return fields, and it does cover operation options, defaults, a special requirement, and calculation semantics. Remaining minor gaps are ambiguous behavior such as how customer_most_orders handles the limit parameter and what happens when an invalid combination of operation and year is given, but these do not block correct use in common cases.
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 schema provides 0% description coverage, so the description must explain the parameters, and it does: operation values map to concrete aggregations, limit has per-operation defaults, year is required for revenue_by_year, and all calculation semantics are explained. This goes well beyond the bare enum/schema and provides enough detail to invoke each operation correctly.
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 that this tool provides shop aggregations without hand-written SQL, and it enumerates exactly five named operations with their output fields. This distinguishes it from the SQL-oriented sibling tools (execute_readonly_sql) while making the tool's exact scope immediately evident.
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 phrase 'without hand-written SQL' effectively tells the agent to use this tool for shop aggregation reporting instead of writing SQL, and it names concrete operations such as top_customers_by_spend and revenue_by_year. It provides explicit per-operation constraints like the year requirement and default limits, though it does not explicitly state when to use a sibling tool like describe_table or execute_readonly_sql.
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.
4 tool updates
v0.1.0- First observed
describe_table - First observed
execute_readonly_sql - First observed
list_tables - First observed
shop_analytics
TDQS
Scored across 4 tools
The schema-discovery tools are clearly separated from the querying/analytics tools. There is some overlap between execute_readonly_sql and shop_analytics, but the descriptions explicitly steer agents toward shop_analytics for rankings and revenue, reducing confusion.
Three tools follow a clear verb-first snake_case pattern: list_tables, describe_table, execute_readonly_sql. shop_analytics breaks that pattern as a nouny resource name, though it is still understandable and not chaotic.
Four tools is a well-scoped set for a read-only shop database. Each tool fills a distinct role: schema discovery, table metadata, raw SQL execution, and prebuilt analytics, with no redundancy.
For a read-only database exploration server, the workflow is complete: list the tables, describe one, run arbitrary safe SQL, and get common analytics. There are no missing mutations or write operations because the server is explicitly read-only.
Maintenance
Related MCP Connectors
Query your org's data in natural language — read-only MCP access to SQL, NoSQL, files & warehouses.
- dataOAuthco.thinair
PostgreSQL, MySQL, and SQL Server in one session. 26 read-only MCP tools for AI agents.
Text-to-SQL MCP server: read-only queries on PostgreSQL, MySQL and SQL Server with your real schema
Read-only MCP for AI usage profiles, leaderboards, stats, and docs; no writes or private data.
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceEnables natural-language sales queries against a SQLite database, generating and executing read-only SQL through a secure MCP server with table listing, schema description, and query execution.-
- FlicenseNot gradedqualityCmaintenanceEnables safe, read-only analysis of an online store's SQLite database, providing schema introspection, restricted SELECT queries, and specialized analytics tools through MCP.-
- FlicenseNot gradedqualityCmaintenanceThis MCP server lets an AI agent securely connect to a read-only SQLite store database, inspect its tables and schema, and run analytical SQL queries without modifying any data.-
- FlicenseNot gradedqualityCmaintenanceEnables AI agents to read-only analyze a SQLite e-commerce database, exploring schema and running analytical SQL queries over stdio.-