viewgate-mcp 1.0.18 → 1.0.21

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 +113 -21
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -51,7 +51,9 @@ function createMcpServer(apiKey, personalKey) {
51
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
- properties: {},
54
+ properties: {
55
+ limit: { type: "number", description: "Maximum number of annotations to retrieve (default: 3)", default: 3 }
56
+ },
55
57
  },
56
58
  },
57
59
  {
@@ -118,7 +120,8 @@ function createMcpServer(apiKey, personalKey) {
118
120
  path: { type: "string", description: "The relative path of the endpoint" },
119
121
  method: { type: "string", description: "HTTP method (GET, POST, etc.)" },
120
122
  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." }
123
+ hash: { type: "string", description: "Optional SHA256 hash of the endpoint definition for efficient diffing." },
124
+ contract: { type: "string", description: "Optional JSON string or description of the request/response contract (payload)." }
122
125
  },
123
126
  required: ["path", "method", "description"]
124
127
  }
@@ -142,6 +145,25 @@ function createMcpServer(apiKey, personalKey) {
142
145
  type: "object",
143
146
  properties: {},
144
147
  },
148
+ },
149
+ {
150
+ name: "get_optimizations",
151
+ description: "Retrieves reported JSON payload optimizations (unused fields). WORKFLOW: 1. Get optimizations, 2. Locate the backend code for the endpoint, 3. Remove unused fields from the response, 4. Call 'mark_optimization_applied' with the ID.",
152
+ inputSchema: {
153
+ type: "object",
154
+ properties: {},
155
+ },
156
+ },
157
+ {
158
+ name: "mark_optimization_applied",
159
+ description: "Marks a payload optimization as applied in the backend after you have modified the code to remove unused fields.",
160
+ inputSchema: {
161
+ type: "object",
162
+ properties: {
163
+ id: { type: "string", description: "The ID of the optimization report to mark as applied" }
164
+ },
165
+ required: ["id"]
166
+ },
145
167
  }
146
168
  ],
147
169
  };
