Usar o SQL MCP Server com modelos locais

Importante

O SERVIDOR MCP (Protocolo de Contexto do Modelo SQL) está disponível no Construtor de API de Dados versão 1.7. Para os recursos mais recentes e correções de bug, use a versão prévia 2.0.

O SERVIDOR MCP (Protocolo de Contexto do Modelo SQL) funciona com qualquer cliente compatível com MCP, não apenas com serviços de IA hospedados na nuvem. Se o seu ambiente restringe o acesso a modelos de linguagem grandes (LLMs) na nuvem — algo comum nos setores de saúde, defesa, finanças, energia e indústria marítima —, você pode conectar um modelo local disponibilizado por meio do Ollama ou de ferramentas semelhantes. Este guia aborda configuração, configuração de metadados de campo e padrões de prompt que tornam pequenos modelos locais confiáveis.

Pré-requisitos

  • CLI do Construtor de API de Dados instalada e configurada com pelo menos uma entidade. Instale a CLI.
  • Ollama com um modelo que dá suporte à chamada de ferramenta (por exemplo, qwen3:8b, ). llama3.1:8b
  • Python 3.10+ com os pacotes mcp e ollama.
  • Uma instância de SQL Server em execução com dados.

Etapa 1: Configurar metadados de campo

Os metadados de campo são a etapa de configuração mais importante para a precisão do modelo local. Sem nomes e descrições de campos, os agentes veem apenas os nomes das entidades e adivinham incorretamente os nomes das colunas.

Aviso

Ignorar essa etapa produz um servidor MCP que funciona tecnicamente, mas é funcionalmente inutilizável por qualquer modelo que leia as respostas da ferramenta. O modelo não tem informações sobre suas colunas.

Adicione sua entidade com uma descrição e adicione descrições de campo que incluam valores válidos para colunas restritas:

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"

Para obter a referência completa da CLI e as práticas recomendadas, incluindo valores restritos, descrições de parâmetro e padrões de script, consulte Adicionar descrições a entidades.

Note

A dab update CLI trata vírgulas como separadores de argumento. Se sua descrição contiver vírgulas, edite dab-config.json diretamente.

Etapa 2: Iniciar o SQL MCP Server

dab start

O SQL MCP Server escuta em http://localhost:5000/mcp usando transporte HTTP com streaming por padrão. Qualquer cliente que implemente o protocolo MCP pode se conectar a esse ponto de extremidade.

Etapa 3: Conectar seu modelo local

Crie um cliente MCP que conecte seu modelo Ollama ao SQL MCP Server. O exemplo de Python a seguir usa o MCP Python SDK e o pacote ollama.

Instalar dependências

pip install mcp ollama

Arreio de Python mínimo

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?"))

Esse arcabouço lida com o ciclo completo: pré-injeção de esquema, descoberta de ferramentas, chamadas de ferramentas em vários turnos e extração da resposta final. Ajuste MODEL e MCP_URL para seu ambiente.

Pré-injetar esquema na inicialização

Modelos locais pequenos (com parâmetros abaixo de 14B) produzem chamadas de ferramenta mais confiáveis quando os metadados de esquema estão no prompt do sistema antes do início da conversa. Em vez de depender do modelo para chamar describe_entities por conta própria durante a conversa, chame-o na inicialização do harness e injete o resultado.

Por que a pré-injeção é importante

Abordagem Comportamento com modelos pequenos
Descoberta dinâmica O modelo deve decidir chamar describe_entities primeiro, depois interpretar os resultados e, em seguida, chamar a ferramenta certa com nomes de campo corretos. Vários pontos de falha.
Pré-injeção O modelo vê nomes de entidade, nomes de campo e descrições imediatamente. Corrija as chamadas de ferramentas na primeira tentativa.

O exemplo de harness na seção anterior demonstra esse padrão. A get_schema() função chama describe_entities uma vez na inicialização e formata o resultado no prompt do sistema.

Dica

Modelos de nuvem maiores (GPT-4o, Claude) normalmente inferem o esquema durante a conversa sem pré-injeção. Esse padrão é mais valioso para modelos com parâmetros 14B.

Restringir respostas de modelo

Um modelo pode fazer uma chamada de ferramenta correta, recuperar os dados certos e ainda produzir uma resposta errada. Por exemplo, um modelo ao qual se perguntou "quantos servidores de produção?" pode recuperar 16 linhas corretamente e, em seguida, responder com um resumo executivo de 40 linhas contendo exemplos inventados em vez do número 16.

Adicione regras negativas explícitas ao prompt do 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.

A fidelidade no uso de chamadas de ferramentas e a disciplina de resposta são problemas diferentes. O DAB garante a recuperação precisa de dados por meio da camada de ferramentas. A estrutura de prompt controla como o modelo apresenta os resultados.

Considerações

Tópico Detalhes
Hardware A chamada de ferramenta funciona em hardware modesto. Um modelo de parâmetro 8B em uma GPU Nvidia de consumidor (8 GB de RAM de vídeo) produz resultados úteis. Espere uma latência na casa de dezenas de segundos por pergunta, o que é adequado para cargas de trabalho em lote.
Lote versus interativo Modelos pequenos são adequados para processamento em lote (relatórios de desempenho, consultas de inventário) em que a tolerância à latência é maior.
Disponibilidade da ferramenta aggregate_records está disponível apenas na versão prévia 2.0 e posterior. Na versão 1.7.x, as consultas de contagem e agregação forçam o modelo a ler todas as linhas correspondentes. Consulte a disponibilidade da ferramenta por versão.
Transporte Os modelos locais se conectam via HTTP com streaming a /mcp. O transporte padrão de entrada/saída (stdio) é uma alternativa para configurações de processo único.
Autenticação Para o desenvolvimento local, use as permissões anonymous. Para produção, configure a autenticação apropriada para seu ambiente.