Skip to main content
Glama
MCP GraphQL Server Multi-Fuente

MCP GraphQL Server Multi-Fuente

by Denisijcu

📄 README.md

# MCP GraphQL Server Multi-Fuente



Servidor MCP (Model Context Protocol) que expone una API GraphQL dinámica sobre múltiples fuentes de datos: CSV, Google Sheets, SQLite, PostgreSQL, MySQL, MongoDB y Oracle.

## ✨ Características

- 🔌 **Adaptadores múltiples**: CSV, Google Sheets, SQLite, PostgreSQL, MySQL, MongoDB, Oracle (preparado).
- 🧠 **Esquema GraphQL dinámico**: genera automáticamente el esquema según los datos.
- 🔍 **Consultas flexibles**: filtros avanzados (`where` con operadores), ordenamiento, paginación, selección de campos.
- ✍️ **Mutaciones**: crear, actualizar y eliminar registros con confirmación para eliminaciones.
- 🚀 **Batching**: ejecuta varias consultas en una sola petición.
- 💾 **Persisted Queries**: guarda consultas frecuentes y reutilízalas por hash.
- 📊 **Métricas**: seguimiento de rendimiento de consultas y mutaciones.
- 🛡️ **Seguridad**: límite de complejidad, errores personalizados, directiva `@auth` de ejemplo.
- 🔄 **Cambio de fuente dinámico**: alterna entre bases de datos sin reiniciar.

## 🏗️ Arquitectura

Cliente MCP (LM Studio, Claude Desktop) │ (stdio) ▼ Servidor MCP (index.ts) │ ├── Herramientas: graphql_query, graphql_mutation, switch_source, list_sources, etc. │ ▼ Capa GraphQL (schema.ts + resolvers.ts) │ ├── Adaptadores (BaseAdapter) │ ├── CSVAdapter │ ├── GoogleSheetsAdapter │ ├── SQLiteAdapter │ ├── PostgresAdapter │ ├── MySQLAdapter │ ├── MongoDBAdapter │ └── OracleAdapter │ ▼ Fuentes de datos (CSV, Google Sheets, SQLite, ...)


## 📦 Requisitos

- Node.js 18 o superior
- npm 9+
- Para SQLite: `better-sqlite3`
- Para PostgreSQL: `pg`
- Para MySQL: `mysql2`
- Para MongoDB: `mongodb`
- Para Oracle: `oracledb` (requiere cliente nativo)

## 🛠️ Instalación

