Datalake-mcp

Servidor MCP (Model Context Protocol) para conectar un Azure Data Lake Storage Gen2 a Claude Desktop u otros agentes

Documentación

Datalake-MCP

Servidor MCP (Model Context Protocol) que expone un Azure Data Lake Storage Gen2 a Claude, permitiendo navegar por los archivos, leer su contenido en formato CSV, Parquet, texto (.txt), markdown (.md) o XML, y guardar archivos (texto, markdown, CSV, Parquet, PDF) con un índice buscable.

Listed on mcpservers.org

Cómo funciona

Arquitectura

flowchart LR
    U([Utente]) <--> C["Claude<br/>(Desktop / Code)"]
    C <-->|"MCP via stdio"| T

    subgraph S["Datalake.Mcp.Server (.NET 9)"]
        direction TB
        T["Tools/DataLakeTools<br/>tool MCP"]
        subgraph R["Lettura (streaming)"]
            direction LR
            CSV[CsvReaderService]
            PQ[ParquetReaderService]
            TXT[TextReaderService]
            XML[XmlReaderService]
            F[RowFilter]
        end
        subgraph W["Scrittura"]
            direction LR
            FW[FileWriterService]
            IDX[FileIndex]
        end
        DL[DataLakeService]
        T --> R
        T --> W
        R --> DL
        W --> DL
        R -.-> F
    end

    DL <-->|"Azure.Storage.Files.DataLake<br/>AccountName + AccountKey"| ADLS[("Azure Data Lake<br/>Storage Gen2")]
    IDX -.->|"saved-files-index.csv<br/>(ETag)"| ADLS

Flujo de lectura y consulta

sequenceDiagram
    actor U as Utente
    participant C as Claude
    participant M as Server MCP
    participant L as Data Lake

    U->>C: "Mostrami gli ordini APERTI > 1000"
    C->>M: list_filesystems / list_directory
    M->>L: navigazione
    L-->>C: filesystem, cartelle, file
    C->>M: get_parquet_schema (colonne e tipi)
    C->>M: read_parquet(filter, columns, maxRows, offset)
    M->>L: OpenReadAsync (download lazy)
    loop un row-group / riga alla volta
        L-->>M: byte necessari
        M->>M: filtro → offset → maxRows
    end
    M-->>C: righe + truncated / nextOffset
    C-->>U: risposta in linguaggio naturale
    Note over C,M: se truncated=true si richiama con offset=nextOffset

Flujo de guardado y búsqueda

sequenceDiagram
    actor U as Utente
    participant C as Claude
    participant M as Server MCP
    participant L as Data Lake

    U->>C: "Salva il report in report/2026"
    C->>M: save_csv / save_parquet / save_pdf / ...
    M->>M: validazione formato ed estensione
    M->>L: upload condizionale (If-None-Match: *)
    alt esiste già e overwrite=false
        L-->>M: errore, nessuna sovrascrittura
    else
        L-->>M: file salvato
        loop fino a 5 tentativi
            M->>L: leggi indice (ETag)
            M->>L: scrivi indice (If-Match: ETag)
        end
    end
    M-->>C: esito
    U->>C: "Trova il report"
    C->>M: search_file(nomeFile, tipoFile)
    M->>L: legge l'indice
    M-->>C: voci trovate (+ contenuto se un solo file)

Estructura de la solución

Datalake-MCP.sln
src/Datalake.Mcp.Server/         Server MCP (host .NET Generic Host, trasporto stdio)
  Configuration/DataLakeOptions.cs   Opzioni di connessione (AccountName/AccountKey/DefaultFileSystem)
  Services/DataLakeService.cs        Wrapper su Azure.Storage.Files.DataLake (navigazione, streaming)
  Services/CsvReaderService.cs       Lettura CSV con limite di righe (streaming)
  Services/ParquetReaderService.cs   Lettura Parquet a row-group, con proiezione colonne
  Services/TextReaderService.cs      Lettura file di testo/markdown riga per riga (streaming)
  Services/XmlReaderService.cs       Lettura XML tabellare elemento per elemento, con proiezione colonne
  Services/FileWriterService.cs     Costruzione/validazione dei byte da salvare (testo, CSV, Parquet, PDF)
  Services/FileIndex.cs              Indice CSV dei file salvati (upsert, parsing, ricerca)
  Tools/DataLakeTools.cs             Tool MCP esposti al client (list_filesystems, read_csv, ...)
tests/Datalake.Mcp.Server.Tests/ Test xUnit per reader CSV/Parquet/testo/XML, writer e indice

Herramientas MCP expuestas

HerramientaDescripción
list_filesystemsLista los filesystems (contenedores) de la cuenta
list_directoryLista archivos y directorios en una ruta (opcionalmente recursivo)
get_file_infoMetadatos de un archivo (tamaño, fecha de última modificación)
read_csvLee un CSV, con límite maxRows, delimitador configurable y offset para la paginación; filtro opcional filter
get_parquet_schemaDevuelve el esquema (columnas/tipos) de un Parquet sin leer sus datos
read_parquetLee un Parquet, con maxRows, proyección opcional de columnas y offset para la paginación; filtro opcional filter
read_textLee un archivo de texto (.txt), con maxLines y offset para la paginación; filtro opcional contains
read_markdownLee un archivo markdown (.md), con maxLines y offset para la paginación; filtro opcional contains
get_xml_schemaDevuelve el esquema (columnas, entre atributos y elementos) del elemento record de un XML tabular sin leer sus datos
read_xmlLee un XML tabular (raíz con elementos record repetidos), con maxRows, elemento record y proyección de columnas opcionales, y offset para la paginación; filtro opcional filter
create_folderCrea una carpeta en la raíz del filesystem o como subcarpeta de una carpeta existente (el padre debe existir; error si la carpeta ya existe)
save_textGuarda un archivo .txt en una carpeta/subcarpeta del datalake
save_markdownGuarda un archivo .md
save_csvGuarda un archivo .csv desde texto CSV (validado: mismo número de campos por línea)
save_parquetGuarda un archivo .parquet desde una lista de filas (objetos columna → valor); los tipos se deducen (bool, entero, decimal, cadena)
save_pdfGuarda un archivo .pdf desde contenido base64 (verificada la cabecera %PDF-)
search_fileBusca en el índice de archivos guardados por nomeFile (contiene, case-insensitive) y/o tipoFile (csv, parquet, pdf, md, txt) y devuelve las entradas encontradas (path utilizable con las herramientas read_*). Si el resultado es un solo archivo, devuelve también su contenido (csv, parquet, txt, md; primeras maxRows líneas, luego se continúa con read_* y nextOffset; para los pdf solo los metadatos)

