orquestra-mcp 1.2.0 → 1.3.2
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/package.json +1 -1
- package/src/api.mjs +11 -2
- package/src/configFile.mjs +27 -1
- package/src/server.mjs +13 -3
- package/src/setup.mjs +16 -3
package/package.json
CHANGED
package/src/api.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readConfigFile, CONFIG_PATH } from './configFile.mjs'
|
|
1
|
+
import { readConfigFile, resolveProjectForCwd, CONFIG_PATH } from './configFile.mjs'
|
|
2
2
|
|
|
3
3
|
const DEFAULT_API_BASE = 'https://api.orquestra.me'
|
|
4
4
|
|
|
@@ -7,7 +7,16 @@ export function loadConfig() {
|
|
|
7
7
|
const apiBase = process.env.ORQUESTRA_API_BASE || fileConfig?.apiBase || DEFAULT_API_BASE
|
|
8
8
|
const apiToken = process.env.ORQUESTRA_API_TOKEN || fileConfig?.apiToken
|
|
9
9
|
const workspaceId = process.env.ORQUESTRA_WORKSPACE_ID || fileConfig?.workspaceId
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
// ORQUESTRA_DEFAULT_PROJECT_ID (env var, ej. desde un MCP config con
|
|
12
|
+
// scope local/project de Claude Code) siempre gana -- es una anulación
|
|
13
|
+
// explícita. Si no hay env var, se busca en el mapa carpeta->proyecto del
|
|
14
|
+
// config file, subiendo desde cwd (ver resolveProjectForCwd). Si ninguna
|
|
15
|
+
// carpeta ancestro está mapeada, defaultProjectId queda undefined a
|
|
16
|
+
// propósito -- resolveProjectId() en server.mjs debe fallar explícito en
|
|
17
|
+
// vez de usar el proyecto de otra carpeta.
|
|
18
|
+
const defaultProjectId = process.env.ORQUESTRA_DEFAULT_PROJECT_ID
|
|
19
|
+
|| resolveProjectForCwd(fileConfig?.projects, process.cwd())
|
|
11
20
|
|
|
12
21
|
const missing = []
|
|
13
22
|
if (!apiToken) missing.push('ORQUESTRA_API_TOKEN')
|
package/src/configFile.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs'
|
|
2
2
|
import { homedir } from 'os'
|
|
3
|
-
import { join, dirname } from 'path'
|
|
3
|
+
import { join, dirname, sep } from 'path'
|
|
4
4
|
|
|
5
5
|
export const CONFIG_PATH = join(homedir(), '.orquestra', 'mcp-config.json')
|
|
6
6
|
|
|
@@ -17,3 +17,29 @@ export function writeConfigFile(data) {
|
|
|
17
17
|
mkdirSync(dirname(CONFIG_PATH), { recursive: true })
|
|
18
18
|
writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), { mode: 0o600 })
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
// Guarda/actualiza el projectId de UNA carpeta sin pisar las demás -- setup
|
|
22
|
+
// se puede correr varias veces, una por cada carpeta contenedora de repos
|
|
23
|
+
// (ver resolveProjectForCwd), y cada corrida solo debe tocar su propia
|
|
24
|
+
// entrada.
|
|
25
|
+
export function upsertProjectMapping({ apiBase, apiToken, workspaceId, folderPath, projectId }) {
|
|
26
|
+
const existing = readConfigFile() || {}
|
|
27
|
+
const projects = { ...(existing.projects || {}) }
|
|
28
|
+
projects[folderPath] = projectId
|
|
29
|
+
writeConfigFile({ apiBase, apiToken, workspaceId, projects })
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Busca, subiendo desde cwd hacia la raíz, la carpeta mapeada más específica
|
|
33
|
+
// -- mismo criterio que .editorconfig/.gitconfig: el ancestro más cercano
|
|
34
|
+
// gana, así que un repo individual con su propio mapeo puede sobreescribir
|
|
35
|
+
// el de la carpeta contenedora que lo engloba.
|
|
36
|
+
export function resolveProjectForCwd(projects, cwd) {
|
|
37
|
+
if (!projects) return undefined
|
|
38
|
+
let best = null
|
|
39
|
+
for (const folderPath of Object.keys(projects)) {
|
|
40
|
+
const normalized = folderPath.endsWith(sep) ? folderPath.slice(0, -1) : folderPath
|
|
41
|
+
if (cwd !== normalized && !cwd.startsWith(normalized + sep)) continue
|
|
42
|
+
if (!best || normalized.length > best.length) best = normalized
|
|
43
|
+
}
|
|
44
|
+
return best ? projects[best] : undefined
|
|
45
|
+
}
|
package/src/server.mjs
CHANGED
|
@@ -50,13 +50,14 @@ const SERVER_INSTRUCTIONS = `Este server conecta con Orquestra, la app de gesti
|
|
|
50
50
|
Al empezar una sesión de trabajo en este proyecto, llama una vez a get_project_context para saber en qué fase está, qué tareas hay abiertas/vencidas/bloqueadas y qué se hizo recientemente. Úsalo como contexto de fondo, no lo repitas en cada mensaje.
|
|
51
51
|
|
|
52
52
|
Si get_project_context devuelve un proyecto vacío (sin módulos ni tareas), es la primera vez que se usa este MCP aquí -- pero "vacío en Orquestra" NO significa "recién empezado en la realidad". Antes de ofrecer nada, pregúntale al usuario: ¿este proyecto es una idea nueva, o ya existe y solo lo estás conectando por primera vez? Según la respuesta:
|
|
53
|
-
- Si es una idea nueva: llama a get_setup_guide y ofrece un playbook de etapa "pre" (get_stage_playbook + apply_stage_playbook).
|
|
54
|
-
- Si ya existe y está avanzado:
|
|
53
|
+
- Si es una idea nueva: llama a get_setup_guide y ofrece un playbook de etapa "pre" (get_stage_playbook + apply_stage_playbook) -- ahí sí basta con eso, el proyecto de verdad no tiene nada más que sincronizar todavía.
|
|
54
|
+
- Si ya existe y está avanzado: NO te limites a update_project ni a las distributions -- eso es solo el primer paso, no el trabajo completo. Llama a get_setup_guide y recorre sus 9 pasos en orden real (estatus/flujo, categorías, infraestructura completa -- servicios Y entornos, no solo distribuciones --, módulos, tareas, ideas, notas, changelog, docs), usando list_* de cada uno antes de crear para no duplicar. No asumas ni dejes vacío lo que no puedas inferir del código -- pregúntale al usuario los servicios/entornos reales, los módulos o áreas de trabajo, y las tareas pendientes reales que tenga en mente. Ofrece el playbook de etapa "build" (no "pre") solo como plantilla de módulo+tareas inicial, no como sustituto de sincronizar el resto.
|
|
55
55
|
|
|
56
56
|
Durante el trabajo normal de código, sin que el usuario te lo pida explícitamente:
|
|
57
57
|
- 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.
|
|
58
58
|
- Al terminar, mueve la tarea de estatus con update_task y registra una entrada de changelog con create_changelog_entry -- así el usuario nunca tiene que documentar esto a mano.
|
|
59
59
|
- 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.
|
|
60
|
+
- Si tienes acceso al repo real de una distribución (ej. puedes correr "git remote get-url origin" en ese código), llena repoUrl en create_distribution/update_distribution sin preguntar -- es solo informativo, no requiere credenciales. Esto es distinto de conectar el repo con PAT para el changelog automático (Workspace → Conexiones en orquestra-web): eso sí es un paso deliberado del usuario, con una credencial real -- nunca lo hagas tú solo ni sugieras que ya está conectado por haber llenado repoUrl.
|
|
60
61
|
|
|
61
62
|
No le preguntes al usuario por workspaceId ni projectId -- ya están configurados. Solo pregúntale por el proyecto si tiene más de uno y no queda claro a cuál te refieres.
|
|
62
63
|
|
|
@@ -68,7 +69,14 @@ export function createServer() {
|
|
|
68
69
|
|
|
69
70
|
function resolveProjectId(projectId) {
|
|
70
71
|
if (config.defaultProjectId) return config.defaultProjectId
|
|
71
|
-
if (!projectId)
|
|
72
|
+
if (!projectId) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`No hay ningún proyecto de Orquestra configurado para esta carpeta (${process.cwd()}). ` +
|
|
75
|
+
`No asumas que se refiere a otro proyecto que hayas visto en esta cuenta -- dile al usuario que ` +
|
|
76
|
+
`corra "npx orquestra-mcp setup" en esta carpeta (o en la carpeta contenedora, si este proyecto ` +
|
|
77
|
+
`vive repartido en varios repos) para conectarla.`
|
|
78
|
+
)
|
|
79
|
+
}
|
|
72
80
|
return projectId
|
|
73
81
|
}
|
|
74
82
|
|
|
@@ -488,6 +496,7 @@ export function createServer() {
|
|
|
488
496
|
stack: z.array(z.string()).optional(),
|
|
489
497
|
version: z.string().optional().describe('Versión en store'),
|
|
490
498
|
reviewVersion: z.string().optional().describe('Build en revisión -- apps'),
|
|
499
|
+
repoUrl: z.string().optional().describe('URL del repo de este código (ej. de "git remote get-url origin") -- solo informativo, no requiere credenciales. Distinto de conectar el repo con PAT (eso es Workspace → Conexiones, un paso deliberado del usuario, nunca lo hagas solo).'),
|
|
491
500
|
})
|
|
492
501
|
registerUpdate('update_distribution', '/v1/distributions', 'Edita una distribución existente.', {
|
|
493
502
|
label: z.string().optional(),
|
|
@@ -505,6 +514,7 @@ export function createServer() {
|
|
|
505
514
|
stack: z.array(z.string()).optional(),
|
|
506
515
|
version: z.string().optional(),
|
|
507
516
|
reviewVersion: z.string().optional(),
|
|
517
|
+
repoUrl: z.string().optional().describe('URL del repo de este código -- solo informativo, no requiere credenciales.'),
|
|
508
518
|
})
|
|
509
519
|
|
|
510
520
|
// ═══ COMPUESTAS (nivel C) ═══════════════════════════════════════════════════
|
package/src/setup.mjs
CHANGED
|
@@ -2,7 +2,9 @@ import { createServer } from 'http'
|
|
|
2
2
|
import { randomBytes } from 'crypto'
|
|
3
3
|
import { exec } from 'child_process'
|
|
4
4
|
import { createInterface } from 'readline'
|
|
5
|
-
import {
|
|
5
|
+
import { homedir } from 'os'
|
|
6
|
+
import { resolve } from 'path'
|
|
7
|
+
import { upsertProjectMapping, CONFIG_PATH } from './configFile.mjs'
|
|
6
8
|
|
|
7
9
|
const DEFAULT_API_BASE = 'https://api.orquestra.me'
|
|
8
10
|
const DEFAULT_WEB_URL = 'https://app.orquestra.me'
|
|
@@ -114,8 +116,19 @@ export async function runSetup() {
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
|
|
117
|
-
|
|
118
|
-
console.log(
|
|
119
|
+
console.log(`\nEsta conexión se guarda por carpeta -- así puedes tener distintos proyectos de Orquestra`)
|
|
120
|
+
console.log(`en distintos repos sin que se mezclen entre sí.`)
|
|
121
|
+
const folderAnswer = await prompt(
|
|
122
|
+
`¿A qué carpeta aplica? [Enter para usar la actual: ${process.cwd()}]\n` +
|
|
123
|
+
`(usa la carpeta contenedora, ej. la que junta varios repos de un mismo proyecto, si aplica): `
|
|
124
|
+
)
|
|
125
|
+
const expanded = folderAnswer.trim().startsWith('~')
|
|
126
|
+
? folderAnswer.trim().replace('~', homedir())
|
|
127
|
+
: folderAnswer.trim()
|
|
128
|
+
const folderPath = expanded ? resolve(expanded) : process.cwd()
|
|
129
|
+
|
|
130
|
+
upsertProjectMapping({ apiBase, apiToken: token, workspaceId, folderPath, projectId: defaultProjectId })
|
|
131
|
+
console.log(`\nListo. "${folderPath}" (y sus subcarpetas) ya apunta a este proyecto -- guardado en ${CONFIG_PATH}.`)
|
|
119
132
|
console.log('\nSiguiente paso -- conéctalo a tu agente de IA:\n')
|
|
120
133
|
console.log(' Claude Code:')
|
|
121
134
|
console.log(' claude mcp add orquestra -- npx orquestra-mcp\n')
|