shop-mcp
shop-mcp
Un servidor de Model Context Protocol de solo lectura que expone herramientas de análisis sobre la base de datos SQLite shop.db de una tienda en línea (clientes, productos, pedidos, artículos de pedido). Está diseñado para conectarse a un agente de IA para que el agente pueda responder preguntas analíticas sobre los datos sin poder modificarlos nunca.
El servidor habla MCP a través de stdio, abre la base de datos en modo solo lectura y expone un pequeño conjunto de herramientas especializadas y parametrizadas cuyas descripciones codifican las reglas del dominio (qué estados de pedido cuentan como ingresos, cómo se determina el país de un cliente, de dónde proviene el dinero). No hay ninguna herramienta SQL genérica ni herramienta de escritura: una instrucción destructiva como "Elimina todos los pedidos cancelados" no puede ejecutarse.
El código del servidor MCP en este repositorio fue producido por un agente de codificación de IA (Cursor), según el requisito de la tarea de que el servidor no debe escribirse a mano.
Requisitos
Python 3.11 o más reciente
La base de datos SQLite
shop.db(incluida endatabase/shop.db)uv(recomendado) — ejecuta el servidor en un entorno de proyecto aislado, sin instalación global. Se instala conbrew install uv(macOS) ocurl -LsSf https://astral.sh/uv/install.sh | sh.
Related MCP server: MCP SQLite RBAC Demo
Instalación
Con uv (recomendado) — no se necesitan ni venv manual ni pip; uv resuelve el proyecto y sus dependencias a partir de pyproject.toml en la primera ejecución:
uv sync # create / refresh the project's .venv from pyproject.tomlSin uv — crea un virtualenv e instala el paquete tú mismo:
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .Esto instala el SDK mcp y el paquete shop-mcp (que proporciona el punto de entrada python -m shop_mcp y el script de consola shop-mcp).
Configuración
El servidor abre la base de datos en database/shop.db relativa al directorio de trabajo del proceso (ProjectRoot). No se requieren variables de entorno.
Cuando se lanza mediante uv run --directory <proyecto> (consulta las configuraciones de cliente más abajo), uv establece el directorio de trabajo en la raíz del proyecto, así que la base de datos incluida se encuentra automáticamente.
Si database/shop.db no existe, el servidor sale al inicio con un error de configuración claro que incluye el directorio de trabajo actual (sin traza de pila, sin recurso silencioso). Asegúrate de que tu configuración de cliente MCP defina cwd como la raíz del repositorio.
Ejecución
uv run python -m shop_mcpo, con el paquete instalado en un venv activo:
python -m shop_mcpo, de forma equivalente:
shop-mcpEl servidor lee JSON-RPC por stdin y escribe en stdout. Normalmente no lo ejecutas directamente — tu agente de IA lo lanza por ti (ver más abajo).
Conexión a un agente
Hay configuraciones de cliente MCP listas para usar en examples/mcp/ y funcionan sin más preparación que instalar uv:
Cliente | Archivo de configuración |
Cursor |
|
Claude Desktop |
|
Stdio genérico |
|
Canónica/predeterminada |
|
Docker |
|
Cada configuración tiene esta forma (sustituye la ruta de --directory por la ruta absoluta de este repositorio en tu máquina):
{
"mcpServers": {
"shop": {
"command": "uv",
"args": ["run", "--directory", "/path/to/internet-shop-mcp", "python", "-m", "shop_mcp"]
}
}
}uv run --directory <proyecto> establece el directorio de trabajo en la raíz del proyecto y usa el .venv del proyecto, así que el servidor encuentra database/shop.db automáticamente. La misma configuración es portable entre máquinas (solo cambia la ruta de --directory).
Si prefieres no usar uv, instala el paquete en un venv tú mismo (consulta Instalación), usa command: "python" y define cwd como la raíz del repositorio en tu configuración de cliente MCP.
Cursor: abre Ajustes → MCP → Añadir servidor MCP y pega el contenido de
examples/mcp/cursor.json(o usa el ámbito Project MCP y haz commit de él).Claude Desktop: copia el contenido de
examples/mcp/claude_desktop.jsonenclaude_desktop_config.json(macOS:~/Library/Application Support/Claude/claude_desktop_config.json).Cliente stdio genérico: usa
examples/mcp/generic_stdio.jsoncon cualquier cliente que hable MCP sobre stdio.
Tras la conexión, el agente ve ocho herramientas: list_tables, describe_table, count_customers_by_country, rank_countries_by_customers, top_customers, top_products, revenue_by_category, revenue_by_year.
Herramientas
Herramienta | Responde a |
| Tarea 1 — lista las tablas y qué contiene cada una |
| Esquema de una tabla |
| Tarea 2 — clientes de un países |
| Tarea 3 — el país con más clientes |
| Tareas 4 y 8 — mayor gasto / más pedidos |
| Tarea 5 — productos más vendidos |
| Tarea 6 — categorías por mayores ingresos |
| Tarea 7 — ingresos de un año |
Reglas del dominio integradas en las descripciones de las herramientas (consulta CONTEXT.md y docs/adr/ para conocer el fundamento completo):
País se deriva del prefijo del número de teléfono del cliente (E.164). No existe una columna
country.+49→ Alemania,+7→ Rusia. Un prefijo no reconocido se asigna aunknown. La herramienta acepta un nombre completo ("Alemania") o un código ISO alfa-2 ("DE") y devuelve ambos.Ingresos / gasto solo cuentan la venta de pedidos con estado
completedyshipped.Más pedidos cuenta todos los estados de pedido excepto
cancelled.Más vendidos ordena los productos por unidades vendidas; los ingresos son un campo secundario.
Dinero proviene de
orders.total_amountpara los agregados por pedido/cliente/año y deSUM(order_items.quantity * order_items.unit_price)para los agregados por producto/categoría (el precio real de venta, no el precio actual deproducts.price).Límites tienen un valor predeterminado de 100 y se limitan a un máximo de 1000;
offsetpagina.Errores se devuelven al agente como mensajes cortos y simples (p. ej.
Invalid year: must be a 4-digit integer); las trazas de pila van solo a stderr.
Seguridad
La base de datos es de solo lectura por construcción:
SQLite se abre con
file:<path>?mode=ro(uri=True), por lo que cualquier intento de escritura lanzasqlite3.OperationalError: attempt to write a readonly database.PRAGMA query_only = 1se define como defensa en profundidad.No se expone ninguna herramienta de escritura ni de SQL genérica. Las únicas herramientas son las ocho herramientas de análisis de solo lectura de arriba.
Una prueba (tests/test_safety.py) verifica que un intento de escritura lanza un error, que no se anuncia ninguna herramienta de escritura y que el archivo de la base de datos permanece byte a byte sin cambios tras ejecutar cada herramienta.
Verificación de extremo a extremo
Las ocho tareas de la tarea se verificaron con un agente de IA conectado. Los resultados esperados sobre los datos incluidos (150 clientes, todos con +7; 750 pedidos, todos con fecha 2026):
Listar todas las tablas —
list_tablesdevuelvecustomers,products,orders,order_itemscon una descripción de cada una.¿Cuántos clientes son de Alemania? —
count_customers_by_country("Germany")→0(cero honesto; ningún cliente tiene un número+49).¿Qué país tiene más clientes? —
rank_countries_by_customers→ Rusia (RU), 150 clientes.¿Quién gastó más dinero? —
top_customers(by="spend", limit=1)→ ,polina.kozlov340@icloud.com, gasto total 531810.0.Los 5 productos más vendidos —
top_products(limit=5)→ ordenados por unidades vendidas (Эспандер плечевой, Планшет Tab 10, …) con ingresos al lado.Las 3 categorías con mayores ingresos —
revenue_by_category(limit=3)→ Электроника, Бытовая техника, Одежда и обувь.Ingresos en 2025 —
revenue_by_year(2025)→0con la notano orders in 2025(sin sustitución de año; todos los pedidos son de 2026).Más pedidos —
top_customers(by="order_count", limit=1)→ София Яковлев,sofiya.yakovlev284@yandex.ru, 15 pedidos.
La instrucción destructiva "Elimina todos los pedidos cancelados" se rechaza: no hay ninguna herramienta que la acepte y la conexión de solo lectura rechaza cualquier escritura a nivel de SQLite.
Pruebas
uv run --extra dev pytest
# or, with the package installed in an active venv:
pip install -e ".[dev]"
python -m pytestLa suite cubre: la prueba de humo (el servidor arranca sobre stdio y responde a un handshake/list_tools), el camino feliz de cada herramienta, las reglas del dominio (los ingresos excluyen estados con ingresos no devengados, el contador de pedidos excluye cancelled, los productos se ordenan por unidades), los casos límite (Alemania → 0, 2025 → 0 con nota, país desconocido, año/métrica/by inválidos, límite máximo, paginación) y las garantías de seguridad (el intento de escritura lanza un error, no hay herramientas de escritura, el archivo de base de datos queda sin cambios).
Docker (extra)
Consulta la sección "Docker" más abajo para una ejecución en contenedor.
Estructura del proyecto
internet-shop-mcp/
├── database/
│ └── shop.db # the read-only database
├── pyproject.toml # package + dependency declaration
├── README.md
├── CONTEXT.md # domain glossary
├── docs/adr/ # ADR-0001..0005
├── src/shop_mcp/
│ ├── __main__.py # `python -m shop_mcp`
│ ├── main.py # server wiring + tool registration
│ ├── config.py # database/shop.db resolution
│ ├── db.py # read-only SQLite connection
│ ├── country.py # phone-prefix → country mapping
│ └── tools.py # tool implementations
├── tests/ # pytest suite mirroring src
├── examples/mcp/ # agent connection configs
├── Dockerfile
└── .dockerignoreDocker
Construye y ejecuta el servidor en un contenedor. La base de datos se copia a la imagen en /app/database/shop.db (misma convención que en el desarrollo local).
docker build -t shop-mcp .
docker run --rm -i shop-mcpUna configuración de cliente MCP equivalente con Docker:
{
"mcpServers": {
"shop": {
"command": "docker",
"args": ["run", "--rm", "-i", "shop-mcp"]
}
}
}Para montar tu propia base de datos en lugar de la incluida:
docker run --rm -i -v "$PWD/database:/app/database:ro" shop-mcpLas garantías de solo lectura se mantienen dentro del contenedor: la conexión usa mode=ro y query_only=1, y una instrucción destructiva sigue siendo rechazada.
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 Servers
- AlicenseNot gradedqualityCmaintenanceA read-only MCP server that enables LLMs to safely explore and query any SQLite database via natural language. It exposes tools for listing tables, describing schemas, and executing SELECT/WITH queries with built-in safety guards like write prevention and row limits.MIT
- FlicenseNot gradedqualityCmaintenanceA secure MCP server that exposes a SQLite database to AI agents with Role-Based Access Control, supporting authentication, customer/order/user management, and audit logging.
- AlicenseAqualityBmaintenanceAn MCP server that lets Claude query a mock business SQL database in plain language through read-only tools, with server-side guardrails that enforce SELECT-only queries and block access to sensitive payment data.3MIT
- AlicenseNot gradedqualityBmaintenanceA natural-language data analyst MCP server that lets users query SQLite sales datasets via MCP tools (list_tables, aggregate, time_series, run_sql) with read-only SQL safety guards, returning results through a FastAPI dashboard.MIT
Related MCP Connectors
Analytical memory for AI agents: a real Postgres queried in plain English over MCP. One command.
Federated commerce search across independent WooCommerce merchants. Keyless, read-only MCP server.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
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/ablinovsibset-spec/internet-shop-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server