mcp-bd-readonly
This is a read-only MCP server for exploring and querying the MySQL back database, including finance/audit reporting, with strong read-only safeguards.
Explore schemas:
list_databases,list_tables, anddescribe_table.Run safe read-only SQL via
run_query(SELECT/SHOW/DESCRIBE/EXPLAIN/WITH) with row limits.Get invoicing/finance data:
facturas_venta,resumen_iva,remesas_pendientes, andcuadre_factura.Run audit/reconciliation reports:
conciliar_remesas,saldos_cliente,excepciones, andinforme_financiero(Markdown + CSV).Prepare local SSH tunnel access with
setup_sshin stdio mode.Operate locally over stdio or remotely over HTTP with Bearer API keys, health checks, rate limits, and read-only replica fallback.
Rely on read-only enforcement: SQL parser checks, no multi-statements, dedicated SELECT-only MySQL user, and JSONL audit logging.
Provides read-only access to a MySQL database (the back database), enabling inventory and invoicing queries such as listing tables, describing schemas, running SELECT queries, and financial reporting.
Click on "Deploy 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., "@mcp-bd-readonly Show me pending payments and the total outstanding amount."
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-optima-bd (antes mcp-bd-readonly)
Servidor MCP SOLO-LECTURA sobre la BD de Optima (back). Nombre público nuevo: mcp-optima-bd; la carpeta del repo conserva el nombre antiguo para no romper rutas de config.
Servidor MCP (Model Context Protocol) de solo lectura sobre una base de datos MySQL (esquema back). Expone herramientas para consultas de inventario/facturación sin ningún acceso de escritura.
Módulo autocontenido: este servidor es solo MySQL (back). No depende de zero-teams-mcp (Teams/Graph) ni de ningún otro MCP. En configs de cliente se registra de forma independiente; activar/desactivar otros MCPs no lo afecta.
Seguridad: combinación de barreras
Parser en MCP (
security.py) — toda query pasa porenforce_read_only()enQueryExecutor.run()antes de abrir conexión. Dos barreras: la primera palabra debe serSELECT / SHOW / DESCRIBE / DESC / EXPLAIN / WITH, y ningún verbo DML/DDL puede aparecer en ninguna posición. Lo segundo es lo que cierraWITH c AS (...) DELETE FROM t, que MySQL 8 acepta y el allowlist de primera palabra por sí solo dejaba pasar. También vetaFOR UPDATE/LOCK IN SHARE MODEy los esquemasmysql,performance_schemaysys.Driver sin multi-statement (
pymysql) —CLIENT.MULTI_STATEMENTSdesactivado por defecto: siquieraSELECT 1; SELECT 2es rechazado por el driver (1064) antes de llegar a MySQL. UnSELECT 1; DROP TABLE xademás lo veta el parser.Usuario MySQL dedicado de solo lectura — con GRANT SELECT únicamente sobre
back.*, conecta por TCP127.0.0.1:3306(vía túnel SSH al host configurado enTUNNEL_HOST). CualquierUPDATE/INSERT/DELETEfalla incluso si el parser se evadiera:ERROR 1142 (42000): UPDATE command denied to user '...'@'localhost'. Verificado contra la BD real.
Si el parser falla, MySQL niega; si MySQL falla, el parser niega. Sin usuario de escritura configurado.
Related MCP server: MySQL MCP Server
Modo remoto (HTTP + réplica de solo lectura)
Además del modo local por stdio, el servidor puede correr como servicio HTTP en la misma máquina que la réplica, sin túneles:
mcp-optima-bd --transport http # 127.0.0.1:8443, endpoint /mcp con BearerLecturas a la réplica; si el lag supera
MYSQL_REPLICA_LAG_MAX_S, el router hace fallback al primario y lo reporta. Nunca escribe.API keys con SHA-256 (no se guarda el secreto), scopes, caducidad y revocación:
python -m mcp_bd_readonly.auth --db ... create|list|revoke.TUNNEL_ENABLED=0y pool acotado (MYSQL_POOL_SIZE) en servidor;setup_sshno se registra en modo HTTP.Excel en memoria: en HTTP el fichero llega en
contenido_b64y se procesa sobre los bytes, sin escribir nada en disco (el recálculo de fórmulas lo haceformualizeren memoria). En HTTP no se aceptan rutas del servidor; solo si definesMCP_FILES_DIRse permite además leer dentro de ese directorio. En stdio las rutas siguen funcionando y el temporal de recálculo se borra al terminar./healthzsin autenticación;/mcpexigeAuthorization: Bearer mcp_<id>_<secreto>y limita peticiones por minuto.Puesta en marcha:
deploy/README.md. Plan por fases con rollback:deploy/PLAN-DESPLIEGUE.md.
El modo stdio sigue siendo el default y no cambia el flujo local.
Requisitos
Python 3.10+ (venv en
.venv)Acceso SSH al host remoto de MySQL (alias
db-hosten~/.ssh/config, configurable conSSH_HOST/TUNNEL_HOST)~/.zt-readonly.env(modo 600) con las credenciales:MYSQL_HOST=127.0.0.1 MYSQL_PORT=13306 MYSQL_DB=back MYSQL_USER=back_readonly MYSQL_PASSWORD=... DATA_DIR=./data TUNNEL_HOST=db-hostNo se invalida si el archivo no existe; las variables de entorno
MYSQL_*/DATA_DIR/TUNNEL_HOSTganan sobre el archivo. En Windows el archivo cae en%USERPROFILE%\.zt-readonly.env.
Soporte Windows: el código es portable (pathlib + pymysql + os.environ, sin rutas Unix). Diferencias: entry point en .venv\Scripts\mcp-optima-bd.exe, túnel con scripts/tunnel.ps1. Instrucción completa para Claude en SETUP-WINDOWS.md.
Uso
Setup guiado (SSH + credenciales MySQL + registro en agentes). Un solo comando:
bash scripts/setup.sh # macOS/Linux pwsh scripts/setup.ps1 # WindowsHace, en orden: genera clave SSH ed25519 (si falta) + bloque
~/.ssh/config; pide credenciales MySQL y escribe~/.zt-readonly.env(modo 600); registra el MCP en Claude Code / OpenCode / Cursor / Claude Desktop; y verificaSELECT 1.Alternativa manual (solo SSH, sin wizard):
bash scripts/setup-ssh.shgenera la clave y el hostdb-host— solo pide tu email. Configura valores reales conSSH_HOST/SSH_HOSTNAME/SSH_KEY/SSH_USER. Al final imprime la clave pública para añadirla al servidor (1 paso manual). Verificado:ssh db-host 'echo OK'.Ejecutar el servidor MCP (stdio). El túnel SSH se gestiona solo: si
127.0.0.1:13306no responde, el MCP lanzassh -N -L 13306:127.0.0.1:3306 db-hostcomo subproceso y lo cierra al terminar:.venv/bin/mcp-optima-bd # macOS/Linux .venv\Scripts\mcp-optima-bd.exe # WindowsPara arranque manual previo del túnel (opcional, si quieres voz propia sobre la conexión):
scripts/tunnel.sh # macOS/Linuxscripts\tunnel.ps1 # Windows
El host SSH a usar por el auto-túnel se configura con TUNNEL_HOST (default: host en ~/.zt-readonly.env o db-host).
Herramientas
Núcleo (Tabularis):
list_databases— bases visibleslist_tables(schema?)— tablas de un schema (defaultback)describe_table(table)— columnas de una tablarun_query(query, limit=100)— SELECT/SHOW/DESCRIBE libre con límite. Query correctas verificadas contra BD real:SELECT(con JOIN, WHERE, GROUP BY, subqueries,UNION),WITH(CTE),SHOW TABLES,DESCRIBE/DESC,EXPLAIN SELECT, y consultas precedidas por comentarios--.EXPLAIN UPDATEpasa el parser pero lo niega MySQL (1142, barrera #3). ElLIMITse inyecta en SQL solo paraSELECT/WITHde un statement; paraSHOW/DESCRIBEtrunca en Python tras traer filas.
Finanzas:
facturas_venta(fecha_desde, fecha_hasta, cliente?)— facturas y total del periodo (Decimal exacto + formato es-ES1.234,56 €)resumen_iva(trimestre, anio)— base/IVA/total del trimestreremesas_pendientes(max_n=50)— efectos de pago sin pagar, porfecha_vencimientoASC (límitemax_n) + total de pendientes.fecha_vencimientopuede sernullen BD real (efectos sin vencimiento).cuadre_factura(factura_id)— comprueba que la suma de líneas == total de cabecera. Factura inexistente →ok:false,exists:false.
Auditoría:
conciliar_remesas()— total emitido vs acreditado (fecha_pagado IS NOT NULL)saldos_cliente(cliente_id)— facturado vs cobrado (víavista_efectos_pago) y pendienteexcepciones(fecha_desde, fecha_hasta, umbral)— facturas sobre umbral clasificadas por materialidadinforme_financiero(fecha_desde, fecha_hasta)— informe Markdown + CSV (;)
Aritmética
Todo el dinero es Decimal (nunca float). Sumas exactas con quantize(0.01, ROUND_HALF_UP); strings es-ES separador de miles . y decimal ,.
Auditoría de acceso
Cada llamada a tool registra una línea JSON en data_dir/audit.jsonl (DATA_DIR). No contiene credenciales.
Available Tools
13 toolsconciliar_remesasC
Total emitido vs acreditado de remesas (pago = fecha_pagado)
Inputs: no named parameters.
cuadre_facturaC
Comprueba que la suma de líneas == total de cabecera
Inputs: factura_id (required).
describe_tableC
Columnas y tipos de una tabla (DESCRIBE).
Inputs: table (required).
excepcionesC
Facturas sobre umbral clasificadas por materialidad
Inputs: umbral (required), fecha_desde (required), fecha_hasta (required).
facturas_ventaC
Facturas en un rango de fechas (max_n filas, default 200) + total_periodo exacto
Inputs: fecha_desde (required), fecha_hasta (required), max_n, cliente.
informe_financieroC
Informe Markdown + CSV(;) de un periodo (max_n filas, default 200)
Inputs: fecha_desde (required), fecha_hasta (required), max_n.
list_databasesB
Lista las bases de datos disponibles (SHOW DATABASES).
Inputs: no named parameters.
list_tablesC
Lista las tablas de un esquema (default 'back').
Inputs: schema.
remesas_pendientesC
Efectos pendientes (últimos por vencimiento, max_n límite) y total
Inputs: max_n.
resumen_ivaC
Base/IVA/Total de un trimestre (anio + trimestre 1-4)
Inputs: anio (required), trimestre (required).
run_queryB
SQL solo-lectura; devuelve {columns, rows} (JSON). limit clamp filas (default 100; 0=sólo conteo, None=todo).
Inputs: query (required), limit.
saldos_clienteC
Facturado vs cobrado y pendiente de un cliente
Inputs: cliente_id (required).
setup_sshB
Prepara SSH para el túnel de BD: genera clave ed25519 si falta, añade el host al config, y devuelve la clave pública lista para Forge.
Inputs: email.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 13 tools
Generic DB tools (list_databases, list_tables, describe_table, run_query) are clearly distinct, but several domain-report tools overlap: facturas_venta, excepciones, and informe_financiero all operate on invoices over periods, and cuadre_factura, conciliar_remesas, and saldos_cliente all touch reconciliation/balance concerns. Descriptions help differentiate but boundaries remain fuzzy.
All names use snake_case, which is consistent, but the set mixes English generic verbs (list_databases, run_query, describe_table, setup_ssh) with Spanish noun-phrase domain tools (facturas_venta, resumen_iva, saldos_cliente, excepciones). Verb_noun and bare-noun patterns are intermixed without a clear rule.
13 tools is a reasonable, well-scoped set: four generic DB primitives plus eight domain reports and one setup helper. Nothing feels redundant enough to trim, though setup_ssh sits slightly apart from the read-only query purpose.
The read-only surface covers discovery (databases/tables/columns), ad-hoc querying, and the main financial reporting workflows (invoices, VAT, remittances, reconciliation, balances, exceptions, reports). A generic export or trend/aggregation helper is missing, but run_query provides a solid fallback.
Related MCP Connectors
Read-only MCP access to a used-car dealer's inventory, profit, expenses, sales, debts and cash.
Read-only MCP access to a documented IT fleet: state, changes, posture. 15 tools.
Read-only MCP server for ClassQuill, a tutoring-business-management platform.
Read-only restaurant finance, cost, stock and staff-hours assistant for restoorun owners.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables safe interaction with MySQL databases through SELECT queries, table structure inspection, and database schema exploration. Provides read-only access to query data and examine database metadata.1-
- AlicenseNot gradedqualityDmaintenanceProvides read-only access to MySQL databases, enabling schema exploration, table inspection, and safe SELECT query execution via MCP.1ISC
- FlicenseAqualityCmaintenanceSecurity-hardened, read-only MySQL MCP server that enables safe, read-only access to MySQL databases for running SELECT queries, exploring schemas, and sampling data via MCP clients.9-
- AlicenseNot gradedqualityDmaintenanceEnables read-only SQL querying and schema inspection across MSSQL, PostgreSQL, and MySQL databases via MCP tools.ISC