feat(mcp): MCP server for AI clients, consuming the REST API

New app apps/mcp (NestJS + @nestjs-mcp/server 2): Streamable HTTP at
POST /mcp, stateless.

- 24 tools: projects (mine, public, details with settings, board, stats,
  analytics, activity), tickets (my work, search, details with comments and
  history, create, update, move, assign, release, comment, link), releases
  (list, upcoming, details with progress and burnup, create, publish) and
  users (whoami, search). Admin operations stay in the web.
- No credentials of its own: each call's Authorization header (a Pireon
  token) is forwarded to the API; without it only public projects are read.
- Typed REST client generated from apps/api/openapi.json (openapi-fetch +
  openapi-typescript via `nx run mcp:openapi-types`); API refusals become
  readable tool errors; parameters validated with zod.
- Tests: the real MCP against a simulated API (token forwarding, errors,
  validation, writes).
- Docker target `mcp` (Node 24) and an optional compose service under the
  `mcp` profile; zod declared as a root dependency.
- Docs: chapter 9 «Servidor MCP», references in 01/06/07 and the index;
  Word/PDF regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 18:59:38 +02:00
parent 71dc2d6f2d
commit 9236cb73c6
36 changed files with 6054 additions and 38 deletions

View File

@@ -40,7 +40,7 @@ Todos tienen healthcheck; `web` espera a que `api` esté sana, y `api` a las tre
### Imágenes
El `Dockerfile` tiene dos destinos que comparten la instalación de dependencias:
El `Dockerfile` tiene tres destinos que comparten la instalación de dependencias:
- **Instalación**: `npm ci` del workspace. `@pi/ui` viene del Nexus privado; el token llega como **build secret**
desde la variable `NEXUS_TOKEN` (`secrets.nexus_token` en `docker-compose.yml`), se escribe en un `npmrc` temporal y
@@ -48,6 +48,8 @@ El `Dockerfile` tiene dos destinos que comparten la instalación de dependencias
- **`api`**: `nx run api:prune` genera el bundle con un `package.json` y un lockfile podados a partir de
`apps/api/package.json`. La imagen final solo instala esas dependencias (sin Angular ni paquetes privados).
Si la API empieza a usar un paquete nuevo **en tiempo de ejecución**, hay que añadirlo a `apps/api/package.json`.
- **`mcp`**: el [servidor MCP](09-mcp.md), podado igual que la API (`nx run mcp:prune`), sobre Node 24. Su servicio
en `docker-compose.yml` va en el perfil `mcp`: solo arranca con `--profile mcp` (en Dokploy, `COMPOSE_PROFILES=mcp`).
- **`web`**: build de producción de Angular servido por nginx (`apps/web/nginx.conf`): fallback de rutas a
`index.html`, caché larga para los bundles con hash y sin caché para `index.html`.