orquestra-mcp 1.16.1 → 1.16.3

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 **38 tools**
3
+ Servidor MCP (Model Context Protocol) para Orquestra. Expone **89 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 —
@@ -192,11 +192,13 @@ create/update sigue siendo criterio del agente y del humano.
192
192
 
193
193
  ## Estado
194
194
 
195
- 38 tools: 9 de lectura (contexto/tasks/search + dashboard/workspace/infra/
196
- paridad/setup guide/stage playbook) + 6 `list_*` + 19 de creación/edición
197
- (tasks/ideas/changelog/notes/docs + módulos/flujo/categorías/servicios/
198
- entornos/distribuciones/proyecto) + 2 de Agentes (create_agent_run/get_agent_run) +
199
- 2 compuestas (init_project, apply_stage_playbook). No hay `delete_*`, ni
200
- `update_idea`/`update_note`/`update_doc`/`update_changelog_entry`
201
- todavía. Publicado en npm como `orquestra-mcp` (unscoped) -- `npx
202
- orquestra-mcp setup`.
195
+ 89 tools: lectura (contexto, dashboard, workspace, infra, paridad, standup,
196
+ sync report, setup guide, playbooks de etapa y de plataforma, catálogo de
197
+ skills, search) + `list_*` de cada colección + creación/edición de tareas
198
+ (con checklist, tiempo, adjuntos, merge), ideas (con comentarios), notas,
199
+ docs, changelog (con corte de versión), módulos, flujo, categorías,
200
+ infraestructura, proyecto, contenido (canales, campañas, contenido,
201
+ Postproxy), agentes, skills y sugerencias + compuestas (init_project,
202
+ apply_stage_playbook, apply_platform_playbook, install_skill). Sin
203
+ `delete_*` salvo adjuntos e ítems de checklist. Publicado en npm como
204
+ `orquestra-mcp` (unscoped) -- `npx orquestra-mcp setup`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orquestra-mcp",
3
- "version": "1.16.1",
3
+ "version": "1.16.3",
4
4
  "description": "Servidor MCP de Orquestra -- 89 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": {
@@ -102,7 +102,7 @@ export const PLATFORM_PLAYBOOKS = {
102
102
  {
103
103
  title: 'Preparar capturas de pantalla en los tamaños exactos que pide App Store Connect',
104
104
  description: 'Las dimensiones válidas cambian con cada generación de iPhone/iPad -- si App Store Connect rechaza una captura al subirla, el mensaje de error indica el tamaño exacto que espera para ese dispositivo; ajusta según ese mensaje real, no de memoria.',
105
- type: 'business', priority: 'medium', tags: ['publicacion', 'ios'], offsetDays: 7,
105
+ type: 'business', priority: 'medium', tags: ['publicacion', 'ios'], offsetDays: 7, checklistTool: 'screenshots',
106
106
  },
107
107
  {
108
108
  title: 'Completar el cuestionario de privacidad de la tienda (Data Collection)',
@@ -251,7 +251,7 @@ export const PLATFORM_PLAYBOOKS = {
251
251
  {
252
252
  title: 'Preparar capturas de pantalla en los tamaños exactos que pide Play Console',
253
253
  description: 'Mínimo 2 capturas de teléfono, más el gráfico destacado (1024x500) y el ícono (512x512) -- Play Console valida las dimensiones al subir, ajusta según lo que rechace.',
254
- type: 'business', priority: 'medium', tags: ['publicacion', 'android'], offsetDays: 7,
254
+ type: 'business', priority: 'medium', tags: ['publicacion', 'android'], offsetDays: 7, checklistTool: 'screenshots',
255
255
  },
256
256
  {
257
257
  title: 'Completar el formulario de seguridad de los datos (Data safety)',
package/src/server.mjs CHANGED
@@ -10,6 +10,10 @@ import { PLATFORM_PLAYBOOKS } from './platformPlaybooks.mjs'
10
10
  import { SKILLS_CATALOG } from './skillsCatalog.mjs'
11
11
  import { parseSource, previewSkill, installSkill } from './skillInstall.mjs'
12
12
 
13
+ // Versión leída de package.json (3 sep 2026) -- antes estaba hardcodeada
14
+ // acá y quedaba atrás en cada bump (decía 1.16.0 con package.json en 1.16.2).
15
+ const PKG_VERSION = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version
16
+
13
17
  function errorResult(err) {
14
18
  const text = err instanceof ApiError ? `Error (${err.status}): ${err.message}` : `Error: ${err.message}`
15
19
  return { content: [{ type: 'text', text }], isError: true }
@@ -115,7 +119,7 @@ Si el usuario pregunta explícito qué Claude Skills de terceros le faltan (o pi
115
119
 
116
120
  export function createServer() {
117
121
  const config = loadConfig()
118
- const server = new McpServer({ name: 'orquestra-mcp', version: '1.16.0' }, { instructions: SERVER_INSTRUCTIONS })
122
+ const server = new McpServer({ name: 'orquestra-mcp', version: PKG_VERSION }, { instructions: SERVER_INSTRUCTIONS })
119
123
 
120
124
  function resolveProjectId(projectId) {
121
125
  if (config.defaultProjectId) return config.defaultProjectId
@@ -613,10 +617,10 @@ export function createServer() {
613
617
  server.registerTool(
614
618
  'connect_postproxy_channel',
615
619
  {
616
- description: 'Inicia la conexión de un canal (facebook/instagram/tiktok) a Postproxy. Devuelve UNA de dos formas: {url} -- OAuth hosteado por Postproxy, el usuario tiene que abrirlo y completarlo a mano (el agente no puede terminar un OAuth por su cuenta), pásale esa URL tal cual; o {needsPageSelection, profileId, pages} -- solo pasa con facebook, cuando ya hay un login de Facebook conectado en la cuenta (una sola cuenta da acceso a varias Pages, no hace falta repetir el OAuth) y hace falta elegir cuál Page corresponde a este canal. Esa elección hoy es un flujo de la web (Cuentas conectadas) -- si te llega `needsPageSelection`, dile al usuario que complete la selección ahí, esta tool no tiene una contraparte para elegir la página. No confundir con connect_channel_to_buttondown -- esto es solo para los tipos que soporta Postproxy.',
620
+ description: 'Inicia la conexión de un canal (facebook/instagram/tiktok/linkedin) a Postproxy. Devuelve UNA de dos formas: {url} -- OAuth hosteado por Postproxy, el usuario tiene que abrirlo y completarlo a mano (el agente no puede terminar un OAuth por su cuenta), pásale esa URL tal cual; o {needsPageSelection, profileId, pages} -- pasa con facebook y linkedin, cuando ya hay un login de esa red conectado en la cuenta (un solo login da acceso a varias Pages de Facebook, o al perfil personal y las Organization Pages de LinkedIn, no hace falta repetir el OAuth) y hace falta elegir cuál corresponde a este canal. Esa elección hoy es un flujo de la web (Cuentas conectadas) -- si te llega `needsPageSelection`, dile al usuario que complete la selección ahí, esta tool no tiene una contraparte para elegir la página. Solo para los tipos que soporta Postproxy -- un canal newsletter (Buttondown) se conecta desde la web, no con esta tool.',
617
621
  inputSchema: {
618
622
  projectId: z.string().optional().describe(PROJECT_ID_DESC),
619
- channelId: z.string().describe('Canal a conectar (ver list_channels) -- su `type` tiene que ser facebook/instagram/tiktok'),
623
+ channelId: z.string().describe('Canal a conectar (ver list_channels) -- su `type` tiene que ser facebook/instagram/tiktok/linkedin'),
620
624
  platform: z.string().describe('Plataforma tal cual la espera Postproxy (mismo valor que channel.type -- ej. "instagram")'),
621
625
  },
622
626
  },
@@ -1518,7 +1522,7 @@ export function createServer() {
1518
1522
 
1519
1523
  registerCreate('create_channel', '/v1/channels', 'Crea un canal (cuenta de contenido) en un proyecto -- ej. "LinkedIn", "Blog de Atlas". No conecta ninguna cuenta real todavía (eso es OAuth, fuera de alcance por ahora); solo registra el canal para poder programar contenido en él.', {
1520
1524
  name: z.string().describe('Ej. "LinkedIn"'),
1521
- type: z.string().optional().describe('linkedin | x | blog | newsletter | instagram | other -- libre'),
1525
+ type: z.string().optional().describe('facebook | instagram | tiktok | linkedin | x | blog | newsletter | other -- libre. facebook/instagram/tiktok/linkedin se conectan después con connect_postproxy_channel'),
1522
1526
  handle: z.string().optional().describe('Ej. "@atlaspagos" o una URL/dominio'),
1523
1527
  color: z.string().optional(),
1524
1528
  cadenceCount: z.number().optional().describe('Ritmo objetivo de publicaciones, ej. 2'),
@@ -1632,24 +1636,26 @@ export function createServer() {
1632
1636
  // Un agente tiene un `kind` atado a una máquina (runnerId); los 3 kinds de
1633
1637
  // hoy (23 ago 2026: qa/security/performance) exigen stack+localPath (un
1634
1638
  // checkout real en esa máquina), y performance además perfUrl (URL viva
1635
- // contra la que corre Lighthouse). Los 3 solo tienen lógica real para
1636
- // stack="web" por ahora. "orquestra-qa-agent setup" crea/actualiza solo
1637
- // agentes kind="qa" -- security/performance se crean a mano acá o desde
1638
- // la web.
1639
- const AGENT_KINDS = ['qa', 'security', 'performance']
1639
+ // contra la que corre Lighthouse). qa/security/performance solo tienen
1640
+ // lógica real para stack="web" por ahora; screenshots es lo inverso, solo
1641
+ // stack="ios"|"android" (captura automática para el checklist de
1642
+ // publicación, ver ScreenshotChecklist.jsx en orquestra-web). "orquestra-qa-agent
1643
+ // setup" crea/actualiza solo agentes kind="qa" -- el resto se crean a
1644
+ // mano acá o desde la web.
1645
+ const AGENT_KINDS = ['qa', 'security', 'performance', 'screenshots']
1640
1646
  const AGENT_STACKS = ['web', 'ios', 'android', 'node', 'nestjs']
1641
1647
 
1642
1648
  registerRead('list_agents', '/v1/agents',
1643
1649
  'Lista los agentes (kind+máquina+stack+ruta local) configurados en un proyecto. Úsala antes de create_agent o de create_agent_run con stack, para saber si ya existe uno.',
1644
- { kind: z.enum(AGENT_KINDS).optional().describe('Filtra por kind: "qa" (lint/test/build/E2E), "security" (npm audit + gitleaks) o "performance" (build size + Lighthouse)') },
1650
+ { kind: z.enum(AGENT_KINDS).optional().describe('Filtra por kind: "qa" (lint/test/build/E2E), "security" (npm audit + gitleaks), "performance" (build size + Lighthouse) o "screenshots" (captura de pantallas para el checklist de publicación, solo ios/android)') },
1645
1651
  (args, projectId) => ({ projectId }))
1646
1652
 
1647
- registerCreate('create_agent', '/v1/agents', 'Crea un agente: asocia un kind ("qa" | "security" | "performance") a una máquina (runner, ver Workspace → Máquinas), un stack de este proyecto y una ruta de checkout en ESA máquina. kind="performance" además necesita perfUrl.', {
1653
+ registerCreate('create_agent', '/v1/agents', 'Crea un agente: asocia un kind ("qa" | "security" | "performance" | "screenshots") a una máquina (runner, ver Workspace → Máquinas), un stack de este proyecto y una ruta de checkout en ESA máquina. kind="performance" además necesita perfUrl.', {
1648
1654
  name: z.string().describe('Nombre a mostrar, ej. "Agente web"'),
1649
- kind: z.enum(AGENT_KINDS).default('qa').describe('"qa" (lint/test/build/E2E), "security" (npm audit + gitleaks) o "performance" (build size + Lighthouse) -- default "qa"'),
1655
+ kind: z.enum(AGENT_KINDS).default('qa').describe('"qa" (lint/test/build/E2E), "security" (npm audit + gitleaks), "performance" (build size + Lighthouse) o "screenshots" (captura de pantallas para tiendas, solo stack ios/android) -- default "qa"'),
1650
1656
  runnerId: z.string().describe('ID de la máquina emparejada -- ver list_agents o Workspace → Máquinas'),
1651
- stack: z.enum(AGENT_STACKS).optional().describe('Requerido para los 3 kinds -- security/performance solo tienen lógica real para "web" hoy'),
1652
- localPath: z.string().optional().describe('Requerido para los 3 kinds -- ruta absoluta del checkout en esa máquina'),
1657
+ stack: z.enum(AGENT_STACKS).optional().describe('Requerido para los 4 kinds. security/performance solo tienen lógica real para "web" hoy; screenshots solo para "ios"/"android"'),
1658
+ localPath: z.string().optional().describe('Requerido para los 4 kinds -- ruta absoluta del checkout en esa máquina'),
1653
1659
  branch: z.string().optional().describe('Rama de este agente -- default "main" si no se manda'),
1654
1660
  distributionId: z.string().optional().describe('Distribución vinculada (repo/fuente de conocimiento)'),
1655
1661
  enabled: z.boolean().optional(),
@@ -1684,7 +1690,7 @@ export function createServer() {
1684
1690
  minPerfScore: z.number().optional(),
1685
1691
  })
1686
1692
 
1687
- registerCreate('create_agent_run', '/v1/agent-runs', 'Dispara una corrida de agente (qa: lint/tests/build/E2E; security: npm audit + gitleaks; performance: build size + Lighthouse) en la rama indicada. Necesita al menos un agente activo para el stack (o falla explícito -- ver list_agents/create_agent). La corrida queda "queued" -- nunca asumas que pasó, confirma con get_agent_run.', {
1693
+ registerCreate('create_agent_run', '/v1/agent-runs', 'Dispara una corrida de agente (qa: lint/tests/build/E2E; security: npm audit + gitleaks; performance: build size + Lighthouse; screenshots: captura de pantallas para el checklist de publicación) en la rama indicada. Necesita al menos un agente activo para el stack (o falla explícito -- ver list_agents/create_agent). La corrida queda "queued" -- nunca asumas que pasó, confirma con get_agent_run.', {
1688
1694
  agentId: z.string().optional().describe('Agente específico -- si se manda, gana sobre stack/kind'),
1689
1695
  branch: z.string().optional().describe('Rama a probar -- default: la del agente, o "main"'),
1690
1696
  commit: z.string().optional(),
@@ -1692,7 +1698,7 @@ export function createServer() {
1692
1698
  stack: z.string().optional().describe('Stack a probar (ej. "web", "ios", "android") -- resuelve contra los agentes activos de ese stack. Falla si hay 0 (créalo con create_agent) o más de 1 (usa agentId o suma kind para desambiguar).'),
1693
1699
  kind: z.enum(AGENT_KINDS).optional().describe('Desambigua junto con stack cuando el proyecto tiene más de un agente para el mismo stack (ej. un "qa" y un "security", ambos "web") -- sin esto, resuelve por stack solo y falla explícito si hay más de uno.'),
1694
1700
  runnerId: z.string().optional().describe('Máquina específica -- si se manda, gana sobre la del agente resuelto'),
1695
- 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). No combinar con moduleId.'),
1701
+ 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.'),
1696
1702
  moduleId: z.string().optional().describe('Igual que taskId pero acota a un módulo completo. No combinar con taskId.'),
1697
1703
  })
1698
1704