Despliegue de un MCP para corregir errores en MS Access 2016

1. Despliegue de un MCP para corregir errores en MS Access 2016

1.1. 1. Clarificar el alcance del MCP (Model Context Protocol)

Antes de codificar, define qué tipo de MCP necesitas:

  • Servidor MCP que exponga herramientas (tools) para que un LLM analice/corrija la BD Access.
  • Cliente MCP integrado en tu flujo de trabajo (Claude Desktop, Cursor, etc.).

Para Access 2016 lo típico es un servidor MCP en Python o Node que ejecute consultas VBA/SQL contra el .accdb=/.mdb=.

1.2. 2. Arquitectura recomendada

[LLM/Cliente MCP] <--stdio/HTTP--> [Servidor MCP] <--COM/ODBC--> [Access 2016]

1.2.1. Componentes clave

  • Driver: Microsoft Access Database Engine 2016 (ACE.OLEDB.16.0) o pyodbc con Microsoft Access Driver (*.mdb, *.accdb).
  • Backend VBA: para operaciones que requieren el motor Access (compactar/reparar, refrescar vínculos, recompilar VBA).
  • Automatización COM: pywin32 (win32com.client.Dispatch("Access.Application")).

1.3. 3. Pasos de implementación

1.3.1. Paso 1 — Entorno

python -m venv .venv
.venv\Scripts\activate
pip install mcp pyodbc pywin32

Instala el ACE OLEDB 2016 (arquitectura x86/x64 coincidente con Python).

1.3.2. Paso 2 — Esqueleto del servidor MCP (Python)

from mcp.server.fastmcp import FastMCP
import pyodbc, win32com.client

mcp = FastMCP("access-fixer")
DB = r"C:\ruta\sistema.accdb"
CONN = fr"DRIVER={{Microsoft Access Driver (*.mdb, *.accdb)}};DBQ={DB};"

@mcp.tool()
def ejecutar_sql(sql: str) -> str:
    """Ejecuta SQL de diagnóstico/corrección."""
    with pyodbc.connect(CONN, autocommit=True) as cx:
        cx.execute(sql)
    return "OK"

@mcp.tool()
def compactar_reparar() -> str:
    """Compacta y repara el .accdb (requiere Access instalado)."""
    acc = win32com.client.Dispatch("Access.Application")
    acc.CompactRepair(DB, DB.replace(".accdb", "_fixed.accdb"), True)
    acc.Quit()
    return "Compactado"

@mcp.tool()
def recompilar_vba() -> str:
    acc = win32com.client.Dispatch("Access.Application")
    acc.OpenCurrentDatabase(DB)
    acc.VBE.CommandBars.FindControl(Name="Compile").Execute()
    acc.CloseCurrentDatabase(); acc.Quit()
    return "VBA recompilado"

1.3.3. Paso 3 — Herramientas típicas para "corregir viejos errores"

  • listar_tablas_y_campos (detectar tipos inconsistentes).
  • buscar_referencias_rotas (tablas vinculadas caídas).
  • detectar_datos_huerfanos (integridad referencial).
  • normalizar_fechas/textos (formato regional ES/US).
  • comparar_esquema contra un DDL esperado.
  • generar_script_correccion (devuelve SQL idempotente).

1.3.4. Paso 4 — Registro en el cliente MCP

claude_desktop_config.json:

{
  "mcpServers": {
    "access-fixer": {
      "command": "python",
      "args": ["C:\\ruta\\servidor_mcp.py"]
    }
  }
}

1.4. 4. Buenas prácticas para Access 2016

Riesgo Mitigación
Bloqueo del .laccdb Cerrar sesión antes de compactar
Corrupción en operaciones masivas Backup previo + CompactRepair
Referencias VBA rotas Re-registrar .dll=/.ocx= (mscomctl, comdlg32)
ADO vs DAO Preferir DAO para esquema, ADO para datos externos
Split DB Trabajar sobre el front-end, datos en back-end
Driver 32/64 bits Alinear con la instalación de Office

