Quería usar mis modelos locales (Ollama, vLLM) con herramientas que solo hablan los formatos de API de OpenAI o Anthropic — Claude Code, OpenCode, Cursor y agentes personalizados. Ejecutar LiteLLM me parecía excesivo. Así que construí Relay: un solo binario Go (~12 MB, estático) que conecta cualquier backend local con los formatos de API que tus herramientas ya entienden.
Relay es un gateway de IA local que expone endpoints compatibles con OpenAI Chat Completions y Anthropic Messages mientras se conecta a tus modelos locales.
Arquitectura
┌──────────────────────┐
curl ─┐ │ │
opencode ─┤ │ relay ├──→ Ollama
Claude Code ─┤ │ (gateway IA local) │──→ OpenAI-compat (vLLM/LiteLLM)
Cursor ─┘ │ │──→ CLI agent (claude/opencode)
└──────────────────────┘
La idea es simple: un adaptador a nivel de red que se sienta entre tus herramientas y tus modelos. Sin necesidad de archivos de configuración para empezar, sin runtime Python, sin contenedores.
Características Clave
API de Protocolo Dual
Un solo binario sirve ambos formatos de API:
| Protocolo | Endpoint | Ejemplo |
|---|---|---|
| OpenAI | POST /api/v1/chat/completions | Funciona con cualquier SDK OpenAI |
| OpenAI (legacy) | POST /api/v1/generate | Generación simplificada |
| Anthropic | POST /v1/messages | Anthropic Messages API |
| Modelos | GET /api/v1/models | Lista modelos disponibles |
| Health | GET /api/v1/health | Sin autenticación |
Backends Intercambiables
| Backend | Caso de Uso |
|---|---|
| ollama | Modelos locales vía API de Ollama |
| openai-compat | vLLM, LiteLLM o cualquier servidor compatible con OpenAI |
| claude | Usa tu suscripción de claude CLI como backend |
| opencode | Usa OpenCode CLI como backend |
| echo | Backend de prueba — siempre responde ECHO: <mensaje> |
Modo Servidor MCP
Relay también expone 5 herramientas MCP via stdio:
generate_key,revoke_key,list_keys— gestión de API keyslist_models— consulta backends disponibleshealth— estado del servidor
Perfecto para agentes que necesitan levantar un endpoint de inferencia local dinámicamente.
Streaming SSE
Streaming en tiempo real compatible con formatos de eventos SSE de OpenAI y Anthropic.
Stack Tecnológico
| Componente | Elección | Por qué |
|---|---|---|
| Lenguaje | Go 1.26+ | Binario estático único, sin deps de runtime |
| Servidor API | net/http + gorilla/mux | Estándar, bien probado |
| Config | YAML + flags CLI | Overrides rápidos sin editar archivos |
| Auth | API keys auto-generadas | Seguridad zero-config |
| Persistencia | ~/.localmcp/keys.json | Keys sobreviven reinicios |
| Tamaño | ~12 MB binario estático | Sin Python, sin Node, sin contenedores |
| Tests | Go test suite | Tests de API core y backends |
Inicio Rápido
git clone https://github.com/fxckcode/relay.git
cd relay
make build
./bin/localmcp
Eso es todo. La API key se auto-genera en el primer inicio. Default escucha en 127.0.0.1:8080.
# Probarlo
KEY=$(./bin/localmcp --show-key)
curl -X POST http://127.0.0.1:8080/api/v1/chat/completions \
-H "X-API-Key: $KEY" \
-H "Content-Type: application/json" \
-d '{"model":"echo","messages":[{"role":"user","content":"Hola"}]}'
El backend echo responde inmediatamente — perfecto para probar. Con Ollama corriendo, usa "model":"llama3.2".
¿Por Qué no LiteLLM / Ollama?
LiteLLM es un proyecto Python completo con dependencias pesadas. Relay es un solo binario Go — sin pip install, sin virtualenv, sin gestión de versiones de Python. Además añade el backend CLI agent (usa tu suscripción de claude CLI como API), que ni LiteLLM ni Ollama pueden hacer.
La compatibilidad con OpenAI de Ollama es sólida pero limitada a modelos de Ollama. Relay se encadena a cualquier backend.
El proyecto tiene licencia MIT y está abierto en GitHub. Contribuciones bienvenidas.