Usare SQL MCP Server con modelli locali

Importante

Il server MCP (SQL Model Context Protocol) è disponibile in Generatore API dati versione 1.7. Per le funzionalità e le correzioni di bug più recenti, usare la versione di anteprima 2.0.

Sql Model Context Protocol (MCP) Server funziona con qualsiasi client compatibile con MCP, non solo con i servizi di intelligenza artificiale ospitati nel cloud. Se l'ambiente limita l'accesso LLM (Cloud Large Language Model), comune nelle industrie sanitarie, di difesa, di finanza, di energia e marittime, è possibile connettere un modello locale servito tramite Ollama o strumenti simili. Questa guida illustra la configurazione, la configurazione dei metadati dei campi e i modelli di richiesta che rendono affidabili i modelli locali di piccole dimensioni.

Prerequisiti

  • CLI di Data API Builder installata e configurata con almeno un'entità. Installare la CLI.
  • Ollama con un modello che supporta la chiamata di strumenti (ad esempio, qwen3:8b, llama3.1:8b).
  • Python 3.10+ con i pacchetti mcp e ollama.
  • Istanza di SQL Server in esecuzione con i dati.

Passaggio 1: Configurare i metadati dei campi

I metadati dei campi sono il passaggio di configurazione più importante per l'accuratezza del modello locale. Senza nomi di campo e descrizioni, gli agenti visualizzano solo nomi di entità e indovinano erroneamente i nomi delle colonne.

Avvertimento

Ignorare questo passaggio genera un server MCP che tecnicamente funziona, ma non è utilizzabile dal punto di vista funzionale da qualsiasi modello che legge le risposte degli strumenti. Il modello non dispone di informazioni sulle tue colonne.

Aggiungere l'entità con una descrizione, quindi aggiungere descrizioni dei campi che includono valori validi per le colonne vincolate:

dab add ServerInventory \
  --source dbo.ServerInventory \
  --permissions "anonymous:read" \
  --description "SQL Server instance inventory with version, environment, and sizing data"

dab update ServerInventory \
  --fields.name InstanceName --fields.primary-key true \
  --fields.description "SQL Server instance name (e.g., YOURSERVER01)"

dab update ServerInventory \
  --fields.name Environment \
  --fields.description "Deployment environment. Valid values: Prod, Dev, Test, UAT"

Per informazioni di riferimento complete sull'interfaccia della riga di comando e procedure consigliate, inclusi valori vincolati, descrizioni dei parametri e modelli di scripting, vedere Aggiungere descrizioni alle entità.

Note

La dab update CLI tratta le virgole come separatori di argomenti. Se la descrizione contiene virgole, modificare dab-config.json direttamente.

Passaggio 2: Avviare SQL MCP Server

dab start

SQL MCP Server è in ascolto su http://localhost:5000/mcp tramite il trasporto HTTP streamable per impostazione predefinita. Qualsiasi client che implementa il protocollo MCP può connettersi a questo endpoint.

Passaggio 3: Connettere il modello locale

Creare un client MCP che connette il modello Ollama a SQL MCP Server. L'esempio di Python seguente usa MCP Python SDK e il pacchetto /ollama.

Installa le dipendenze

pip install mcp ollama

Minimo Python imbracatura

import asyncio
import json
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client
import ollama

MCP_URL = "http://localhost:5000/mcp"
MODEL = "qwen3:8b"

async def get_schema(session: ClientSession) -> str:
    """Call describe_entities and format results for the system prompt."""
    result = await session.call_tool("describe_entities", arguments={})
    entities = json.loads(result.content[0].text)
    lines = []
    for entity in entities.get("entities", []):
        fields = ", ".join(
            f"{f['name']} ({f.get('description', 'no description')})"
            for f in entity.get("fields", [])
        )
        lines.append(f"- {entity['name']}: {entity.get('description', '')}")
        if fields:
            lines.append(f"  Fields: {fields}")
    return "\n".join(lines)

