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.
- package/dist/index.js +77 -19
- 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
|
-
|
|
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: {
|
|
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({
|
|
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
|
|
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
|
}
|