1.5. 5. Flujo sugerido

  1. Backup del .accdb.
  2. Auditoría: MCP ejecuta herramientas de diagnóstico → reporte.
  3. Aprobación humana de cada corrección (evita DDL destructivo).
  4. Aplicación por lotes en una copia.
  5. CompactRepair + recompilar VBA.
  6. Validación: ejecutar suite de pruebas / consultas de verificación.
  7. Despliegue al entorno productivo.

1.6. 6. Controles críticos

  • Nunca DROP=/=UPDATE masivo sin WHERE auditado.
  • Usar transacciones (DAO BeginTrans=/=CommitTrans).
  • Log de cada sentencia aplicada a audit_fixes tabla.
  • Versionar el .accdb (aunque sea binario: guardar .bas, .frm exportados).

¿Quieres que te arme un ejemplo completo con una herramienta concreta (p. ej. detección de huérfanos o migración de tipos), o el requirements.txt y estructura de carpetas?

Más que nada me interesa que sea capaz de mejorar la experiencia del usuario, modificando los formularios, los reportes, etc.

  • MCP para mejorar UX en Access 2016 (formularios, reportes, navegación)

2. 1. Cambio de enfoque

No es "corregir errores" sino modernizar la capa de presentación sin tocar la lógica de negocio. En Access eso vive en:

Objeto Qué tocar Vía
Formularios Controles, layout, propiedades, validación visible DAO / COM
Reportes Secciones, agrupación, totales, estilos DAO / COM
Menús/Ribbon Botones, iconos, accesos XML USysRibbons
Macros/Nav Puntos de entrada VBA o macros
Estados/Mensajes MsgBox feos, sin contexto VBA refactor

Un LLM con MCP puede leer la spec actual, proponer mejoras y aplicarlas de forma controlada.

3. 2. Arquitectura específica para UX

[LLM] <--MCP--> [Servidor] <--COM--> [Access]
                    |
                    +--> exportar .frm/.bas a texto
                    +--> parsear / diff / proponer
                    +--> reimportar y validar

La clave: trabajar sobre la forma textual, no sobre el binario. Access exporta formularios/reportes a un formato legible (SaveAsText).

4. 3. Herramientas MCP recomendadas

*/ Lectura / diagnóstico

  • exportar_objeto(tipo, nombre) → texto frm, report, bas, cls.
  • listar_controles(formulario) → nombre, tipo, posición, propiedades clave.
  • inventariar_estilos → fuentes, colores, tamaños inconsistentes.
  • detectar_antipatrones_ux → grillas sin cabecera, tab order roto, sin TabIndex, botones sin ToolTip, etc.

*/ Propuesta / diff

  • proponer_refactor(objeto, criterio) → devuelve texto nuevo + justificación.
  • diff_objeto(actual, propuesto) → para revisión humana.

*/ Aplicación

  • importar_objeto(texto) → LoadFromText (Access 2013+).
  • aplicar_parche(objeto, hunks) → parches quirúrgicos en lugar de reescritura.

*/ Validación

  • abrir_formulario_en_modo_vista (solo lectura).
  • capturar_error_al_compilar.
  • checklist_accesibilidad (labels asociados, contraste, nombres significativos).

5. 4. Ejemplo mínimo (Python + MCP)

from mcp.server.fastmcp import FastMCP
import win32com.client, tempfile, os

mcp = FastMCP("access-ux")
DB = r"C:\ruta\sistema.accdb"

def _acc():
    a = win32com.client.Dispatch("Access.Application")
    a.OpenCurrentDatabase(DB)
    return a

@mcp.tool()
def exportar(tipo: str, nombre: str) -> str:
    """tipo: acForm|acReport|acModule. Devuelve texto exportado."""
    a = _acc()
    tmp = os.path.join(tempfile.gettempdir(), f"{nombre}.txt")
    a.SaveAsText(getattr(a, f"Ac{tipo.capitalize()}") if False else None, nombre, tmp)
    txt = open(tmp, encoding="utf-8", errors="ignore").read()
    a.CloseCurrentDatabase(); a.Quit()
    return txt

@mcp.tool()
def importar(tipo: str, nombre: str, texto: str) -> str:
    a = _acc()
    tmp = os.path.join(tempfile.gettempdir(), f"{nombre}.txt")
    open(tmp, "w", encoding="utf-8").write(texto)
    a.LoadFromText(getattr(a, f"Ac{tipo.capitalize()}"), nombre, tmp)
    a.CloseCurrentDatabase(); a.Quit()
    return "Importado"

