orquestra-mcp 1.38.0 → 1.40.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 +8 -5
- package/bin/orquestra-mcp.mjs +1 -1
- package/package.json +2 -2
- package/src/server.mjs +170 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# orquestra-mcp
|
|
2
2
|
|
|
3
|
-
Servidor MCP (Model Context Protocol) para Orquestra. Expone **
|
|
3
|
+
Servidor MCP (Model Context Protocol) para Orquestra. Expone **135 tools**
|
|
4
4
|
que llaman a la API de `orquestra-infra`: lectura de contexto/dashboard/
|
|
5
5
|
workspace/infra/paridad/listados, escritura de tareas/ideas/changelog/
|
|
6
6
|
notas/docs/módulos/flujo/categorías/infra/proyectos, y corridas de QA —
|
|
@@ -133,6 +133,7 @@ crear/editar, sin `delete_*`:
|
|
|
133
133
|
| Entidad | Tools | Notas |
|
|
134
134
|
|---|---|---|
|
|
135
135
|
| Tareas | `create_task`, `update_task` | `update_task` incluye `scope` — úsalo para resolver desfases de paridad |
|
|
136
|
+
| 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` |
|
|
136
137
|
| Ideas | `create_idea` | |
|
|
137
138
|
| Changelog | `create_changelog_entry` | Estilo Keep a Changelog |
|
|
138
139
|
| Notas | `create_note` | |
|
|
@@ -195,13 +196,15 @@ create/update sigue siendo criterio del agente y del humano.
|
|
|
195
196
|
|
|
196
197
|
## Estado
|
|
197
198
|
|
|
198
|
-
|
|
199
|
+
135 tools: lectura (contexto, dashboard, workspace, infra, paridad, standup,
|
|
199
200
|
sync report, setup guide, playbooks de etapa y de plataforma, catálogo de
|
|
200
201
|
skills, search) + `list_*` de cada colección + creación/edición de tareas
|
|
201
|
-
(con checklist, tiempo, adjuntos, merge), ideas (con comentarios), notas,
|
|
202
|
+
(con checklist, verificaciones por plataforma, tiempo, adjuntos, merge), ideas (con comentarios), notas,
|
|
202
203
|
docs, changelog (con corte de versión), módulos, flujo, categorías,
|
|
203
204
|
infraestructura, proyecto, contenido (canales, campañas, contenido,
|
|
204
|
-
Postproxy), agentes, skills y
|
|
205
|
+
Postproxy), agentes, skills, sugerencias y vínculos entre ítems
|
|
206
|
+
(`link_items`/`unlink_items`/`list_relations`) + compuestas (init_project,
|
|
205
207
|
apply_stage_playbook, apply_platform_playbook, install_skill). Sin
|
|
206
|
-
`delete_*` salvo adjuntos
|
|
208
|
+
`delete_*` salvo adjuntos, ítems de checklist, verificaciones y vínculos
|
|
209
|
+
(`unlink_items`). Publicado en npm como
|
|
207
210
|
`orquestra-mcp` (unscoped) -- `npx orquestra-mcp setup`.
|
package/bin/orquestra-mcp.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import { createServer } from '../src/server.mjs'
|
|
|
4
4
|
import { runSetup } from '../src/setup.mjs'
|
|
5
5
|
import { runVaultSync } from '../src/vaultSync.mjs'
|
|
6
6
|
|
|
7
|
-
const HELP_TEXT = `orquestra-mcp -- Servidor MCP de Orquestra (
|
|
7
|
+
const HELP_TEXT = `orquestra-mcp -- Servidor MCP de Orquestra (132 tools)
|
|
8
8
|
|
|
9
9
|
Uso:
|
|
10
10
|
npx orquestra-mcp Inicia el servidor MCP por stdio -- lo usa tu cliente
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orquestra-mcp",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Servidor MCP de Orquestra --
|
|
3
|
+
"version": "1.40.0",
|
|
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": {
|
|
7
7
|
"orquestra-mcp": "bin/orquestra-mcp.mjs"
|
package/src/server.mjs
CHANGED
|
@@ -31,6 +31,16 @@ const TASK_TYPES = ['feature', 'bug', 'improvement', 'tech', 'docs', 'idea', 'de
|
|
|
31
31
|
const ACTIVITY_TYPES = ['meeting', 'call', 'followup']
|
|
32
32
|
const ACTIVITY_STATUSES = ['scheduled', 'done', 'cancelled']
|
|
33
33
|
const TASK_PRIORITIES = ['high', 'medium', 'low']
|
|
34
|
+
// Relaciones (ORQ-326) -- misma lista que orquestra-infra/schema/enums/RelationItemType.json.
|
|
35
|
+
const RELATION_TYPES = ['task', 'activity', 'note', 'doc', 'idea']
|
|
36
|
+
// Verificaciones por plataforma de una tarea (ORQ-319) -- ver
|
|
37
|
+
// orquestra-infra/functions/api/lib/verifications.mjs para las reglas reales.
|
|
38
|
+
const VERIFICATION_PLATFORMS = ['web', 'ios', 'android', 'api', 'other']
|
|
39
|
+
const VERIFICATION_MODES = ['human', 'agent', 'either']
|
|
40
|
+
const VERIFICATION_STATUSES = ['pending', 'passed', 'failed', 'waived']
|
|
41
|
+
const VERIFICATION_PLATFORM_DESC = 'Plataforma donde se confirma: "web" | "ios" | "android" | "api" | "other". Una verificación por plataforma.'
|
|
42
|
+
const VERIFICATION_INSTRUCTIONS_DESC = 'Pasos CONCRETOS para confirmar que quedó bien (qué abrir, qué hacer, qué se espera ver) -- ej. "En un iPhone físico con la build de TestFlight: abre Tareas, desliza una tarea a la izquierda y confirma que aparece Archivar". Nada genérico tipo "probar que funcione".'
|
|
43
|
+
const VERIFICATION_MODE_DESC = '"human" (default: solo una persona puede confirmarla, ej. dispositivo físico), "agent" (la puede confirmar un agente con revisión con IA) o "either" (cualquiera de los dos).'
|
|
34
44
|
const CHANGELOG_SECTIONS = ['Added', 'Changed', 'Deprecated', 'Removed', 'Fixed', 'Security']
|
|
35
45
|
// 'postmortem' faltaba acá (gap preexistente, encontrado 12 ago 2026) --
|
|
36
46
|
// mismo fix del lado de write.mjs en orquestra-infra.
|
|
@@ -100,10 +110,12 @@ Analítica y anuncios en un sitio web: antes de instalar o tocar Google Analytic
|
|
|
100
110
|
Durante el trabajo normal de código, sin que el usuario te lo pida explícitamente y SIN ESPERAR a que lo mencione (si tienes esta tool disponible en la sesión, se usa por default en todo trabajo real, no solo cuando alguien dice "usa Orquestra"):
|
|
101
111
|
- Si te pide una funcionalidad o arreglo real (no una pregunta rápida ni exploración de código sin cambios), revisa con list_tasks/search si ya existe una tarea relacionada; si no, créala con create_task ANTES de empezar a trabajar, en el estatus inicial del proyecto (ver list_statuses). Si no hay un proyecto default configurado para esta carpeta, no te rindas ahí -- usa get_workspace_summary para encontrar el proyecto correcto y pásalo explícito como projectId en cada llamada.
|
|
102
112
|
- Orquestra es el ÚNICO lugar donde se planea y se lleva el avance del trabajo: el plan de pasos va como checklist de la tarea (add_checklist_item) y se marca con update_checklist_item conforme terminas cada uno. No lleves una lista de pendientes paralela en el chat, en archivos temporales ni en la herramienta de tareas de tu propio cliente -- se pierde al cerrar la sesión y el usuario no la ve. Si retomas trabajo en una sesión nueva, parte de la tarea y sus ítems pendientes (list_tasks + list_checklist_items), no de cero. Excepción: un cambio de un solo paso (renombrar algo, responder una pregunta) no necesita tarea.
|
|
103
|
-
-
|
|
113
|
+
- Verificaciones por plataforma (distintas del checklist): cuando terminas código que necesita confirmación humana o en otra plataforma (probar en un iPhone/Android físico, revisar en la web en producción, pegarle al endpoint real desplegado...), NO lo agregues como ítem de checklist ni dejes la tarea abierta sin más. Registra UNA verificación por plataforma con instrucciones concretas (qué abrir, qué hacer, qué se espera ver) -- con add_verification, o con verifications en create_task si ya lo sabes al crearla -- y mueve la tarea a "En revisión" con un comment que diga qué falta confirmar. La tarea no se puede cerrar con verificaciones abiertas y se cierra SOLA cuando todas quedan aprobadas (update_verification status "passed"; si una falla, "failed" con note y la tarea regresa a su estatus anterior). El checklist es para trabajo; las verificaciones, para confirmar. Si la verificación tiene mode "agent"/"either" y hay un agente con revisión con IA, puedes encolarla con verify_with_agent. Nunca marques passed sin evidencia real de que se probó, y no uses waiveVerifications (ni status "waived") salvo que el usuario lo confirme explícito.
|
|
114
|
+
- Mientras trabajas, mueve la tarea por los estatus reales según avanzas (no la dejes en el inicial hasta el final). Al terminar, muévela a su estatus final con update_task (o a "En revisión" si quedaron verificaciones por plataforma abiertas, ver arriba) y registra una entrada de changelog con create_changelog_entry -- así el usuario nunca tiene que documentar esto a mano. Si sabes en qué repo real estás trabajando (podés correr "git remote get-url origin" o ya lo sabes por la carpeta), pásalo SIEMPRE como "repo" ("owner/name") -- encontrado real (17 ago 2026): ni el hook local ni el GitHub Action ni la reconciliación de orquestra-infra lo estaban mandando pese a que el campo existe hace rato, así que ninguna entrada automática sabía de qué repo/plataforma venía. Si además la distribución de ese repo ya está identificada (ver list_distributions), pásala en "distributions" -- sin esto el changelog no puede filtrar/agrupar por plataforma.
|
|
104
115
|
- Todo cambio de statusId vía update_task valida la transición (nextIds) y queda en el historial de la tarea -- pero ese historial no dice nada por sí solo. Manda SIEMPRE el parámetro "comment" cuando cambies statusId, explicando qué hiciste o por qué -- sin esto, el usuario ve que la tarea cambió pero no sabe por qué ni qué se hizo de verdad (encontrado real: quedaba invisible, a diferencia de cuando un humano mueve la tarjeta a mano en el kanban).
|
|
105
116
|
- Conocimiento que sirve más allá de un proyecto (guías, procesos, decisiones transversales) va en la base del workspace: revisa list_knowledge antes de documentarlo de nuevo, créalo con create_knowledge o súbelo con promote_to_knowledge; lo de un solo proyecto sigue en notas/docs.
|
|
106
117
|
- Reuniones, llamadas y seguimientos NO son tareas: son actividades (no se entregan, se programan y se registran). Usa log_activity para agendarlas o registrarlas, update_activity para marcarlas hechas con su resultado (outcome) y siguiente paso (nextStep), y list_activities para ver la agenda/bitácora -- nunca create_task con esos tipos. Si del siguiente paso sale trabajo real, eso sí es una tarea (create_task normal, con módulo y fecha).
|
|
118
|
+
- Para dejar constancia de que una nota, doc, idea o tarea es DE una reunión/llamada (o de otra cosa del proyecto) -- "esta nota es de la reunión X", "esta tarea sale de este doc" --, vincúlalas con link_items en vez de meter la referencia como texto en la descripción/cuerpo; list_relations muestra todo lo relacionado de un ítem.
|
|
107
119
|
- Antes de crear un módulo/estatus/categoría/servicio/entorno/distribución, revisa con el list_* correspondiente que no exista ya uno con ese nombre.
|
|
108
120
|
- Si una nota que vas a crear (create_note) es claramente sobre un módulo o una tarea específica -- por ejemplo durante un setup guiado donde acabas de crear ambos -- mándale moduleId/taskId para ligarla, en vez de dejarla suelta. No inventes la relación si no es clara.
|
|
109
121
|
- create_changelog_entry SIEMPRE deja la entrada en Unreleased (nunca mandes version salvo que el usuario te haya dado un número real) -- cortar una versión es release_changelog_version, una acción DELIBERADA que solo se llama si el usuario la pide explícitamente ("cortá la versión", "hacé el release de X") o confirma un número/fecha real que vos propusiste. No la dispares solo porque terminaste una tarea o un lote de trabajo grande.
|
|
@@ -644,13 +656,18 @@ export function createServer() {
|
|
|
644
656
|
resolvedCommitMessage: z.string().optional(),
|
|
645
657
|
resolvedCommitUrl: z.string().optional(),
|
|
646
658
|
resolvedCommitAt: z.number().optional().describe('Timestamp en ms del commit resolutor.'),
|
|
659
|
+
verifications: z.array(z.object({
|
|
660
|
+
platform: z.enum(VERIFICATION_PLATFORMS).describe(VERIFICATION_PLATFORM_DESC),
|
|
661
|
+
instructions: z.string().min(1).describe(VERIFICATION_INSTRUCTIONS_DESC),
|
|
662
|
+
mode: z.enum(VERIFICATION_MODES).optional().describe(VERIFICATION_MODE_DESC),
|
|
663
|
+
})).optional().describe('Verificaciones por plataforma desde la creación (mismo efecto que add_verification después). Son confirmaciones humanas o en otra plataforma ("probar en iPhone físico", "revisar en la web en producción"), NO pasos de trabajo -- esos van en el checklist. La tarea no se puede cerrar mientras alguna siga abierta, y se cierra sola cuando todas quedan aprobadas.'),
|
|
647
664
|
}
|
|
648
665
|
)
|
|
649
666
|
|
|
650
667
|
registerUpdate(
|
|
651
668
|
'update_task',
|
|
652
669
|
'/v1/tasks',
|
|
653
|
-
'Edita una tarea existente (incluido su scope multiplataforma, para resolver desfases de paridad). Si cambias statusId, el server valida que la transición sea válida (nextIds del estatus actual -- ver list_statuses) y deja rastro en el historial de la tarea (quién/cuándo/de qué a qué) -- pásale SIEMPRE `comment` cuando cambies statusId para que ese rastro también diga QUÉ hiciste o POR QUÉ, no solo el cambio de id. No deja pasar a un estatus final (isFinal) con ítems del checklist sin terminar (400 "Quedan X de Y..."): marca primero los ítems que de verdad hiciste con update_checklist_item; usa completeChecklist:true solo si el usuario confirma que lo pendiente ya no aplica o ya está hecho.',
|
|
670
|
+
'Edita una tarea existente (incluido su scope multiplataforma, para resolver desfases de paridad). Si cambias statusId, el server valida que la transición sea válida (nextIds del estatus actual -- ver list_statuses) y deja rastro en el historial de la tarea (quién/cuándo/de qué a qué) -- pásale SIEMPRE `comment` cuando cambies statusId para que ese rastro también diga QUÉ hiciste o POR QUÉ, no solo el cambio de id. No deja pasar a un estatus final (isFinal) con ítems del checklist sin terminar (400 "Quedan X de Y..."): marca primero los ítems que de verdad hiciste con update_checklist_item; usa completeChecklist:true solo si el usuario confirma que lo pendiente ya no aplica o ya está hecho. Tampoco deja cerrar con verificaciones por plataforma abiertas (pending/failed, ver list_verifications): no cierres a mano -- deja la tarea en "En revisión" y se cierra sola cuando todas quedan aprobadas; waiveVerifications:true solo con confirmación explícita del usuario.',
|
|
654
671
|
{
|
|
655
672
|
title: z.string().optional(),
|
|
656
673
|
description: z.string().optional(),
|
|
@@ -658,6 +675,7 @@ export function createServer() {
|
|
|
658
675
|
priority: z.enum(TASK_PRIORITIES).optional(),
|
|
659
676
|
statusId: z.string().optional(),
|
|
660
677
|
completeChecklist: z.boolean().optional().describe('Solo junto con un statusId final: marca como hechos los ítems pendientes del checklist y cierra (queda comentado en la tarea). Sin esto, cerrar con checklist pendiente responde 400.'),
|
|
678
|
+
waiveVerifications: z.boolean().optional().describe('Solo junto con un statusId final: marca como omitidas ("waived", nota "Omitida al cerrar la tarea") las verificaciones abiertas y cierra (queda comentado en la tarea). Sin esto, cerrar con verificaciones pendientes o fallidas responde 400. NO lo uses salvo que el usuario confirme explícito que esas verificaciones ya no aplican -- lo normal es dejar la tarea en "En revisión" y que se cierre sola al aprobarse.'),
|
|
661
679
|
categoryId: z.string().optional(),
|
|
662
680
|
moduleId: z.string().optional(),
|
|
663
681
|
dueDate: z.string().optional().describe('YYYY-MM-DD'),
|
|
@@ -881,6 +899,49 @@ export function createServer() {
|
|
|
881
899
|
(args, projectId) => ({ projectId, status: args.status, type: args.type, moduleId: args.moduleId, from: args.from, to: args.to, limit: args.limit })
|
|
882
900
|
)
|
|
883
901
|
|
|
902
|
+
// Relaciones (ORQ-326): vínculo manual NO dirigido entre dos cosas del proyecto. El server ordena el par y
|
|
903
|
+
// el id es determinístico (vincular dos veces no duplica). Ver orquestra-infra/functions/api/lib/relations.mjs.
|
|
904
|
+
registerRead(
|
|
905
|
+
'list_relations',
|
|
906
|
+
'/v1/relations',
|
|
907
|
+
'Sección "Relacionado" de una tarea, actividad (reunión/llamada/seguimiento), nota, doc o idea: junta los vínculos manuales (link_items, source "manual", con relationId para unlink_items) Y los que ya salen de campos existentes (nota de la tarea/minuta de la reunión, nota relacionada, ADR publicado, tarea que proviene de una nota, siguiente paso de una reunión, tareas ligadas a una idea -- source = esa etiqueta, relationId null, no se pueden quitar desde acá). Sin duplicados (el manual gana) y sin extremos borrados. No incluye menciones [[...]] -- esas van en get_backlinks.',
|
|
908
|
+
{
|
|
909
|
+
type: z.enum(RELATION_TYPES).describe('"activity" para reunión/llamada/seguimiento, "task" para cualquier otra tarea -- el server rechaza el tipo equivocado'),
|
|
910
|
+
id: z.string().describe('id del ítem (de list_tasks/list_activities/list_notes/list_docs/list_ideas)'),
|
|
911
|
+
},
|
|
912
|
+
(args, projectId) => ({ projectId, type: args.type, id: args.id })
|
|
913
|
+
)
|
|
914
|
+
|
|
915
|
+
registerCreate(
|
|
916
|
+
'link_items',
|
|
917
|
+
'/v1/relations',
|
|
918
|
+
'Vincula a mano dos cosas del mismo proyecto (tarea, actividad, nota, doc o idea) -- ej. "esta nota es de la reunión X", "esta tarea sale de este doc", "este doc documenta esa idea". El vínculo no tiene dirección (el orden a/b da igual, el server lo ordena) y es idempotente: vincular dos veces lo mismo no duplica (responde alreadyLinked). Saca los ids de list_tasks, list_activities, list_notes, list_docs y list_ideas; una reunión/llamada/seguimiento es "activity", no "task" (el server valida el tipo real y que ambos existan). No se puede vincular algo consigo mismo. Úsalo en vez de escribir "ver reunión X" en el texto.',
|
|
919
|
+
{
|
|
920
|
+
aType: z.enum(RELATION_TYPES).describe('Tipo del primer ítem'),
|
|
921
|
+
aId: z.string().describe('id del primer ítem'),
|
|
922
|
+
bType: z.enum(RELATION_TYPES).describe('Tipo del segundo ítem'),
|
|
923
|
+
bId: z.string().describe('id del segundo ítem'),
|
|
924
|
+
}
|
|
925
|
+
)
|
|
926
|
+
|
|
927
|
+
server.registerTool(
|
|
928
|
+
'unlink_items',
|
|
929
|
+
{
|
|
930
|
+
description: 'Quita un vínculo manual entre dos ítems (creado con link_items). relationId sale de list_relations (solo los de source "manual" tienen uno; los derivados de campos existentes no se quitan acá). No borra ninguno de los dos ítems. 404 si el vínculo ya no existe.',
|
|
931
|
+
inputSchema: {
|
|
932
|
+
projectId: z.string().optional().describe(PROJECT_ID_DESC),
|
|
933
|
+
relationId: z.string().describe('relationId de list_relations, ej. "activity_abc__note_xyz"'),
|
|
934
|
+
},
|
|
935
|
+
},
|
|
936
|
+
async ({ projectId, relationId }) => {
|
|
937
|
+
try {
|
|
938
|
+
return textResult(await apiDelete(config, '/v1/relations', { projectId: resolveProjectId(projectId), id: relationId }))
|
|
939
|
+
} catch (err) {
|
|
940
|
+
return errorResult(err)
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
)
|
|
944
|
+
|
|
884
945
|
// Fusionar tareas (20 ago 2026) -- registradas directo con
|
|
885
946
|
// server.registerTool (no registerCreate/registerUpdate) porque son
|
|
886
947
|
// POST a `${path}/${id}/merge|unmerge`, no un CRUD estándar. Fusión
|
|
@@ -1404,6 +1465,112 @@ export function createServer() {
|
|
|
1404
1465
|
}
|
|
1405
1466
|
)
|
|
1406
1467
|
|
|
1468
|
+
// Verificaciones por plataforma de una tarea (ORQ-319). Distintas del
|
|
1469
|
+
// checklist: el checklist es TRABAJO de la tarea; una verificación es la
|
|
1470
|
+
// CONFIRMACIÓN (humana o de un agente) de que quedó bien en una plataforma.
|
|
1471
|
+
// Mismo criterio que el checklist -- dos ids dinámicos en la ruta, así que
|
|
1472
|
+
// server.registerTool directo. Reglas reales (gate de cierre, cierre
|
|
1473
|
+
// automático, regreso de estatus al fallar) viven en
|
|
1474
|
+
// orquestra-infra/functions/api/lib/verifications.mjs.
|
|
1475
|
+
registerRead(
|
|
1476
|
+
'list_verifications',
|
|
1477
|
+
'/v1/verifications',
|
|
1478
|
+
'Lista las verificaciones por plataforma del proyecto (con taskId/shortCode/taskTitle/taskStatusId/assignedTo de su tarea). Por default solo las abiertas (pending + failed) de tareas que no están cerradas -- úsala para ver qué falta confirmar en cada plataforma (ej. "qué tengo que probar en iOS").',
|
|
1479
|
+
{
|
|
1480
|
+
status: z.enum(['open', 'pending', 'failed', 'passed', 'waived', 'all']).optional().describe('Default "open" (pending + failed, excluye tareas en estatus final/cancelado/archivado). "all" trae todo, incluidas tareas cerradas.'),
|
|
1481
|
+
platform: z.enum(VERIFICATION_PLATFORMS).optional().describe('Filtra por plataforma'),
|
|
1482
|
+
},
|
|
1483
|
+
(args, projectId) => ({ projectId, status: args.status, platform: args.platform })
|
|
1484
|
+
)
|
|
1485
|
+
|
|
1486
|
+
server.registerTool(
|
|
1487
|
+
'add_verification',
|
|
1488
|
+
{
|
|
1489
|
+
description: 'Registra una verificación por plataforma en una tarea: algo que una persona (o un agente) tiene que CONFIRMAR después de que el código ya está hecho -- probar en un iPhone/Android físico, revisar en la web en producción, pegarle al endpoint real, etc. NO es un ítem de checklist (el checklist es trabajo por hacer). Una por plataforma, con instrucciones concretas. Después mueve la tarea a "En revisión": no se puede cerrar mientras haya verificaciones abiertas, y se cierra sola cuando todas quedan aprobadas.',
|
|
1490
|
+
inputSchema: {
|
|
1491
|
+
projectId: z.string().optional().describe(PROJECT_ID_DESC),
|
|
1492
|
+
taskId: z.string().describe('ID de la tarea'),
|
|
1493
|
+
platform: z.enum(VERIFICATION_PLATFORMS).describe(VERIFICATION_PLATFORM_DESC),
|
|
1494
|
+
instructions: z.string().min(1).describe(VERIFICATION_INSTRUCTIONS_DESC),
|
|
1495
|
+
mode: z.enum(VERIFICATION_MODES).optional().describe(VERIFICATION_MODE_DESC),
|
|
1496
|
+
},
|
|
1497
|
+
},
|
|
1498
|
+
async ({ projectId, taskId, ...body }) => {
|
|
1499
|
+
try {
|
|
1500
|
+
const data = await apiPost(config, `/v1/tasks/${taskId}/verifications`, { projectId: resolveProjectId(projectId), ...body })
|
|
1501
|
+
return textResult(data)
|
|
1502
|
+
} catch (err) {
|
|
1503
|
+
return errorResult(err)
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
)
|
|
1507
|
+
|
|
1508
|
+
server.registerTool(
|
|
1509
|
+
'update_verification',
|
|
1510
|
+
{
|
|
1511
|
+
description: 'Edita o resuelve una verificación de una tarea. status: "passed" (aprobada), "failed" (falló -- exige note con lo que se vio), "waived" (omitida -- exige note con el motivo; solo si el usuario confirma que ya no aplica) o "pending" (re-verificar: limpia nota y resolución). Al resolver (passed/waived) la ÚLTIMA abierta, el server cierra la tarea solo si su estatus actual tiene un estatus final en sus transiciones y el checklist no tiene pendientes (la respuesta trae autoClosed:true); si no puede, comenta y avisa al responsable. Al marcar "failed", la tarea regresa a su estatus anterior (típico: En revisión → En progreso; ver movedBackTo en la respuesta) y se notifica al responsable. Marca passed solo con evidencia real de que se probó, nunca por suponer que funciona.',
|
|
1512
|
+
inputSchema: {
|
|
1513
|
+
projectId: z.string().optional().describe(PROJECT_ID_DESC),
|
|
1514
|
+
taskId: z.string().describe('ID de la tarea'),
|
|
1515
|
+
verificationId: z.string().describe('ID de la verificación (ver list_verifications o la tarea)'),
|
|
1516
|
+
status: z.enum(VERIFICATION_STATUSES).optional().describe('"pending" | "passed" | "failed" | "waived". failed y waived exigen note.'),
|
|
1517
|
+
note: z.string().optional().describe('Obligatoria con status "failed" (qué falló) o "waived" (por qué se omite).'),
|
|
1518
|
+
instructions: z.string().optional().describe(VERIFICATION_INSTRUCTIONS_DESC),
|
|
1519
|
+
platform: z.enum(VERIFICATION_PLATFORMS).optional(),
|
|
1520
|
+
mode: z.enum(VERIFICATION_MODES).optional().describe(VERIFICATION_MODE_DESC),
|
|
1521
|
+
},
|
|
1522
|
+
},
|
|
1523
|
+
async ({ projectId, taskId, verificationId, ...body }) => {
|
|
1524
|
+
try {
|
|
1525
|
+
const data = await apiPatch(config, `/v1/tasks/${taskId}/verifications`, { projectId: resolveProjectId(projectId), id: verificationId, ...body })
|
|
1526
|
+
return textResult(data)
|
|
1527
|
+
} catch (err) {
|
|
1528
|
+
return errorResult(err)
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
)
|
|
1532
|
+
|
|
1533
|
+
server.registerTool(
|
|
1534
|
+
'delete_verification',
|
|
1535
|
+
{
|
|
1536
|
+
description: 'Borra una verificación de una tarea (ej. se registró por error o en la plataforma equivocada). Si la verificación sigue aplicando pero no se va a hacer, no la borres: márcala "waived" con update_verification y una nota, para que quede rastro.',
|
|
1537
|
+
inputSchema: {
|
|
1538
|
+
projectId: z.string().optional().describe(PROJECT_ID_DESC),
|
|
1539
|
+
taskId: z.string().describe('ID de la tarea'),
|
|
1540
|
+
verificationId: z.string().describe('ID de la verificación a borrar'),
|
|
1541
|
+
},
|
|
1542
|
+
},
|
|
1543
|
+
async ({ projectId, taskId, verificationId }) => {
|
|
1544
|
+
try {
|
|
1545
|
+
const data = await apiDelete(config, `/v1/tasks/${taskId}/verifications`, { projectId: resolveProjectId(projectId), id: verificationId })
|
|
1546
|
+
return textResult(data)
|
|
1547
|
+
} catch (err) {
|
|
1548
|
+
return errorResult(err)
|
|
1549
|
+
}
|
|
1550
|
+
}
|
|
1551
|
+
)
|
|
1552
|
+
|
|
1553
|
+
server.registerTool(
|
|
1554
|
+
'verify_with_agent',
|
|
1555
|
+
{
|
|
1556
|
+
description: 'Encola una corrida de agente que confirma una verificación siguiendo sus instrucciones. Solo para verificaciones con mode "agent" o "either", y requiere un agente con revisión con IA activada (aiReviewEnabled). Sin agentId, el server elige el agente por la plataforma (web→"web", ios→"ios", android→"android", api→"node"). La corrida queda "queued": al terminar marca la verificación aprobada/fallida sola (inconclusa la deja pending con un comentario) -- nunca la des por aprobada sin confirmar con get_agent_run.',
|
|
1557
|
+
inputSchema: {
|
|
1558
|
+
projectId: z.string().optional().describe(PROJECT_ID_DESC),
|
|
1559
|
+
taskId: z.string().describe('ID de la tarea'),
|
|
1560
|
+
verificationId: z.string().describe('ID de la verificación a confirmar'),
|
|
1561
|
+
agentId: z.string().optional().describe('Agente específico (ver list_agents) -- si no se manda, se resuelve por la plataforma de la verificación'),
|
|
1562
|
+
},
|
|
1563
|
+
},
|
|
1564
|
+
async ({ projectId, taskId, verificationId, ...body }) => {
|
|
1565
|
+
try {
|
|
1566
|
+
const data = await apiPost(config, `/v1/tasks/${taskId}/verifications/${verificationId}/agent-run`, { projectId: resolveProjectId(projectId), ...body })
|
|
1567
|
+
return textResult(data)
|
|
1568
|
+
} catch (err) {
|
|
1569
|
+
return errorResult(err)
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1572
|
+
)
|
|
1573
|
+
|
|
1407
1574
|
// Adjuntos (imágenes + código) en tasks/notes/ideas/docs -- mismo criterio
|
|
1408
1575
|
// que checklist: entityType/entityId van en el path (dos segmentos
|
|
1409
1576
|
// dinámicos), así que server.registerTool directo. Ver
|
|
@@ -2442,6 +2609,7 @@ export function createServer() {
|
|
|
2442
2609
|
runnerId: z.string().optional().describe('Máquina específica -- si se manda, gana sobre la del agente resuelto'),
|
|
2443
2610
|
taskId: z.string().optional().describe('Acota la revisión con IA (si el agente la tiene activada) a esta tarea en vez de "revisa todo el proyecto" -- útil para pedir "corre QA de esto que acabo de hacer". Sin efecto en los pasos de script (lint/test/build corren igual siempre). Para kind="screenshots" es además OBLIGATORIO en la práctica: es la tarea a la que se van a adjuntar solas las capturas al terminar la corrida -- sin taskId, las capturas se suben pero nadie las liga a nada. No combinar con moduleId.'),
|
|
2444
2611
|
moduleId: z.string().optional().describe('Igual que taskId pero acota a un módulo completo. No combinar con taskId.'),
|
|
2612
|
+
verificationId: z.string().optional().describe('Verificación de la tarea (requiere taskId) que esta corrida debe confirmar siguiendo sus instrucciones -- al terminar, el resultado la marca aprobada/fallida solo. Solo para verificaciones con mode "agent" o "either" y un agente con revisión con IA activada. Preferí verify_with_agent, que resuelve el agente por la plataforma.'),
|
|
2445
2613
|
})
|
|
2446
2614
|
|
|
2447
2615
|
server.registerTool(
|