MCP GraphQL Server Multi-Fuente
Allows querying and mutating data in Google Sheets through a dynamically generated GraphQL schema, including support for multiple sheets/tabs such as employee records and departments.
Allows querying and mutating collections in MongoDB with filtering, ordering, pagination, and CRUD operations through GraphQL.
Allows querying and mutating tables in MySQL databases with filtering, ordering, pagination, and CRUD operations through GraphQL.
Allows querying and mutating tables in PostgreSQL databases with filtering, ordering, pagination, and CRUD operations through GraphQL.
Allows querying and mutating records in SQLite databases with filtering, ordering, pagination, and CRUD operations through GraphQL.
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 GraphQL Server Multi-Fuenteconsulta los empleados con salario mayor a 50000 ordenados por salario"
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.
📄 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=empleadosRelated MCP server: Polyglot DB MCP
🚀 Uso
Compilar
npm run buildIniciar el servidor
node dist/index.jsEl servidor se conecta por stdio, listo para que un cliente MCP (como LM Studio o Claude Desktop) lo utilice.
Configurar en LM Studio
Abre LM Studio y carga un modelo (ej. Gemma).
Ve a la configuración del chat y agrega un servidor MCP.
Comando:
nodeArgumentos:
H:\deepseek-graphql-mcp\dist\index.jsVariables 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. Aceptasourcepara 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 |
|
| ✅ Probado |
Google Sheets |
|
| ✅ Probado |
SQLite |
|
| ✅ Probado |
PostgreSQL |
|
| 📦 Catálogo |
MySQL |
|
| 📦 Catálogo |
MongoDB |
|
| 📦 Catálogo |
Oracle |
|
| 📦 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 aceptansourcey el servidor lo verifica antes de ejecutar. Revisa que el modelo lo esté declarando.Compilar no despliega: tras
npm run buildhay 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:
dotenvbusca el.enven 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.jsonincluya solosrc/**/*.
📝 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ñadidocoaccionar(), 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.
clearCacheestaba duplicado en los siete adaptadores. Ahora hay uno solo enBaseAdapter.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_schemallevaba su propia lista de consultas escrita a mano. Al añadiraggregateal 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
wherey por un argumento suelto. Se pagaba dos veces en el esquema. Eliminados los sueltos.La consulta
departamentosse 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: truevalí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
sourcey el servidor lo verifica. Evita escribir en la fuente equivocada cuando el modelo asume mal.
Adaptadores de base de datos
MongoDB comparaba
_idcomo cadena contra unObjectId: no coincidía nunca.deleteRecordde MongoDB devolvíatrueaunque 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 toolsget_metricsC
Obtiene métricas de rendimiento
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. "Obtiene" implies a read, but nothing is said about safety, permissions, rate limits, or response shape. For a tool with zero annotation coverage, this is a significant gap.
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 short phrase with no filler, but it is under-specified rather than genuinely concise-and-complete. It is front-loaded but adds no structure or scoping detail.
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 no annotations, no output schema, and no parameter detail, the description is the sole source of information and leaves an agent unable to determine what metrics are returned or where they come from. Inadequate for even a simple zero-arg 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 tool takes zero parameters, so there is no parameter semantics burden; baseline 4 applies. The description appropriately adds no param detail since none exist.
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 ("Obtiene métricas de rendimiento"), so an agent knows it retrieves performance metrics. However, it doesn't specify which metrics, over what scope, or from which source, leaving the purpose vague relative to the graphql-oriented sibling tools. Adequate but with clear ambiguity.
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?
There is no indication of when to call this tool versus the many siblings (graphql_query, list_sources, get_schema, etc.). No context, prerequisites, or exclusions are given, so an agent must guess at its role.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden and does well: it discloses the dependency ordering (must precede the first query and follow every switch_source) and the volatility of the payload (fields change from source to source). It omits error behavior, caching, and cost, but the core operational traits are covered.
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?
Three tight sentences, front-loaded with what is returned before the imperative instruction. Every clause adds information: payload contents, call timing, and the reason (fields differ per source). 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 zero-parameter tool with no output schema, the description compensates by enumerating the return contents (name, typed fields, queries, examples) and the mandatory call timing. An agent has everything it needs to invoke this correctly.
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 takes zero parameters, which is the baseline-4 case; there is nothing for the description to disambiguate. Schema coverage is trivially complete, so no compensation is needed.
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?
States a specific verb ('Devuelve') and resource (the ACTIVE source's schema), and enumerates exactly what the return contains: source name, typed fields, available queries, and examples. It also anchors itself against the sibling switch_source, so an agent can place it in the workflow without opening another definition.
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?
Gives an explicit, emphatic trigger: call before the first query and every time switch_source is used. That is unusually actionable sequencing guidance. It stops short of naming when NOT to use it or pointing to alternatives such as list_sources, so it falls just short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
graphql_batchB
Ejecuta múltiples consultas GraphQL en una sola llamada
| Name | Required | Description | Default |
|---|---|---|---|
| queries | Yes | Lista de consultas GraphQL | |
| variables | No | Lista de variables |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden, yet it discloses nothing about execution semantics: ordering of results, whether queries run serially or in parallel, how partial failures or per-query errors are surfaced, or whether authorization applies per query. For a batch execution tool with zero annotation coverage this is a substantial gap.
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?
A single short sentence with zero waste and the core action front-loaded. It is efficient, though its brevity is also what leaves the behavioral and usage gaps unaddressed.
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?
No output schema and no annotations, so the description is the only source of behavioral detail — and it omits result shape, error semantics, and ordering. For a batch tool whose callers must reason about multiple sequential inputs, this is not complete enough.
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% ('Lista de consultas GraphQL', 'Lista de variables'), so the schema already defines both parameters. The description adds no positional/index correspondence between the queries array and the variables array, so it does not improve on the schema — baseline 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?
Specific verb+resource: 'Ejecuta múltiples consultas GraphQL en una sola llamada' clearly states batch execution of GraphQL queries, and the word 'múltiples' implicitly contrasts with the single-query sibling graphql_query. It stops short of naming graphql_query or graphql_mutation explicitly, so the differentiation is left to inference.
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 'en una sola llamada' implies the tool is for batching many queries, which hints at when it beats graphql_query. But there is no explicit when-to-use/when-not guidance, no mention of graphql_mutation as the alternative for writes, and no stated limits or batching conditions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | La mutación GraphQL | |
| source | No | Fuente sobre la que crees estar trabajando. Se comprueba contra la activa antes de ejecutar nada. | |
| confirm | No | Confirmación para DELETE | |
| variables | No | Variables opcionales |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral load and does well: it discloses the two-step delete confirmation protocol, the source-vs-active-source guard that rejects rather than writes to the wrong place, and the write/mutation scope. Missing explicit auth/permissions or error-response detail, but the safety behavior is disclosed.
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?
Three front-loaded sentences covering scope, delete workflow, and the source guard. Dense but each sentence earns its place; 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 mutation tool with no annotations and no output schema, the description covers purpose, the confirm gating for destructive deletes, and the source-mismatch safety check. Nested variables and exact error/permission semantics are thin, but the critical callable behavior is present.
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 coverage is 100%, so the schema documents all four parameters including the source enum and confirm optionality. The description reinforces source ('DECLARA SIEMPRE ... source') and the delete/confirm relationship but adds little syntactic meaning beyond the schema, so baseline 3 is appropriate.
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?
States a specific verb+resource: 'Ejecuta una mutacion GraphQL (createRecord, updateRecord, deleteRecord) contra la fuente ACTIVA.' The write scope plus the 'ACTIVA' qualifier distinguishes it cleanly from graphql_query and graphql_batch.
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?
Gives concrete when-to-use procedural guidance: for deletion, call first without confirm to get the warning, then again with confirm:true and the same id. It does not explicitly route to sibling alternatives (graphql_query/graphql_batch), but the delete workflow and the source-mismatch rejection rule are strong context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| hash | No | Hash de consulta persistida | |
| query | Yes | Consulta GraphQL. Ej: { records(limit: 10) { id nombre salario } } Con filtro: { records(where: { salario: { operator: gt, value: 50000 } }) { nombre salario } } Operadores: eq, neq, gt, gte, lt, lte, contains, startsWith, endsWith, in, between. | |
| variables | No | Variables opcionales |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It usefully discloses a failure mode (unknown field breaks the query) and the one-table-per-source constraint, but says nothing about read-only vs mutating behavior, authentication needs, or rate limits, leaving key behavioral traits unstated.
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?
Front-loaded with the purpose, then the prerequisite and the constraint, in four tight sentences with no padding. Slightly dense but every clause carries information.
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 no annotations and no output schema, the description covers the prerequisite call, the failure mode, and the table/source model well. It omits expected return shape and how it relates to the mutation sibling, which is a minor gap.
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 coverage is 100%, so the baseline is 3, but the description adds real meaning beyond the schema by clarifying that there is no table/collection argument and that each source exposes exactly one table addressed via records(...). The hash and variables parameters are left to the schema, which explains them.
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?
States a specific verb (ejecuta) and resource (consulta GraphQL) scoped to the ACTIVE data source, and explicitly differentiates itself from siblings by naming get_schema and switch_source and by ruling out a 'tabla'/'coleccion' argument. An agent can distinguish it from graphql_mutation and graphql_batch purely from the text.
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?
Gives an explicit prerequisite ('llama primero a get_schema') plus the failure condition if skipped, and names switch_source as the way to change tables. It does not contrast with graphql_mutation or graphql_batch, so the when-not guidance is incomplete, but the core usage path is unambiguous.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sourcesA
Lista todas las fuentes de datos disponibles y cuál está activa actualmente
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It does disclose the return content (all sources plus the currently active one), which is the key trait for a listing tool, but says nothing about ordering, auth requirements, or output format details.
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?
A single front-loaded sentence with no filler; the active-source detail is appended efficiently rather than padding the text.
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 read tool with no output schema, the description is nearly sufficient: it explains what you get back, which is the only thing the schema cannot convey. Minor gaps remain around the shape of the returned source records.
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 takes zero parameters, so the baseline is 4. There is nothing parameter-related the description could add or omit, and its claim of full scope ("todas las fuentes") correctly signals there is no filtering input.
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 gives a clear verb ("Lista") and resource ("fuentes de datos") plus the scope detail that it also reports which source is active. This is specific enough to distinguish it from siblings like switch_source or get_schema, though it never names an alternative explicitly.
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?
Usage is only implied: an agent can infer this is the discovery step before calling switch_source, but the description states no when-to-use condition, no prerequisites, and no exclusions relative to the sibling tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
register_persisted_queryC
Registra una consulta persistida y devuelve su hash
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | Consulta GraphQL a persistir |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden, yet it only says the tool registers and returns a hash. It omits whether registration is idempotent, what permissions it needs, whether the hash is content-derived or server-assigned, and whether an existing query is overwritten.
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?
A single compact sentence that front-loads the action and the return value with no filler. It is terse to the point of being thin, but nothing is wasted.
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 one-parameter mutation with no annotations and no output schema, the description at least discloses the return value (the hash), but it leaves out auth, idempotency, and error behavior, so it is only minimally adequate.
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% and there is a single required parameter ('query', documented in Spanish as a GraphQL query to persist), so the schema already does the heavy lifting. The description adds no format or constraint detail beyond it.
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?
States a specific verb ('Registra') and resource ('consulta persistida') and discloses the return value ('devuelve su hash'). It is distinguishable from siblings like graphql_query or graphql_mutation, though it never explicitly names an alternative.
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?
No when-to-use, prerequisites, or alternative-routing guidance is given. An agent cannot tell from the text when persisting a query is preferable to simply calling graphql_query.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
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".
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | Nombre exacto de la fuente: csv, google-sheets o sqlite |
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 well: it discloses the single-active-source invariant, that all queries run against the active source, that each source has distinct fields, and that the previous schema is invalidated after the switch. It stops short of describing error behavior or whether the switch is reversible.
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?
Front-loaded with the core action, then the invariant, then the required follow-up, then the allowed values. Each sentence earns its place, though the final enumeration of sources partly duplicates the schema enum.
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-annotation, no-output-schema mutation tool this is nearly complete: purpose, invariant, and required follow-up call are all covered. Missing only details such as return value or error/side-effect behavior for invalid names.
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% and the enum already constrains the source values, so the schema does the heavy lifting. The description restates the source names but adds no format or semantics beyond what the schema and its enum provide; baseline 3 is appropriate.
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?
States a specific verb (cambia/cambiar) and resource (fuente de datos activa), and clarifies the singular-active-source model. It also implicitly distinguishes itself from siblings by naming get_schema as the required follow-up, so an agent can tell it is the state-changing tool rather than a query or schema tool.
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 a clear trigger (when you need to change the active data source) and an explicit post-condition workflow: after switching you must call get_schema again because the old schema is invalid. It does not name alternatives or when-not-to-use cases, but the sequencing guidance is strong.
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.
8 tool updates
v0.1.0- First observed
get_metrics - First observed
get_schema - First observed
graphql_batch - First observed
graphql_mutation - First observed
graphql_query - First observed
list_sources - First observed
register_persisted_query - First observed
switch_source
TDQS
Scored across 8 tools
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.
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.
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.
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
Related MCP Connectors
A collaborative substrate over your data: vector, knowledge graph, SQL, geospatial, streaming.
Query your Google Sheets as structured JSON: list sheets and tabs, read schemas, filter rows.
Query, join, profile, clean and convert CSV/JSON/Parquet with server-side DuckDB over MCP.
Draxlr's remote MCP server connects AI assistants to your SQL databases and dashboards. Explore schemas, run read-only queries, manage saved queries and dashboards, and export results, all with row-level security so each user sees only their own data.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceAutomatically 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.1MIT
- -licenseNot gradedqualityNot gradedmaintenanceEnables interaction with 20+ databases (PostgreSQL, MongoDB, Neo4j, Elasticsearch, Redis, and more) through a single unified interface, allowing cross-database queries and operations via natural language.1-
- FlicenseAqualityDmaintenanceProvides GraphQL access to Airtable and Google Sheets data, enabling natural language queries for data exploration, schema introspection, and record management.6-
- AlicenseNot gradedqualityDmaintenanceEnables interaction with multiple databases (MySQL, PostgreSQL, SQLite, Supabase) through a unified interface with security features like SQL injection detection and rate limiting.50 npmMIT