structured.sh
Servidor MCP auto-hospedado para memória persistente de agentes. Defina esquemas tipados, escreva registros e consulte com SQL via DuckDB em arquivos Parquet no disco.
Documentação
■ structured
memória nativa de esquema para agentes de IA
structured.sh · Início Rápido · Conectar ao Claude · Ferramentas MCP · Referência da API · Implantação
Defina esquemas. Escreva dados estruturados. Consulte com SQL. Tudo como arquivos Parquet que você possui.
docker compose up
O que é isso?
Structured dá aos agentes de IA (e humanos) memória persistente e consultável:
- Defina uma memória — nome + esquema tipado (como uma tabela)
- Escreva registros — armazenados em buffer e liberados automaticamente para arquivos Parquet
- Consulte com SQL — DuckDB executa diretamente contra os arquivos Parquet
- Possua seus dados — tudo são arquivos locais no disco, sem dependência de fornecedor
Funciona com Claude Desktop, Cursor, Windsurf, Cline ou qualquer cliente compatível com MCP.
Arquitetura
┌──────────────────────────────────────────────────────┐
│ docker compose up │
│ │
│ ┌──────────┐ ┌──────────────┐ ┌────────────┐ │
│ │Dashboard │ │ REST API │ │ MCP Server │ │
│ │ :3000 │───▶│ :3001 │◀───│ stdio │ │
│ │ │ │ │ │ │ │
│ │Vite+React│ │ Hono + WASM │ │ 9 tools │ │
│ └──────────┘ │ │ └────────────┘ │
│ │ SQLite (sql.js) │
│ │ DuckDB (wasm) │
│ │ Parquet (tiny-parquet) │
│ └──────┬───────┘ │
│ │ │
│ ./data/ │
│ ├── structured.db ← metadata │
│ └── parquet/ ← your data │
│ ├── user_prefs/ │
│ │ └── 2026/04/09/...parquet │
│ └── campaign_data/ │
│ └── 2026/04/09/...parquet │
└──────────────────────────────────────────────────────┘
Zero dependências nativas. Tudo roda em WASM — sem compilações C++, sem problemas de plataforma.
Início Rápido
1. Clone e configure
git clone https://github.com/structured-sh/structured.git
cd structured
Edite docker-compose.yml e defina suas credenciais:
environment:
- API_KEY=your-secret-api-key # Used by MCP clients & scripts
- DASHBOARD_PASSWORD=your-password # Protects the dashboard UI
Duas credenciais separadas:
API_KEY— autenticação de máquina para clientes MCP, scripts e ingestão de análisesDASHBOARD_PASSWORD— autenticação humana para o painel web. Deixe não definido para desativar o login (uso apenas local).
2. Inicie o stack
docker compose up -d
| Serviço | URL |
|---|---|
| Painel | http://localhost:3000 |
| API | http://localhost:3001 |
| MCP | stdio (conectado automaticamente) |
3. Crie uma memória
curl -X POST http://localhost:3001/memories \
-H "Authorization: Bearer your-secret-api-key" \
-H "Content-Type: application/json" \
-d '{
"name": "user_preferences",
"fields": [
{ "name": "key", "type": "string" },
{ "name": "value", "type": "string" },
{ "name": "priority", "type": "int32" }
],
"description": "User preference settings"
}'
4. Escreva dados
curl -X POST http://localhost:3001/memories/user_preferences/write \
-H "Authorization: Bearer your-secret-api-key" \
-H "Content-Type: application/json" \
-d '{
"data": [
{ "key": "theme", "value": "dark", "priority": 1 },
{ "key": "language", "value": "en", "priority": 2 }
]
}'
5. Consulte com SQL
curl -X POST http://localhost:3001/query \
-H "Authorization: Bearer your-secret-api-key" \
-H "Content-Type: application/json" \
-d '{ "sql": "SELECT * FROM user_preferences ORDER BY priority" }'
Os nomes de memória funcionam como nomes de tabela — o DuckDB os resolve para arquivos Parquet automaticamente.
6. Acesse arquivos brutos
# Files on disk
ls ./data/parquet/user_preferences/
# DuckDB CLI
duckdb -c "SELECT * FROM read_parquet('./data/parquet/user_preferences/**/*.parquet')"
# Python
import duckdb
duckdb.sql("SELECT * FROM './data/parquet/user_preferences/**/*.parquet'").show()
Conectar ao Claude / Cursor
Local (Docker)
Adicione a ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"structured": {
"command": "docker",
"args": ["exec", "-i", "structured-mcp", "node", "index.js"]
}
}
}
Para Cursor, adicione em Configurações → Recursos → Servidores MCP:
{
"structured": {
"command": "docker",
"args": ["exec", "-i", "structured-mcp", "node", "index.js"]
}
}
Nuvem (structured.sh)
Em breve — versão hospedada em structured.sh
{
"mcpServers": {
"structured": {
"command": "npx",
"args": ["-y", "@anthropic-ai/mcp-proxy", "https://mcp.structured.sh"]
}
}
}
Ferramentas MCP
Depois de conectado, basta falar naturalmente. A IA escolhe a ferramenta certa.
| Ferramenta | O que dizer |
|---|---|
create_memory | "Crie uma memória para rastrear vendas diárias com campos: data, receita, unidades" |
list_memories | "Que memórias eu tenho?" |
describe_memory | "Mostre-me o esquema para daily_sales" |
write_memory | "Salve as vendas de hoje: data=2026-04-09, receita=1250.50, unidades=42" |
query_memory | "Qual é a receita total deste mês?" |
store_document | "Lembre-se desta configuração para depois" |
get_document | "Obtenha o documento abc-123" |
flush_memory | "Libere todos os dados pendentes para o disco" |
delete_memory | "Exclua a memória test_data" |
Ingerindo Dados de Seus Aplicativos
Use os modelos em templates/ para enviar eventos de sistemas externos:
| Modelo | Caso de uso |
|---|---|
templates/ingest-app-analytics.js | Eventos de aplicativos móveis/web (instalações, ações, compras) |
templates/ingest-webhook.js | Webhooks do Stripe, GitHub, Shopify |
templates/query-report.js | Gere relatórios SQL → terminal, Markdown ou Slack |
// Example: track an install from your iOS app
import { track } from './templates/ingest-app-analytics.js';
await track('install', 'user_abc', { platform: 'ios', app_version: '1.0.0' });
Então consulte todos os seus eventos:
SELECT event, COUNT(*) as n, COUNT(DISTINCT user_id) as users
FROM app_events
WHERE timestamp > now() - INTERVAL '30 days'
GROUP BY event ORDER BY n DESC
Fila de Mensagens Mortas
Registros rejeitados pelos modos de esquema strict ou evolve não são descartados — eles são automaticamente gravados em _dlq_{memory_name} para inspeção:
-- See what was rejected and why
SELECT _reason, _payload, _rejected_at
FROM _dlq_app_events
ORDER BY _rejected_at DESC
LIMIT 20
Rotação de Chave de API
Gire sua chave de API a qualquer momento na página Conectar do painel sem reiniciar:
- Vá para Conectar → seção Chave de API
- Clique em Girar Chave
- Copie a nova chave (mostrada uma vez)
- Atualize sua configuração MCP e quaisquer scripts
A chave antiga é invalidada imediatamente.
Referência da API
Autenticação (Painel)
| Método | Caminho | Descrição |
|---|---|---|
GET | /auth/status | Verifica se a autenticação do painel está habilitada |
POST | /auth/login | Login com { password }, retorna token de sessão |
GET | /auth/me | Valida a sessão atual (cabeçalho X-Session-Token) |
POST | /auth/logout | Logout (o cliente descarta o token) |
Memórias
| Método | Caminho | Descrição |
|---|---|---|
GET | /memories | Listar todas as memórias |
POST | /memories | Criar uma memória |
GET | /memories/:name | Obter detalhes da memória |
PUT | /memories/:name | Atualizar memória |
DELETE | /memories/:name | Excluir memória |
POST | /memories/:name/write | Escrever registros |
POST | /memories/:name/flush | Liberar para Parquet |
GET | /memories/:name/preview | Visualizar dados |
GET | /memories/:name/files | Listar arquivos Parquet |
Consulta
| Método | Caminho | Descrição |
|---|---|---|
POST | /query | Executar SQL do DuckDB |
Armazenamento (Documentos)
| Método | Caminho | Descrição |
|---|---|---|
POST | /documents | Armazenar um documento JSON |
GET | /documents/collections | Listar coleções |
GET | /documents/:collection | Listar documentos |
DELETE | /documents/:collection/:id | Excluir documento |
Configurações
| Método | Caminho | Descrição |
|---|---|---|
GET | /settings/api-key | Obter chave de API atual mascarada |
POST | /settings/rotate-key | Gerar nova chave de API |
Arquivos
| Método | Caminho | Descrição |
|---|---|---|
GET | /files/* | Baixar arquivo Parquet bruto |
MCP (SSE)
| Método | Caminho | Descrição |
|---|---|---|
GET | /sse | Fluxo SSE para clientes MCP |
POST | /messages | Mensagens JSON-RPC |
Modos de Esquema
| Modo | Comportamento |
|---|---|
flex | Aceitar todos os campos, sem validação (padrão) |
evolve | Aceitar todos, detectar e registrar desvio de esquema |
strict | Rejeitar registros com campos incompatíveis → DLQ |
Tipos de Campo
| Tipo | Tipo Parquet | Observações |
|---|---|---|
string | BYTE_ARRAY (UTF-8) | Padrão |
int32 | INT32 | |
int64 | INT64 | |
float32 | FLOAT | |
float64 | DOUBLE | |
boolean | BOOLEAN | |
timestamp | INT64 (millis) | ms Unix, UTC |
Stack
Apenas 7 pacotes npm. Sem complementos nativos — tudo roda em WASM ou JS puro.
| Pacote | O que faz |
|---|---|
hono + @hono/node-server | Roteador HTTP — API rápida e padrão Web |
@duckdb/duckdb-wasm | Mecanismo de consulta SQL, roda totalmente em WASM |
sql.js | SQLite em WASM — armazena metadados de esquema |
tiny-parquet | Escritor Parquet em JS puro, zero dependências nativas |
@modelcontextprotocol/sdk | Registro de servidor/ferramenta MCP |
zod | Validação de esquema para entradas de API |
Runtime: Node.js ≥ 20
Como tudo roda em WASM, não há compilações C++, sem node-gyp, sem binários específicos de plataforma. A imagem Docker funciona em qualquer arquitetura que o Docker suporte.
Desenvolvimento
# Local dev (no Docker)
cd api && npm install && node index.js
cd dashboard && npm install && npm run dev
# Full stack
docker compose up --build
Licença
Apache 2.0
Construído com tiny-parquet · Alimentado por DuckDB · structured.sh