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.
Files changed (2) hide show
  1. package/dist/index.js +53 -60
  2. 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.BACKEND_URL || "https://view-gate.vercel.app";
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
- console.error(`[MCP Config] API_KEY Prefix: ${process.env.API_KEY?.substring(0, 5)}...`);
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("TOOL_CALL_BLOCKED: tool not allowed in idle");
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
- throw new Error("TOOL_CALL_BLOCKED: tool not allowed in active flow");
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 === "mark_annotation_ready") {
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 === "mark_annotation_ready") {
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: "mark_annotation_ready",
293
- description: "Mark as ready/applied. Use internal IDs. IMPORTANT: appliedChanges must be in the project's preferredLanguage (e.g. SPANISH).",
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 "mark_annotation_ready": {
607
+ case "mark_annotations_as_live": {
621
608
  const args = argsAny;
622
609
  const results = args.results;
623
- console.error(`[mark_annotation_ready] Submitting results for ${results?.length} items`);
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 data = (await response.json());
704
- const langHint = data.preferredLanguage === 'es'
705
- ? "\n*** [INSTRUCTION: Project is in SPANISH. Provide all CSS/Visual changes in SPANISH comments if requested.] ***\n\n\n\n"
706
- : "";
707
- return { content: [{ type: "text", text: langHint + JSON.stringify(data, null, 2) }] };
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);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viewgate-mcp",
3
- "version": "1.0.46",
3
+ "version": "1.0.48",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "viewgate-mcp": "./dist/index.js"