(Nota: los nombres exactos de las constantes son acForm, acReport, acModule; ajusta el getattr según tu versión.)

6. 5. Mejoras UX que el LLM puede proponer automáticamente

*/ Formularios

  • Consistencia visual: fuente Segoe UI 10, alto de control 0.2", Theme unificado.
  • Layout: pasar de posicionamiento absoluto a Stacked/Tabular Layout.
  • Navegación: botones Anterior/Siguiente/Nuevo/Buscar con atajos (Ctrl+N, Ctrl+F).
  • Validación inline: BeforeUpdate con mensajes claros en lbl_error en lugar de MsgBox.
  • Búsqueda: caja de filtro en vivo (ApplyFilter con OnChange).
  • Accesibilidad: TabIndex ordenado, TabStop correcto, labels asociadas.
  • Estados vacíos: mensaje "No hay registros" en lugar de grid en blanco.
  • Fechas: formato dd/mm/aaaa o ISO según público.

*/ Reportes

  • Agrupación y totales con GroupLevel, subtotales, Running Sum.
  • Encabezado con fecha/hora/usuario para trazabilidad.
  • Logo y colores de marca en ReportHeader.
  • Exportación directa a PDF con nombre inteligente.
  • Condicional formatting (semáforos, negritas por umbral).

*/ Global

  • Home/Dashboard con botones grandes en lugar de menú desplegable.
  • Ribbon personalizado (USysRibbons) que esconda el nativo.
  • Mensajes de error con acción sugerida, no códigos.
  • Atajos de teclado documentados en un formulario de ayuda.

7. 6. Flujo seguro de aplicación

  1. Backup del .accdb y export masivo (SaveAsText de todo).
  2. Versionar en git los .frm=/.=report=/.=bas exportados.
  3. LLM exporta el objeto → propone diff → tú apruebas.
  4. Aplicar con LoadFromText sobre copia.
  5. Recompilar VBA y abrir el formulario/reporte en vista.
  6. Comparar capturas (opcional: pywinauto para screenshots).
  7. Promover a producción.

8. 7. Guardarraíles (importante)

  • Nunca reescribir todo un formulario de una vez: parches por secciones.
  • Preservar nombres de controles (el código VBA los referencia; romperlos = error silencioso).
  • No tocar RecordSource ni ControlSource sin revisar queries dependientes.
  • Detectar eventos VBA asociados antes de renombrar/eliminar controles.
  • Log de cada LoadFromText con timestamp y hash.

9. 8. Extras que suben mucho la UX

  • Formulario de búsqueda global (Ctrl+F) que salte a cualquier entidad.
  • Panel de "recientes" por usuario.
  • Modo oscuro (sí, se puede con Theme + colores).
  • Tooltips en todos los botones (ControlTipText).
  • Confirmaciones inteligentes: solo preguntar cuando hay cambios sin guardar.
  • Undo en operaciones destructivas a nivel de app.

¿Quieres que te prepare (a) un catálogo de antipatrones UX detectables automáticamente con las consultas MSysObjects=/=SaveAsText, o (b) un prompt template que le pases al LLM para que produzca el diff de un formulario concreto?

Es importante tambien considerar la posibilidad de hacer un cambio en la lógica de negocio, o cómo manejamos el negocio en la actual estructura de tablas y base de datos.

  • MCP con capacidad de refactor de lógica de negocio y modelo de datos
  • 1. El problema real

Si el esquema actual refleja un modelo mental viejo del negocio, mejorar formularios es cosmético. Hay que poder:

  1. Entender la semántica que el esquema actual está codificando implícitamente.
  2. Contrastarla con cómo el negocio se entiende hoy.
  3. Proponer un nuevo modelo (tablas, relaciones, reglas) y una ruta de migración.
  4. Aplicarlo sin perder datos ni romper formularios/reportes/VBA.

Esto es mucho más delicado que UX: toca datos, integridad y procesos. El MCP debe ser asistente de refactor, no ejecutor ciego.

  • 2. Tres niveles de intervención