Las lecturas están diseñadas para no cargar archivos completos en memoria: CSV, texto/markdown y XML se leen línea/elemento por línea/elemento deteniéndose en el límite solicitado, mientras que Parquet se lee un row-group a la vez. Los archivos remotos se abren con streaming de carga diferida (DataLakeFileClient.OpenReadAsync), que descarga solo los bytes realmente necesarios. La lectura XML deshabilita el procesamiento de DTD y la resolución de entidades externas para evitar ataques XXE.

Filtros

read_csv, read_parquet y read_xml aceptan un parámetro opcional filter: una lista de condiciones { column, operator, value } combinadas en AND, por ejemplo:

[{"column": "stato", "operator": "eq", "value": "APERTO"},
 {"column": "importo", "operator": "gt", "value": "1000"}]

Operadores: eq (=), ne (!=), gt (>), gte (>=), lt (<), lte (<=), contains, startswith, endswith, isnull, isnotnull (estos últimos dos no requieren value; una cadena vacía cuenta como null). Las comparaciones son numéricas cuando celda y valor son números (formato invariante, ej. 12.5), sobre timestamps Parquet cuando el valor es una fecha, de lo contrario textuales case-insensitive. El filtro puede referirse también a columnas no proyectadas; una columna inexistente o un operador no válido producen un error que enumera los valores permitidos.

El filtro se aplica durante la lectura en streaming, antes de offset y maxRows: la paginación (truncated/nextOffset) cuenta por tanto solo las filas que satisfacen el filtro. read_text y read_markdown aceptan en cambio contains, que selecciona las filas que contienen el texto indicado (case-insensitive).

Paginación

Las respuestas de read_csv, read_parquet, read_text, read_markdown y read_xml están sujetas al límite de tamaño de las llamadas a herramientas (aproximadamente 1 MB). Para archivos que exceden maxRows/maxLines (o el límite de tamaño), el resultado reporta truncated: true y un nextOffset: llamando nuevamente a la herramienta con offset = nextOffset se obtiene la página siguiente, saltando las filas ya devueltas sin tener que releerlas por completo. Cuando no hay más que leer, truncated es false y nextOffset es null.

Guardado de archivos e índice

Las herramientas save_* aceptan path (carpetas y subcarpetas se crean si faltan), fileSystem, description y overwrite. Sin overwrite=true un archivo existente nunca se reemplaza (carga condicional If-None-Match: *). La extensión de la ruta debe corresponder al formato.

Cada guardado registra el archivo en el índice DataLake:SavedFilesIndexPath (por defecto saved-files-index.csv, en la raíz del filesystem), un CSV legible con read_csv con columnas path,name,format,sizeBytes,savedAt,description. Guardar de nuevo la misma ruta actualiza la fila existente. El índice se actualiza con concurrencia optimista (ETag, hasta 5 intentos).

Configuración

Las credenciales de la cuenta (accountName y accountKey) nunca deben commitearse. En desarrollo, usa los .NET user-secrets desde la carpeta src/Datalake.Mcp.Server:

dotnet user-secrets init
dotnet user-secrets set "DataLake:AccountName" "<nome-account>"
dotnet user-secrets set "DataLake:AccountKey" "<chiave-account>"
dotnet user-secrets set "DataLake:DefaultFileSystem" "<container-predefinito>"

Alternativamente, mediante variables de entorno (útil para el despliegue):

$env:DataLake__AccountName = "<nome-account>"
$env:DataLake__AccountKey = "<chiave-account>"
$env:DataLake__DefaultFileSystem = "<container-predefinito>"

appsettings.json contiene solo los placeholders vacíos y puede permanecer en el repositorio.

Build, test y ejecución

dotnet build
dotnet test
dotnet run --project src/Datalake.Mcp.Server

El servidor se comunica vía stdio según el protocolo MCP: por tanto debe registrarse como servidor MCP en el cliente (ej. Claude Desktop / Claude Code), apuntando al ejecutable del proyecto Datalake.Mcp.Server, no lanzarse manualmente en una terminal interactiva.

Registro en Claude Desktop y uso del MCP

Un ejemplo de configuración está disponible en claude_desktop_config.example.json. Para usarlo:

  1. Ejecuta dotnet build src/Datalake.Mcp.Server -c Release para generar el DLL en bin/Release/net9.0. O usa el contenido de la carpeta si ya está compilado.
  2. Copia el contenido del archivo de ejemplo en el archivo de configuración de Claude Desktop (%APPDATA%\Claude\claude_desktop_config.json), uniéndolo a la clave mcpServers si ya existe.
  3. Actualiza la ruta en args si el repositorio está en otro lugar, y valora AccountName/AccountKey/DefaultFileSystem en env con las credenciales reales (nunca las commitees en el repositorio).
  4. Reinicia Claude Desktop: el servidor "datalake" aparecerá entre las herramientas disponibles.