orquestra-mcp 1.58.0 → 1.61.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.
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # orquestra-mcp
2
2
 
3
- Servidor MCP (Model Context Protocol) para Orquestra. Expone **149 tools**
3
+ Servidor MCP (Model Context Protocol) para Orquestra. Expone **158 tools**
4
4
  (conteo al 24 oct 2026, v1.49.0; la lista real está en `src/server.mjs`)
5
5
  que llaman a la API de `orquestra-infra`: lectura de contexto/dashboard/
6
6
  workspace/infra/paridad/listados, escritura de tareas/ideas/changelog/
@@ -42,6 +42,14 @@ de su caché.
42
42
  publicada. Con `@latest` cada arranque la usa; el servidor que ya está corriendo conserva
43
43
  la suya hasta que reconectas (en Claude Code: `/mcp` → reconectar).
44
44
 
45
+ **Forzar la actualización:** reinicia la sesión (o `/mcp` → reconectar) y, si sigue la
46
+ versión vieja, `npx clear-npx-cache`. Si registraste el MCP como `orquestra-mcp` sin
47
+ `@latest`, migra con un comando:
48
+ `claude mcp remove orquestra && claude mcp add orquestra -e ORQUESTRA_AGENT=claude-code -- npx -y orquestra-mcp@latest`.
49
+ `diagnostico_conexion` (cuando no hay conexión) muestra la versión en uso frente a la
50
+ última publicada y detecta configs sin `@latest`; con conexión, `get_project_context`
51
+ trae `orquestraMcpUpdate` si hay versión nueva.
52
+
45
53
  Variable opcional `ORQUESTRA_WEB_URL` para apuntar el login a otro lugar
46
54
  (ej. `http://localhost:5173` mientras desarrollas `orquestra-web` local en
47
55
  vez de contra producción).
@@ -140,7 +148,9 @@ Lectura de contexto:
140
148
  | Tool | Args | Descripción |
141
149
  |---|---|---|
142
150
  | `get_project_context` | `projectId?` | Snapshot compacto del proyecto (fase, tareas abiertas/vencidas/bloqueadas, módulos, ideas, changelog reciente) |
143
- | `list_tasks` | `projectId?`, `statusId?` | Lista de tareas, filtro opcional por estatus |
151
+ | `list_tasks` | `projectId?`, `statusId?`, `summary?`, `fields?`, `limit?`, `cursor?` | Lista de tareas, filtro opcional por estatus; en proyectos grandes usa `summary`/`fields`/`limit` y pagina con `nextCursor` |
152
+ | `get_task` | `code?` o `id?` | Una tarea completa (checklist y verificaciones) por folio o id; 404 si no existe, 409 si el código es ambiguo |
153
+ | `update_tasks` | `items[]` (1-50), `opId?` | Edita varias tareas en una llamada; respuesta parcial por ítem |
144
154
  | `search` | `projectId?`, `q` | Búsqueda por texto en tareas/notas/ideas/docs |
145
155
  | `get_dashboard_summary` | `projectId?` | Hoy/vencidas/bloqueadas, salud de módulos, actividad reciente |
146
156
  | `get_project_findings` | `projectId?` | Qué le falta al proyecto, priorizado por severidad (determinístico, sin créditos de IA) |
@@ -166,7 +176,7 @@ parcial: la lista completa está en `src/server.mjs`:
166
176
  | Entidad | Tools | Notas |
167
177
  |---|---|---|
168
178
  | Tareas | `create_task`, `update_task` | `update_task` incluye `scope` — úsalo para resolver desfases de paridad |
169
- | Verificaciones por plataforma | `list_verifications`, `add_verification`, `update_verification`, `delete_verification`, `verify_with_agent` | Confirmaciones (humanas o de agente) de que la tarea quedó bien en web/iOS/Android/API — NO van en el checklist. La tarea no cierra con verificaciones abiertas y se cierra sola al aprobarse la última; `failed` (con `note`) la regresa a su estatus anterior. También: `verifications` en `create_task`, `waiveVerifications` en `update_task` (solo con confirmación del usuario) y `verificationId` en `create_agent_run` |
179
+ | Verificaciones por plataforma | `list_verifications`, `add_verification`, `add_verifications` (lote), `update_verification`, `delete_verification`, `verify_with_agent` | Confirmaciones (humanas o de agente) de que la tarea quedó bien en web/iOS/Android/API — NO van en el checklist. La tarea no cierra con verificaciones abiertas y se cierra sola al aprobarse la última; `failed` (con `note`) la regresa a su estatus anterior. También: `verifications` en `create_task`, `waiveVerifications` en `update_task` (solo con confirmación del usuario) y `verificationId` en `create_agent_run` |
170
180
  | Ideas | `list_ideas`, `create_idea`, `update_idea` | |
