## Asset Header

- **Asset ID:** SOP-EL-SX-GuiaInstalacion-v01
- **Version:** v01
- **Status:** Draft
- **Owner:** Victor Heredia
- **IntellBank:** IB-EL-EmpowerLabs
- **Tipo:** SOP — Standard Operating Procedure
- **Propósito:** Guía de Instalación — BrainOS
- **Última actualización:** 2026-04-11

---

# Guía de Instalación — BrainOS
## SHA-GuiaInstalacion-v01

---


---

## Elige tu track

| | Track A — Servicio Gestionado | Track B — Auto-instalación |
|---|---|---|
| **¿Quién instala?** | Victor (EmpowerLabs) | El cliente, guiado paso a paso |
| **Tiempo del cliente** | 5 minutos | 30-60 minutos |
| **Tiempo de Victor** | 15-20 minutos por cliente | Soporte puntual |
| **Infraestructura** | Victor opera todo | Cliente opera su Supabase |
| **Control de datos** | EmpowerLabs (con acuerdo) | Cliente (soberanía total) |
| **Complejidad técnica** | Ninguna para el cliente | Media — requiere terminal |
| **Recomendado para** | Clientes Re100X / co-construcción | Clientes técnicos o con preferencia por soberanía |

> **Recomendación por defecto:** Track A para el modelo de co-construcción actual. Track B disponible para clientes que prefieren operar su propia infraestructura.

---

## TRACK A — SERVICIO GESTIONADO (EmpowerLabs opera el BrainOS)

> Victor crea y administra un proyecto Supabase dedicado por cliente. El cliente solo conecta una URL y una clave en Claude Desktop. Tiempo del cliente: **5 minutos**.

---

### Para Victor — Setup de un nuevo cliente (15-20 min)

#### Paso 1 — Crear proyecto Supabase para el cliente

