@saulwade/swl-ses 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/CLAUDE.md +225 -209
  2. package/README.md +578 -561
  3. package/agentes/arquitecto-swl.md +33 -1
  4. package/agentes/nemesis-auditor-swl.md +59 -19
  5. package/bin/swl-mcp-server.js +214 -214
  6. package/bin/swl-ses.js +49 -7
  7. package/comandos/swl/.evolved.json +22 -22
  8. package/comandos/swl/contribuir.md +233 -233
  9. package/comandos/swl/nemesis.md +230 -56
  10. package/gateway/lib/event-channel.js +191 -191
  11. package/habilidades/backend-production-resilience/SKILL.md +288 -288
  12. package/habilidades/benchmark-memoria/SKILL.md +186 -186
  13. package/habilidades/diagrama-arquitectura/assets/template.html +276 -276
  14. package/habilidades/doubt-driven-review/SKILL.md +171 -171
  15. package/habilidades/doubt-driven-review/recursos/EXAMPLES.md +130 -130
  16. package/habilidades/ejecutar-task-iterativo/SKILL.md +278 -278
  17. package/habilidades/eval-framework/SKILL.md +212 -212
  18. package/habilidades/feynman-auditor-swl/SKILL.md +123 -123
  19. package/habilidades/feynman-auditor-swl/recursos/preguntas-language-agnostic.md +108 -108
  20. package/habilidades/harness-claude-code/SKILL.md +299 -299
  21. package/habilidades/infra-github-actions/SKILL.md +166 -166
  22. package/habilidades/legacy-code-rescue/SKILL.md +267 -267
  23. package/habilidades/manejo-errores/.evolved.json +8 -8
  24. package/habilidades/meta-skills-estandar/SKILL.md +207 -4
  25. package/habilidades/meta-skills-estandar/recursos/convencion-examples.md +93 -93
  26. package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -163
  27. package/habilidades/nemesis-evaluacion-json/SKILL.md +266 -0
  28. package/habilidades/nemesis-redistribuir/SKILL.md +341 -0
  29. package/habilidades/node-experto/SKILL.md +94 -4
  30. package/habilidades/patrones-python/SKILL.md +229 -229
  31. package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -469
  32. package/habilidades/planear-fase/SKILL.md +319 -319
  33. package/habilidades/protocolo-revision-swl/SKILL.md +350 -276
  34. package/habilidades/release-semver/.evolved.json +8 -8
  35. package/habilidades/state-inconsistency-auditor-swl/SKILL.md +166 -166
  36. package/habilidades/state-inconsistency-auditor-swl/recursos/coupled-state-patterns.md +147 -147
  37. package/habilidades/tdd-workflow/SKILL.md +121 -4
  38. package/habilidades/testing-python/SKILL.md +340 -340
  39. package/habilidades/web-fetcher-routing/SKILL.md +75 -75
  40. package/hooks/check-update.js +31 -3
  41. package/hooks/claudemd-bloat-detector.js +161 -161
  42. package/hooks/extraccion-aprendizajes.js +11 -0
  43. package/hooks/lib/agent-routing.js +107 -107
  44. package/hooks/lib/auto-consolidator.js +335 -335
  45. package/hooks/lib/error-classifier.js +308 -308
  46. package/hooks/lib/merkle-audit.js +96 -96
  47. package/hooks/lib/provenance-tracker.js +191 -191
  48. package/hooks/lib/rate-limit-tracker.js +253 -253
  49. package/hooks/lib/resource-quota.js +122 -122
  50. package/hooks/lib/retry-jitter.js +165 -165
  51. package/hooks/lib/security-net.js +201 -201
  52. package/hooks/lib/skill-auditor.js +588 -588
  53. package/hooks/lib/sync-status.js +228 -228
  54. package/hooks/lib/taint-tracker.js +107 -107
  55. package/hooks/lib/text-similarity.js +241 -241
  56. package/hooks/lib/toon-compressor.js +245 -245
  57. package/hooks/registro-turnos.js +209 -209
  58. package/hooks/sugerir-regenerar-inventario.js +170 -170
  59. package/hooks/validar-formato-post-subagente.js +140 -140
  60. package/hooks/validar-memoria-hook.js +218 -218
  61. package/instintos/prompt-appendices.yaml +57 -57
  62. package/manifiestos/agent-output-schemas.json +57 -57
  63. package/manifiestos/modulos.json +1324 -1321
  64. package/manifiestos/skills-lock.json +1142 -1114
  65. package/package.json +5 -4
  66. package/plantillas/auditor-veto-template.md +105 -105
  67. package/plantillas/github-workflows/README.md +47 -47
  68. package/plantillas/github-workflows/release-please.yml +44 -44
  69. package/plantillas/github-workflows/swl-ci.yml +107 -107
  70. package/plantillas/github-workflows/swl-security.yml +51 -51
  71. package/plugin.json +355 -351
  72. package/reglas/analisis-previo-tareas-grandes.md +172 -172
  73. package/reglas/arreglar-al-detectar.md +147 -147
  74. package/reglas/fragmentos-compartidos.md +152 -152
  75. package/reglas/harness-claude-code.md +213 -213
  76. package/reglas/registro-componentes-nuevos.md +192 -0
  77. package/reglas/usar-context7.md +226 -226
  78. package/schemas/diary-entry.schema.json +80 -80
  79. package/scripts/actualizar.js +110 -1
  80. package/scripts/audit-tools/audit-history.js +330 -330
  81. package/scripts/audit-tools/bundle-tracker.js +290 -290
  82. package/scripts/audit-tools/canary-monitor.js +352 -352
  83. package/scripts/audit-tools/code-profiler.js +605 -605
  84. package/scripts/audit-tools/dep-doctor.js +320 -320
  85. package/scripts/audit-tools/env-validator.js +206 -206
  86. package/scripts/audit-tools/lib/fs-walk.js +48 -48
  87. package/scripts/audit-tools/lib/output.js +23 -23
  88. package/scripts/audit-tools/migration-checker.js +392 -392
  89. package/scripts/audit-tools/pentest-scanner.js +1436 -1436
  90. package/scripts/benchmark-memoria.js +167 -167
  91. package/scripts/configurar-branch-protection.js +418 -418
  92. package/scripts/derivar-feature-list.js +489 -489
  93. package/scripts/desinstalar.js +105 -24
  94. package/scripts/detectar-aprendizajes-duplicados.js +151 -151
  95. package/scripts/doctor.js +27 -0
  96. package/scripts/field-report.js +199 -199
  97. package/scripts/generar-checklists-consolidados.js +273 -273
  98. package/scripts/generar-inventario.js +420 -420
  99. package/scripts/generar-matriz-lenguajes.js +271 -271
  100. package/scripts/instalador.js +55 -4
  101. package/scripts/lib/artefactos-python.js +43 -43
  102. package/scripts/lib/benchmark-metrics.js +160 -160
  103. package/scripts/lib/budget-enforcer.js +252 -252
  104. package/scripts/lib/configurar-ci.js +380 -380
  105. package/scripts/lib/contadores-inventario.js +217 -217
  106. package/scripts/lib/detectar-stack-detallado.js +307 -307
  107. package/scripts/lib/diary-entry.js +234 -234
  108. package/scripts/lib/eval-metrics-store.js +218 -218
  109. package/scripts/lib/eval-quality.js +171 -171
  110. package/scripts/lib/eval-schemas.js +144 -144
  111. package/scripts/lib/eval-self-correct.js +106 -106
  112. package/scripts/lib/eval-validator.js +185 -185
  113. package/scripts/lib/expandir-targets.js +71 -71
  114. package/scripts/lib/jaccard-similarity.js +98 -98
  115. package/scripts/lib/longmemeval-runner.js +125 -125
  116. package/scripts/lib/mcp_config.py +127 -0
  117. package/scripts/lib/npm-version.js +261 -261
  118. package/scripts/lib/paquetes-conocidos.js +50 -50
  119. package/scripts/lib/parsear-opciones.js +3 -0
  120. package/scripts/lib/prompt-builder.js +264 -264
  121. package/scripts/lib/rrf-fusion.js +175 -175
  122. package/scripts/lib/scoring-instintos.js +277 -277
  123. package/scripts/lib/semantic-search.js +252 -252
  124. package/scripts/lib/toml-merge.js +204 -204
  125. package/scripts/lib/transformadores/codex.js +375 -375
  126. package/scripts/lib/transformadores/cursor.js +359 -359
  127. package/scripts/lib/ui.js +148 -22
  128. package/scripts/limpiar-artefactos-python.js +131 -131
  129. package/scripts/mcp-orchestrator.py +8 -18
  130. package/scripts/mcp-pool-manager.py +12 -23
  131. package/scripts/mcp-server/README.md +170 -170
  132. package/scripts/mcp-server/auth.js +105 -105
  133. package/scripts/mcp-server/cache.js +106 -106
  134. package/scripts/mcp-server/telemetry.js +78 -78
  135. package/scripts/migrar-csv-a-array.js +168 -168
  136. package/scripts/migrar-fase-dominio.js +201 -201
  137. package/scripts/publicar.js +511 -511
  138. package/scripts/run-eval.js +141 -141
  139. package/scripts/tui/componentes/selector-multi.js +189 -0
  140. package/scripts/tui/componentes/selector-unico.js +158 -0
  141. package/scripts/tui/ejecutores.js +375 -0
  142. package/scripts/tui/index.js +162 -0
  143. package/scripts/tui/lib/colores.js +129 -0
  144. package/scripts/tui/lib/render.js +264 -0
  145. package/scripts/tui/lib/teclas.js +113 -0
  146. package/scripts/tui/pantallas/inspect.js +173 -0
  147. package/scripts/tui/pantallas/install-wizard.js +334 -0
  148. package/scripts/tui/pantallas/menu-principal.js +52 -0
  149. package/scripts/tui/pantallas/progreso.js +274 -0
  150. package/scripts/tui/pantallas/resumen.js +132 -0
  151. package/scripts/tui/pantallas/uninstall-wizard.js +208 -0
  152. package/scripts/tui/pantallas/update-wizard.js +232 -0
  153. package/scripts/tui/pantallas/welcome.js +187 -0
  154. package/scripts/validar-userland-vacio.js +110 -110
  155. package/scripts/verificar-docs-vs-codigo.js +425 -0
