Como Construir um Servidor MCP para Seu Data Lake
MCP (Model Context Protocol) permite que agentes de IA chamem ferramentas — como consultar um banco de dados. O DataSpoc Lens vem com um servidor MCP integrado que transforma seu data lake Parquet em uma API consultável para Claude, GPT, agentes LangGraph e qualquer cliente compatível com MCP.
Este tutorial mostra como ir de dados brutos no S3 a um servidor MCP totalmente funcional em menos de 10 minutos.
O Resultado Final
Após a configuração, qualquer agente de IA pode:
- Descobrir tabelas no seu data lake
- Inspecionar schemas e dados de amostra
- Executar consultas SQL com DuckDB
- Fazer perguntas em linguagem natural
- Obter métricas e KPIs pré-construídos
Tudo sem nenhum código customizado.
Passo 1: Ingerir Dados com Pipe
Se seus dados já estão em Parquet no S3/GCS/Azure, pule para o Passo 2. Caso contrário, extraia das suas fontes:
pip install dataspoc-pipe
dataspoc-pipe init sales-pipelinedataspoc-pipe add postgres \ --host db.company.com \ --database sales \ --tables orders,customers,products,revenue \ --incremental updated_at \ --destination s3://company-lake
dataspoc-pipe runSeu bucket agora tem:
s3://company-lake/ .dataspoc/manifest.json raw/postgres/orders/*.parquet raw/postgres/customers/*.parquet raw/postgres/products/*.parquet raw/postgres/revenue/*.parquetPasso 2: Instalar DataSpoc Lens com MCP
pip install dataspoc-lens[mcp]Isso instala o CLI core do Lens mais as dependências do servidor MCP.
Passo 3: Configurar e Iniciar o Servidor MCP
# Point Lens at your bucketdataspoc-lens add-bucket s3://company-lake
# Discover tablesdataspoc-lens discover# Found 4 tables: orders, customers, products, revenue
# Start the MCP serverdataspoc-lens mcpSaída:
DataSpoc Lens MCP Server runningTransport: stdioTables: 4 discoveredTools: 7 available - list_tables - get_schema - sample_data - query - ask - get_metrics - explain_table
Waiting for MCP client connection...Passo 4: Configurar Claude Desktop
Adicione ao seu arquivo de configuração do Claude Desktop (~/.config/claude/claude_desktop_config.json no Linux, ~/Library/Application Support/Claude/claude_desktop_config.json no macOS):
{ "mcpServers": { "data-lake": { "command": "dataspoc-lens", "args": ["mcp"], "env": { "AWS_PROFILE": "data-lake", "DATASPOC_BUCKET": "s3://company-lake" } } }}Reinicie o Claude Desktop. Você verá o ícone de ferramentas indicando 7 ferramentas disponíveis.
As 7 Ferramentas MCP
1. list_tables — Descobrir Dados Disponíveis
Chamada:
{ "tool": "list_tables"}Resposta:
{ "tables": [ {"name": "raw.postgres.orders", "rows": 1247893, "size_mb": 340}, {"name": "raw.postgres.customers", "rows": 89421, "size_mb": 12}, {"name": "raw.postgres.products", "rows": 2431, "size_mb": 1.1}, {"name": "raw.postgres.revenue", "rows": 4201847, "size_mb": 890} ]}2. get_schema — Inspecionar Estrutura da Tabela
Chamada:
{ "tool": "get_schema", "arguments": {"table": "raw.postgres.orders"}}Resposta:
{ "table": "raw.postgres.orders", "columns": [ {"name": "id", "type": "INTEGER", "nullable": false}, {"name": "customer_id", "type": "INTEGER", "nullable": false}, {"name": "product_id", "type": "INTEGER", "nullable": false}, {"name": "amount", "type": "DECIMAL(10,2)", "nullable": false}, {"name": "status", "type": "VARCHAR", "nullable": false}, {"name": "created_at", "type": "TIMESTAMP", "nullable": false}, {"name": "updated_at", "type": "TIMESTAMP", "nullable": false} ], "row_count": 1247893}3. sample_data — Visualizar Linhas de Amostra
Chamada:
{ "tool": "sample_data", "arguments": {"table": "raw.postgres.orders", "limit": 5}}Resposta:
{ "table": "raw.postgres.orders", "sample": [ {"id": 1, "customer_id": 42, "product_id": 7, "amount": 299.00, "status": "completed", "created_at": "2024-01-15T10:23:00"}, {"id": 2, "customer_id": 15, "product_id": 3, "amount": 49.99, "status": "completed", "created_at": "2024-01-15T11:05:00"}, {"id": 3, "customer_id": 42, "product_id": 12, "amount": 799.00, "status": "pending", "created_at": "2024-01-15T14:30:00"} ]}4. query — Executar SQL
Chamada:
{ "tool": "query", "arguments": { "sql": "SELECT DATE_TRUNC('month', created_at) AS month, SUM(amount) AS revenue FROM raw.postgres.orders WHERE created_at >= '2024-01-01' GROUP BY 1 ORDER BY 1" }}Resposta:
{ "columns": ["month", "revenue"], "rows": [ {"month": "2024-01-01", "revenue": 342891.50}, {"month": "2024-02-01", "revenue": 389012.75}, {"month": "2024-03-01", "revenue": 421547.00} ], "row_count": 3, "execution_time_ms": 234}5. ask — Perguntas em Linguagem Natural
Chamada:
{ "tool": "ask", "arguments": { "question": "Which customers spent the most last quarter?" }}Resposta:
{ "answer": "The top 5 customers by spending last quarter were: Acme Corp ($89,234), GlobalTech ($67,891), Initech ($54,320), Umbrella Inc ($48,900), and Wayne Enterprises ($45,670).", "sql": "SELECT c.name, SUM(o.amount) AS total_spent FROM raw.postgres.orders o JOIN raw.postgres.customers c ON o.customer_id = c.id WHERE o.created_at >= '2024-07-01' AND o.created_at < '2024-10-01' GROUP BY c.name ORDER BY total_spent DESC LIMIT 5", "data": [ {"name": "Acme Corp", "total_spent": 89234.00}, {"name": "GlobalTech", "total_spent": 67891.00}, {"name": "Initech", "total_spent": 54320.00}, {"name": "Umbrella Inc", "total_spent": 48900.00}, {"name": "Wayne Enterprises", "total_spent": 45670.00} ]}6. get_metrics — KPIs Pré-construídos
Chamada:
{ "tool": "get_metrics", "arguments": {"period": "last_30_days"}}Resposta:
{ "period": "2024-09-15 to 2024-10-15", "metrics": { "total_revenue": 487293.00, "order_count": 12847, "avg_order_value": 37.93, "unique_customers": 3421, "new_customers": 289 }}7. explain_table — Documentação dos Dados
Chamada:
{ "tool": "explain_table", "arguments": {"table": "raw.postgres.orders"}}Resposta:
{ "table": "raw.postgres.orders", "description": "Transaction records from the e-commerce platform. Each row represents one purchase.", "columns": { "id": "Unique order identifier", "customer_id": "FK to customers table", "amount": "Total order value in USD", "status": "One of: pending, completed, refunded, cancelled", "created_at": "When the order was placed" }, "relationships": ["customers (customer_id)", "products (product_id)"], "common_queries": [ "Revenue by month: SELECT DATE_TRUNC('month', created_at), SUM(amount) FROM orders GROUP BY 1", "Orders by status: SELECT status, COUNT(*) FROM orders GROUP BY 1" ]}Conversação Multi-turno Realista com Agente
Veja como fica quando o Claude usa o servidor MCP:
Usuário: “Como está a tendência da nossa retenção? Estamos perdendo clientes?”
Chamadas internas de ferramentas do Claude:
- Chama
list_tablespara ver quais dados estão disponíveis - Chama
get_schema("raw.postgres.orders")para entender a estrutura de pedidos - Chama
get_schema("raw.postgres.customers")para verificar datas de cadastro - Chama
querycom:
WITH monthly_cohorts AS ( SELECT DATE_TRUNC('month', c.created_at) AS cohort_month, DATE_TRUNC('month', o.created_at) AS order_month, COUNT(DISTINCT o.customer_id) AS active_customers FROM raw.postgres.customers c JOIN raw.postgres.orders o ON c.id = o.customer_id WHERE c.created_at >= '2024-01-01' GROUP BY 1, 2),cohort_sizes AS ( SELECT cohort_month, COUNT(DISTINCT id) AS cohort_size FROM raw.postgres.customers WHERE created_at >= '2024-01-01' GROUP BY 1)SELECT mc.cohort_month, mc.order_month, mc.active_customers, cs.cohort_size, ROUND(mc.active_customers::FLOAT / cs.cohort_size * 100, 1) AS retention_pctFROM monthly_cohorts mcJOIN cohort_sizes cs ON mc.cohort_month = cs.cohort_monthORDER BY mc.cohort_month, mc.order_monthResposta do Claude:
Analisando os dados de retenção por coorte, aqui está a tendência:
Coorte Mês 1 Mês 2 Mês 3 Mês 6 Jan 2024 100% 68% 52% 34% Abr 2024 100% 71% 55% 38% Jul 2024 100% 74% 59% — Boas notícias: a retenção está na verdade melhorando. A retenção do Mês 2 foi de 68% para 74% ao longo do ano. As mudanças de produto no Q2 (onboarding self-serve) parecem estar funcionando.
Porém, a queda no Mês 6 para 34% sugere que perdemos clientes por volta da marca de 6 meses — possivelmente quando contratos anuais vencem para renovação.
Modelo de Segurança
O servidor MCP é somente leitura por design:
- Nenhuma instrução INSERT, UPDATE, DELETE, DROP ou CREATE é permitida
- Consultas são validadas antes da execução
- O servidor roda com as permissões IAM do processo (seu perfil AWS)
- Controle de acesso no nível do bucket significa que agentes só veem dados que estão autorizados a ver
# Agent can only access buckets your IAM role permitsexport AWS_PROFILE=analyst # Has access to s3://company-product onlydataspoc-lens mcp # Only exposes tables in permitted bucketsSem chaves de API para gerenciar. Sem tokens de autenticação. Apenas IAM.
SDK Python para CrewAI / LangGraph
Se você está construindo agentes em Python em vez de usar o Claude Desktop, use o SDK diretamente:
from dataspoc_lens import LensClient
# Initialize (reads from same config as CLI)client = LensClient(bucket="s3://company-lake")
# Same capabilities as MCP toolstables = client.list_tables()schema = client.get_schema("raw.postgres.orders")result = client.query("SELECT COUNT(*) FROM raw.postgres.orders")answer = client.ask("What's our churn rate?")Integração com CrewAI
from crewai import Agent, Task, Crewfrom crewai_tools import toolfrom dataspoc_lens import LensClient
client = LensClient()
@tooldef query_data_lake(sql: str) -> str: """Execute a SQL query against the company data lake.""" result = client.query(sql) return str(result)
@tooldef discover_tables() -> str: """List all available tables in the data lake.""" tables = client.list_tables() return "\n".join([f"{t['name']} ({t['rows']} rows)" for t in tables])
analyst = Agent( role="Data Analyst", goal="Answer business questions using SQL on the data lake", tools=[query_data_lake, discover_tables], llm="gpt-4o",)
task = Task( description="Analyze customer lifetime value by acquisition channel", agent=analyst,)
crew = Crew(agents=[analyst], tasks=[task])result = crew.kickoff()Integração com LangGraph
Veja o tutorial completo: Construindo um Agente Analista de Dados com LangGraph.
O Padrão AGENT.md
Para agentes que trabalham autonomamente com seu data lake, crie um arquivo AGENT.md que descreve os dados disponíveis:
# Data Lake Agent Instructions
## Available Data
You have access to a data lake via the DataSpoc Lens MCP server.
## Tables
- `raw.postgres.orders` — All orders (1.2M rows). Key columns: customer_id, amount, status, created_at- `raw.postgres.customers` — Customer profiles (89K rows). Key columns: name, email, plan, created_at- `raw.postgres.products` — Product catalog (2.4K rows). Key columns: name, category, price- `curated.finance.revenue` — Monthly revenue rollups (4.2M rows). Key columns: month, mrr, arr, churn_rate
## Common Queries
- Revenue by month: `SELECT DATE_TRUNC('month', created_at), SUM(amount) FROM raw.postgres.orders GROUP BY 1`- Active customers: `SELECT COUNT(DISTINCT customer_id) FROM raw.postgres.orders WHERE created_at > CURRENT_DATE - INTERVAL '30 days'`- Churn: `SELECT month, churn_rate FROM curated.finance.revenue ORDER BY month DESC LIMIT 12`
## Rules
- Always use the `query` tool for exact numbers- Use `ask` for exploratory questions when you're not sure about the schema- Never modify data — all queries are read-only- When presenting numbers, always show the SQL you used (for auditability)Coloque isso na raiz do seu projeto. Agentes que leem contexto do projeto (Claude Code, Cursor, Cline) vão usá-lo para entender como interagir com seus dados.
Executando em Produção
Para deploys em produção, rode o servidor MCP como um processo persistente:
# systemd service[Unit]Description=DataSpoc Lens MCP ServerAfter=network.target
[Service]Type=simpleUser=dataspocExecStart=/usr/local/bin/dataspoc-lens mcp --transport sse --port 8080Environment=AWS_PROFILE=data-lakeEnvironment=DATASPOC_BUCKET=s3://company-lakeRestart=always
[Install]WantedBy=multi-user.targetOu com Docker:
FROM python:3.11-slimRUN pip install dataspoc-lens[mcp]ENV DATASPOC_BUCKET=s3://company-lakeCMD ["dataspoc-lens", "mcp", "--transport", "sse", "--port", "8080"]docker run -d \ -p 8080:8080 \ -e AWS_ACCESS_KEY_ID \ -e AWS_SECRET_ACCESS_KEY \ -e DATASPOC_BUCKET=s3://company-lake \ dataspoc-lens-mcpResumo
Em 4 passos, você transformou um monte de arquivos Parquet em uma API inteligente para agentes de IA:
- Ingira dados com Pipe (ou traga seu próprio Parquet)
- Instale
dataspoc-lens[mcp] - Inicie
dataspoc-lens mcp - Conecte Claude Desktop, LangGraph, CrewAI ou qualquer cliente MCP
Seu data lake agora é uma ferramenta de primeira classe para qualquer agente de IA — descobrível, consultável e seguro.