configuracion de entorno de desarrollo

This commit is contained in:
Carlos Sandoval
2026-09-02 18:02:43 +00:00
commit bc9fb0dd0f
22 changed files with 1985 additions and 0 deletions
@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-02
@@ -0,0 +1,89 @@
# Design: create-outline-mcp-server
## Context
El repositorio está vacío: el proyecto `outline-mcp` se construye desde cero. Es un servidor MCP (Model Context Protocol) en Go que actúa como puente entre clientes de IA y una instancia self-hosted de Outline. Restricciones clave:
- El desarrollo se realiza dentro de un contenedor (no se requiere Go local); por eso el primer entregable es el devcontainer.
- La distribución se realiza mediante releases binarios publicados en Gitea (no hay registry de contenedores para el binario final).
- El binario debe ser capaz de actualizarse a sí mismo desde la propia instancia de Gitea.
## Goals / Non-Goals
**Goals:**
- Servidor MCP funcional con transporte stdio y 4 herramientas sobre la API de Outline.
- Distribución reproducible: pipeline de Gitea Actions que publica binarios estáticos multi-plataforma.
- Auto-update del binario sin intervención manual (descarga + `selfupdate.Apply`).
- Entorno de desarrollo reproducible en contenedor con tooling de Go preconfigurado.
**Non-Goals:**
- Transporte HTTP/SSE del servidor MCP (solo stdio en esta iteración).
- Gestión avanzada de Outline (actualizar/borrar documentos, permisos, comentarios, attachments).
- Firma de binarios / notarización.
- Suite de tests de integración contra Outline real.
## Decisions
### D1: SDK de MCP — `github.com/mark3labs/mcp-go`
- **Elección**: usar `mcp-go` (paquetes `mcp` y `server`) con su `server.NewMCPServer` y transporte `ServeStdio`.
- **Alternativa**: implementar el protocolo JSON-RPC manualmente. Se descarta por coste y riesgo; el SDK ya resuelve handshake, esquemas de herramientas y serialización.
- **Nota**: `mcp-go` permite declarar esquemas de entrada tipados (`mcp.WithString(...)`, `mcp.Required()`) que se traducen a JSON Schema para el cliente.
### D2: Arquitectura de un solo archivo (`main.go`)
- **Elección**: mantener todo el código en `main.go` (CLI, cliente HTTP, herramientas, auto-update) con structs y funciones bien delimitados.
- **Alternativa**: dividir en paquetes (`internal/outline`, `internal/updater`). Se descarta por ahora: el alcance es pequeño y un solo archivo facilita el bootstrap; la extracción a paquetes queda como refactor futuro sin impacto en specs.
### D3: Configuración por variables de entorno
- **Elección**: `OUTLINE_URL` y `OUTLINE_API_KEY` se leen en runtime al construir `OutlineClient`; los errores de configuración se devuelven como resultado MCP de error (no panic).
- **Alternativa**: flags de línea de comandos o archivo de config. Se descarta: los clientes MCP (ej. Claude Desktop, opencode) inyectan `env` por proceso, por lo que el entorno es el canal natural.
### D4: Auto-update con `minio/selfupdate` + API de releases de Gitea
- **Elección**:
1. `GET {GiteaURL}/api/v1/repos/{RepoOwner}/{RepoName}/releases/latest` para obtener tag y assets.
2. Comparación semver simple: si el tag es igual o superior a `Version`, no se hace nada. Los tags siguen el formato `vX.Y.Z`; el prefijo `v` se recorta antes de comparar. La comparación se realiza parseando los tres componentes numéricos (no se introducirá una librería semver externa para mantener las dependencias mínimas).
3. Selección de asset por convención de nombres `<name>_<GOOS>_<GOARCH>[.exe]` (ej. `outline-mcp_darwin_arm64`), filtrando con `runtime.GOOS`/`runtime.GOARCH`.
4. Descarga del asset y aplicación con `selfupdate.Apply` (que reemplaza atómicamente el binario y respalda el antiguo en `.old`).
- **Alternativa**: librería `go-selfupdate` (creativeprojects) con detección de assets automática. Se descarta: está orientada a GitHub y añade complejidad; la API de Gitea es compatible con el flujo simple de 4 pasos.
- **Riesgo asumido**: la convención de nombres de assets es un contrato implícito entre el pipeline y el updater; se documenta en el pipeline.
### D5: Convención de nombres de assets
- **Elección**: el pipeline nombrará los binarios como `outline-mcp_{GOOS}_{GOARCH}` (con `.exe` en Windows). El updater busca ese patrón. `GOOS`/`GOARCH` se usan literalmente para que el mapeo sea directo.
### D6: Pipeline de release
- **Elección**: workflow en `.gitea/workflows/release.yml` con `on: push: tags: ['v*']`, runner `ubuntu-latest`, setup de Go 1.22 (action `actions/setup-go@v5`, compatible con Gitea Actions), bucle de build sobre las 3 plataformas con `CGO_ENABLED=0` y `ldflags` inyectando `main.Version` (desde `github.ref_name`), `main.GiteaURL`, `main.RepoOwner`, `main.RepoName` (desde `github.server_url` y el contexto del repo). Publicación con la acción `akkuman/gitea-release-action` o el CLI `tea release create` como fallback.
- **Alternativa**: generar los binarios en Docker dentro del pipeline. Se descarta: el runner de Gitea ya provee el toolchain vía setup-go y es más rápido.
### D7: Devcontainer
- **Elección**: imagen `mcr.microsoft.com/devcontainers/go:1-1.22-bookworm` con:
- Features: `ghcr.io/devcontainers/features/golang:1` no es necesaria (la imagen ya incluye Go); se añade la feature `docker-in-docker` opcional no requerida — se omite para minimizar superficie.
- `postCreateCommand`: instalación de `golangci-lint` vía script oficial y `go mod download` si existe `go.mod`.
- Extensiones: `golang.go` (Go oficial, incluye gopls), `eamodio.gitlens`.
- `go.useLanguageServer: true` en settings del editor.
- **Alternativa**: devcontainer con Dockerfile propio. Se descarta: la imagen oficial ya cubre todo el stack necesario.
## Risks / Trade-offs
- [Contrato de nombres de assets roto si alguien renombra manualmente en Gitea] → El updater devuelve error claro "asset no encontrado para <GOOS>/<GOARCH>"; convención documentada en el workflow.
- [Comparación semver casera falla con tags no numéricos (ej. `v1.0.0-rc1`)] → Si el parseo falla, se informa y no se actualiza (fail-safe); los tags del pipeline seguirán `vX.Y.Z`.
- [`selfupdate.Apply` no funciona en algunos entornos (ej. binario en ruta sin permiso de escritura, Windows con AV bloqueando el reemplazo)] → `Apply` reemplaza atómicamente y respalda en `.old`; se devuelve el error al usuario sin dejar el binario corrupto.
- [API key de Outline expuesta en el entorno del proceso] → Es el patrón estándar para servidores MCP stdio; no se loguea nunca la API key.
- [Rate limits o cambios de la API de Outline] → Los endpoints usados (`collections.list`, `documents.search`, `documents.info`, `documents.create`) son estables; los errores HTTP se propagan con el mensaje de la API para diagnosticar rápido.
- [Gitea Actions sin runners disponibles] → El release fallará visiblemente en el push del tag; el binario se puede compilar manualmente con los mismos comandos documentados en el workflow.
## Migration Plan
No aplica (proyecto nuevo). Rollback: los releases de Gitea conservan los binarios anteriores; para revertir una actualización basta reinstalar el asset de la versión previa (el updater respalda el binario anterior en `<binary>.old`).
## Open Questions
- URL exacta de la instancia de Gitea y `owner/repo` definitivos: se inyectan en tiempo de build; se usarán placeholders en el workflow derivados del contexto del repositorio.
- ¿Publicar también una imagen de contenedor del binario en el registry de Gitea? Fuera de alcance para este change; candidato para un change futuro.
@@ -0,0 +1,45 @@
# Proposal: create-outline-mcp-server
## Why
El equipo necesita que los asistentes de IA (clientes MCP) puedan consultar y crear contenido en nuestra instancia self-hosted de Outline de forma segura y estructurada. Actualmente no existe ningún servidor MCP para Outline en el ecosistema interno, por lo que es necesario construirlo desde cero en Go, con un entorno de desarrollo reproducible en contenedores y una cadena de distribución (releases binarios) basada en Gitea Actions.
## What Changes
- Creación de un proyecto Go nuevo (`outline-mcp`) que implementa un servidor MCP con transporte stdio.
- CLI básica con comandos `version` y `update`; sin argumentos arranca el servidor MCP.
- Cliente HTTP (`OutlineClient`) para la API de Outline, autenticado mediante `OUTLINE_URL` y `OUTLINE_API_KEY`.
- Cuatro herramientas MCP: `outline_list_collections`, `outline_search`, `outline_get_document` y `outline_create_document`.
- Mecanismo de auto-actualización que consulta la última release de Gitea y aplica el binario correspondiente al SO/arquitectura actual.
- Entorno de desarrollo en contenedor (`.devcontainer/devcontainer.json`) con imagen oficial de Go 1.22, gopls y golangci-lint.
- Pipeline de CI/CD en Gitea Actions (`.gitea/workflows/release.yml`) que compila binarios estáticos para linux/amd64, darwin/arm64 y windows/amd64 y publica releases al pushear tags `v*`.
## Capabilities
### New Capabilities
- `mcp-server`: Servidor MCP en Go con transporte stdio, CLI básica (`version`, `update`) e inyección de metadatos de build mediante `-ldflags`.
- `outline-api-client`: Cliente HTTP para la API de Outline con autenticación Bearer y las cuatro herramientas MCP sobre colecciones y documentos.
- `self-update`: Actualización automática del binario comparando la versión actual con el último tag de release en Gitea y aplicando el asset compatible con `GOOS`/`GOARCH`.
- `release-pipeline`: Pipeline de Gitea Actions que compila binarios estáticos multi-plataforma y publica releases en Gitea.
- `dev-environment`: Entorno de desarrollo en contenedor (devcontainer) con tooling de Go preconfigurado.
### Modified Capabilities
(ninguna — el proyecto se crea desde cero)
## No objetivos
- No se implementará transporte HTTP/SSE para el servidor MCP; solo stdio.
- No se gestionarán operaciones avanzadas de Outline (eliminar/actualizar documentos, gestionar permisos, comentarios, attachments).
- No se implementará autenticación OAuth del servidor MCP hacia los clientes; la seguridad se apoya en la API key de Outline vía entorno.
- No se configurará firma de binarios ni notarización (macOS/Windows).
- No se incluirá despliegue continuo ni instalación automática en servidores; solo publicación de releases.
- No se desarrollará test suite de integración contra una instancia real de Outline.
## Impact
- **Código**: archivos nuevos en la raíz del repo (`main.go`, `go.mod`, `go.sum`, `.devcontainer/devcontainer.json`, `.gitea/workflows/release.yml`).
- **Dependencias Go**: `github.com/mark3labs/mcp-go` (SDK MCP), `github.com/minio/selfupdate` (auto-update).
- **APIs externas**: API REST de Outline (`/api/collections.list`, `/api/documents.search`, `/api/documents.info`, `/api/documents.create`) y API de releases de Gitea (`/api/v1/repos/{owner}/{repo}/releases/latest`).
- **Infraestructura**: requiere Gitea con Actions habilitadas y un repositorio con registro de releases; el desarrollo no requiere Go local (contenedor).
@@ -0,0 +1,17 @@
# Spec: dev-environment
## ADDED Requirements
### Requirement: Contenedor de desarrollo con Go 1.22
El sistema SHALL incluir un devcontainer basado en la imagen oficial `mcr.microsoft.com/devcontainers/go:1-1.22-bookworm` que permita desarrollar el proyecto sin Go instalado localmente.
#### Scenario: Apertura del proyecto en el contenedor
- **WHEN** el usuario abre el proyecto en DevPod o Dev Containers
- **THEN** el contenedor se construye a partir de la imagen oficial de Go 1.22 y dispone del toolchain necesario para compilar y ejecutar el proyecto
### Requirement: Tooling del editor preconfigurado
El devcontainer SHALL preconfigurar el soporte de `gopls` (language server de Go) e instalar `golangci-lint`, además de las extensiones básicas de Go para el editor.
#### Scenario: Experiencia de edición en el contenedor
- **WHEN** el desarrollador edita archivos Go dentro del devcontainer
- **THEN** dispone de autocompletado y diagnóstico vía gopls, de linting vía golangci-lint y de las extensiones de Go instaladas automáticamente
@@ -0,0 +1,38 @@
# Spec: mcp-server
## ADDED Requirements
### Requirement: Arranque del servidor por defecto
Cuando el binario se ejecuta sin argumentos, el sistema SHALL iniciar el servidor MCP usando transporte stdio.
#### Scenario: Ejecución sin argumentos
- **WHEN** el usuario ejecuta el binario sin ningún argumento
- **THEN** el sistema arranca el servidor MCP en modo stdio y queda a la espera de mensajes del cliente
### Requirement: Comando version
El sistema SHALL exponer el comando `version` que imprime la versión del binario.
#### Scenario: Consulta de versión
- **WHEN** el usuario ejecuta el binario con el argumento `version`
- **THEN** el sistema imprime por stdout la versión inyectada en tiempo de compilación mediante `-ldflags`
### Requirement: Comando update
El sistema SHALL exponer el comando `update` que ejecuta el proceso de auto-actualización del binario.
#### Scenario: Ejecución de actualización
- **WHEN** el usuario ejecuta el binario con el argumento `update`
- **THEN** el sistema consulta la última release de Gitea y aplica la actualización si existe una versión superior
### Requirement: Metadatos de build inyectados
El sistema SHALL definir variables globales (`Version`, `GiteaURL`, `RepoOwner`, `RepoName`) que MUST ser inyectables en tiempo de compilación mediante `-ldflags -X`.
#### Scenario: Compilación con ldflags
- **WHEN** el binario se compila pasando valores para `main.Version`, `main.GiteaURL`, `main.RepoOwner` y `main.RepoName` vía `-ldflags`
- **THEN** el comando `version` y la lógica de auto-update utilizan esos valores en tiempo de ejecución
### Requirement: Registro de herramientas MCP
El servidor MCP SHALL registrar las herramientas `outline_list_collections`, `outline_search`, `outline_get_document` y `outline_create_document` y MUST exponerlas vía el protocolo MCP.
#### Scenario: Listado de herramientas desde un cliente MCP
- **WHEN** un cliente MCP solicita la lista de herramientas disponibles
- **THEN** el servidor responde incluyendo las cuatro herramientas de Outline con sus esquemas de entrada definidos
@@ -0,0 +1,61 @@
# Spec: outline-api-client
## ADDED Requirements
### Requirement: Configuración por variables de entorno
El sistema SHALL configurar el cliente de Outline a partir de las variables de entorno `OUTLINE_URL` (URL base de la instancia) y `OUTLINE_API_KEY` (token de API).
#### Scenario: Cliente configurado correctamente
- **WHEN** las variables `OUTLINE_URL` y `OUTLINE_API_KEY` están definidas en el entorno
- **THEN** el cliente construye las peticiones contra la URL base indicada y autentica con el token provisto
#### Scenario: Variables de entorno ausentes
- **WHEN** `OUTLINE_URL` o `OUTLINE_API_KEY` no están definidas al invocar una herramienta
- **THEN** el sistema responde con un mensaje de error descriptivo indicando la configuración faltante
### Requirement: Petición POST genérica autenticada
El cliente HTTP SHALL implementar un método genérico para realizar peticiones POST a los endpoints de la API de Outline, incluyendo el header `Authorization: Bearer <TOKEN>` y el body en formato JSON.
#### Scenario: Petición autenticada
- **WHEN** el cliente envía una petición a cualquier endpoint de la API de Outline
- **THEN** la petición incluye el header `Authorization: Bearer` con el token configurado y el payload serializado como JSON
#### Scenario: Error de la API de Outline
- **WHEN** la API de Outline responde con un código HTTP de error
- **THEN** el sistema propaga un error descriptivo (incluyendo el código y el mensaje de la API) hacia el llamador
### Requirement: Herramienta outline_list_collections
La herramienta `outline_list_collections` SHALL invocar el endpoint `/api/collections.list` y devolver el ID, el nombre y la descripción de cada colección.
#### Scenario: Listado de colecciones exitoso
- **WHEN** se invoca `outline_list_collections` sin parámetros
- **THEN** la herramienta devuelve la lista de colecciones con sus campos `id`, `name` y `description`
### Requirement: Herramienta outline_search
La herramienta `outline_search` SHALL invocar el endpoint `/api/documents.search` recibiendo el parámetro `query` y devolver los resultados de la búsqueda.
#### Scenario: Búsqueda con resultados
- **WHEN** se invoca `outline_search` con un `query` válido
- **THEN** la herramienta devuelve los documentos coincidentes con su información relevante (título, id y extracto)
#### Scenario: Búsqueda sin resultados
- **WHEN** se invoca `outline_search` con un `query` que no coincide con ningún documento
- **THEN** la herramienta devuelve una lista vacía sin error
### Requirement: Herramienta outline_get_document
La herramienta `outline_get_document` SHALL invocar el endpoint `/api/documents.info` recibiendo el parámetro `id` y devolver el título y el texto del documento en formato Markdown.
#### Scenario: Lectura de documento existente
- **WHEN** se invoca `outline_get_document` con el `id` de un documento existente
- **THEN** la herramienta devuelve el título del documento y su contenido en Markdown
#### Scenario: Documento inexistente
- **WHEN** se invoca `outline_get_document` con un `id` que no corresponde a ningún documento
- **THEN** la herramienta devuelve un error indicando que el documento no fue encontrado
### Requirement: Herramienta outline_create_document
La herramienta `outline_create_document` SHALL invocar el endpoint `/api/documents.create` recibiendo los parámetros `title`, `text` (Markdown) y `collection_id`, y devolver la información del documento creado.
#### Scenario: Creación de documento exitosa
- **WHEN** se invoca `outline_create_document` con `title`, `text` y un `collection_id` válido
- **THEN** la herramienta crea el documento en la colección indicada y devuelve su `id` y `title`
@@ -0,0 +1,42 @@
# Spec: release-pipeline
## ADDED Requirements
### Requirement: Disparo por tags de versión
El pipeline de release SHALL ejecutarse cuando se realice push de tags cuyo nombre comience con `v` (por ejemplo `v1.0.0`).
#### Scenario: Push de tag de release
- **WHEN** se pushea al repositorio un tag que empieza con `v`
- **THEN** el workflow de Gitea Actions se dispara automáticamente
#### Scenario: Push sin tag de release
- **WHEN** se pushea una rama sin tags o un tag que no empieza con `v`
- **THEN** el workflow de release no se ejecuta
### Requirement: Entorno de compilación
El pipeline SHALL utilizar una imagen de Ubuntu y SHALL configurar Go 1.22 como versión del toolchain antes de compilar.
#### Scenario: Job de build
- **WHEN** el pipeline se ejecuta
- **THEN** el entorno de build dispone de Go 1.22 instalado sobre una imagen Ubuntu
### Requirement: Inyección de variables en la compilación
El pipeline SHALL inyectar en tiempo de compilación las variables `Version`, `GiteaURL`, `RepoOwner` y `RepoName` mediante `-ldflags`, derivadas del tag y del repositorio.
#### Scenario: Compilación con metadatos
- **WHEN** el pipeline compila los binarios
- **THEN** los binarios resultantes contienen la versión del tag y los datos del repositorio Gitea para el mecanismo de auto-update
### Requirement: Compilación multi-plataforma estática
El pipeline SHALL compilar binarios estáticos (`CGO_ENABLED=0`) para las plataformas linux/amd64, darwin/arm64 y windows/amd64.
#### Scenario: Artefactos generados
- **WHEN** el job de build completa la compilación
- **THEN** se generan tres binarios estáticos: uno para linux amd64, uno para darwin arm64 (Apple Silicon) y uno para windows amd64
### Requirement: Publicación del release en Gitea
El pipeline SHALL publicar un release en Gitea asociado al tag, adjuntando los binarios compilados como assets, utilizando la acción oficial de Gitea o un CLI compatible.
#### Scenario: Release publicado
- **WHEN** la compilación multi-plataforma finaliza con éxito
- **THEN** se crea (o actualiza) el release del tag en Gitea con los tres binarios adjuntos
@@ -0,0 +1,47 @@
# Spec: self-update
## ADDED Requirements
### Requirement: Consulta de la última release de Gitea
El sistema SHALL consultar el endpoint `/api/v1/repos/{owner}/{repo}/releases/latest` de la instancia de Gitea configurada para obtener la última release disponible.
#### Scenario: Consulta exitosa de última release
- **WHEN** se ejecuta la lógica de auto-actualización y la API de Gitea responde correctamente
- **THEN** el sistema obtiene el tag de la release y la lista de assets publicados
#### Scenario: Gitea no accesible
- **WHEN** la instancia de Gitea no es accesible o responde con error
- **THEN** el sistema finaliza con un mensaje de error sin modificar el binario actual
### Requirement: Comparación de versiones
El sistema SHALL comparar la versión actual del binario (`Version` inyectada vía ldflags) con el tag de la última release de Gitea, y MUST omitir la actualización si la versión actual es igual o superior.
#### Scenario: Versión actualizada disponible
- **WHEN** el tag de Gitea indica una versión superior a la versión actual
- **THEN** el sistema procede a descargar el asset correspondiente
#### Scenario: Versión ya actualizada
- **WHEN** la versión actual es igual o superior al tag de la última release
- **THEN** el sistema informa que no hay actualizaciones y no realiza cambios en el binario
### Requirement: Descarga del asset compatible
El sistema SHALL seleccionar el asset de la release cuyo nombre corresponda al sistema operativo y arquitectura actuales (`runtime.GOOS`, `runtime.GOARCH`), y MUST descargarlo antes de aplicar la actualización.
#### Scenario: Asset compatible disponible
- **WHEN** la release contiene un asset que coincide con el `GOOS`/`GOARCH` actuales
- **THEN** el sistema descarga dicho asset para aplicar la actualización
#### Scenario: Asset compatible no disponible
- **WHEN** la release no contiene un asset para la plataforma actual
- **THEN** el sistema finaliza con un error indicando que no existe binario para la plataforma
### Requirement: Aplicación del binario descargado
El sistema SHALL aplicar el binario descargado utilizando `selfupdate.Apply` (github.com/minio/selfupdate), reemplazando el binario en ejecución.
#### Scenario: Actualización aplicada correctamente
- **WHEN** el asset descargado es un binario válido
- **THEN** el sistema reemplaza el binario actual mediante `selfupdate.Apply` e informa el éxito de la operación
#### Scenario: Asset corrupto o inválido
- **WHEN** el asset descargado no es un binario válido
- **THEN** el sistema aborta la actualización e informa el error sin dejar el binario en estado inconsistente
@@ -0,0 +1,53 @@
# Tasks: create-outline-mcp-server
## 1. Entorno de desarrollo (devcontainer)
- [x] 1.1 Crear `.devcontainer/devcontainer.json` con la imagen `mcr.microsoft.com/devcontainers/go:1-1.22-bookworm`
- [x] 1.2 Configurar extensiones del editor (`golang.go` con gopls) y settings (`go.useLanguageServer: true`)
- [x] 1.3 Añadir `postCreateCommand` que instale `golangci-lint` y ejecute `go mod download` cuando exista `go.mod`
- [x] 1.4 Verificar: Given el proyecto abierto en DevPod/Dev Containers, When el contenedor se construye, Then dispone de Go 1.22, gopls y golangci-lint operativos
## 2. Inicialización del módulo Go
- [ ] 2.1 Ejecutar `go mod init outline-mcp` dentro del contenedor
- [ ] 2.2 Instalar dependencias: `go get github.com/mark3labs/mcp-go/mcp github.com/mark3labs/mcp-go/server`
- [ ] 2.3 Instalar la librería de auto-update: `go get github.com/minio/selfupdate`
- [ ] 2.4 Verificar: Given `go.mod` creado, When se ejecuta `go mod tidy`, Then no hay errores y `go.sum` queda generado
## 3. CLI y esqueleto del servidor MCP
- [ ] 3.1 Crear `main.go` con variables globales inyectables (`Version`, `GiteaURL`, `RepoOwner`, `RepoName`) y parsing de argumentos (`version`, `update`; sin argumentos → servidor MCP)
- [ ] 3.2 Implementar el comando `version` que imprime la versión compilada
- [ ] 3.3 Arrancar el servidor MCP con `server.NewMCPServer` y transporte stdio (`ServeStdio`)
- [ ] 3.4 Verificar: Given el binario compilado con `-ldflags -X main.Version=v0.0.1-dev`, When se ejecuta `version`, Then imprime `v0.0.1-dev`; When se ejecuta sin argumentos, Then el proceso queda a la espera en stdio
## 4. Cliente HTTP de Outline
- [ ] 4.1 Implementar el struct `OutlineClient` configurado desde `OUTLINE_URL` y `OUTLINE_API_KEY`
- [ ] 4.2 Implementar método genérico `post(ctx, path, payload, result)` que serialice JSON, incluya el header `Authorization: Bearer <TOKEN>` y propague errores HTTP con el mensaje de la API
- [ ] 4.3 Verificar: Given `OUTLINE_URL`/`OUTLINE_API_KEY` ausentes, When se invoca una herramienta, Then se responde con error descriptivo sin panic
## 5. Herramientas MCP
- [ ] 5.1 Implementar `outline_list_collections` contra `/api/collections.list` devolviendo `id`, `name` y `description`
- [ ] 5.2 Implementar `outline_search` contra `/api/documents.search` con parámetro `query`
- [ ] 5.3 Implementar `outline_get_document` contra `/api/documents.info` con parámetro `id`, devolviendo título y texto en Markdown
- [ ] 5.4 Implementar `outline_create_document` contra `/api/documents.create` con parámetros `title`, `text` y `collection_id`
- [ ] 5.5 Registrar las cuatro herramientas en el servidor MCP con sus esquemas de entrada (`mcp.WithString`, `mcp.Required()`)
- [ ] 5.6 Verificar: Given un cliente MCP conectado por stdio, When se lista `tools/list`, Then aparecen las cuatro herramientas con sus esquemas; When se invoca `outline_search` con query sin coincidencias, Then devuelve lista vacía sin error
## 6. Auto-update
- [ ] 6.1 Implementar `doUpdate`: consulta a `{GiteaURL}/api/v1/repos/{RepoOwner}/{RepoName}/releases/latest` y manejo de errores de red
- [ ] 6.2 Implementar comparación de versiones (parseo de `vX.Y.Z` frente a `Version`; fail-safe si el tag no es parseable)
- [ ] 6.3 Implementar selección y descarga del asset por convención `outline-mcp_{GOOS}_{GOARCH}[.exe]` usando `runtime.GOOS`/`runtime.GOARCH`
- [ ] 6.4 Aplicar el binario descargado con `selfupdate.Apply` e informar el resultado
- [ ] 6.5 Verificar: Given `Version` igual o superior al tag de Gitea, When se ejecuta `update`, Then informa que no hay actualizaciones y no modifica el binario; Given la API de Gitea inaccesible, Then finaliza con error sin tocar el binario
## 7. Pipeline de release (Gitea Actions)
- [ ] 7.1 Crear `.gitea/workflows/release.yml` con trigger `on: push: tags: ['v*']` y runner `ubuntu-latest`
- [ ] 7.2 Configurar Go 1.22 en el job (`actions/setup-go@v5`)
- [ ] 7.3 Implementar el build con `CGO_ENABLED=0` para linux/amd64, darwin/arm64 y windows/amd64, nombrando los artefactos `outline-mcp_{GOOS}_{GOARCH}[.exe]` e inyectando `-ldflags` con `Version` (desde `github.ref_name`), `GiteaURL`, `RepoOwner` y `RepoName` (desde el contexto del repo)
- [ ] 7.4 Publicar el release en Gitea adjuntando los tres binarios (acción oficial de Gitea o CLI `tea release create`)
- [ ] 7.5 Verificar: Given un push de tag `v0.1.0`, When el workflow se ejecuta, Then el release queda publicado en Gitea con los tres assets y el comando `version` del binario publicado reporta `v0.1.0`
+31
View File
@@ -0,0 +1,31 @@
schema: spec-driven
# Project context (optional)
# This is shown to AI when creating artifacts.
# Add your tech stack, conventions, style guides, domain knowledge, etc.
# Example:
# context: |
# Tech stack: TypeScript, React, Node.js
# We use conventional commits
# Domain: e-commerce platform
# Per-artifact rules (optional)
# Add custom rules for specific artifacts.
# Example:
# rules:
# proposal:
# - Keep proposals under 500 words
# - Always include a "Non-goals" section
# tasks:
# - Break tasks into chunks of max 2 hours
context: |
Idioma: Español.
Todos los artefactos deben escribirse en español.
Mantener los terminos tecnicos en inglés cuando corresponda (por ejemplo: API, frontend, backend, database).
Usar un tono formal y profesional.
rules:
proposal:
- Incluir siempre una sección de "No objetivos" para aclarar lo que no se abordará.
tasks:
- Use Given/When/Then format