@@ -1,170 +1,170 @@
1
- # swl-mcp-server v1.0.0
2
-
3
- Servidor MCP de solo lectura para exponer la memoria de swl-ses
4
- (aprendizajes, sesiones, instintos) a clientes MCP externos como Cursor,
5
- Codex CLI y Gemini CLI.
6
-
7
- Promovido de stub experimental (v0.1.x) a v1.0.0 en ADR-0019 Sub-fase 3.
8
-
9
- ## Qué hace
10
-
11
- Expone 5 endpoints sobre stdio JSON-RPC:
12
-
13
- 1. **`swl_memory_search`** — búsqueda hybrid sobre memoria SWL
14
- (aprendizajes + sesiones + instintos) usando `hooks/lib/memory-search`
15
- con RRF fusion.
16
- 2. **`swl_aprendizajes_recientes`** — últimos N aprendizajes de
17
- `.planning/APRENDIZAJES.md`.
18
- 3. **`swl_instintos_activos`** — instintos con `effective_confidence ≥
19
- umbral`.
20
- 4. **`swl_list_skills`** (Sub-fase 9 v1.5.0) — lista skills SWL
21
- disponibles con nombre + descripción del frontmatter. Útil para
22
- descubrir conocimiento operacional antes de invocar uno.
23
- 5. **`swl_invoke_skill`** (Sub-fase 9 v1.5.0) — devuelve el SKILL.md
24
- completo de un skill por nombre. Para clientes MCP que no cargan
25
- skills filesystem nativamente (Codex `--local`, Gemini CLI, otros) —
26
- el cliente recibe el cuerpo del SKILL.md como texto y lo usa como
27
- contexto en su próxima llamada.
28
-
29
- El server lee el estado file-based de swl-ses tal como existe en `cwd`
30
- (o el directorio especificado por `SWL_MCP_BASE_DIR`). NO escribe — solo
31
- lectura. NO ejecuta scripts referenciados desde un skill.
32
-
33
- ### Resolución del directorio de skills
34
-
35
- Para `swl_list_skills` y `swl_invoke_skill`, el server busca skills en
36
- el primer directorio que exista, en este orden:
37
-
38
- 1. `<baseDir>/habilidades/` — repo SWL como project root.
39
- 2. `<baseDir>/.claude/skills/` — proyecto consumidor con SWL instalado
40
- en Claude Code.
41
- 3. `<baseDir>/.cursor/skills/` — proyecto con SWL instalado en Cursor.
42
-
43
- ## Features v1.0.0
44
-
45
- | Feature | Cómo activar | Default |
46
- |---|---|---|
47
- | Auth opt-in (Bearer en `params._auth`) | `SWL_MCP_API_KEY=<token>` en el env del server | sin auth (backward-compat) |
48
- | Caching mtime-based con TTL | Siempre activo | 60 segundos |
49
- | Override TTL del cache | `SWL_MCP_CACHE_TTL_MS=<ms>` | 60000 |
50
- | Telemetría JSONL por call | `SWL_MCP_METRICS=1` | sin telemetría |
51
- | Schema versioning por handler | Siempre presente en `tools/list` | `1.0.0` |
52
-
53
- ## Cómo arrancar (testing)
54
-
55
- ```bash
56
- # Smoke standalone
57
- echo '{"jsonrpc":"2.0","id":1,"method":"initialize"}' | node bin/swl-mcp-server.js
58
-
59
- # Output esperado (sin auth):
60
- # {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{...},"serverInfo":{"name":"swl-mcp-server","version":"1.0.0","authRequired":false,"telemetryEnabled":false}}}
61
-
62
- # Con auth opt-in
63
- SWL_MCP_API_KEY="secret-123" node bin/swl-mcp-server.js
64
-
65
- # Cliente debe enviar params._auth:
66
- echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"_auth":"secret-123","name":"swl_aprendizajes_recientes","arguments":{"limit":5}}}' | SWL_MCP_API_KEY=secret-123 node bin/swl-mcp-server.js
67
- ```
68
-
69
- ## Configuración en clientes MCP
70
-
71
- ### Cursor (autoconfig disponible)
72
-
73
- Desde v1.5.0 el instalador puede registrar el server automáticamente:
74
-
75
- ```bash
76
- npx @saulwade/swl-ses@latest install --target cursor --with-mcp
77
- ```
78
-
79
- Esto genera `.cursor/mcp.json` (per-proyecto) o `~/.cursor/mcp.json`
80
- (con `--global`) preservando otros mcpServers configurados.
81
-
82
- Configuración manual:
83
-
84
- ```json
85
- {
86
- "mcpServers": {
87
- "swl-memory": {
88
- "command": "node",
89
- "args": ["/path/to/swl-ses/bin/swl-mcp-server.js"],
90
- "env": {
91
- "SWL_MCP_BASE_DIR": "/path/to/proyecto",
92
- "SWL_MCP_API_KEY": "opcional-token-secreto"
93
- }
94
- }
95
- }
96
- }
97
- ```
98
-
99
- ### Codex CLI (autoconfig disponible)
100
-
101
- ```bash
102
- npx @saulwade/swl-ses@latest install --target codex --global --with-mcp
103
- ```
104
-
105
- Esto inserta `[mcp_servers.swl-memory]` en `~/.codex/config.toml`
106
- preservando otros servers configurados. Verificar con `codex mcp list`.
107
-
108
- ### Gemini CLI
109
-
110
- Manualmente similar a Cursor — el server expone stdio JSON-RPC estándar.
111
-
112
- ### Claude Code (NO necesario)
113
-
114
- Claude Code ya tiene acceso directo a los archivos de swl-ses dentro de
115
- su propio runtime. NO usar el MCP server desde Claude Code en el mismo
116
- proyecto — sería redundante.
117
-
118
- ## Cambios v0.1.x → v1.0.0
119
-
120
- | Aspecto | v0.1.x (stub) | v1.0.0 |
121
- |---|---|---|
122
- | Auth | sin auth | opt-in con `SWL_MCP_API_KEY` + Bearer en `params._auth` |
123
- | Caching | sin caching | mtime-based con TTL configurable |
124
- | Telemetría | logs stderr | JSONL en `.planning/evolucion/mcp-metrics.jsonl` (opt-in) |
125
- | Schema versioning | implícito | `_schemaVersion` en cada tool de `tools/list` |
126
- | Tests | smoke manual | 38 tests unitarios (`tests/mcp-server/*.test.js`) |
127
- | Estado | "NO usar en producción" | apto para los proyectos del usuario |
128
-
129
- ## Backward compatibility
130
-
131
- v1.0.0 es 100% backward-compatible con clientes que conectan sin auth.
132
- Si `SWL_MCP_API_KEY` no está set en el env del server, el comportamiento
133
- es idéntico al stub v0.1.x — no se requiere ningún cambio en clientes
134
- configurados antes.
135
-
136
- ## Diseño futuro (cuando aparezca demanda real)
137
-
138
- - **HTTP transport opcional**: además de stdio, ofrecer servidor HTTP/SSE
139
- con TLS y CORS configurable.
140
- - **Handlers de escritura** (`swl:memory:write`, `swl:instintos:write`)
141
- fuera de scope v1.0 — requerirían scopes en el token y validación
142
- semántica de cada mutación.
143
- - **Rate limiting** por API key cuando aparezca un caso multi-cliente.
144
- - **OpenTelemetry** para latencias p95 distribuidas si el server se
145
- consume desde múltiples editores en paralelo.
146
-
147
- ## Estado de seguridad
148
-
149
- - ✓ Read-only — no ejecuta código ni modifica archivos.
150
- - ✓ Auth opt-in con comparación constante para defender contra timing
151
- attacks.
152
- - ✓ Caching con invalidación correcta (mtime + TTL).
153
- - ✓ Telemetría con error silencioso — nunca rompe el server.
154
- - ✗ `baseDir` no se valida contra patrón "proyecto SWL válido". Un
155
- cliente con acceso al stdio puede apuntarlo a cualquier directorio
156
- con `APRENDIZAJES.md`. Mitigación: el operador configura el server
157
- con `SWL_MCP_BASE_DIR` explícito.
158
- - ✗ Sin límite de tamaño de query — un cliente malicioso podría enviar
159
- una query gigante. Mitigación parcial: `limit` está clampeado a 50/100.
160
-
161
- Para casos de uso single-user en máquinas confiables del operador, los
162
- puntos restantes son aceptables. Para uso multi-usuario o exposición a
163
- red, evaluar primero el alcance del riesgo y considerar las features
164
- de "diseño futuro" arriba.
165
-
166
- ## Referencias
167
-
168
- - ADR-0019 Sub-fase 3: `.planning/adrs/0019-integracion-codex-y-cursor-completa.md`.
169
- - Tests: `tests/mcp-server/*.test.js` (auth, cache, telemetry, rutear).
170
- - Configuración Cursor: `docs/MCP-SERVER-CURSOR-NOTAS.md`.
1
+ # swl-mcp-server v1.0.0
2
+
3
+ Servidor MCP de solo lectura para exponer la memoria de swl-ses
4
+ (aprendizajes, sesiones, instintos) a clientes MCP externos como Cursor,
5
+ Codex CLI y Gemini CLI.
6
+
7
+ Promovido de stub experimental (v0.1.x) a v1.0.0 en ADR-0019 Sub-fase 3.
8
+
9
+ ## Qué hace
10
+
11
+ Expone 5 endpoints sobre stdio JSON-RPC:
12
+
13
+ 1. **`swl_memory_search`** — búsqueda hybrid sobre memoria SWL
14
+ (aprendizajes + sesiones + instintos) usando `hooks/lib/memory-search`
15
+ con RRF fusion.
16
+ 2. **`swl_aprendizajes_recientes`** — últimos N aprendizajes de
17
+ `.planning/APRENDIZAJES.md`.
18
+ 3. **`swl_instintos_activos`** — instintos con `effective_confidence ≥
19
+ umbral`.
20
+ 4. **`swl_list_skills`** (Sub-fase 9 v1.5.0) — lista skills SWL
21
+ disponibles con nombre + descripción del frontmatter. Útil para
22
+ descubrir conocimiento operacional antes de invocar uno.
23
+ 5. **`swl_invoke_skill`** (Sub-fase 9 v1.5.0) — devuelve el SKILL.md
24
+ completo de un skill por nombre. Para clientes MCP que no cargan
25
+ skills filesystem nativamente (Codex `--local`, Gemini CLI, otros) —
26
+ el cliente recibe el cuerpo del SKILL.md como texto y lo usa como
27
+ contexto en su próxima llamada.
28
+
29
+ El server lee el estado file-based de swl-ses tal como existe en `cwd`
30
+ (o el directorio especificado por `SWL_MCP_BASE_DIR`). NO escribe — solo
31
+ lectura. NO ejecuta scripts referenciados desde un skill.
32
+
33
+ ### Resolución del directorio de skills
34
+
35
+ Para `swl_list_skills` y `swl_invoke_skill`, el server busca skills en
36
+ el primer directorio que exista, en este orden:
37
+
38
+ 1. `<baseDir>/habilidades/` — repo SWL como project root.
39
+ 2. `<baseDir>/.claude/skills/` — proyecto consumidor con SWL instalado
40
+ en Claude Code.
41
+ 3. `<baseDir>/.cursor/skills/` — proyecto con SWL instalado en Cursor.
42
+
43
+ ## Features v1.0.0
44
+
45
+ | Feature | Cómo activar | Default |
46
+ |---|---|---|
47
+ | Auth opt-in (Bearer en `params._auth`) | `SWL_MCP_API_KEY=<token>` en el env del server | sin auth (backward-compat) |
48
+ | Caching mtime-based con TTL | Siempre activo | 60 segundos |
49
+ | Override TTL del cache | `SWL_MCP_CACHE_TTL_MS=<ms>` | 60000 |
50
+ | Telemetría JSONL por call | `SWL_MCP_METRICS=1` | sin telemetría |
51
+ | Schema versioning por handler | Siempre presente en `tools/list` | `1.0.0` |
52
+
53
+ ## Cómo arrancar (testing)
54
+
55
+ ```bash
56
+ # Smoke standalone
57
+ echo '{"jsonrpc":"2.0","id":1,"method":"initialize"}' | node bin/swl-mcp-server.js
58
+
59
+ # Output esperado (sin auth):
60
+ # {"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{...},"serverInfo":{"name":"swl-mcp-server","version":"1.0.0","authRequired":false,"telemetryEnabled":false}}}
61
+
62
+ # Con auth opt-in
63
+ SWL_MCP_API_KEY="secret-123" node bin/swl-mcp-server.js
64
+
65
+ # Cliente debe enviar params._auth:
66
+ echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"_auth":"secret-123","name":"swl_aprendizajes_recientes","arguments":{"limit":5}}}' | SWL_MCP_API_KEY=secret-123 node bin/swl-mcp-server.js
67
+ ```
68
+
69
+ ## Configuración en clientes MCP
70
+
71
+ ### Cursor (autoconfig disponible)
72
+
73
+ Desde v1.5.0 el instalador puede registrar el server automáticamente:
74
+
75
+ ```bash
76
+ npx @saulwade/swl-ses@latest install --target cursor --with-mcp
77
+ ```
78
+
79
+ Esto genera `.cursor/mcp.json` (per-proyecto) o `~/.cursor/mcp.json`
80
+ (con `--global`) preservando otros mcpServers configurados.
81
+
82
+ Configuración manual:
83
+
84
+ ```json
85
+ {
86
+ "mcpServers": {
87
+ "swl-memory": {
88
+ "command": "node",
89
+ "args": ["/path/to/swl-ses/bin/swl-mcp-server.js"],
90
+ "env": {
91
+ "SWL_MCP_BASE_DIR": "/path/to/proyecto",
92
+ "SWL_MCP_API_KEY": "opcional-token-secreto"
93
+ }
94
+ }
95
+ }
96
+ }
97
+ ```
98
+
99
+ ### Codex CLI (autoconfig disponible)
100
+
101
+ ```bash
102
+ npx @saulwade/swl-ses@latest install --target codex --global --with-mcp
103
+ ```
104
+
105
+ Esto inserta `[mcp_servers.swl-memory]` en `~/.codex/config.toml`
106
+ preservando otros servers configurados. Verificar con `codex mcp list`.
107
+
108
+ ### Gemini CLI
109
+
110
+ Manualmente similar a Cursor — el server expone stdio JSON-RPC estándar.
111
+
112
+ ### Claude Code (NO necesario)
113
+
114
+ Claude Code ya tiene acceso directo a los archivos de swl-ses dentro de
115
+ su propio runtime. NO usar el MCP server desde Claude Code en el mismo
116
+ proyecto — sería redundante.
117
+
118
+ ## Cambios v0.1.x → v1.0.0
119
+
120
+ | Aspecto | v0.1.x (stub) | v1.0.0 |
121
+ |---|---|---|
122
+ | Auth | sin auth | opt-in con `SWL_MCP_API_KEY` + Bearer en `params._auth` |
123
+ | Caching | sin caching | mtime-based con TTL configurable |
124
+ | Telemetría | logs stderr | JSONL en `.planning/evolucion/mcp-metrics.jsonl` (opt-in) |
125
+ | Schema versioning | implícito | `_schemaVersion` en cada tool de `tools/list` |
126
+ | Tests | smoke manual | 38 tests unitarios (`tests/mcp-server/*.test.js`) |
127
+ | Estado | "NO usar en producción" | apto para los proyectos del usuario |
128
+
129
+ ## Backward compatibility
130
+
131
+ v1.0.0 es 100% backward-compatible con clientes que conectan sin auth.
132
+ Si `SWL_MCP_API_KEY` no está set en el env del server, el comportamiento
133
+ es idéntico al stub v0.1.x — no se requiere ningún cambio en clientes
134
+ configurados antes.
135
+
136
+ ## Diseño futuro (cuando aparezca demanda real)
137
+
138
+ - **HTTP transport opcional**: además de stdio, ofrecer servidor HTTP/SSE
139
+ con TLS y CORS configurable.
140
+ - **Handlers de escritura** (`swl:memory:write`, `swl:instintos:write`)
141
+ fuera de scope v1.0 — requerirían scopes en el token y validación
142
+ semántica de cada mutación.
143
+ - **Rate limiting** por API key cuando aparezca un caso multi-cliente.
144
+ - **OpenTelemetry** para latencias p95 distribuidas si el server se
145
+ consume desde múltiples editores en paralelo.
146
+
147
+ ## Estado de seguridad
148
+
149
+ - ✓ Read-only — no ejecuta código ni modifica archivos.
150
+ - ✓ Auth opt-in con comparación constante para defender contra timing
151
+ attacks.
152
+ - ✓ Caching con invalidación correcta (mtime + TTL).
153
+ - ✓ Telemetría con error silencioso — nunca rompe el server.
154
+ - ✗ `baseDir` no se valida contra patrón "proyecto SWL válido". Un
155
+ cliente con acceso al stdio puede apuntarlo a cualquier directorio
156
+ con `APRENDIZAJES.md`. Mitigación: el operador configura el server
157
+ con `SWL_MCP_BASE_DIR` explícito.
158
+ - ✗ Sin límite de tamaño de query — un cliente malicioso podría enviar
159
+ una query gigante. Mitigación parcial: `limit` está clampeado a 50/100.
160
+
161
+ Para casos de uso single-user en máquinas confiables del operador, los
162
+ puntos restantes son aceptables. Para uso multi-usuario o exposición a
163
+ red, evaluar primero el alcance del riesgo y considerar las features
164
+ de "diseño futuro" arriba.
165
+
166
+ ## Referencias
167
+
168
+ - ADR-0019 Sub-fase 3: `.planning/adrs/0019-integracion-codex-y-cursor-completa.md`.
169
+ - Tests: `tests/mcp-server/*.test.js` (auth, cache, telemetry, rutear).
170
+ - Configuración Cursor: `docs/MCP-SERVER-CURSOR-NOTAS.md`.
@@ -1,105 +1,105 @@
1
- 'use strict';
2
-
3
- /**
4
- * Auth opt-in para swl-mcp-server v1.0.0 (ADR-0019 Sub-fase 3).
5
- *
6
- * El stub experimental v0.1.x corría sin auth. Cualquier proceso con acceso al
7
- * stdio podía leer toda la memoria SWL. Esa decisión era aceptable solo en
8
- * single-user local — no en multi-usuario, no expuesto a red, no compartido.
9
- *
10
- * v1.0.0 introduce auth **opt-in**:
11
- * - Si `SWL_MCP_API_KEY` NO está definida en el entorno del server, el comportamiento
12
- * es idéntico al stub (sin auth). Compatibilidad total con clientes existentes.
13
- * - Si `SWL_MCP_API_KEY` ESTÁ definida, cada `tools/call` debe incluir
14
- * `params._auth = "<api-key>"`. Sin el token o con token incorrecto, se devuelve
15
- * `-32001 Unauthorized`.
16
- *
17
- * Decisión deliberada de NO usar header `Authorization: Bearer ...`:
18
- * - El protocolo MCP sobre stdio NO transporta headers HTTP.
19
- * - Inventar un campo en `initialize.capabilities` específico para swl-ses
20
- * rompería la spec del protocolo.
21
- * - `_auth` como campo en `params` es el patrón de menor fricción.
22
- *
23
- * Limitaciones aceptadas:
24
- * - Token estático sin rotación automática — el operador rota manualmente
25
- * cambiando la env var del proceso.
26
- * - Sin scopes (read/write) porque v1 sigue siendo read-only.
27
- *
28
- * @module scripts/mcp-server/auth
29
- */
30
-
31
- const ENV_VAR_NAME = 'SWL_MCP_API_KEY';
32
- const ERROR_CODE_UNAUTHORIZED = -32001;
33
- const ERROR_CODE_FORBIDDEN = -32002;
34
-
35
- /**
36
- * Construye un validador de auth desde el entorno actual.
37
- *
38
- * Pattern de "construct once, use many": leer la env var una sola vez al arranque
39
- * y devolver una función pura que valida cada request. Evita race conditions con
40
- * tests que mutan process.env.
41
- *
42
- * @param {object} [opciones] - { env: NodeJS.ProcessEnv } sustituible para tests.
43
- * @returns {{ requerida: boolean, validar: (request: object) => { ok: boolean, code?: number, message?: string } }}
44
- */
45
- function construirValidador(opciones = {}) {
46
- const env = opciones.env || process.env;
47
- const apiKey = env[ENV_VAR_NAME];
48
- const requerida = typeof apiKey === 'string' && apiKey.length > 0;
49
-
50
- return {
51
- requerida,
52
- validar: (request) => {
53
- if (!requerida) return { ok: true };
54
- // Solo validar tools/call — initialize, ping, tools/list son metadata pública.
55
- const metodo = request && request.method;
56
- if (metodo !== 'tools/call') return { ok: true };
57
-
58
- const params = request.params || {};
59
- const tokenCliente = params._auth;
60
-
61
- if (typeof tokenCliente !== 'string' || tokenCliente.length === 0) {
62
- return {
63
- ok: false,
64
- code: ERROR_CODE_UNAUTHORIZED,
65
- message: 'swl-mcp-server requiere autenticación: SWL_MCP_API_KEY está configurada en el server. El cliente debe enviar params._auth con el API key.',
66
- };
67
- }
68
- if (!comparacionConstante(tokenCliente, apiKey)) {
69
- return {
70
- ok: false,
71
- code: ERROR_CODE_FORBIDDEN,
72
- message: 'Token inválido.',
73
- };
74
- }
75
- return { ok: true };
76
- },
77
- };
78
- }
79
-
80
- /**
81
- * Comparación de strings en tiempo constante para evitar timing attacks
82
- * sobre el API key. Implementación zero-deps simple.
83
- *
84
- * Si las longitudes difieren, igual se itera la longitud máxima para no filtrar
85
- * información sobre el largo del secreto vía duración de la comparación.
86
- */
87
- function comparacionConstante(a, b) {
88
- if (typeof a !== 'string' || typeof b !== 'string') return false;
89
- const len = Math.max(a.length, b.length);
90
- let diff = a.length ^ b.length;
91
- for (let i = 0; i < len; i++) {
92
- const ca = i < a.length ? a.charCodeAt(i) : 0;
93
- const cb = i < b.length ? b.charCodeAt(i) : 0;
94
- diff |= ca ^ cb;
95
- }
96
- return diff === 0;
97
- }
98
-
99
- module.exports = {
100
- construirValidador,
101
- comparacionConstante,
102
- ENV_VAR_NAME,
103
- ERROR_CODE_UNAUTHORIZED,
104
- ERROR_CODE_FORBIDDEN,
105
- };
1
+ 'use strict';
2
+
3
+ /**
4
+ * Auth opt-in para swl-mcp-server v1.0.0 (ADR-0019 Sub-fase 3).
5
+ *
6
+ * El stub experimental v0.1.x corría sin auth. Cualquier proceso con acceso al
7
+ * stdio podía leer toda la memoria SWL. Esa decisión era aceptable solo en
8
+ * single-user local — no en multi-usuario, no expuesto a red, no compartido.
9
+ *
10
+ * v1.0.0 introduce auth **opt-in**:
11
+ * - Si `SWL_MCP_API_KEY` NO está definida en el entorno del server, el comportamiento
12
+ * es idéntico al stub (sin auth). Compatibilidad total con clientes existentes.
13
+ * - Si `SWL_MCP_API_KEY` ESTÁ definida, cada `tools/call` debe incluir
14
+ * `params._auth = "<api-key>"`. Sin el token o con token incorrecto, se devuelve
15
+ * `-32001 Unauthorized`.
16
+ *
17
+ * Decisión deliberada de NO usar header `Authorization: Bearer ...`:
18
+ * - El protocolo MCP sobre stdio NO transporta headers HTTP.
19
+ * - Inventar un campo en `initialize.capabilities` específico para swl-ses
20
+ * rompería la spec del protocolo.
21
+ * - `_auth` como campo en `params` es el patrón de menor fricción.
22
+ *
23
+ * Limitaciones aceptadas:
24
+ * - Token estático sin rotación automática — el operador rota manualmente
25
+ * cambiando la env var del proceso.
26
+ * - Sin scopes (read/write) porque v1 sigue siendo read-only.
27
+ *
28
+ * @module scripts/mcp-server/auth
29
+ */
30
+
31
+ const ENV_VAR_NAME = 'SWL_MCP_API_KEY';
32
+ const ERROR_CODE_UNAUTHORIZED = -32001;
33
+ const ERROR_CODE_FORBIDDEN = -32002;
34
+
35
+ /**
36
+ * Construye un validador de auth desde el entorno actual.
37
+ *
38
+ * Pattern de "construct once, use many": leer la env var una sola vez al arranque
39
+ * y devolver una función pura que valida cada request. Evita race conditions con
40
+ * tests que mutan process.env.
41
+ *
42
+ * @param {object} [opciones] - { env: NodeJS.ProcessEnv } sustituible para tests.
43
+ * @returns {{ requerida: boolean, validar: (request: object) => { ok: boolean, code?: number, message?: string } }}
44
+ */
45
+ function construirValidador(opciones = {}) {
46
+ const env = opciones.env || process.env;
47
+ const apiKey = env[ENV_VAR_NAME];
48
+ const requerida = typeof apiKey === 'string' && apiKey.length > 0;
49
+
50
+ return {
51
+ requerida,
52
+ validar: (request) => {
53
+ if (!requerida) return { ok: true };
54
+ // Solo validar tools/call — initialize, ping, tools/list son metadata pública.
55
+ const metodo = request && request.method;
56
+ if (metodo !== 'tools/call') return { ok: true };
57
+
58
+ const params = request.params || {};
59
+ const tokenCliente = params._auth;
60
+
61
+ if (typeof tokenCliente !== 'string' || tokenCliente.length === 0) {
62
+ return {
63
+ ok: false,
64
+ code: ERROR_CODE_UNAUTHORIZED,
65
+ message: 'swl-mcp-server requiere autenticación: SWL_MCP_API_KEY está configurada en el server. El cliente debe enviar params._auth con el API key.',
66
+ };
67
+ }
68
+ if (!comparacionConstante(tokenCliente, apiKey)) {
69
+ return {
70
+ ok: false,
71
+ code: ERROR_CODE_FORBIDDEN,
72
+ message: 'Token inválido.',
73
+ };
74
+ }
75
+ return { ok: true };
76
+ },
77
+ };
78
+ }
79
+
80
+ /**
81
+ * Comparación de strings en tiempo constante para evitar timing attacks
82
+ * sobre el API key. Implementación zero-deps simple.
83
+ *
84
+ * Si las longitudes difieren, igual se itera la longitud máxima para no filtrar
85
+ * información sobre el largo del secreto vía duración de la comparación.
86
+ */
87
+ function comparacionConstante(a, b) {
88
+ if (typeof a !== 'string' || typeof b !== 'string') return false;
89
+ const len = Math.max(a.length, b.length);
90
+ let diff = a.length ^ b.length;
91
+ for (let i = 0; i < len; i++) {
92
+ const ca = i < a.length ? a.charCodeAt(i) : 0;
93
+ const cb = i < b.length ? b.charCodeAt(i) : 0;
94
+ diff |= ca ^ cb;
95
+ }
96
+ return diff === 0;
97
+ }
98
+
99
+ module.exports = {
100
+ construirValidador,
101
+ comparacionConstante,
102
+ ENV_VAR_NAME,
103
+ ERROR_CODE_UNAUTHORIZED,
104
+ ERROR_CODE_FORBIDDEN,
105
+ };