viewgate-mcp 1.0.10 → 1.0.12

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 +77 -19
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ const sessions = new Map();
34
34
  /**
35
35
  * Create a new MCP server instance for a specific context.
36
36
  */
37
- function createMcpServer(apiKey) {
37
+ function createMcpServer(apiKey, personalKey) {
38
38
  const server = new Server({
39
39
  name: "viewgate-mcp",
40
40
  version: "1.0.0",
@@ -48,7 +48,7 @@ function createMcpServer(apiKey) {
48
48
  tools: [
49
49
  {
50
50
  name: "get_annotations",
51
- description: "Retrieves all feedback annotations. WORKFLOW: 1. Read these annotations, 2. Open the source files and apply SURGICAL fixes based on '_ia_fix_instruction'. 3. IMMEDIATELY call 'mark_annotation_ready' with the results for EACH ticket you fixed. Use 'outerHtml' and 'source' (file:line) to locate the exact code block without manual searching. IMPORTANT: All AI analysis and comments MUST be in the 'preferredLanguage' specified in the output.",
51
+ description: "Retrieves all feedback annotations. WORKFLOW: 1. Read these annotations, 2. Open the source files and apply SURGICAL fixes based on '_ia_fix_instruction'. 3. IMMEDIATELY call 'mark_annotation_ready' with the results for EACH ticket you fixed. Use 'outerHtml' and 'source' (file:line) to locate the exact code block without manual searching. IMPORTANT: All AI analysis and comments MUST be in the 'preferredLanguage' specified in the output. Failure to follow the language setting is UNACCEPTABLE.",
52
52
  inputSchema: {
53
53
  type: "object",
54
54
  properties: {},
@@ -56,7 +56,7 @@ function createMcpServer(apiKey) {
56
56
  },
57
57
  {
58
58
  name: "mark_annotation_ready",
59
- description: "CRITICAL: Call this tool AFTER applying code fixes for annotations. It marks tickets as 'Ready for Review' in the ViewGate dashboard and stores your AI-generated change summary. Support batch processing of multiple tickets at once. IMPORTANT: The 'appliedChanges' summary MUST be written in the 'preferredLanguage' specified by 'get_annotations' output.",
59
+ description: "CRITICAL: Call this tool AFTER applying code fixes for annotations. It marks tickets as 'Ready for Review' in the ViewGate dashboard and stores your AI-generated change summary. Support batch processing of multiple tickets at once. IMPORTANT: The 'appliedChanges' summary MUST be written in the 'preferredLanguage' specified by 'get_annotations' output. DO NOT use English if the preferred language is Spanish.",
60
60
  inputSchema: {
61
61
  type: "object",
62
62
  properties: {
@@ -66,7 +66,7 @@ function createMcpServer(apiKey) {
66
66
  type: "object",
67
67
  properties: {
68
68
  id: { type: "string", description: "The ID of the annotation to mark as ready" },
69
- appliedChanges: { type: "string", description: "Descriptive summary of what was changed in the code for this specific ticket" }
69
+ appliedChanges: { type: "string", description: "Descriptive summary of what was changed in the code for this specific ticket. MUST be in the preferredLanguage." }
70
70
  },
71
71
  required: ["id", "appliedChanges"]
72
72
  }
@@ -77,7 +77,7 @@ function createMcpServer(apiKey) {
77
77
  },
78
78
  {
79
79
  name: "planning",
80
- description: "Planning tool for backlog tickets. CALL WITHOUT ARGUMENTS to fetch backlog tickets that need analysis. CALL WITH 'results' to submit AI analysis in batch. Rules: complejidad (1-3), incertidumbre (1-3), impacto (1-3), riesgo (1-3), tipo (AI-friendly|AI-assisted|Human-critical). IMPORTANT: All AI analysis and comments MUST be in the 'preferredLanguage' specified in the output.",
80
+ description: "Planning tool for backlog tickets. CALL WITHOUT ARGUMENTS to fetch backlog tickets that need analysis. CALL WITH 'results' to submit AI analysis in batch. Rules: complejidad (1-3), incertidumbre (1-3), impacto (1-3), riesgo (1-3), tipo (AI-friendly|AI-assisted|Human-critical). IMPORTANT: All AI analysis, 'aiAnalysis' descriptions, and comments MUST be in the 'preferredLanguage' specified in the output.",
81
81
  inputSchema: {
82
82
  type: "object",
83
83
  properties: {
@@ -92,7 +92,7 @@ function createMcpServer(apiKey) {
92
92
  impacto: { type: "number", minimum: 1, maximum: 3 },
93
93
  riesgo: { type: "number", minimum: 1, maximum: 3 },
94
94
  tipo: { type: "string", enum: ["AI-friendly", "AI-assisted", "Human-critical"] },
95
- aiAnalysis: { type: "string", description: "Reasoning or summary of the analysis" }
95
+ aiAnalysis: { type: "string", description: "Reasoning or summary of the analysis. MUST be in the preferredLanguage." }
96
96
  },
97
97
  required: ["id", "complejidad", "incertidumbre", "impacto", "riesgo", "tipo", "aiAnalysis"]
98
98
  }
@@ -106,7 +106,7 @@ function createMcpServer(apiKey) {
106
106
  },
107
107
  {
108
108
  name: "sync_endpoints",
109
- description: "Synchronizes a batch of backend endpoints with the ViewGate server. High-performance batch processing for language-agnostic mapping (Express, Java, .NET, Python, etc.).",
109
+ description: "Synchronizes a batch of backend endpoints with the ViewGate server. High-performance batch processing for language-agnostic mapping (Express, Java, .NET, Python, etc.). IMPORTANT: The 'description' for each endpoint MUST be written in the project's preferred language (e.g., Spanish if preferredLanguage is 'es').",
110
110
  inputSchema: {
111
111
  type: "object",
112
112
  properties: {
@@ -117,14 +117,31 @@ function createMcpServer(apiKey) {
117
117
  properties: {
118
118
  path: { type: "string", description: "The relative path of the endpoint" },
119
119
  method: { type: "string", description: "HTTP method (GET, POST, etc.)" },
120
- description: { type: "string", description: "Human-readable description of what the endpoint does" }
120
+ description: { type: "string", description: "Human-readable description of what the endpoint does. MUST be in the preferredLanguage." },
121
+ hash: { type: "string", description: "Optional SHA256 hash of the endpoint definition for efficient diffing." }
121
122
  },
122
123
  required: ["path", "method", "description"]
123
124
  }
125
+ },
126
+ clean: {
127
+ type: "boolean",
128
+ description: "If true, clears all existing endpoints before adding the new ones. Useful for the first batch of a fresh scan."
129
+ },
130
+ globalHash: {
131
+ type: "string",
132
+ description: "Optional SHA256 hash of the entire endpoint set. If provided and matches the backend, the entire sync is skipped for performance."
124
133
  }
125
134
  },
126
135
  required: ["endpoints"]
127
136
  }
137
+ },
138
+ {
139
+ name: "get_synced_endpoints",
140
+ description: "Retrieves the list of endpoints currently synchronized in the backend for this project. Use this to perform diffing and avoid redundant synchronization calls.",
141
+ inputSchema: {
142
+ type: "object",
143
+ properties: {},
144
+ },
128
145
  }
129
146
  ],
130
147
  };
@@ -136,7 +153,8 @@ function createMcpServer(apiKey) {
136
153
  const statuses = 'pending,bug_fixing';
137
154
  const response = await fetch(`${BACKEND_URL}/api/mcp/annotations?status=${statuses}`, {
138
155
  headers: {
139
- 'x-api-key': apiKey
156
+ 'x-api-key': apiKey,
157
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
140
158
  }
141
159
  });
142
160
  if (!response.ok) {
@@ -196,12 +214,15 @@ function createMcpServer(apiKey) {
196
214
  componentPath: ann.reference?.componentPath,
197
215
  selector: ann.reference?.selector,
198
216
  tag: ann.reference?.tag,
199
- _ia_fix_instruction: `### 🔬 SURGICAL FIX PROTOCOL
217
+ backendEndpoints: ann.backendEndpoints || [ann.backendEndpoint].filter(Boolean),
218
+ _ia_fix_instruction: `### 🔬 SURGICAL FIX PROTOCOL (Language: ${data.preferredLanguage || 'en'})
200
219
  1. **PRIMARY**: Search for \`data-vg-id="${ann.reference?.vgId}"\`.
201
220
  2. **SECONDARY**: Check \`${file}\` L${line} (Fiber Source).
202
221
  3. **TERTIARY**: Match Tag(\`${ann.reference?.tag}\`) + Role(\`${ann.reference?.fingerprint?.role}\`) + Text("${ann.reference?.text?.slice(0, 30)}").
203
222
  4. **VALIDATE**: Confirm parent context matches \`${ann.reference?.parentContext?.slice(0, 50).replace(/`/g, "'")}...\`.
204
223
 
224
+ IMPORTANT: All your analysis and implementation comments MUST BE IN ${data.preferredLanguage === 'es' ? 'SPANISH' : 'ENGLISH'}.
225
+
205
226
  Confidence: [vgId: ${ann.reference?.confidence?.vgId || 0}, Fiber: ${ann.reference?.confidence?.fiber || 0}, Fingerprint: ${ann.reference?.confidence?.fingerprint || 0}]
206
227
  Instruction: ${ann.message}`
207
228
  };
@@ -237,7 +258,8 @@ Instruction: ${ann.message}`
237
258
  method: 'PATCH',
238
259
  headers: {
239
260
  'Content-Type': 'application/json',
240
- 'x-api-key': apiKey
261
+ 'x-api-key': apiKey,
262
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
241
263
  },
242
264
  body: JSON.stringify({ results: args.results })
243
265
  });
@@ -262,7 +284,10 @@ Instruction: ${ann.message}`
262
284
  if (!args.results) {
263
285
  // Fetch Backlog Mode
264
286
  const response = await fetch(`${BACKEND_URL}/api/mcp/backlog`, {
265
- headers: { 'x-api-key': apiKey }
287
+ headers: {
288
+ 'x-api-key': apiKey,
289
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
290
+ }
266
291
  });
267
292
  if (!response.ok) {
268
293
  throw new Error(`Backend responded with ${response.status}`);
@@ -284,7 +309,8 @@ Instruction: ${ann.message}`
284
309
  method: 'PATCH',
285
310
  headers: {
286
311
  'Content-Type': 'application/json',
287
- 'x-api-key': apiKey
312
+ 'x-api-key': apiKey,
313
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
288
314
  },
289
315
  body: JSON.stringify({ results: args.results, force: args.force })
290
316
  });
@@ -314,16 +340,21 @@ Instruction: ${ann.message}`
314
340
  method: 'POST',
315
341
  headers: {
316
342
  'Content-Type': 'application/json',
317
- 'x-api-key': apiKey
343
+ 'x-api-key': apiKey,
344
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
318
345
  },
319
- body: JSON.stringify({ endpoints: args.endpoints })
346
+ body: JSON.stringify({
347
+ endpoints: args.endpoints,
348
+ clean: args.clean,
349
+ globalHash: args.globalHash
350
+ })
320
351
  });
321
352
  if (!response.ok) {
322
353
  throw new Error(`Backend responded with ${response.status}`);
323
354
  }
324
355
  const result = (await response.json());
325
356
  return {
326
- content: [{ type: "text", text: `Endpoints synchronized successfully: ${result.count} routes mapped.` }]
357
+ content: [{ type: "text", text: `Endpoints synchronized successfully: ${result.count} routes processed. ${result.saved ? 'Changes saved.' : 'No changes detected.'}` }]
327
358
  };
328
359
  }
329
360
  catch (error) {
@@ -333,6 +364,32 @@ Instruction: ${ann.message}`
333
364
  };
334
365
  }
335
366
  }
367
+ case "get_synced_endpoints": {
368
+ try {
369
+ const response = await fetch(`${BACKEND_URL}/api/projects/endpoints`, {
370
+ headers: {
371
+ 'x-api-key': apiKey,
372
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
373
+ }
374
+ });
375
+ if (!response.ok) {
376
+ throw new Error(`Backend responded with ${response.status}`);
377
+ }
378
+ const data = (await response.json());
379
+ return {
380
+ content: [{
381
+ type: "text",
382
+ text: JSON.stringify(data.endpoints || [], null, 2)
383
+ }]
384
+ };
385
+ }
386
+ catch (error) {
387
+ return {
388
+ content: [{ type: "text", text: `Error fetching synced endpoints: ${error.message}` }],
389
+ isError: true
390
+ };
391
+ }
392
+ }
336
393
  default:
337
394
  throw new Error("Unknown tool");
338
395
  }
@@ -345,11 +402,12 @@ if (!useSSE) {
345
402
  // STDIO Mode (NPM Package Default)
346
403
  // In Stdio mode, we use the API key from environment variable
347
404
  const apiKey = process.env.VIEWGATE_API_KEY || process.env.API_KEY || "";
405
+ const personalKey = process.env.VIEWGATE_PERSONAL_KEY || "";
348
406
  if (!apiKey) {
349
407
  console.error("Error: VIEWGATE_API_KEY environment variable is required in STDIO mode.");
350
408
  process.exit(1);
351
409
  }
352
- const server = createMcpServer(apiKey);
410
+ const server = createMcpServer(apiKey, personalKey);
353
411
  const transport = new StdioServerTransport();
354
412
  server.connect(transport).catch((error) => {
355
413
  console.error("Failed to start Stdio transport:", error);
@@ -373,12 +431,13 @@ else {
373
431
  });
374
432
  app.get("/sse", async (req, res) => {
375
433
  const apiKey = req.query.apiKey || req.headers['x-api-key'];
434
+ const personalKey = req.query.personalKey || req.headers['x-personal-key'];
376
435
  if (!apiKey) {
377
436
  res.status(401).send("API Key is required");
378
437
  return;
379
438
  }
380
439
  const transport = new SSEServerTransport("/message", res);
381
- const server = createMcpServer(apiKey);
440
+ const server = createMcpServer(apiKey, personalKey);
382
441
  await server.connect(transport);
383
442
  const sessionId = transport.sessionId;
384
443
  sessions.set(sessionId, { server, transport });
@@ -394,6 +453,5 @@ else {
394
453
  await session.transport.handlePostMessage(req, res);
395
454
  });
396
455
  app.listen(port, () => {
397
- console.log(`ViewGate MCP (SSE) listening on port ${port}`);
398
456
  });
399
457
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viewgate-mcp",
3
- "version": "1.0.10",
3
+ "version": "1.0.12",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "viewgate-mcp": "./dist/index.js"