viewgate-mcp 1.0.46 → 1.0.48
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/dist/index.js +53 -60
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -27,9 +27,10 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
27
27
|
const __dirname = path.dirname(__filename);
|
|
28
28
|
dotenv.config({ path: path.join(__dirname, "..", ".env") });
|
|
29
29
|
const port = process.env.PORT || 3000;
|
|
30
|
-
const BACKEND_URL = process.env.
|
|
30
|
+
const BACKEND_URL = process.env.VIEWGATE_BACKEND_URL || "https://view-gate.vercel.app";
|
|
31
31
|
console.error(`[MCP Config] BACKEND_URL: ${BACKEND_URL}`);
|
|
32
|
-
|
|
32
|
+
const LOG_API_KEY = (process.env.VIEWGATE_API_KEY || process.env.API_KEY || "");
|
|
33
|
+
console.error(`[MCP Config] API_KEY Prefix: ${LOG_API_KEY.substring(0, 5)}...`);
|
|
33
34
|
const agentId = `${os.hostname()}-${process.pid}`;
|
|
34
35
|
console.error(`[MCP Identity] Agent ID: ${agentId}`);
|
|
35
36
|
// Store active sessions for SSE: sessionId -> { server, transport }
|
|
@@ -67,7 +68,6 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
67
68
|
case "mark_ui_component_generated":
|
|
68
69
|
return "ui_components";
|
|
69
70
|
case "get_annotations":
|
|
70
|
-
case "mark_annotation_ready":
|
|
71
71
|
case "mark_annotations_as_live":
|
|
72
72
|
return "annotations";
|
|
73
73
|
case "get_ui_improvements":
|
|
@@ -123,10 +123,13 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
123
123
|
break;
|
|
124
124
|
default:
|
|
125
125
|
if (guard.flow === "idle") {
|
|
126
|
-
throw new Error(
|
|
126
|
+
throw new Error(`TOOL_CALL_BLOCKED: tool '${toolName}' not allowed in idle. Please start a workflow with 'get_annotations', 'get_ui_components', or 'get_ui_improvements'.`);
|
|
127
127
|
}
|
|
128
128
|
else {
|
|
129
|
-
|
|
129
|
+
const nextTool = guard.flow === "annotations" ? "mark_annotations_as_live" :
|
|
130
|
+
guard.flow === "ui_components" ? "mark_ui_component_generated" :
|
|
131
|
+
guard.flow === "ui_improvements" ? "mark_annotations_as_live" : "the next workflow step";
|
|
132
|
+
throw new Error(`TOOL_CALL_BLOCKED: tool '${toolName}' not allowed while in '${guard.flow}' workflow. You must call '${nextTool}' to complete the current task before starting another.`);
|
|
130
133
|
}
|
|
131
134
|
}
|
|
132
135
|
guard.startedAt = now;
|
|
@@ -159,16 +162,12 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
159
162
|
// Allow re-fetching at any time during the flow
|
|
160
163
|
guard.step = 1;
|
|
161
164
|
}
|
|
162
|
-
else if (toolName === "
|
|
165
|
+
else if (toolName === "mark_annotations_as_live") {
|
|
163
166
|
if (guard.step !== 1)
|
|
164
167
|
throw new Error("TOOL_CALL_BLOCKED: unexpected step");
|
|
165
168
|
// Stop here and reset flow as per USER_REQUEST (MCP only reaches 'applied')
|
|
166
169
|
resetGuard();
|
|
167
170
|
}
|
|
168
|
-
else if (toolName === "mark_annotations_as_live") {
|
|
169
|
-
// Optional step if the model decides to use it, but no longer part of the required chain
|
|
170
|
-
resetGuard();
|
|
171
|
-
}
|
|
172
171
|
else {
|
|
173
172
|
throw new Error("TOOL_CALL_BLOCKED: tool not allowed in active flow");
|
|
174
173
|
}
|
|
@@ -177,14 +176,11 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
177
176
|
if (toolName === "get_ui_improvements") {
|
|
178
177
|
guard.step = 1;
|
|
179
178
|
}
|
|
180
|
-
else if (toolName === "
|
|
179
|
+
else if (toolName === "mark_annotations_as_live") {
|
|
181
180
|
if (guard.step !== 1)
|
|
182
181
|
throw new Error("TOOL_CALL_BLOCKED: unexpected step");
|
|
183
182
|
resetGuard();
|
|
184
183
|
}
|
|
185
|
-
else if (toolName === "mark_annotations_as_live") {
|
|
186
|
-
resetGuard();
|
|
187
|
-
}
|
|
188
184
|
else {
|
|
189
185
|
throw new Error("TOOL_CALL_BLOCKED: tool not allowed in active flow");
|
|
190
186
|
}
|
|
@@ -289,8 +285,8 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
289
285
|
},
|
|
290
286
|
},
|
|
291
287
|
{
|
|
292
|
-
name: "
|
|
293
|
-
description: "Mark as
|
|
288
|
+
name: "mark_annotations_as_live",
|
|
289
|
+
description: "Mark tickets (functional or UI/UX) as applied. Use this tool after fixing the code to submit your changes. IMPORTANT: appliedChanges must be in the project's preferredLanguage (e.g. SPANISH).",
|
|
294
290
|
inputSchema: {
|
|
295
291
|
type: "object",
|
|
296
292
|
properties: {
|
|
@@ -309,21 +305,6 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
309
305
|
required: ["results"]
|
|
310
306
|
},
|
|
311
307
|
},
|
|
312
|
-
{
|
|
313
|
-
name: "mark_annotations_as_live",
|
|
314
|
-
description: "Mark as live (ready_for_review). IDs required.",
|
|
315
|
-
inputSchema: {
|
|
316
|
-
type: "object",
|
|
317
|
-
properties: {
|
|
318
|
-
ids: {
|
|
319
|
-
type: "array",
|
|
320
|
-
items: { type: "string" },
|
|
321
|
-
description: "Internal IDs."
|
|
322
|
-
}
|
|
323
|
-
},
|
|
324
|
-
required: ["ids"]
|
|
325
|
-
},
|
|
326
|
-
},
|
|
327
308
|
{
|
|
328
309
|
name: "planning",
|
|
329
310
|
description: "Planning tool for backlog tickets. Fetch tickets or submit analysis. IMPORTANT: aiAnalysis must be in the project's preferredLanguage (e.g. SPANISH).",
|
|
@@ -607,6 +588,12 @@ Endpoints: ${ann.backendEndpoints?.length ? ann.backendEndpoints.join(', ') : 'N
|
|
|
607
588
|
Feedback previo: ${ann.corrections && Array.isArray(ann.corrections) && ann.corrections.length > 0 ? ann.corrections[ann.corrections.length - 1].text : 'Ninguno'}
|
|
608
589
|
Tarea: ${ann.message}
|
|
609
590
|
Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
591
|
+
|
|
592
|
+
### FLUJO DE TRABAJO OBLIGATORIO ###
|
|
593
|
+
1. Analiza el código y el problema.
|
|
594
|
+
2. Aplica la solución técnica necesaria.
|
|
595
|
+
3. AL TERMINAR, DEBES LLAMAR A 'mark_annotations_as_live' con el id '${ann._id}' y un resumen de tus cambios en 'appliedChanges' (en ESPAÑOL).
|
|
596
|
+
4. El estado final del ticket será 'applied'. NO intentes usar otros estados o herramientas hasta completar este paso.
|
|
610
597
|
(RECUERDA: Toda tu respuesta, comentarios y análisis DEBEN estar en ESPAÑOL)`
|
|
611
598
|
};
|
|
612
599
|
});
|
|
@@ -617,10 +604,10 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
|
617
604
|
content: [{ type: "text", text: langHint + JSON.stringify({ preferredLanguage: rawData.preferredLanguage || 'en', annotations: annotationsWithTips }, null, 2) }],
|
|
618
605
|
};
|
|
619
606
|
}
|
|
620
|
-
case "
|
|
607
|
+
case "mark_annotations_as_live": {
|
|
621
608
|
const args = argsAny;
|
|
622
609
|
const results = args.results;
|
|
623
|
-
console.error(`[
|
|
610
|
+
console.error(`[mark_annotations_as_live] Submitting results for ${results?.length} items as applied`);
|
|
624
611
|
const response = await fetch(`${BACKEND_URL}/api/mcp/annotations/batch-ready`, {
|
|
625
612
|
method: 'PATCH',
|
|
626
613
|
headers: {
|
|
@@ -640,27 +627,6 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
|
640
627
|
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
641
628
|
};
|
|
642
629
|
}
|
|
643
|
-
case "mark_annotations_as_live": {
|
|
644
|
-
const args = argsAny;
|
|
645
|
-
const ids = args.ids;
|
|
646
|
-
console.error(`[mark_annotations_as_live] Marking ${ids?.length} items as live`);
|
|
647
|
-
const response = await fetch(`${BACKEND_URL}/api/mcp/annotations/mark-as-live`, {
|
|
648
|
-
method: 'POST',
|
|
649
|
-
headers: {
|
|
650
|
-
'Content-Type': 'application/json',
|
|
651
|
-
'x-api-key': apiKey,
|
|
652
|
-
'x-mcp-tool-name': toolName,
|
|
653
|
-
'x-personal-key': personalKey || ''
|
|
654
|
-
},
|
|
655
|
-
body: JSON.stringify({ ids })
|
|
656
|
-
});
|
|
657
|
-
if (!response.ok)
|
|
658
|
-
throw new Error(`Backend responded with ${response.status}`);
|
|
659
|
-
const data = (await response.json());
|
|
660
|
-
return {
|
|
661
|
-
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
662
|
-
};
|
|
663
|
-
}
|
|
664
630
|
case "planning": {
|
|
665
631
|
const args = argsAny;
|
|
666
632
|
const url = args.results ? `${BACKEND_URL}/api/mcp/annotations/batch-planning` : `${BACKEND_URL}/api/mcp/backlog`;
|
|
@@ -680,6 +646,7 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
|
680
646
|
}
|
|
681
647
|
case "get_ui_improvements": {
|
|
682
648
|
const args = argsAny;
|
|
649
|
+
const agentId = personalKey || 'mcp-agent-ui-' + (apiKey?.slice(-6) || 'generic');
|
|
683
650
|
const fetchUrl = new URL(`${BACKEND_URL}/api/mcp/ui-improvements`);
|
|
684
651
|
if (args.limit)
|
|
685
652
|
fetchUrl.searchParams.append("limit", args.limit.toString());
|
|
@@ -689,6 +656,10 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
|
689
656
|
fetchUrl.searchParams.append("key", args.key);
|
|
690
657
|
if (args.ids)
|
|
691
658
|
fetchUrl.searchParams.append("ids", args.ids);
|
|
659
|
+
// Add lock and agentId parameters to enable blocking flow
|
|
660
|
+
fetchUrl.searchParams.append("lock", "true");
|
|
661
|
+
fetchUrl.searchParams.append("agentId", agentId);
|
|
662
|
+
console.error(`[get_ui_improvements] Fetching with lock: ${fetchUrl.toString()}`);
|
|
692
663
|
const response = await fetch(fetchUrl, {
|
|
693
664
|
headers: {
|
|
694
665
|
'x-api-key': apiKey,
|
|
@@ -700,11 +671,33 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
|
700
671
|
const errorBody = await response.text();
|
|
701
672
|
throw new Error(`Backend responded with ${response.status}: ${errorBody}`);
|
|
702
673
|
}
|
|
703
|
-
const
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
: "";
|
|
707
|
-
|
|
674
|
+
const rawData = (await response.json());
|
|
675
|
+
let rawImprovements = Array.isArray(rawData) ? rawData : (rawData?.data || rawData?.improvements || []);
|
|
676
|
+
if (!Array.isArray(rawImprovements)) {
|
|
677
|
+
return { content: [{ type: "text", text: "Error: Invalid format from backend" }], isError: true };
|
|
678
|
+
}
|
|
679
|
+
const improvementsWithTips = rawImprovements.map((ann) => {
|
|
680
|
+
return {
|
|
681
|
+
...ann,
|
|
682
|
+
_ia_fix_instruction: `### INSTRUCCIONES PARA LA IA (MEJORA UI - IMPORTANTE) ###
|
|
683
|
+
A continuación se presenta un ticket de MEJORA VISUAL/UX que requiere tu atención.
|
|
684
|
+
DEBES RESPONDER EN ESPAÑOL.
|
|
685
|
+
Proyecto: ${rawData.name || 'ViewGate'}
|
|
686
|
+
Tarea: ${ann.message}
|
|
687
|
+
Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
688
|
+
|
|
689
|
+
### FLUJO DE TRABAJO OBLIGATORIO ###
|
|
690
|
+
1. Analiza el diseño y los estilos CSS actuales.
|
|
691
|
+
2. Aplica los cambios visuales solicitados (STRICTLY LIMITED TO VISUAL/CSS CHANGES).
|
|
692
|
+
3. AL TERMINAR, DEBES LLAMAR A 'mark_annotations_as_live' con el id '${ann._id}' y un resumen de tus cambios en 'appliedChanges' (en ESPAÑOL).
|
|
693
|
+
4. El estado final del ticket será 'applied'. NO intentes usar otros estados o herramientas hasta completar este paso.
|
|
694
|
+
(RECUERDA: Toda tu respuesta, comentarios y análisis DEBEN estar en ESPAÑOL)`
|
|
695
|
+
};
|
|
696
|
+
});
|
|
697
|
+
const langHint = rawData.preferredLanguage === 'es'
|
|
698
|
+
? "\n*** [INSTRUCTION: Project is in SPANISH. Provide all comments and changes in SPANISH ONLY.] ***\n\n"
|
|
699
|
+
: (rawData.preferredLanguage === 'en' ? "\n*** [INSTRUCTION: Provide all comments and analysis in English.] ***\n\n" : "");
|
|
700
|
+
return { content: [{ type: "text", text: langHint + JSON.stringify({ preferredLanguage: rawData.preferredLanguage || 'en', improvements: improvementsWithTips }, null, 2) }] };
|
|
708
701
|
}
|
|
709
702
|
case "sync_endpoints": {
|
|
710
703
|
const args = argsAny;
|
|
@@ -753,7 +746,7 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
|
|
|
753
746
|
const useSSE = process.argv.includes("--sse") || process.env.MCP_TRANSPORT === "sse";
|
|
754
747
|
if (!useSSE) {
|
|
755
748
|
const apiKey = process.env.VIEWGATE_API_KEY || process.env.API_KEY || "";
|
|
756
|
-
const personalKey = process.env.VIEWGATE_PERSONAL_KEY || "";
|
|
749
|
+
const personalKey = process.env.VIEWGATE_PERSONAL_KEY || process.env.PERSONAL_KEY || "";
|
|
757
750
|
if (!apiKey) {
|
|
758
751
|
console.error("Error: VIEWGATE_API_KEY environment variable is required.");
|
|
759
752
|
process.exit(1);
|