Skip to content

Commit 36ed2b5

Browse files
authored
Merge pull request #75 from decocms/feat/registry-updates-from-main
Feat/registry updates from main
2 parents 1fc0d1c + 715d3bb commit 36ed2b5

File tree

8 files changed

+1786
-387
lines changed

8 files changed

+1786
-387
lines changed

registry/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1-
.dev.vars
1+
.dev.vars
2+
.env

registry/package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@
1313
"check": "tsc --noEmit",
1414
"build:server": "NODE_ENV=production bun build server/main.ts --target=bun --outfile=dist/server/main.js",
1515
"build": "bun run build:server",
16-
"publish": "cat app.json | deco registry publish -w /shared/deco -y"
16+
"publish": "cat app.json | deco registry publish -w /shared/deco -y",
17+
"sync:supabase": "bun run scripts/populate-supabase.ts",
18+
"sync:supabase:force": "FORCE_UPDATE=true bun run scripts/populate-supabase.ts",
19+
"enrich:ai": "bun run scripts/enrich-with-ai.ts",
20+
"enrich:ai:force": "bun run scripts/enrich-with-ai.ts --force",
21+
"enrich:ai:test": "bun run scripts/enrich-with-ai.ts --limit=3",
22+
"enrich:ai:retry": "bun run scripts/enrich-with-ai.ts --limit=400"
1723
},
1824
"dependencies": {
1925
"@decocms/bindings": "^1.0.3",
2026
"@decocms/runtime": "^1.0.3",
27+
"@supabase/supabase-js": "^2.89.0",
2128
"zod": "^3.24.3"
2229
},
2330
"devDependencies": {

registry/scripts/create-table.sql

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
-- ═══════════════════════════════════════════════════════════════
2+
-- MCP Servers Table for Registry
3+
--
4+
-- This table stores ALL data from the MCP Registry API plus
5+
-- additional metadata from the Mesh (tags, categories, etc.)
6+
--
7+
-- Run this in your Supabase SQL Editor
8+
-- ═══════════════════════════════════════════════════════════════
9+
10+
CREATE TABLE IF NOT EXISTS mcp_servers (
11+
-- ═══════════════════════════════════════════════════════════════
12+
-- DADOS ORIGINAIS DO REGISTRY (indexados)
13+
-- ═══════════════════════════════════════════════════════════════
14+
15+
-- Identificação (chave primária composta para suportar múltiplas versões)
16+
name TEXT NOT NULL, -- "ai.exa/exa"
17+
version TEXT NOT NULL, -- "3.1.3"
18+
PRIMARY KEY (name, version),
19+
schema_url TEXT, -- "$schema" URL
20+
21+
-- Conteúdo
22+
description TEXT, -- Descrição original do registry (duplicada em short_description)
23+
website_url TEXT,
24+
25+
-- Objetos complexos (JSONB para queries flexíveis)
26+
repository JSONB, -- {"url": "...", "source": "github"}
27+
remotes JSONB, -- [{"type": "streamable-http", "url": "..."}]
28+
packages JSONB, -- [{"type": "npm", "name": "..."}]
29+
icons JSONB, -- [{"src": "...", "mimeType": "..."}]
30+
31+
-- Metadados oficiais do registry
32+
registry_status TEXT DEFAULT 'active', -- status do registry oficial
33+
published_at TIMESTAMPTZ,
34+
registry_updated_at TIMESTAMPTZ,
35+
is_latest BOOLEAN DEFAULT TRUE,
36+
37+
-- ═══════════════════════════════════════════════════════════════
38+
-- DADOS EXTRAS DA MESH (agregados)
39+
-- ═══════════════════════════════════════════════════════════════
40+
41+
-- Metadados descritivos enriquecidos
42+
friendly_name TEXT, -- Nome amigável para UI
43+
short_description TEXT, -- Cópia do description (para consistência com outros campos mesh)
44+
mesh_description TEXT, -- Descrição completa markdown (será populada por IA/manual)
45+
tags TEXT[], -- ["search", "web", "ai"]
46+
categories TEXT[], -- ["productivity", "research"]
47+
48+
-- Flags da Mesh (curadas manualmente ou por AI)
49+
verified BOOLEAN DEFAULT FALSE, -- Verificado pela mesh
50+
unlisted BOOLEAN DEFAULT TRUE, -- TRUE = não aparece (padrão), FALSE = aparece (allowlist)
51+
has_oauth BOOLEAN DEFAULT FALSE, -- Requer OAuth/autenticação
52+
53+
-- Flags computadas (preenchidas pelo script de sync)
54+
has_remote BOOLEAN DEFAULT FALSE, -- remotes IS NOT NULL AND jsonb_array_length(remotes) > 0
55+
is_npm BOOLEAN DEFAULT FALSE, -- packages contém type: "npm"
56+
is_local_repo BOOLEAN DEFAULT FALSE, -- só tem repository, sem remote/npm
57+
58+
-- ═══════════════════════════════════════════════════════════════
59+
-- CONTROLE INTERNO
60+
-- ═══════════════════════════════════════════════════════════════
61+
created_at TIMESTAMPTZ DEFAULT NOW(),
62+
updated_at TIMESTAMPTZ DEFAULT NOW()
63+
);
64+
65+
-- ═══════════════════════════════════════════════════════════════
66+
-- INDEXES
67+
-- ═══════════════════════════════════════════════════════════════
68+
69+
-- Filtros principais
70+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_is_latest ON mcp_servers(is_latest);
71+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_verified ON mcp_servers(verified);
72+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_unlisted ON mcp_servers(unlisted);
73+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_has_remote ON mcp_servers(has_remote);
74+
75+
-- Índice composto para listagem (query mais comum: is_latest=true + unlisted=false)
76+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_listing ON mcp_servers(is_latest, unlisted, verified DESC, name);
77+
78+
-- Busca por arrays
79+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_tags ON mcp_servers USING GIN(tags);
80+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_categories ON mcp_servers USING GIN(categories);
81+
82+
-- Full-text search
83+
CREATE INDEX IF NOT EXISTS idx_mcp_servers_search ON mcp_servers USING GIN(
84+
to_tsvector('english', coalesce(name, '') || ' ' ||
85+
coalesce(description, '') || ' ' ||
86+
coalesce(friendly_name, '') || ' ' ||
87+
coalesce(short_description, ''))
88+
);
89+
90+
-- Ordenação comum (deprecated - use idx_mcp_servers_listing)
91+
-- CREATE INDEX IF NOT EXISTS idx_mcp_servers_verified_name ON mcp_servers(verified DESC, name);
92+
93+
-- ═══════════════════════════════════════════════════════════════
94+
-- TRIGGERS
95+
-- ═══════════════════════════════════════════════════════════════
96+
97+
-- Auto-update updated_at timestamp
98+
CREATE OR REPLACE FUNCTION update_updated_at_column()
99+
RETURNS TRIGGER AS $$
100+
BEGIN
101+
NEW.updated_at = NOW();
102+
RETURN NEW;
103+
END;
104+
$$ language 'plpgsql';
105+
106+
DROP TRIGGER IF EXISTS update_mcp_servers_updated_at ON mcp_servers;
107+
CREATE TRIGGER update_mcp_servers_updated_at
108+
BEFORE UPDATE ON mcp_servers
109+
FOR EACH ROW
110+
EXECUTE FUNCTION update_updated_at_column();
111+
112+
-- ═══════════════════════════════════════════════════════════════
113+
-- RLS POLICIES (Row Level Security)
114+
-- ═══════════════════════════════════════════════════════════════
115+
116+
-- Enable RLS
117+
ALTER TABLE mcp_servers ENABLE ROW LEVEL SECURITY;
118+
119+
-- Allow public read access (anon key) - only visible (non-unlisted) items
120+
CREATE POLICY "Allow public read access" ON mcp_servers
121+
FOR SELECT
122+
USING (unlisted = false);
123+
124+
-- Allow authenticated users to insert/update (service role key)
125+
CREATE POLICY "Allow service role full access" ON mcp_servers
126+
FOR ALL
127+
USING (auth.role() = 'service_role');
128+
129+
-- ═══════════════════════════════════════════════════════════════
130+
-- COMMENTS
131+
-- ═══════════════════════════════════════════════════════════════
132+
133+
COMMENT ON TABLE mcp_servers IS 'MCP servers indexed from the official registry with mesh metadata';
134+
COMMENT ON COLUMN mcp_servers.name IS 'Unique server name from registry (e.g., ai.exa/exa)';
135+
COMMENT ON COLUMN mcp_servers.verified IS 'Whether the server is verified by mesh';
136+
COMMENT ON COLUMN mcp_servers.unlisted IS 'TRUE = hidden (default for new servers), FALSE = visible (allowlist servers)';
137+

0 commit comments

Comments
 (0)