async def run(user_question: str):
    async with streamable_http_client(MCP_URL) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Preinject schema into the system prompt
            schema_text = await get_schema(session)
            system_prompt = f"""You query a SQL database through MCP tools.

Available entities:
{schema_text}

Rules:
- Use the exact field names shown above.
- Answer count questions with the count only.
- Do not produce summaries unless asked.
- Do not invent example data. Only return data from tool responses.
- If no results, say "No results found" and stop.
"""
            # Get available tools for Ollama
            tools_result = await session.list_tools()
            ollama_tools = [
                {
                    "type": "function",
                    "function": {
                        "name": t.name,
                        "description": t.description or "",
                        "parameters": t.inputSchema,
                    },
                }
                for t in tools_result.tools
            ]

            messages = [
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": user_question},
            ]

            # Chat loop: let the model call tools until it produces a final answer
            while True:
                response = ollama.chat(
                    model=MODEL, messages=messages, tools=ollama_tools
                )
                msg = response["message"]
                messages.append(msg)

                if not msg.get("tool_calls"):
                    print(msg["content"])
                    break

                for tc in msg["tool_calls"]:
                    result = await session.call_tool(
                        tc["function"]["name"],
                        arguments=tc["function"]["arguments"],
                    )
                    messages.append(
                        {
                            "role": "tool",
                            "content": result.content[0].text,
                        }
                    )

asyncio.run(run("How many SQL 2019 servers are in production?"))

Questo cablaggio gestisce il ciclo completo: preiscizione dello schema, individuazione degli strumenti, chiamata di strumenti a più turni ed estrazione di risposte finali. Modifica MODEL e MCP_URL in base al tuo ambiente.

Preiniettare lo schema all'avvio

I modelli locali di piccole dimensioni (con parametri 14B) producono chiamate di strumenti più affidabili quando i metadati dello schema si trovano nella richiesta di sistema prima dell'inizio della conversazione. Invece di affidarsi al modello perché richiami autonomamente describe_entities durante la conversazione, richiamalo all'avvio dell'harness e inseriscine il risultato.

Perché la preiscizione è importante

Approccio Comportamento con modelli di piccole dimensioni
Individuazione dinamica Il modello deve decidere di chiamare describe_entities prima, quindi interpretare i risultati, quindi chiamare lo strumento corretto con nomi di campo corretti. Molteplici punti di guasto.
Preiniezione Il modello visualizza immediatamente nomi di entità, nomi di campo e descrizioni. Correggete le chiamate agli strumenti al primo tentativo.

L'esempio di harness nella sezione precedente illustra questo modello. La get_schema() funzione chiama describe_entities una volta all'avvio e formatta il risultato nel prompt di sistema.

Tip

I modelli cloud più grandi (GPT-4o, Claude) in genere individuano lo schema durante la conversazione senza preinfrazione. Questo schema è particolarmente utile per i modelli con meno di 14 miliardi di parametri.

Vincolare le risposte del modello

Un modello può effettuare una chiamata allo strumento corretta, recuperare i dati corretti e produrre comunque una risposta errata. Ad esempio, a un modello a cui venga chiesto "quanti server di produzione?" potrebbe recuperare correttamente 16 righe, per poi rispondere con un riepilogo esecutivo di 40 righe contenente esempi inventati anziché il numero 16.

Aggiungere regole negative esplicite al prompt del sistema:

Rules:
- Answer count questions with the count only.
- Do not produce summaries unless the user asks for one.
- Do not invent example data. Only return data from tool responses.
- If a tool returns no results, say "No results found" and stop.

La fedeltà nell'invocazione degli strumenti e la disciplina nelle risposte sono problemi diversi. DAB garantisce un recupero preciso dei dati attraverso il livello degli strumenti. Il prompt harness controlla il modo in cui il modello presenta i risultati.

Considerations

Argomento Dettagli
Hardware La chiamata di strumenti funziona anche su hardware poco potente. Un modello con parametri 8B su una GPU Nvidia consumer (8 GB di RAM video) produce risultati utili. Prevedi una latenza dell'ordine di decine di secondi per ogni domanda, adatta ai carichi di lavoro batch.
Confronto tra Batch e interattivo I modelli di piccole dimensioni sono particolarmente adatti per l'elaborazione batch (report sulle prestazioni, query di inventario) in cui la tolleranza di latenza è superiore.
Disponibilità degli strumenti aggregate_records è disponibile solo nella versione di anteprima 2.0 e successive. Nella versione 1.7.x le query di conteggio e aggregazione forzano il modello a leggere tutte le righe corrispondenti. Vedere Disponibilità degli strumenti in base alla versione.
Trasporto I modelli locali si connettono tramite HTTP in streaming a /mcp. Il trasporto standard di input/output (stdio) è un'alternativa per le configurazioni a processo singolo.
Autenticazione Per lo sviluppo in locale, usa i permessi anonymous. Per la produzione, configurare l'autenticazione appropriata per l'ambiente .