orquestra-mcp 1.18.0 → 1.18.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 +14 -10
- package/src/configFile.mjs +40 -10
- package/src/setup.mjs +7 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orquestra-mcp",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.2",
|
|
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": {
|
package/src/api.mjs
CHANGED
|
@@ -4,19 +4,23 @@ const DEFAULT_API_BASE = 'https://api.orquestra.me'
|
|
|
4
4
|
|
|
5
5
|
export function loadConfig() {
|
|
6
6
|
const fileConfig = readConfigFile()
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
// Todo sale de la MISMA carpeta mapeada (ver resolveProjectForCwd) --
|
|
8
|
+
// apiToken/workspaceId/projectId siempre son de una sola cuenta, nunca
|
|
9
|
+
// el token de una carpeta con el proyecto de otra.
|
|
10
|
+
const folderConfig = resolveProjectForCwd(fileConfig?.projects, process.cwd())
|
|
11
|
+
|
|
12
|
+
const apiBase = process.env.ORQUESTRA_API_BASE || folderConfig?.apiBase || DEFAULT_API_BASE
|
|
13
|
+
const apiToken = process.env.ORQUESTRA_API_TOKEN || folderConfig?.apiToken
|
|
14
|
+
const workspaceId = process.env.ORQUESTRA_WORKSPACE_ID || folderConfig?.workspaceId
|
|
10
15
|
|
|
11
16
|
// ORQUESTRA_DEFAULT_PROJECT_ID (env var, ej. desde un MCP config con
|
|
12
17
|
// scope local/project de Claude Code) siempre gana -- es una anulación
|
|
13
|
-
// explícita. Si no hay env var, se
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
const defaultProjectId = process.env.ORQUESTRA_DEFAULT_PROJECT_ID
|
|
19
|
-
|| resolveProjectForCwd(fileConfig?.projects, process.cwd())
|
|
18
|
+
// explícita. Si no hay env var, se usa el projectId de la carpeta
|
|
19
|
+
// resuelta arriba. Si ninguna carpeta ancestro está mapeada,
|
|
20
|
+
// defaultProjectId queda undefined a propósito -- resolveProjectId() en
|
|
21
|
+
// server.mjs debe fallar explícito en vez de usar el proyecto de otra
|
|
22
|
+
// carpeta.
|
|
23
|
+
const defaultProjectId = process.env.ORQUESTRA_DEFAULT_PROJECT_ID || folderConfig?.projectId
|
|
20
24
|
|
|
21
25
|
const missing = []
|
|
22
26
|
if (!apiToken) missing.push('ORQUESTRA_API_TOKEN')
|
package/src/configFile.mjs
CHANGED
|
@@ -4,13 +4,40 @@ import { join, dirname, sep } from 'path'
|
|
|
4
4
|
|
|
5
5
|
export const CONFIG_PATH = join(homedir(), '.orquestra', 'mcp-config.json')
|
|
6
6
|
|
|
7
|
+
// Formato viejo (hasta v1.18.1): apiBase/apiToken/workspaceId GLOBALES a
|
|
8
|
+
// nivel raíz, projects={folderPath: projectId}. Eso pisaba la cuenta de
|
|
9
|
+
// TODAS las carpetas cada vez que corrías "setup" con una cuenta distinta
|
|
10
|
+
// -- no había forma real de tener un proyecto de una cuenta y otro de otra
|
|
11
|
+
// cuenta al mismo tiempo. Migra en el momento a projects={folderPath:
|
|
12
|
+
// {apiBase, apiToken, workspaceId, projectId}}, reusando las credenciales
|
|
13
|
+
// globales viejas para cada carpeta ya mapeada (siguen apuntando a la
|
|
14
|
+
// cuenta con la que se logueó por última vez -- si eso ya está mal, hay
|
|
15
|
+
// que volver a correr "setup" en esa carpeta puntual).
|
|
16
|
+
function migrateLegacyConfig(raw) {
|
|
17
|
+
const entries = Object.entries(raw.projects || {})
|
|
18
|
+
if (!entries.some(([, value]) => typeof value === 'string')) return raw
|
|
19
|
+
|
|
20
|
+
const { apiBase, apiToken, workspaceId } = raw
|
|
21
|
+
const projects = {}
|
|
22
|
+
for (const [folderPath, value] of entries) {
|
|
23
|
+
projects[folderPath] = typeof value === 'string'
|
|
24
|
+
? { apiBase, apiToken, workspaceId, projectId: value }
|
|
25
|
+
: value
|
|
26
|
+
}
|
|
27
|
+
return { projects }
|
|
28
|
+
}
|
|
29
|
+
|
|
7
30
|
export function readConfigFile() {
|
|
8
31
|
if (!existsSync(CONFIG_PATH)) return null
|
|
32
|
+
let raw
|
|
9
33
|
try {
|
|
10
|
-
|
|
34
|
+
raw = JSON.parse(readFileSync(CONFIG_PATH, 'utf8'))
|
|
11
35
|
} catch {
|
|
12
36
|
return null
|
|
13
37
|
}
|
|
38
|
+
const migrated = migrateLegacyConfig(raw)
|
|
39
|
+
if (migrated !== raw) writeConfigFile(migrated)
|
|
40
|
+
return migrated
|
|
14
41
|
}
|
|
15
42
|
|
|
16
43
|
export function writeConfigFile(data) {
|
|
@@ -18,21 +45,24 @@ export function writeConfigFile(data) {
|
|
|
18
45
|
writeFileSync(CONFIG_PATH, JSON.stringify(data, null, 2), { mode: 0o600 })
|
|
19
46
|
}
|
|
20
47
|
|
|
21
|
-
// Guarda/actualiza
|
|
22
|
-
// se puede correr varias veces, una por cada carpeta contenedora de
|
|
23
|
-
// (ver resolveProjectForCwd), y cada corrida solo debe tocar su
|
|
24
|
-
// entrada
|
|
48
|
+
// Guarda/actualiza la cuenta+proyecto de UNA carpeta sin pisar las demás --
|
|
49
|
+
// setup se puede correr varias veces, una por cada carpeta contenedora de
|
|
50
|
+
// repos (ver resolveProjectForCwd), y cada corrida solo debe tocar su
|
|
51
|
+
// propia entrada -- incluida la cuenta (apiToken/workspaceId), para poder
|
|
52
|
+
// tener una carpeta en una cuenta de Orquestra y otra carpeta en otra
|
|
53
|
+
// cuenta distinta al mismo tiempo.
|
|
25
54
|
export function upsertProjectMapping({ apiBase, apiToken, workspaceId, folderPath, projectId }) {
|
|
26
|
-
const existing = readConfigFile() || {}
|
|
55
|
+
const existing = readConfigFile() || { projects: {} }
|
|
27
56
|
const projects = { ...(existing.projects || {}) }
|
|
28
|
-
projects[folderPath] = projectId
|
|
29
|
-
writeConfigFile({
|
|
57
|
+
projects[folderPath] = { apiBase, apiToken, workspaceId, projectId }
|
|
58
|
+
writeConfigFile({ projects })
|
|
30
59
|
}
|
|
31
60
|
|
|
32
61
|
// Busca, subiendo desde cwd hacia la raíz, la carpeta mapeada más específica
|
|
33
62
|
// -- mismo criterio que .editorconfig/.gitconfig: el ancestro más cercano
|
|
34
|
-
// gana, así que un repo individual con su propio mapeo
|
|
35
|
-
// el de la carpeta contenedora que lo engloba.
|
|
63
|
+
// gana, así que un repo individual con su propio mapeo (y su propia cuenta)
|
|
64
|
+
// puede sobreescribir el de la carpeta contenedora que lo engloba. Devuelve
|
|
65
|
+
// el objeto {apiBase, apiToken, workspaceId, projectId} de esa carpeta.
|
|
36
66
|
export function resolveProjectForCwd(projects, cwd) {
|
|
37
67
|
if (!projects) return undefined
|
|
38
68
|
let best = null
|
package/src/setup.mjs
CHANGED
|
@@ -92,15 +92,16 @@ export async function runSetup() {
|
|
|
92
92
|
if (created) {
|
|
93
93
|
defaultProjectId = body.projectId
|
|
94
94
|
console.log(`Se creó un workspace y un proyecto default para ti ("${projects[0].name}") -- puedes renombrarlos cuando quieras desde orquestra-web.`)
|
|
95
|
-
} else if (projects.length === 1) {
|
|
96
|
-
defaultProjectId = projects[0].id
|
|
97
|
-
console.log(`Usando tu proyecto "${projects[0].name}" como default.`)
|
|
98
95
|
} else {
|
|
99
96
|
console.log('\nElige el proyecto que este MCP va a usar por default:')
|
|
100
97
|
console.log(' 0. (crear un proyecto nuevo)')
|
|
101
98
|
projects.forEach((p, i) => console.log(` ${i + 1}. ${p.name}`))
|
|
102
|
-
const
|
|
103
|
-
const
|
|
99
|
+
const singleDefaultIdx = projects.length === 1 ? 1 : null
|
|
100
|
+
const answer = await prompt(
|
|
101
|
+
singleDefaultIdx ? `Número [Enter para usar "${projects[0].name}"]: ` : 'Número: '
|
|
102
|
+
)
|
|
103
|
+
const trimmed = answer.trim()
|
|
104
|
+
const idx = trimmed === '' && singleDefaultIdx !== null ? singleDefaultIdx : parseInt(trimmed, 10)
|
|
104
105
|
if (Number.isNaN(idx) || idx < 0 || idx > projects.length) throw new Error('Selección inválida')
|
|
105
106
|
|
|
106
107
|
if (idx === 0) {
|
|
@@ -117,6 +118,7 @@ export async function runSetup() {
|
|
|
117
118
|
console.log(`Proyecto "${newProject.name}" creado y configurado como default.`)
|
|
118
119
|
} else {
|
|
119
120
|
defaultProjectId = projects[idx - 1].id
|
|
121
|
+
console.log(`Usando tu proyecto "${projects[idx - 1].name}" como default.`)
|
|
120
122
|
}
|
|
121
123
|
}
|
|
122
124
|
|