@@ -150,8 +172,10 @@ function createMcpServer(apiKey, personalKey) {
150
172
  switch (request.params.name) {
151
173
  case "get_annotations": {
152
174
  try {
175
+ const args = request.params.arguments;
176
+ const limit = args.limit || 3;
153
177
  const statuses = 'pending,bug_fixing';
154
- const response = await fetch(`${BACKEND_URL}/api/mcp/annotations?status=${statuses}`, {
178
+ const response = await fetch(`${BACKEND_URL}/api/mcp/annotations?status=${statuses}&limit=${limit}&lock=true`, {
155
179
  headers: {
156
180
  'x-api-key': apiKey,
157
181
  ...(personalKey ? { 'x-personal-key': personalKey } : {})
@@ -193,9 +217,12 @@ function createMcpServer(apiKey, personalKey) {
193
217
  return prioB - prioA;
194
218
  });
195
219
  const annotationsWithTips = sortedAnnotations.map((ann) => {
220
+ const file = ann.reference?.source?.split(':')[0];
221
+ const line = ann.reference?.source?.split(':')[1];
196
222
  const source = ann.reference?.source;
197
- const hasSource = source && source !== 'unknown:0';
198
- const [file, line] = hasSource ? source.split(':') : [null, null];
223
+ const pendingCorrection = Array.isArray(ann.corrections)
224
+ ? ann.corrections.find((c) => c.status === 'pending')
225
+ : (typeof ann.corrections === 'string' ? { text: ann.corrections } : null);
199
226
  // Essential fields for the AI to perform a surgical fix
200
227
  return {
201
228
  id: ann._id,
@@ -203,6 +230,7 @@ function createMcpServer(apiKey, personalKey) {
203
230
  priority: ann.priority,
204
231
  status: ann.status,
205
232
  message: ann.message,
233
+ corrections: ann.corrections, // Include full history
206
234
  source: source,
207
235
  filePath: ann.filePath || file,
208
236
  line: ann.line || (line ? parseInt(line) : undefined),
@@ -219,6 +247,12 @@ function createMcpServer(apiKey, personalKey) {
219
247
  _ia_fix_instruction: `### 🎨 DESIGN CONTEXT (Figma)
220
248
  ${ann.figmaReference ? `A design reference is available: ${ann.figmaReference}. Use the Figma link to understand the UX requirements.` : 'No explicit figma design linked.'}
221
249
 
250
+ ${pendingCorrection ? `### ⚠️ PENDING CORRECTION (FEEDBACK)
251
+ The user has requested the following corrections:
252
+ "${pendingCorrection.text}"
253
+ ${pendingCorrection.author ? `Requested by: ${pendingCorrection.author.name}` : ''}
254
+ PLEASE ENSURE THESE SPECIFIC ISSUES ARE ADDRESSED IN YOUR FIX.` : ''}
255
+
222
256
  ### 🔬 SURGICAL FIX PROTOCOL (Language: ${data.preferredLanguage || 'en'})
223
257
  1. **PRIMARY**: Search for \`data-vg-id="${ann.reference?.vgId}"\`.
224
258
  2. **SECONDARY**: Check \`${file}\` L${line} (Fiber Source).
@@ -228,7 +262,7 @@ ${ann.figmaReference ? `A design reference is available: ${ann.figmaReference}.
228
262
  IMPORTANT: All your analysis and implementation comments MUST BE IN ${data.preferredLanguage === 'es' ? 'SPANISH' : 'ENGLISH'}.
229
263
 
230
264
  Confidence: [vgId: ${ann.reference?.confidence?.vgId || 0}, Fiber: ${ann.reference?.confidence?.fiber || 0}, Fingerprint: ${ann.reference?.confidence?.fingerprint || 0}]
231
- Instruction: ${ann.message}`
265
+ Instruction: ${ann.message}${pendingCorrection ? `\nCorrection Needed: ${pendingCorrection.text}` : ''}`
232
266
  };
233
267
  });
234
268
  return {
@@ -258,22 +292,34 @@ Instruction: ${ann.message}`
258
292
  case "mark_annotation_ready": {
259
293
  try {
260
294
  const args = request.params.arguments;
261
- const response = await fetch(`${BACKEND_URL}/api/mcp/annotations/batch-ready`, {
262
- method: 'PATCH',
263
- headers: {
264
- 'Content-Type': 'application/json',
265
- 'x-api-key': apiKey,
266
- ...(personalKey ? { 'x-personal-key': personalKey } : {})
267
- },
268
- body: JSON.stringify({ results: args.results })
269
- });
270
- if (!response.ok) {
271
- throw new Error(`Backend responded with ${response.status} when updating annotations`);
295
+ let lastError = null;
296
+ for (let attempt = 1; attempt <= 3; attempt++) {
297
+ try {
298
+ const response = await fetch(`${BACKEND_URL}/api/mcp/annotations/batch-ready`, {
299
+ method: 'PATCH',
300
+ headers: {
301
+ 'Content-Type': 'application/json',
302
+ 'x-api-key': apiKey,
303
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
304
+ },
305
+ body: JSON.stringify({ results: args.results })
306
+ });
307
+ if (!response.ok) {
308
+ throw new Error(`Backend responded with ${response.status}`);
309
+ }
310
+ const result = await response.json();
311
+ return {
312
+ content: [{ type: "text", text: `Successfully processed batch update: ${JSON.stringify(result, null, 2)}` }],
313
+ };
314
+ }
315
+ catch (error) {
316
+ lastError = error;
317
+ console.error(`[MCP] mark_annotation_ready attempt ${attempt} failed:`, error.message);
318
+ if (attempt < 3)
319
+ await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
320
+ }
272
321
  }
273
- const result = await response.json();
274
- return {
275
- content: [{ type: "text", text: `Successfully processed batch update: ${JSON.stringify(result, null, 2)}` }],
276
- };
322
+ throw lastError || new Error('Unknown error during batch update');
277
323
  }
278
324
  catch (error) {
279
325
  return {
@@ -394,6 +440,52 @@ Instruction: ${ann.message}`
394
440
  };
395
441
  }
396
442
  }
443
+ case "get_optimizations": {
444
+ try {
445
+ const response = await fetch(`${BACKEND_URL}/api/mcp/optimizations`, {
446
+ headers: {
447
+ 'x-api-key': apiKey,
448
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
449
+ }
450
+ });
451
+ if (!response.ok)
452
+ throw new Error(`Backend responded with ${response.status}`);
453
+ const data = await response.json();
454
+ return {
455
+ content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
456
+ };
457
+ }
458
+ catch (error) {
459
+ return {
460
+ content: [{ type: "text", text: `Error fetching optimizations: ${error.message}` }],
461
+ isError: true
462
+ };
463
+ }
464
+ }
465
+ case "mark_optimization_applied": {
466
+ try {
467
+ const args = request.params.arguments;
468
+ const response = await fetch(`${BACKEND_URL}/api/mcp/optimizations/${args.id}/applied`, {
469
+ method: 'PATCH',
470
+ headers: {
471
+ 'x-api-key': apiKey,
472
+ ...(personalKey ? { 'x-personal-key': personalKey } : {})
473
+ }
474
+ });
475
+ if (!response.ok)
476
+ throw new Error(`Backend responded with ${response.status}`);
477
+ const result = await response.json();
478
+ return {
479
+ content: [{ type: "text", text: `Optimization marked as applied: ${JSON.stringify(result)}` }]
480
+ };
481
+ }
482
+ catch (error) {
483
+ return {
484
+ content: [{ type: "text", text: `Error marking optimization: ${error.message}` }],
485
+ isError: true
486
+ };
487
+ }
488
+ }
397
489
  default:
398
490
  throw new Error("Unknown tool");
399
491
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viewgate-mcp",
3
- "version": "1.0.18",
3
+ "version": "1.0.21",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "viewgate-mcp": "./dist/index.js"