171
181
  | Changelog | `list_changelog`, `create_changelog_entry`, `update_changelog_entry` | Estilo Keep a Changelog |
172
182
  | Notas | `list_notes`, `create_note`, `update_note` | |
@@ -229,7 +239,7 @@ create/update sigue siendo criterio del agente y del humano.
229
239
 
230
240
  ## Estado
231
241
 
232
- 149 tools (ver arriba): lectura (contexto, dashboard, workspace, infra, paridad, standup,
242
+ 158 tools (ver arriba): lectura (contexto, dashboard, workspace, infra, paridad, standup,
233
243
  sync report, setup guide, playbooks de etapa y de plataforma, catálogo de
234
244
  skills, search) + `list_*` de cada colección + creación/edición de tareas
235
245
  (con checklist, verificaciones por plataforma, tiempo, adjuntos, merge), ideas (con comentarios), notas,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orquestra-mcp",
3
- "version": "1.58.0",
3
+ "version": "1.61.0",
4
4
  "description": "Servidor MCP de Orquestra -- 135 tools para leer y escribir tareas, ideas, changelog, infraestructura, contenido, QA y más desde un agente de IA",
5
5
  "type": "module",
6
6
  "bin": {
package/src/api.mjs CHANGED
@@ -68,19 +68,20 @@ function buildUrl(config, path, params) {
68
68
  // Todas pasan por request() (http.mjs, ORQ-343): plazo por intento, cancelación de la tool y
69
69
  // reintentos acotados -- las lecturas ante fallas transitorias, las escrituras solo ante el
70
70
  // throttling del API Gateway (no llegó a la Lambda, no puede duplicar nada).
71
- const auth = config => ({ Authorization: `Bearer ${config.apiToken}` })
71
+ // x-orquestra-client: la API lo lee para el origen de la bitácora de acceso (ORQ-480).
72
+ const auth = config => ({ Authorization: `Bearer ${config.apiToken}`, 'x-orquestra-client': 'mcp' })
72
73
  const jsonHeaders = config => ({ ...auth(config), 'Content-Type': 'application/json' })
73
74
 
74
75
  export async function apiGet(config, path, params = {}) {
75
76
  return request(buildUrl(config, path, params), { headers: auth(config) })
76
77
  }
77
78
 
78
- export async function apiPost(config, path, { projectId, ...body }) {
79
- return request(buildUrl(config, path, { projectId }), { method: 'POST', headers: jsonHeaders(config), body: JSON.stringify(body) })
79
+ export async function apiPost(config, path, { projectId, ...body }, query = {}) {
80
+ return request(buildUrl(config, path, { projectId, ...query }), { method: 'POST', headers: jsonHeaders(config), body: JSON.stringify(body) })
80
81
  }
81
82
 
82
- export async function apiPatch(config, path, { projectId, id, ...body }) {
83
- return request(buildUrl(config, `${path}/${id}`, { projectId }), { method: 'PATCH', headers: jsonHeaders(config), body: JSON.stringify(body) })
83
+ export async function apiPatch(config, path, { projectId, id, ...body }, query = {}) {
84
+ return request(buildUrl(config, `${path}/${id}`, { projectId, ...query }), { method: 'PATCH', headers: jsonHeaders(config), body: JSON.stringify(body) })
84
85
  }
85
86
 
86
87
  // Mismo método que apiPatch, pero para un doc singleton SIN id en la ruta
@@ -94,8 +95,8 @@ export async function apiPatchPath(config, path, { projectId, ...body }) {
94
95
  // -- ver CLAUDE.md, "único delete_* real de la API/MCP"). Mismo shape que
95
96
  // apiPatch (arma la URL como `${path}/${id}`), sin body -- ningún delete de
96
97
  // esta API necesita mandar datos, solo identificar el recurso.
97
- export async function apiDelete(config, path, { projectId, id }) {
98
- return request(buildUrl(config, `${path}/${id}`, { projectId }), { method: 'DELETE', headers: auth(config) })
98
+ export async function apiDelete(config, path, { projectId, id }, query = {}) {
99
+ return request(buildUrl(config, `${path}/${id}`, { projectId, ...query }), { method: 'DELETE', headers: auth(config) })
99
100
  }
100
101
 
101
102
  // DELETE sobre un recurso singleton SIN id en la ruta (ej. /v1/client-portal,
@@ -3,7 +3,7 @@
3
3
  // lo lee directo desde aca (mismo criterio que stages.mjs/foundations.mjs).
4
4
  // Puerto de TRACKING_TOOLS de la web: herramientas de medición conectables a una
5
5
  // distribución web. El ID vive en distributions.publishForm[key]. `pattern` valida
6
- // el formato (se serializa como string en la web, acá es el RegExp directo).
6
+ // el formato (se serializa como string en la web, aquí es el RegExp directo).
7
7
  export const TRACKING_TOOLS = [
8
8
  { key: 'ga4_measurement_id', label: 'Google Analytics 4', idLabel: 'ID de medición', pattern: /^G-[A-Z0-9]{6,12}$/, example: 'G-ABC123DEF4', where: 'Google Analytics → Admin → Flujos de datos' },
9
9
  { key: 'meta_pixel_id', label: 'Meta Pixel', idLabel: 'ID del Pixel', pattern: /^\d{8,20}$/, example: '1234567890123456', where: 'Meta Business → Events Manager' },
@@ -312,7 +312,7 @@ export const PLATFORM_PLAYBOOKS = {
312
312
  {
313
313
  key: 'privacy_policy',
314
314
  title: 'Privacy policy URL',
315
- body: 'Obligatoria para publicar -- Play Console valida que la URL responda 200 al guardarla, no solo que tenga formato de URL. Ojo con apps de una sola página (React Router y similares): si el hosting no tiene configurado el rewrite de SPA (servir index.html para cualquier ruta), una URL como /privacidad puede dar 404 real aunque el deploy haya salido bien -- probar la URL en el navegador ANTES de pegarla acá, no confiar en que "ya se desplegó" alcanza.',
315
+ body: 'Obligatoria para publicar -- Play Console valida que la URL responda 200 al guardarla, no solo que tenga formato de URL. Ojo con apps de una sola página (React Router y similares): si el hosting no tiene configurado el rewrite de SPA (servir index.html para cualquier ruta), una URL como /privacidad puede dar 404 real aunque el deploy haya salido bien -- probar la URL en el navegador ANTES de pegarla aquí, no confiar en que "ya se desplegó" alcanza.',
316
316
  },
317
317
  {
318
318
  key: 'ads_declaration',
@@ -332,7 +332,7 @@ export const PLATFORM_PLAYBOOKS = {
332
332
  {
333
333
  key: 'content_rating',
334
334
  title: 'Content rating questionnaire (IARC)',
335
- body: 'Cuestionario largo, con sub-preguntas que se despliegan según tus respuestas. Puntos donde el criterio NO es obvio: "User Content Sharing" (¿la app permite nativamente intercambiar texto/voz/imágenes/audio entre usuarios?) es MÁS AMPLIO que el "User-Generated Content" de Apple -- Apple exime contenido privado dentro de un equipo, Google NO tiene esa excepción, así que comentarios/notas compartidas entre miembros de un workspace SÍ cuentan como "Yes" acá aunque sean privados. Si contestas "Yes" ahí, "¿las interacciones pueden limitarse a usuarios invitados?" responde "Yes" si el acceso es por invitación (esto ayuda a mantener la clasificación baja). El resto (violencia, sexual, lenguaje, drogas, apuestas) va en "No"/"None" para una app B2B típica -- resultado esperado: la clasificación más baja (3+/PEGI 3/Everyone).',
335
+ body: 'Cuestionario largo, con sub-preguntas que se despliegan según tus respuestas. Puntos donde el criterio NO es obvio: "User Content Sharing" (¿la app permite nativamente intercambiar texto/voz/imágenes/audio entre usuarios?) es MÁS AMPLIO que el "User-Generated Content" de Apple -- Apple exime contenido privado dentro de un equipo, Google NO tiene esa excepción, así que comentarios/notas compartidas entre miembros de un workspace SÍ cuentan como "Yes" aquí aunque sean privados. Si contestas "Yes" ahí, "¿las interacciones pueden limitarse a usuarios invitados?" responde "Yes" si el acceso es por invitación (esto ayuda a mantener la clasificación baja). El resto (violencia, sexual, lenguaje, drogas, apuestas) va en "No"/"None" para una app B2B típica -- resultado esperado: la clasificación más baja (3+/PEGI 3/Everyone).',
336
336
  },
337
337
  {
338
338
  key: 'target_audience',