```bash
# Clonar o descargar el proyecto
git clone <url-del-repo>
cd mcp-graphql-server

# Instalar dependencias base
npm install

# Instalar dependencias específicas según adaptadores a usar
npm install better-sqlite3   # SQLite
npm install pg               # PostgreSQL
npm install mysql2           # MySQL
npm install mongodb          # MongoDB
npm install oracledb         # Oracle (requiere Oracle Instant Client)

⚙️ Configuración

Crea un archivo .env en la raíz con las variables de entorno:

# Fuente activa por defecto: csv, google-sheets, sqlite, postgres, mysql, mongodb, oracle
DEFAULT_SOURCE=google-sheets

# CSV
CSV_FILE_PATH=./src/data/sample.csv

# Google Sheets
GOOGLE_SHEETS_API_URL=https://script.google.com/macros/s/TU_ID/exec
GOOGLE_SHEETS_NAME=Empleados

# SQLite
SQLITE_DB_PATH=./src/data/sample.db
SQLITE_TABLE=empleados

# PostgreSQL
PG_CONNECTION_STRING=postgres://user:password@localhost:5432/dbname
PG_TABLE=empleados

# MySQL
MYSQL_HOST=localhost
MYSQL_USER=root
MYSQL_PASSWORD=secret
MYSQL_DATABASE=test
MYSQL_TABLE=empleados

# MongoDB
MONGO_URI=mongodb://localhost:27017
MONGO_DB_NAME=test
MONGO_COLLECTION=empleados

# Oracle
ORACLE_USER=system
ORACLE_PASSWORD=oracle
ORACLE_CONNECT_STRING=localhost:1521/XEPDB1
ORACLE_TABLE=empleados

Related MCP server: BaseQL MCP Server

🚀 Uso

Compilar

npm run build

Iniciar el servidor

node dist/index.js

El servidor se conecta por stdio, listo para que un cliente MCP (como LM Studio o Claude Desktop) lo utilice.

Configurar en LM Studio

  1. Abre LM Studio y carga un modelo (ej. Gemma).

  2. Ve a la configuración del chat y agrega un servidor MCP.

  3. Comando: node

  4. Argumentos: H:\deepseek-graphql-mcp\dist\index.js

  5. Variables de entorno: copia las de tu .env.

Reinicia la conversación para que el modelo reconozca las herramientas.

Herramientas disponibles

  • graphql_query – Ejecuta consultas GraphQL.

  • graphql_batch – Ejecuta varias consultas en una llamada.

  • graphql_mutation – Crea, actualiza o elimina registros. Acepta source para declarar sobre qué fuente crees estar trabajando; si no coincide con la activa, la operación se cancela sin tocar nada.

  • switch_source – Cambia la fuente de datos activa.

  • list_sources – Lista las fuentes disponibles.

  • register_persisted_query – Registra una consulta persistida.

  • get_metrics – Obtiene métricas de rendimiento.

  • get_schema – Muestra el esquema de la fuente activa, derivado del esquema real.

Agregaciones

{ aggregate(field: "salario") { avg min max sum countNoNulos aviso } }

Devuelve las cinco operaciones a la vez, con nombres fijos (no alias dinámicos del tipo salario_avg). El campo aviso aparece cuando hay algo que el usuario debería saber: filas sin dato, o un campo que no es numérico.

Evita que el modelo se traiga todos los registros para calcular una media él mismo.

🧪 Ejemplos de consultas

Obtener todos los registros

{
  records {
    id
    nombre
    email
  }
}

Filtrar y ordenar

{
  records(
    where: { salario: { operator: gt, value: "50000" } },
    orderBy: [{ field: "salario", direction: "desc" }]
  ) {
    nombre
    salario
  }
}

Obtener departamentos (solo Google Sheets)

{
  departamentos {
    id
    nombre
    ubicacion
  }
}

Crear registro

mutation {
  createRecord(input: { nombre: "Nuevo", email: "nuevo@email.com" }) {
    id
    nombre
  }
}

Eliminar con confirmación

mutation {
  deleteRecord(id: "11")
}

La primera llamada devuelve un aviso con el registro concreto que se va a borrar. La segunda debe llevar confirm: true y el mismo id.

La confirmación está atada al objetivo, no al texto de la consulta: el modelo puede reescribir la mutación, pero no puede confirmar el borrado de otro registro. Es de un solo uso y caduca a los 120 segundos.

Declarar la fuente en las mutaciones

{
  "query": "mutation { deleteRecord(id: \"1\") }",
  "source": "sqlite",
  "confirm": true
}

Si source no coincide con la fuente activa, la operación se cancela sin modificar nada y el error dice qué hacer. Existe porque la fuente activa es un estado invisible para quien llama, y una suposición equivocada puede escribir en la base de datos que no era.

🔌 Adaptadores incluidos

Adaptador

Archivo

Dependencia

Estado

CSV

csv-adapter.ts

csv-parse, csv-stringify

✅ Probado

Google Sheets

google-sheets-adapter.ts

axios

✅ Probado

SQLite

sqlite-adapter.ts

better-sqlite3

✅ Probado

PostgreSQL

postgres-adapter.ts

pg

📦 Catálogo

MySQL

mysql-adapter.ts

mysql2

📦 Catálogo

MongoDB

mongodb-adapter.ts

mongodb

📦 Catálogo

Oracle

oracle-adapter.ts

oracledb

📦 Catálogo

Consulta EXTRA.md para más detalles sobre los adaptadores de base de datos.

🧰 Solución de problemas

  • El modelo escribe en la fuente equivocada: pasa cuando asume que ya cambió de fuente sin llamar a switch_source. Desde la v0.5 las mutaciones aceptan source y el servidor lo verifica antes de ejecutar. Revisa que el modelo lo esté declarando.

  • Compilar no despliega: tras npm run build hay que reiniciar el proceso del servidor. Cerrar la ventana del cliente no siempre lo mata. Si arreglas algo y el comportamiento no cambia, empieza por aquí.

  • El servidor probado no es el que usa el cliente: dotenv busca el .env en el directorio de trabajo actual, que no es el de tu proyecto cuando lo lanza el cliente. Pon todas las variables en la configuración del cliente MCP, con rutas absolutas.

  • Un visor de base de datos muestra datos viejos: los visores cachean al abrir el archivo y no se enteran de los cambios de otros procesos. Recarga antes de concluir que algo no se guardó.

  • Error de tipos en GraphQL: revisa los logs de inicialización para ver el esquema inferido.

  • Google Sheets no carga: verifica que la URL de Apps Script sea accesible y que el nombre de la hoja coincida.

  • SQLite no funciona: comprueba que la base de datos exista y tenga la tabla indicada.

  • Error de compilación TS5055: revisa que tsconfig.json incluya solo src/**/*.

📝 Cambios recientes

v0.5 — correcciones de integridad

Salieron de probar el servidor contra un modelo local y observar qué hacía. Todas compilaban sin error antes del arreglo.

Datos

  • Las comparaciones y la ordenación se hacían sobre texto: en CSV y Google Sheets todo llega como cadena, así que "9" > "50000" era verdadero. Un salario de nueve mil apareciendo en un filtro de "mayor que cincuenta mil". Añadido coaccionar(), que convierte según el tipo declarado antes de comparar.

  • La caché podía servir datos de antes de una modificación. Ahora la clave lleva un número de versión que sube en cada cambio: una entrada vieja no puede servirse.

  • clearCache estaba duplicado en los siete adaptadores. Ahora hay uno solo en BaseAdapter.

  • Un filtro sin valor devolvía lista vacía en silencio, y el modelo entraba en bucle reescribiendo la consulta. Ahora lanza un error que explica la sintaxis correcta.

Esquema

  • Todos los tipos se llamaban Record, en todas las fuentes. Con dos fuentes de campos parecidos, el modelo no tenía nada con que distinguirlas. Ahora el nombre incluye la fuente: RecordSqliteEmpleados.

  • get_schema llevaba su propia lista de consultas escrita a mano. Al añadir aggregate al esquema, ahí no aparecía, y el modelo seguía diciendo que no había agregaciones. Ahora se deriva del esquema real.

  • Cada campo se podía filtrar de dos maneras: por where y por un argumento suelto. Se pagaba dos veces en el esquema. Eliminados los sueltos.

  • La consulta departamentos se declaraba siempre, incluso en fuentes sin tabla de departamentos. Ahora solo donde existe.

  • Expuestas las agregaciones, que ya estaban implementadas y no se podían usar.

Seguridad

  • La confirmación de borrado no estaba atada a nada: confirm: true valía para cualquier mutación. Se podía aprobar el borrado del registro 11 y ejecutar el del 12. Ahora se ata al id, es de un solo uso y caduca.

  • Las mutaciones aceptan source y el servidor lo verifica. Evita escribir en la fuente equivocada cuando el modelo asume mal.

Adaptadores de base de datos

  • MongoDB comparaba _id como cadena contra un ObjectId: no coincidía nunca.

  • deleteRecord de MongoDB devolvía true aunque no borrara nada.

  • Oracle no compilaba por falta de tipos. Añadido src/types/oracledb.d.ts.

Estado de los adaptadores

Los cuatro de base de datos compilan pero no se han ejecutado contra un servidor real. En el único que se revisó a fondo, MongoDB, aparecieron dos bugs de lógica que solo se ven al conectarse. Es razonable esperar más en los otros.

📄 Licencia

MIT – Libre uso y modificación.


Available Tools

8 tools
get_metricsC

Obtiene métricas de rendimiento

Inputs: no named parameters.

get_schemaA

Devuelve el esquema de la fuente ACTIVA: nombre de la fuente, campos con su tipo, consultas disponibles y ejemplos. LLAMA A ESTA HERRAMIENTA ANTES DE LA PRIMERA CONSULTA Y CADA VEZ QUE USES switch_source. Los campos cambian de una fuente a otra.

Inputs: no named parameters.

graphql_batchB

Ejecuta múltiples consultas GraphQL en una sola llamada

Inputs: queries (required), variables.

graphql_mutationA

Ejecuta una mutacion GraphQL (createRecord, updateRecord, deleteRecord) contra la fuente ACTIVA. Para eliminar, llama primero sin confirm para obtener el aviso, y despues con confirm: true y el MISMO id. DECLARA SIEMPRE el parametro "source" con la fuente sobre la que crees que estas trabajando: si no coincide con la activa, la operacion se rechaza en vez de escribir donde no debe.

Inputs: query (required), source, confirm, variables.

graphql_queryA

Ejecuta una consulta GraphQL contra la fuente de datos ACTIVA. IMPORTANTE: llama primero a get_schema para saber que campos existen; cada fuente tiene campos distintos y una consulta con un campo que no existe falla. La consulta principal es records(...). No existe ningun argumento "tabla" ni "coleccion": cada fuente expone UNA sola tabla, y para cambiar de tabla hay que cambiar de fuente con switch_source.

Inputs: query (required), hash, variables.

list_sourcesA

Lista todas las fuentes de datos disponibles y cuál está activa actualmente

Inputs: no named parameters.

register_persisted_queryC

Registra una consulta persistida y devuelve su hash

Inputs: query (required).

switch_sourceA

Cambia la fuente de datos activa. Solo hay UNA activa a la vez, y todas las consultas van contra ella. Cada fuente tiene sus propios campos, asi que DESPUES de cambiar hay que llamar a get_schema otra vez: el esquema anterior ya no vale. Fuentes: "csv", "google-sheets" y "sqlite".

Inputs: source (required).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A3.6/5.0

    Scored across 8 tools

    Disambiguation4/5

    Each tool targets a distinct action: query, batch, mutation, source switching/listing, schema, persisted queries, and metrics. The only mild overlap is graphql_query vs graphql_batch and get_schema vs list_sources, but the descriptions clearly distinguish single vs multi and schema-vs-inventory. No real risk of misselection.

    Naming Consistency4/5

    All names use consistent snake_case with clear verb_noun intent (switch_source, list_sources, get_schema, get_metrics). The graphql_* prefix group (query/batch/mutation) is a minor stylistic deviation but still readable and predictable. No mixed conventions.

    Tool Count5/5

    Eight tools is well-scoped for a multi-source GraphQL server: core query/mutation, source management, schema discovery, and auxiliary features. Each tool earns its place with no redundancy.

    Completeness4/5

    Full lifecycle is covered: schema discovery, query, batch, and create/update/delete mutations across switchable sources. Minor gaps exist around managing persisted queries (no list/delete of registered hashes) and no explicit mutation confirmation helpers beyond the documented pattern.

    Maintenance

    ActivityStale
    ResponsivenessNo recent community issues

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      Not graded
      quality
      D
      maintenance
      Automatically discovers GraphQL APIs through introspection and generates table-formatted queries with pagination, filters, and sorting. Supports multiple authentication types and provides both CLI and REST API interfaces for seamless integration.
      1
      MIT
    • A
      license
      A
      quality
      D
      maintenance
      Provides GraphQL access to Airtable and Google Sheets data, enabling natural language queries for data exploration, schema introspection, and record management.
      6
      MIT
    • A
      license
      Not graded
      quality
      D
      maintenance
      Enables interaction with multiple databases (MySQL, PostgreSQL, SQLite, Supabase) through a unified interface with security features like SQL injection detection and rate limiting.
      259 npm
      MIT
    • A
      license
      Not graded
      quality
      C
      maintenance
      Enables querying, sampling, and exporting datasets from over twenty keyless free public data sources spanning the EU, Switzerland, Germany, the US, and global providers through one uniform set of tools. A single consistent interface lets users list databases and tables, inspect schemas and query guides, run queries, and export results as CSV or JSON without per-API clients.
      Apache 2.0