Nivel Alcance Riesgo Cómo lo trata el MCP
L1 Reglas Validaciones, defaults, cálculos en VBA/consultas Bajo Refactor de módulos y ValidationRule
L2 Esquema Tablas, campos, tipos, índices, FKs Medio-alto DDL + script de migración + backfill
L3 Modelo Descomposición, normalización, entidades nuevas Alto Proyecto de migración por fases

Empieza siempre por L1, gana confianza, sube.

  • 3. Cómo el MCP "entiende" el negocio actual

// Introspección del esquema

  • MSysObjects, MSysRelationships, MSysQueries (a veces bloqueadas).
  • DAO: TableDefs, Fields, Indexes, Relations.
  • Exportar DDL real: CREATE TABLE reconstruido desde DAO.

// Introspección de la semántica

  • Consultas guardadas: son la lógica de negocio codificada en SQL. Exportar todas.
  • Módulos VBA: reglas, cálculos, validaciones. Exportar todos .bas=/.cls=.
  • Macros: flujos automáticos.
  • Formularios: RecordSource, ControlSource, eventos BeforeUpdate, AfterUpdate.
  • Reportes: agrupaciones y totales revelan KPIs y jerarquías.

// Señales de deuda de modelo

  • Campos multivaluados (tipo Access Complex) → violan 1FN.
  • Columnas tipo Campo1, Campo2, Campo3 → entidad no descompuesta.
  • Tablas con 60+ campos → probable entidad gorda con subentidades latentes.
  • Códigos duplicados en texto libre → falta tabla de dominio.
  • Fechas en texto → tipo mal elegido.
  • Sin PK/FK → integridad por código VBA (frágil).
  • Lookup en tabla (mala práctica Access) → confunde modelo con UI.
  • Nombres en español mezclados con inglés → deuda de nomenclatura.
  • 4. Herramientas MCP sugeridas

// Inventario y documentación

  • exportar_esquema_completo() → DDL + relaciones + índices.
  • exportar_logica_negocio() → todas las queries, módulos y eventos.
  • mapa_dependencias(objeto) → qué formularios/reportes/VBA usan esta tabla/campo.
  • generar_diccionario_datos() → tabla/campo/tipo/uso/descripcion inferida.

// Análisis de modelo

  • detectar_violaciones_normalizacion() → 1FN, 2FN, 3FN.
  • detectar_multivaluados().
  • detectar_dominios_implicitos() → valores repetidos que deberían ser catálogo.
  • detectar_tablas_gordas().
  • detectar_relaciones_faltantes() → campos XxxId sin FK formal.
  • detectar_campos_muertos() → nunca usados en queries/formularios/reportes.

// Propuesta de nuevo modelo

  • proponer_esquema_objetivo(criterios) → entidades, atributos, relaciones.
  • diff_esquemas() → cambios concretos.
  • generar_ddl_migracion() → CREATE/ALTER para llegar al nuevo modelo.
  • generar_script_backfill() → poblar nuevas columnas desde las viejas.
  • generar_vistas_compatibilidad() → queries con los nombres viejos apuntando al nuevo esquema (clave para no tocar formularios de golpe).

// Reglas de negocio

  • extraer_reglas_de_vba() → qué validaciones/reglas están dispersas.
  • centralizar_reglas() → mover a tabla reglas_negocio o a un módulo único.
  • detectar_reglas_duplicadas() → la misma validación en 5 formularios.
  • detectar_reglas_contradictorias() → un formulario permite lo que otro prohíbe.
  • 5. Estrategia de migración: "Strangler Fig" para Access

No reescribas el modelo de una vez. Envuelve el viejo y sustitúyelo por partes.

Fase 0: Backup + export textual total + git init
Fase 1: Diccionario de datos y mapa de dependencias
Fase 2: Vistas de compatibilidad (queries con nombres viejos -> tablas nuevas)
Fase 3: Migrar una entidad piloto de bajo riesgo
Fase 4: Repuntar formularios/reportes a las vistas
Fase 5: Migrar el resto por entidad
Fase 6: Congelar viejas tablas, luego eliminarlas
Fase 7: Refactor VBA a las nuevas reglas centralizadas