1. Ir a [supabase.com](https://supabase.com) → Dashboard → New Project
2. Configurar:
   - **Nombre:** `BrainOS-[nombre-cliente]` (ej: `BrainOS-carlos`)
   - **Password:** generar y guardar en el Credential Tracker del cliente
   - **Región:** la más cercana al cliente
3. Esperar ~2 minutos que el proyecto se inicialice
4. Guardar en el Credential Tracker:
   - **Project URL** (ej: `https://xxxxx.supabase.co`)
   - **Project Ref** (el string en la URL del dashboard)
   - **Secret Key** (Settings → API Keys → `service_role`)

#### Paso 2 — Configurar la base de datos

Ir a **SQL Editor** en el dashboard del proyecto nuevo y ejecutar este bloque completo:

```sql
-- Activar extensión vectorial
create extension if not exists vector;

-- Crear tabla thoughts
create table thoughts (
  id uuid default gen_random_uuid() primary key,
  content text not null,
  embedding vector(1536),
  metadata jsonb default '{}'::jsonb,
  created_at timestamptz default now(),
  updated_at timestamptz default now()
);

-- Índices para performance
create index on thoughts using hnsw (embedding vector_cosine_ops);
create index on thoughts using gin (metadata);
create index on thoughts (created_at desc);

-- Trigger de actualización
create or replace function update_updated_at()
returns trigger as $$
begin
  new.updated_at = now();
  return new;
end;
$$ language plpgsql;

create trigger thoughts_updated_at
  before update on thoughts
  for each row
  execute function update_updated_at();

-- Función de búsqueda semántica
create or replace function match_thoughts(
  query_embedding vector(1536),
  match_threshold float default 0.7,
  match_count int default 10,
  filter jsonb default '{}'::jsonb
)
returns table (
  id uuid,
  content text,
  metadata jsonb,
  similarity float,
  created_at timestamptz
)
language plpgsql
as $$
begin
  return query
  select
    t.id,
    t.content,
    t.metadata,
    1 - (t.embedding <=> query_embedding) as similarity,
    t.created_at
  from thoughts t
  where 1 - (t.embedding <=> query_embedding) > match_threshold
  and (filter = '{}'::jsonb or t.metadata @> filter)
  order by t.embedding <=> query_embedding
  limit match_count;
end;
$$;

-- Seguridad por roles
alter table thoughts enable row level security;

create policy "Service role full access"
  on thoughts
  for all
  using (auth.role() = 'service_role');

grant select, insert, update, delete on table public.thoughts to service_role;
```

✅ **Verificar:** Ir a Table Editor → debe aparecer la tabla `thoughts`.

#### Paso 3 — Generar Access Key para el cliente

En terminal (Mac/Linux):
```bash
openssl rand -hex 32
```

En Windows PowerShell:
```powershell
-join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Maximum 256) })
```

Guardar el resultado (64 caracteres) como **MCP Access Key** en el Credential Tracker del cliente.

#### Paso 4 — Desplegar el servidor MCP

En terminal, desde cualquier carpeta:

```bash
# 1. Crear carpeta de trabajo
mkdir BrainOS-[cliente] && cd BrainOS-[cliente]

# 2. Autenticar con Supabase (solo si no está autenticado)
supabase login

# 3. Inicializar y linkar al proyecto del cliente
supabase init
supabase link --project-ref TU_PROJECT_REF_DEL_CLIENTE

# 4. Configurar secretos
supabase secrets set MCP_ACCESS_KEY=LA_KEY_GENERADA_EN_PASO_3
supabase secrets set OPENROUTER_API_KEY=TU_OPENROUTER_KEY

# 5. Crear y descargar los archivos del servidor
supabase functions new BrainOS-mcp

curl -o supabase/functions/BrainOS-mcp/index.ts \
  https://raw.githubusercontent.com/NateBJones-Projects/OB1/main/server/index.ts

curl -o supabase/functions/BrainOS-mcp/deno.json \
  https://raw.githubusercontent.com/NateBJones-Projects/OB1/main/server/deno.json

# 6. Deploy
supabase functions deploy BrainOS-mcp --no-verify-jwt
```

#### Paso 5 — Generar las credenciales para el cliente

Con el Project Ref y el MCP Access Key, construir:

```
MCP Server URL:
https://[PROJECT_REF].supabase.co/functions/v1/BrainOS-mcp

Connection URL (la que recibe el cliente):
https://[PROJECT_REF].supabase.co/functions/v1/BrainOS-mcp?key=[MCP_ACCESS_KEY]
```

Guardar ambas en el Credential Tracker del cliente.

---

### Para el cliente — Conectar en Claude Desktop (5 min)

> Estas son las únicas instrucciones que el cliente necesita ver.

**Victor te envía dos datos:**
- Tu **Connection URL** (una URL larga que termina en `?key=...`)
- Confirmación de que tu BrainOS está listo

**Lo que haces tú:**

1. Abrir **Claude Desktop**
2. Click en el ícono **+** (connectors) → **Add MCP Server**
3. Pegar tu **Connection URL** en el campo URL
4. Nombre: `BrainOS - [Tu nombre]`
5. Guardar y activar el toggle

**Verificar que funciona:**
En una conversación de Claude, escribe:
```
Usa la herramienta thought_stats para decirme cuántos thoughts tengo
```

Si responde con un número (probablemente 0 al inicio), el sistema está conectado. ✅

---

## TRACK B — AUTO-INSTALACIÓN (El cliente instala su propio BrainOS)

> Para clientes técnicos o que prefieren soberanía total de sus datos. Tiempo estimado: 30-60 minutos. Se recomienda hacer esto en la Sesión 2 de co-construcción con Victor presente.

> **Video de referencia:** https://vimeo.com/1174979042/f883f6489a (instalación paso a paso)

---

### Prerequisitos

Antes de empezar, tener listo:
- [ ] Cuenta en [supabase.com](https://supabase.com) (gratuita)
- [ ] Cuenta en [openrouter.ai](https://openrouter.ai) con ~$5 de crédito
- [ ] Terminal (Mac/Linux) o PowerShell (Windows)
- [ ] El Credential Tracker de Tu Sherpa IA (spreadsheet para guardar credenciales)

---

### Paso 1 — Crear proyecto Supabase (5 min)

1. Ir a [supabase.com](https://supabase.com) → autenticarse con GitHub
2. Click **New Project**
3. Configurar:
   - **Nombre:** `BrainOS`
   - **Password:** generar uno fuerte → guardar en Credential Tracker
   - **Región:** la más cercana a ti
4. Esperar ~2 minutos
5. Cuando cargue el dashboard, guardar en Credential Tracker:
   - **Project URL:** `https://XXXXXX.supabase.co` (Settings → API)
   - **Project Ref:** el string en la URL del browser: `supabase.com/dashboard/project/ESTE_PARTE`
   - **Secret Key:** Settings → API Keys → copiar la clave `service_role`

---

### Paso 2 — Configurar la base de datos (10 min)

Ir a **SQL Editor** en el panel izquierdo y ejecutar este bloque completo. **Importante:** copiar el SQL a un archivo de texto antes de pegarlo para evitar que el editor del browser corrompa caracteres especiales.

```sql
create extension if not exists vector;

create table thoughts (
  id uuid default gen_random_uuid() primary key,
  content text not null,
  embedding vector(1536),
  metadata jsonb default '{}'::jsonb,
  created_at timestamptz default now(),
  updated_at timestamptz default now()
);

create index on thoughts using hnsw (embedding vector_cosine_ops);
create index on thoughts using gin (metadata);
create index on thoughts (created_at desc);

create or replace function update_updated_at()
returns trigger as $$
begin
  new.updated_at = now();
  return new;
end;
$$ language plpgsql;

create trigger thoughts_updated_at
  before update on thoughts
  for each row
  execute function update_updated_at();

create or replace function match_thoughts(
  query_embedding vector(1536),
  match_threshold float default 0.7,
  match_count int default 10,
  filter jsonb default '{}'::jsonb
)
returns table (
  id uuid, content text, metadata jsonb, similarity float, created_at timestamptz
)
language plpgsql as $$
begin
  return query
  select t.id, t.content, t.metadata,
    1 - (t.embedding <=> query_embedding) as similarity, t.created_at
  from thoughts t
  where 1 - (t.embedding <=> query_embedding) > match_threshold
  and (filter = '{}'::jsonb or t.metadata @> filter)
  order by t.embedding <=> query_embedding
  limit match_count;
end;
$$;

alter table thoughts enable row level security;

create policy "Service role full access"
  on thoughts for all
  using (auth.role() = 'service_role');

grant select, insert, update, delete on table public.thoughts to service_role;
```

✅ **Verificar:** Table Editor → debe aparecer la tabla `thoughts` con sus columnas.

---

### Paso 3 — Obtener API Key de OpenRouter (5 min)

1. Ir a [openrouter.ai](https://openrouter.ai) → autenticarse
2. Ir a [openrouter.ai/keys](https://openrouter.ai/keys)
3. Crear clave con nombre `BrainOS`
4. **Copiar inmediatamente** → guardar en Credential Tracker
5. Agregar ~$5 de crédito (dura varios meses de uso normal)

---

### Paso 4 — Generar tu Access Key (2 min)

**Mac/Linux** (en terminal):
```bash
openssl rand -hex 32
```

**Windows PowerShell:**
```powershell
-join ((1..32) | ForEach-Object { '{0:x2}' -f (Get-Random -Maximum 256) })
```

Copiar el resultado (64 caracteres) → guardar en Credential Tracker como **MCP Access Key**.

---

### Paso 5 — Instalar Supabase CLI (5 min)

**Mac con Homebrew:**
```bash
brew install supabase/tap/supabase
```

**Mac sin Homebrew:**
```bash
npm install -g supabase
```

**Windows (Scoop):**
```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
Invoke-RestMethod -Uri https://get.scoop.sh | Invoke-Expression
scoop bucket add supabase https://github.com/supabase/scoop-bucket.git
scoop install supabase
```

Verificar:
```bash
supabase --version
```

---

### Paso 6 — Desplegar el servidor MCP (10 min)

```bash
# 1. Crear carpeta
mkdir BrainOS && cd BrainOS

# 2. Autenticar con Supabase
supabase login

# 3. Inicializar y conectar tu proyecto
supabase init
supabase link --project-ref TU_PROJECT_REF

# 4. Configurar tus secretos
supabase secrets set MCP_ACCESS_KEY=TU_ACCESS_KEY_DEL_PASO_4
supabase secrets set OPENROUTER_API_KEY=TU_KEY_DE_OPENROUTER

# 5. Crear función y descargar servidor
supabase functions new BrainOS-mcp

curl -o supabase/functions/BrainOS-mcp/index.ts \
  https://raw.githubusercontent.com/NateBJones-Projects/OB1/main/server/index.ts

curl -o supabase/functions/BrainOS-mcp/deno.json \
  https://raw.githubusercontent.com/NateBJones-Projects/OB1/main/server/deno.json

# Verificar que se descargó correctamente
head -1 supabase/functions/BrainOS-mcp/index.ts
# Debe empezar con: import "jsr:@supabase/functions-js/edge-runtime.d.ts";

# 6. Deploy
supabase functions deploy BrainOS-mcp --no-verify-jwt
```

---

### Paso 7 — Guardar URLs y conectar en Claude Desktop (3 min)

Construir tus URLs con el Project Ref y el Access Key:

```
MCP Server URL:
https://TU_PROJECT_REF.supabase.co/functions/v1/BrainOS-mcp

Connection URL:
https://TU_PROJECT_REF.supabase.co/functions/v1/BrainOS-mcp?key=TU_ACCESS_KEY
```

En **Claude Desktop:**
1. Click **+** → **Add MCP Server**
2. Pegar tu **Connection URL**
3. Nombre: `BrainOS`
4. Guardar y activar

Verificar:
```
Usa la herramienta thought_stats para decirme cuántos thoughts tengo
```

✅ Si responde con un número, estás conectado.

---

## Troubleshooting — Los 5 problemas conocidos

> Documentados durante FI-SHA-VICTOR (Caso 0). Con esta tabla, el tiempo de resolución baja de 4 horas a menos de 10 minutos.

| # | Síntoma | Causa | Solución |
|---|---|---|---|
| **1** | `Relative import path not prefixed with / or ./` al hacer deploy | Deno requiere prefijo `npm:` para paquetes npm | Verificar que el `index.ts` descargado ya incluye los prefijos correctos. Si no, editar manualmente. |
| **2** | MCP conecta pero retorna **401** / "Couldn't reach the server" | Secret guardado como `MCP-ACCESS-KEY` (guiones) pero el código lee `MCP_ACCESS_KEY` (guiones bajos) | Verificar en Supabase → Settings → Secrets que el nombre sea exactamente `MCP_ACCESS_KEY` con guiones bajos. |
| **3** | `Could not find the table 'public.thoughts'` | El SQL del Paso 2 nunca fue ejecutado o falló silenciosamente | Ir a Table Editor → verificar si existe la tabla. Si no, ejecutar el SQL de nuevo, esta vez pegándolo desde un archivo de texto externo. |
| **4** | Error en logs del MCP: `OAuth discovery 401` | El endpoint de OAuth discovery no está configurado para ser público | **No es un error real.** El MCP usa key-based auth, no OAuth. Ignorar este log específico. |
| **5** | Caracteres especiales corruptos en el SQL | El editor de Supabase en el browser interfiere con quotes y comentarios del SQL | Escribir/copiar el SQL en un editor de texto externo → copiar al clipboard → pegar con Cmd+V (no tipear directamente en el browser). |

**Problema adicional:** `"Permission denied for table thoughts"`
→ Causa: Falta el `GRANT` del último bloque SQL.
→ Solución: Ejecutar solo esta línea en el SQL Editor:
```sql
grant select, insert, update, delete on table public.thoughts to service_role;
```

---

## Checklist de verificación final

Antes de declarar el BrainOS operativo:

- [ ] Tabla `thoughts` existe con columnas: id, content, embedding, metadata, created_at, updated_at
- [ ] Función `match_thoughts` existe en SQL Functions
- [ ] Row Level Security activo con policy `service_role`
- [ ] Permisos de `service_role` sobre la tabla confirmados
- [ ] OpenRouter con crédito y API key guardada
- [ ] MCP Access Key generado y guardado
- [ ] Secretos `MCP_ACCESS_KEY` y `OPENROUTER_API_KEY` configurados en Supabase
- [ ] Función `BrainOS-mcp` desplegada exitosamente
- [ ] Connector activo en Claude Desktop
- [ ] `thought_stats` responde sin error ✅

---

## Próximo paso: Memory Migration

Con el BrainOS operativo, el siguiente paso es cargar la memoria inicial del cliente (Source 1 — vault/notas). Ver protocolo de Memory Migration en MPB-[CLIENTE]-MiSherpaIA-v01.

---

*[[SHA-GuiaInstalacion-v01]] v1.0 — EmpowerLabs / Victor Heredia — 2026-03-22*
*Basada en OB1 Getting Started Guide + aprendizajes FI-SHA-VICTOR.*
*Track A recomendado para modelo co-construcción de EmpowerLabs.*
