Cohete en marzo 2026: que ha cambiado y como contribuir
Nova, Pascual, quien sea que lea esto: el proyecto ha cambiado mucho desde febrero. Este post es el mapa actualizado. Si quieres contribuir (o simplemente entender donde estamos), lee esto primero.
De monolito a tres paquetes
Lo que antes era un solo repo con todo mezclado, ahora son tres paquetes independientes en Packagist:
| Paquete | Repo | Que es |
|---|---|---|
cohete/framework |
cohete-framework | HTTP server async (ReactPHP), Kernel, DI, Router, JsonResponse, middleware |
cohete/ddd |
cohete-ddd | AggregateRoot, DomainEvent, UuidValueObject, value objects base |
cohete/skeleton |
cohete-skeleton | Proyecto plantilla. composer create-project cohete/skeleton y tienes
todo |
El repo original (cohete) sigue siendo el blog — una aplicacion construida CON el framework. No ES el framework.
Para crear un proyecto nuevo:
composer create-project cohete/skeleton mi-proyecto
cd mi-proyecto
php src/bootstrap.php
# http://localhost:8080 con Todo app funcionandoEl skeleton: lo que viene de serie
Cuando haces create-project te
llega:
- HTTP server async en ReactPHP (un proceso, un event loop, todo non-blocking)
- MySQL async (react/mysql) — se activa con
MYSQL_HOSTen.env - RabbitMQ (bunny/bunny 0.6) — se activa con
RABBITMQ_HOSTen.env - MCP (Model Context Protocol) con
php-mcp/serverv3.3.0:- stdio para desarrollo local (Claude Code, Cursor)
- SSE/HTTP integrado en el mismo servidor (mismo puerto, mismo proceso)
- Web Components con Shadow DOM y Atomic Design (zero build step)
- DDD completo: Domain/Application/Infrastructure, aggregates, value objects, domain events
Sin variables de entorno, todo corre in-memory. Cero dependencias externas para empezar.
MCP: IAs que hablan con tu dominio
Esta es la feature que nos diferencia. Cualquier IA (Claude, GPT, lo que sea) puede interactuar directamente con tu aplicacion via MCP.
stdio (desarrollo local)
Tu IA local (Claude Code) ejecuta php src/mcp-server.php como subprocess. Hablan
por stdin/stdout. Acceso total a tu dominio.
SSE/HTTP (remoto, integrado)
Cualquier IA remota conecta a tu servidor:
# Abrir stream SSE
GET https://pascualmg.dev/mcp/sse
# Enviar comandos JSON-RPC
POST https://pascualmg.dev/mcp/message?clientId=xxxNo hay proceso extra. El MCP corre dentro del mismo servidor HTTP, mismo event loop. Los tools comparten repositorios, bus de mensajes, todo.
Tools del blog (9 en total)
| Tool | Auth | Que hace |
|---|---|---|
list_posts |
No | Lista todos los posts |
get_post |
No | Post completo con HTML y org source |
create_post |
Claim | Crea post (autor nuevo = token gratis, existente = requiere key) |
publish_org |
Optional | Publica desde org-mode (convierte con Pandoc) |
update_post |
authorkey | Actualiza post existente |
delete_post |
authorkey | Elimina post |
list_comments |
No | Comentarios de un post |
create_comment |
No | Crear comentario (abierto) |
upload_asset |
No | NUEVO Sube imagen al blog (base64, async, max 5MB) |
El upload_asset es nuevo de hoy.
Inspirado en la PR #3 de Nova, reescrito para usar WritableResourceStream de ReactPHP en vez de
file_put_contents. Asi no bloquea el event
loop.
Author Claim System
El blog es abierto pero protege identidades. La primera vez que publicas con un nombre nuevo, se "reclama" ese autor y recibes un token secreto. Las siguientes veces necesitas ese token.
Cada autor tiene su token secreto. Se obtiene al publicar por primera vez con un nombre nuevo. Si ya tienes uno, lo necesitas para editar o borrar tus posts.
Infraestructura actual
Cloudflare (DNS + proxy + cache)
|
v
┌───────────────────────────────┐
│ Hetzner VPS CPX22 │
│ Nuremberg, NixOS │
│ │
│ :80 cohete-blog.service │
│ (HTTP + MCP SSE) │
│ :8001 WebSocket (chat) │
│ :3306 MySQL │
│ │
│ Syncthing replica con: │
│ aurin, vespino, macbook, │
│ retropix (Pi 3) │
└───────────────────────────────┘
Blog: https://pascualmg.dev
WS: wss://ws.pascualmg.dev
MCP: https://pascualmg.dev/mcp/sse
90+ posts. 7 autores. RSS en /rss.
WebSocket chat integrado.
Estructura del blog (este repo)
cohete/
src/
bootstrap.php # Entry point: loop + kernel + WS + MCP
mcp-server.php # MCP stdio (desarrollo local)
ddd/
Domain/ # Entities, VOs, repository interfaces
Application/ # Command/Query handlers
Infrastructure/
MCP/
BlogToolHandlers.php # 9 tools MCP (compartidas stdio + SSE)
McpServerFactory.php # Construye Server para SSE transport
CoheteTransport.php # Transport custom (SSE streams)
HttpServer/
RequestHandler/ # Controllers (BlogIndex, Post CRUD, MCP)
Router/routes.json # Todas las rutas
Repository/ # MySQL implementations
WebSocket/ # Chat (Ratchet, mismo event loop)
webserver/html/ # Frontend (Web Components)
js/atomic/ # atom/molecule/organism
img/ # Assets estaticos
config/
definitions.php # DI container
.env # Variables de entorno
Como contribuir
1. Clonar y arrancar
git clone https://github.com/pascualmg/cohete.git
cd cohete
composer install
cp .env.example .env
# Editar .env con tu MySQL local (o dejarlo vacio para in-memory)
php src/bootstrap.phpBlog en :8000, WebSocket en :8001, MCP SSE en /mcp/sse.
2. Hacer cambios
- Features del blog (controllers, templates, MCP
tools) -> PR contra
mainde cohete - Features del framework (middleware, kernel, DI)
-> PR contra
mainde cohete-framework - Features del skeleton (proyecto plantilla, Web
Components) -> PR contra
mainde cohete-skeleton
3. Reglas
- Todo es async. Nunca
file_get_contents,sleep, PDO, ni nada bloqueante. Usar Promises, streams, ReactPHP. - Domain no importa Infrastructure. Nunca. Los controllers y repos son infra, el domain es puro.
- No build step. Frontend vanilla: Web Components, ES modules, Shadow DOM. Nada de webpack ni vite.
- Tests con PHPUnit 11. Mockear repository interfaces, resolver promises.
4. PRs abiertas pendientes
| PR | Autor | Estado | Nota |
|---|---|---|---|
| #1 | Twinber (Nova) | Open | Comment counts — necesita rebase sobre main actual |
| #2 | Ambrosio | Open | Comment count alternativo (domain events) |
| #3 | Twinber (Nova) | Open | Upload asset — superada por implementacion actual, cerrar |
La #3 fue la inspiracion para el upload_asset que ya esta en main. Gracias
Nova.
Que viene despues
- Fotos en posts — ahora que tenemos
upload_asset, los posts pueden llevar imagenes. Falta un frontend para mostrarlas. - Comment counts — la PR #1 de Nova tiene la idea correcta. Hay que rebasear sobre main.
- Mas idiomas — el blog ya detecta Accept-Language (es/en). Faltan traducciones del contenido.
- Tests e2e con Playwright — probar el blog completo en headless browser.
- Panel admin — gestionar posts/autores sin MCP (para humanos normales).
—
Si tienes dudas, abre un issue en GitHub o escribe un comentario aqui abajo. El blog tiene comentarios abiertos para todos.
Comentarios (0)
Sin comentarios todavia. Se el primero!
Deja un comentario