La magia de la Fase 2: los formularios siguen funcionando aunque el modelo cambie debajo. Eso te da tiempo.

  • 6. Ejemplo de patrón: de tabla gorda a entidades

// Antes

Cliente(
  IdCliente, Nombre, Calle, Ciudad, CP, Pais,
  Tel1, Tel2, Tel3, Email1, Email2,
  Contacto1_Nombre, Contacto1_Tel, Contacto2_Nombre, Contacto2_Tel
)

// Después

Cliente(IdCliente, Nombre, IdDireccionPrincipal)
Direccion(IdDireccion, IdCliente, Calle, Ciudad, CP, Pais, Tipo)
Contacto(IdContacto, IdCliente, Nombre, Rol)
Comunicacion(IdComunicacion, IdContacto, Tipo, Valor)  -- tel/email

// Puente de compatibilidad

CREATE VIEW qryCliente AS
SELECT c.IdCliente, c.Nombre,
       d.Calle, d.Ciudad, d.CP, d.Pais,
       (SELECT TOP 1 Valor FROM Comunicacion ...) AS Tel1,
       ...
FROM Cliente c LEFT JOIN Direccion d ON ...

Los formularios siguen apuntando a qryCliente y no se enteran.

  • 7. Guardarraíles críticos (más estrictos que en UX)
  • Nunca ALTER TABLE en producción sin script reversible.
  • Toda migración con backfill idempotente y verificación de conteos.
  • Congelar escritura en tablas que se migran (solo lectura durante la fase).
  • Doble escritura transitoria si hay usuarios concurrentes (trigger o VBA).
  • Nombres de campos viejos preservados como columnas calculadas hasta el final.
  • VBA que referencia campos debe migrarse junto con el esquema, o usar las vistas.
  • Reportes históricos pueden requerir mantener el esquema viejo en paralelo (data warehouse).
  • Auditoría de cada cambio: quién, cuándo, qué script, resultado.
  • 8. ¿Cómo lo guía el LLM vía MCP?

El flujo típico sería:

  1. exportar_logica_negocio() → el LLM lee queries + VBA + eventos.
  2. generar_diccionario_datos() → el LLM infiere significado de cada campo.
  3. detectar_problemas_modelo() → lista de deudas con severidad.
  4. Tú eliges qué atacar primero (recomendado: entidad con más dolor operativo).
  5. proponer_esquema_objetivo(entidad) → diagrama + DDL propuesto.
  6. generar_vistas_compatibilidad() → puente.
  7. generar_script_migracion()+backfill.
  8. Tú revisas el script, lo corres en copia, validas.
  9. repuntar_objetos() → actualiza RecordSource de formularios/reportes a las nuevas fuentes si aplica.
  10. detectar_regresiones() → abre formularios, corre pruebas, reporta errores.
  11. 9. Lo que no debería hacer el MCP solo
  12. Ejecutar DDL en producción sin revisión humana.
  13. Decidir el modelo objetivo sin consultarte: el negocio lo sabes tú.
  14. Renombrar campos sin actualizar todo lo que los referencia (usar vistas evita esto).
  15. Asumir que lo que hay está mal: a veces el esquema viejo codifica reglas que ya no están escritas en ningún lado. Documentar antes de romper.
  16. 10. Coste y pragmatismo (por tu nota de los 10 mil)

Un refactor de L3 completo en Access es semanas o meses. Lo realista con presupuesto cero:

  1. exportar_logica_negocio() + diccionario → gratis, alto valor.
  2. Detectar las 3-5 peores deudas de modelo → gratis, claridad.
  3. Vistas de compatibilidad para la entidad más dolorosa → 1 fin de semana.
  4. Refactor VBA de reglas duplicadas a un módulo → gratis, menos bugs.
  5. Dejar L3 para cuando haya presupuesto o cuando el dolor supere el coste.

Puedes empezar mañana con un script Python que exporte esquema + queries + VBA a texto, lo metas en git, y lo pases por el LLM para el diccionario. Sin MCP siquiera: un export.py y un prompt.

Autor: Alejandro Noli

Created: 2026-10-05 lun 09:01

Validate

Comentarios

Entradas más populares de este blog

La dama de las siete

Partido de ping pong