Skip to main content
Glama
typescript-mcp-sqlite-mini-lab

typescript-mcp-sqlite-mini-lab

typescript-mcp-sqlite-lab

Pequeño lab de aprendizaje para explorar el Model Context Protocol (MCP) implementando un MCP Server SQLite desde cero en TypeScript.

¿Qué es esto?

Básicamente es un MCP Server local que permite explorar y manipular una pequeña base de datos SQLite. El flujo es:

MCP Client
    ↓
MCP Server
    ↓
SQLite Database

Related MCP server: SQLite-MCP

¿Qué hace?

Actualmente expone cinco Tools via el protocolo MCP:

  • db.list_tables — Lista todas las tablas de la base de datos SQLite

  • db.describe_table — Describe el esquema de una tabla concreta (columnas, tipos, restricciones, claves)

  • db.query — Ejecuta una consulta de solo lectura (SELECT)

  • db.insert — Inserta una fila en una tabla de forma controlada

  • db.export_csv — Exporta los datos de una tabla a formato CSV

Además de las Tools, el servidor expone Resources (contenido accesible por URI):

  • db://schema — Resource estático con el esquema completo de la base de datos (CREATE TABLE)

  • db://table/{tableName} — Resource dinámico mediante ResourceTemplate que devuelve el contenido de una tabla concreta como CSV

db://schema          → CREATE TABLE de todas las tablas
db://table/users     → datos de la tabla users
db://table/products  → datos de la tabla products

Esto es gracioso. En la teoria una Tool ejecuta una acción (callTool); y un Resource se lee como contenido (readResource). Pero por debajo vienen a ser lo mismo.

Cómo se usa

Se conecta a un MCP Client compatible (como Claude Desktop o un cliente custom). El cliente:

  1. Inicia el handshake initialize con el servidor

  2. Descubre las capabilities y tools disponibles via listTools()

  3. Invoca tools via callTool({ name, arguments })

Arquitectura MCP

Flujo general

┌─────────────────┐
│    MCP Client   │
└────────┬────────┘
         │ MCP
         ↓
┌─────────────────┐
│    MCP Server   │
├─────────────────┤
│   Tools         │  ← db.list_tables
│                 │  ← db.describe_table
│                 │  ← db.query
│                 │  ← db.insert
│                 │  ← db.export_csv
│   Resources     │  ← db://schema
│                 │  ← db://table/{tableName}
└────────┬────────┘
         │
         ↓
┌─────────────────┐
│ SQLite Database │
└─────────────────┘

Tool call

Client
 ↓
tools/call { name, arguments }
 ↓
MCP Server
 ↓
valida contra schema (Zod)
 ↓
ejecuta en SQLite
 ↓
devuelve CallToolResult con content blocks

Resource read

Client
 ↓
resources/read { uri }
 ↓
MCP Server
 ↓
devuelve Resource content

Demo interactivo

El proyecto incluye un cliente MCP interactivo (src/demo.ts) que arranca StdioClientTransport y muestra un menú para probar varias opciones, a saber:

  1. Descubrir Tools (listTools)

  2. Listar tablas (db.list_tables)

  3. Describir una tabla (db.describe_table)

  4. Ejecutar query SELECT (db.query)

  5. Insertar registro (db.insert)

  6. Exportar tabla a CSV (db.export_csv)

  7. Descubrir Resources (listResources)

  8. Leer schema (db://schema)

  9. Leer Resource de una tabla (db://table/{tableName})

  10. Salir

Cada opción indica el tipo de operación MCP (Tool Call o Resource Read/Discovery).

Stack

  • TypeScript + Node.js v24 (ESM nativo)

  • @modelcontextprotocol/sdk v1.30.0 (McpServer + StdioServerTransport)

  • better-sqlite3 — base de datos SQLite síncrona

  • zod — validación de schemas para Tools

  • Vitest — framework de tests

  • ESLint v10 (flat config) + Prettier — calidad de código

Estructura del proyecto

src/
├── index.ts                  → Entry point del servidor MCP (McpServer)
├── client.ts                 → Cliente MCP local de prueba directo
├── demo.ts                   → Cliente/demo interactivo (menú didáctico)
└── db/
    ├── connection.ts         → Singleton de conexión SQLite (getDB, getReadOnlyDB)
    ├── operations.ts         → Lógica pura de tools/resources (recibe la conexión por parámetro)
    ├── init.ts               → Inicialización: schema + datos seed (createSchema, seed)
    ├── validate.ts           → Validación de identificadores (isValidIdentifier)
    └── verify.ts             → Verificación manual de la base de datos
tests/
├── helpers.ts                → Construcción de una BD SQLite en memoria para tests
├── smoke.test.ts             → Prueba mínima del entorno
├── db.tools.test.ts          → Tests de las 5 Tools
├── db.resources.test.ts      → Tests de los 2 Resources
└── validate.test.ts          → Tests de isValidIdentifier
dist/                         → Código compilado (generado por tsc)
database.sqlite               → Base de datos SQLite (en .gitignore)

Testing

Los tests, que ha implementado en un 99% el agente, usan Vitest y se ejecutan con npm test. Están diseñados para ser deterministas y rápidos:

  • Aislamiento: se construye una BD SQLite en memoria (:memory:) en cada test reutilizando createSchema()/seed() de src/db/init.ts. No dependen del archivo database.sqlite, ni de servicios externos, ni de un MCP Client real, ni de APIs de OpenAI.

  • Cobertura de comportamiento:

    • db.tools.test.ts — list_tables, describe_table (válida / no existe / id inválido), query (SELECT válido + escritura rechazada), insert (válido / columnas inválidas / id inválido), export_csv (válido / no existe).

    • db.resources.test.ts — db://schema y db://table/{tableName} (leer válido / listar recursos / id inválido / no existe).

    • validate.test.ts — isValidIdentifier (casos válidos e inválidos).

Setup

npm install
npm run build
npm test
npm start          → ejecuta el servidor MCP
npm run client     → ejecuta el cliente local de prueba
npm run demo       → ejecuta el cliente/demo interactivo

Scripts

Comando

Descripción

npm start

Ejecuta el servidor MCP (node dist/index.js)

npm run client

Ejecuta el cliente local de prueba

npm run demo

Ejecuta el cliente/demo interactivo

npm test

Ejecuta los tests con Vitest

npm run build

Compila TypeScript

npm run lint

Lint con ESLint

npm run format

Formatea con Prettier

Available Tools

2 tools
db.describe_tableA

Describe the schema of a specific table

Inputs: tableName (required).

db.list_tablesA

List all tables in the SQLite database

Inputs: no named parameters.

Tool Schema Changelog

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

Loading tool schema changelog…

    TDQS

    A3.5/5.0

    Scored across 2 tools

    Disambiguation5/5

    The two tools, db.list_tables and db.describe_table, have clearly distinct purposes with no functional overlap.

    Naming Consistency5/5

    Both tools follow a consistent 'db.' prefix and snake_case naming pattern, making them predictable.

    Tool Count2/5

    With only 2 tools, the server feels under-scoped for a database interface, falling well below the typical 3-15 range.

    Completeness1/5

    The toolset only supports listing tables and describing schemas, missing essential operations like querying or modifying data, leaving the surface severely incomplete.

    Maintenance

    ActivityStale
    ResponsivenessOutdated data

    Related MCP Connectors

    Related MCP Servers