viewgate-mcp 1.0.25 → 1.0.27
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 +47 -19
- package/dist/test_fix.js +59 -0
- package/dist/test_sse.js +23 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -48,20 +48,22 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
48
48
|
tools: [
|
|
49
49
|
{
|
|
50
50
|
name: "get_annotations",
|
|
51
|
-
description: "Retrieves all feedback annotations. Use 'status' to filter (e.g. 'pending,bug_fixing'). WORKFLOW: 1. Read these annotations, 2. Open the source files and apply SURGICAL fixes. 3. Call 'mark_annotation_ready' for EACH ticket. IMPORTANT:
|
|
51
|
+
description: "Retrieves all feedback annotations. Use 'status' to filter (e.g. 'pending,bug_fixing'). WORKFLOW: 1. Read these annotations, 2. Open the source files and apply SURGICAL fixes. 3. Call 'mark_annotation_ready' for EACH ticket. IMPORTANT: Tickets already resolved by the AI in the current sprint are automatically filtered out to prevent redundant work.",
|
|
52
52
|
inputSchema: {
|
|
53
53
|
type: "object",
|
|
54
54
|
properties: {
|
|
55
55
|
limit: { type: "number", description: "Maximum number of annotations to retrieve (default: 3)", default: 3 },
|
|
56
56
|
status: { type: "string", description: "Comma-separated list (e.g. 'pending,bug_fixing'). Use 'all' for any state.", default: "pending,bug_fixing" },
|
|
57
57
|
search: { type: "string", description: "Search term to filter by message or file." },
|
|
58
|
-
key: { type: "string", description: "Human key (e.g. VG-XXXX) to find
|
|
58
|
+
key: { type: "string", description: "Human key (e.g. VG-XXXX) or comma-separated keys to find specific annotations." },
|
|
59
|
+
keys: { type: "array", items: { type: "string" }, description: "List of human keys to find specific annotations." },
|
|
60
|
+
ids: { type: "string", description: "Comma-separated internal IDs to find specific annotations." }
|
|
59
61
|
},
|
|
60
62
|
},
|
|
61
63
|
},
|
|
62
64
|
{
|
|
63
65
|
name: "mark_annotation_ready",
|
|
64
|
-
description: "CRITICAL: Call this tool AFTER applying code fixes. REQUIREMENT: Use the internal database ID (e.g. 675ba...), NOT the human key (VG-XXXX).",
|
|
66
|
+
description: "CRITICAL: Call this tool AFTER applying code fixes. This also registers the tickets as resolved by the AI for the current sprint to avoid re-fetching them. REQUIREMENT: Use the internal database ID (e.g. 675ba...), NOT the human key (VG-XXXX).",
|
|
65
67
|
inputSchema: {
|
|
66
68
|
type: "object",
|
|
67
69
|
properties: {
|
|
@@ -152,6 +154,11 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
152
154
|
},
|
|
153
155
|
required: ["id"]
|
|
154
156
|
},
|
|
157
|
+
},
|
|
158
|
+
{
|
|
159
|
+
name: "get_ai_resolved_tickets",
|
|
160
|
+
description: "Retrieves the list of ticket IDs that have already been resolved by the AI in the current sprint.",
|
|
161
|
+
inputSchema: { type: "object", properties: {} },
|
|
155
162
|
}
|
|
156
163
|
],
|
|
157
164
|
};
|
|
@@ -166,7 +173,14 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
166
173
|
const limit = args.limit || 3;
|
|
167
174
|
const statuses = args.status || 'pending,bug_fixing';
|
|
168
175
|
const search = args.search || '';
|
|
169
|
-
|
|
176
|
+
// Normalize keys and ids
|
|
177
|
+
let keysToFetch = [];
|
|
178
|
+
if (args.key)
|
|
179
|
+
keysToFetch = keysToFetch.concat(args.key.split(',').map(s => s.trim()));
|
|
180
|
+
if (args.keys)
|
|
181
|
+
keysToFetch = keysToFetch.concat(args.keys);
|
|
182
|
+
const combinedKey = keysToFetch.filter(k => k).join(',');
|
|
183
|
+
const idsToFetch = args.ids || '';
|
|
170
184
|
let fetchUrl = `${BACKEND_URL}/api/mcp/annotations?lock=true`;
|
|
171
185
|
if (statuses && statuses !== 'all')
|
|
172
186
|
fetchUrl += `&status=${statuses}`;
|
|
@@ -174,8 +188,10 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
174
188
|
fetchUrl += `&limit=${limit}`;
|
|
175
189
|
if (search)
|
|
176
190
|
fetchUrl += `&search=${encodeURIComponent(search)}`;
|
|
177
|
-
if (
|
|
178
|
-
fetchUrl += `&key=${encodeURIComponent(
|
|
191
|
+
if (combinedKey)
|
|
192
|
+
fetchUrl += `&key=${encodeURIComponent(combinedKey)}`;
|
|
193
|
+
if (idsToFetch)
|
|
194
|
+
fetchUrl += `&ids=${encodeURIComponent(idsToFetch)}`;
|
|
179
195
|
const response = await fetch(fetchUrl, {
|
|
180
196
|
headers: {
|
|
181
197
|
'x-api-key': apiKey,
|
|
@@ -196,8 +212,13 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
196
212
|
(ann.reference?.source && ann.reference.source.toLowerCase().includes(lowSearch)) ||
|
|
197
213
|
(ann.key && ann.key.toLowerCase().includes(lowSearch)));
|
|
198
214
|
}
|
|
199
|
-
if (
|
|
200
|
-
|
|
215
|
+
if (combinedKey) {
|
|
216
|
+
const keyList = combinedKey.split(',').map(k => k.trim());
|
|
217
|
+
rawAnnotations = rawAnnotations.filter((ann) => keyList.includes(ann.key) || keyList.includes(ann._id));
|
|
218
|
+
}
|
|
219
|
+
if (idsToFetch) {
|
|
220
|
+
const idList = idsToFetch.split(',').map(i => i.trim());
|
|
221
|
+
rawAnnotations = rawAnnotations.filter((ann) => idList.includes(ann._id));
|
|
201
222
|
}
|
|
202
223
|
const priorityMap = { 'urgente': 4, 'urgent': 4, 'alta': 3, 'high': 3, 'media': 2, 'medium': 2, 'baja': 1, 'low': 1 };
|
|
203
224
|
const sortedAnnotations = rawAnnotations.sort((a, b) => {
|
|
@@ -227,16 +248,16 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
227
248
|
line: ann.line || (line ? parseInt(line) : undefined),
|
|
228
249
|
vgId: ann.reference?.vgId,
|
|
229
250
|
outerHtml: ann.reference?.outerHtml,
|
|
230
|
-
_ia_fix_instruction: `### 🎯 DESIGN CONTEXT (Figma)
|
|
231
|
-
${ann.figmaReference ? `A design reference is available: ${ann.figmaReference}` : 'No explicit design linked.'}
|
|
232
|
-
|
|
233
|
-
${pendingCorrection ? `### ⚠️ PENDING CORRECTION\nUser feedback: "${pendingCorrection.text}"` : ''}
|
|
234
|
-
|
|
235
|
-
### 🔬 FIX PROTOCOL
|
|
236
|
-
1. **Target**: \`data-vg-id="${ann.reference?.vgId}"\` in \`${file}\`.
|
|
237
|
-
2. **Context**: \`${ann.reference?.parentContext?.slice(0, 50)}...\`
|
|
238
|
-
|
|
239
|
-
IMPORTANT: Respond in ${rawData.preferredLanguage === 'es' ? 'SPANISH' : 'ENGLISH'}.
|
|
251
|
+
_ia_fix_instruction: `### 🎯 DESIGN CONTEXT (Figma)
|
|
252
|
+
${ann.figmaReference ? `A design reference is available: ${ann.figmaReference}` : 'No explicit design linked.'}
|
|
253
|
+
|
|
254
|
+
${pendingCorrection ? `### ⚠️ PENDING CORRECTION\nUser feedback: "${pendingCorrection.text}"` : ''}
|
|
255
|
+
|
|
256
|
+
### 🔬 FIX PROTOCOL
|
|
257
|
+
1. **Target**: \`data-vg-id="${ann.reference?.vgId}"\` in \`${file}\`.
|
|
258
|
+
2. **Context**: \`${ann.reference?.parentContext?.slice(0, 50)}...\`
|
|
259
|
+
|
|
260
|
+
IMPORTANT: Respond in ${rawData.preferredLanguage === 'es' ? 'SPANISH' : 'ENGLISH'}.
|
|
240
261
|
Instruction: ${ann.message}`
|
|
241
262
|
};
|
|
242
263
|
});
|
|
@@ -307,9 +328,16 @@ Instruction: ${ann.message}`
|
|
|
307
328
|
method: 'PATCH',
|
|
308
329
|
headers: { 'x-api-key': apiKey, ...(personalKey ? { 'x-personal-key': personalKey } : {}) }
|
|
309
330
|
});
|
|
331
|
+
return { content: [{ type: "text", text: "Optimization marked as applied." }] };
|
|
332
|
+
}
|
|
333
|
+
case "get_ai_resolved_tickets": {
|
|
334
|
+
const response = await fetch(`${BACKEND_URL}/api/mcp/resolved-tickets`, {
|
|
335
|
+
headers: { 'x-api-key': apiKey, ...(personalKey ? { 'x-personal-key': personalKey } : {}) }
|
|
336
|
+
});
|
|
310
337
|
if (!response.ok)
|
|
311
338
|
throw new Error(`Backend responded with ${response.status}`);
|
|
312
|
-
|
|
339
|
+
const data = await response.json();
|
|
340
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
313
341
|
}
|
|
314
342
|
default:
|
|
315
343
|
throw new Error("Unknown tool");
|
package/dist/test_fix.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import fetch from "node-fetch";
|
|
2
|
+
async function test() {
|
|
3
|
+
console.log("1. Connecting to http://localhost:3333/sse...");
|
|
4
|
+
const response = await fetch("http://localhost:3333/sse?apiKey=2af5628c9442f10b93cfe6970897d4de26578d958ba43a4e3bcb684fe0f92668");
|
|
5
|
+
if (!response.ok) {
|
|
6
|
+
console.error("Failed to connect to SSE:", response.status, await response.text());
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
console.log("SSE connected. Reading stream for sessionId...");
|
|
10
|
+
const body = response.body;
|
|
11
|
+
let sessionId = null;
|
|
12
|
+
body.on("data", async (chunk) => {
|
|
13
|
+
const text = chunk.toString();
|
|
14
|
+
console.log("SSE Data:", text);
|
|
15
|
+
// Example event:
|
|
16
|
+
// event: endpoint
|
|
17
|
+
// data: /message?sessionId=...
|
|
18
|
+
const match = text.match(/sessionId=([a-f0-9-]+)/);
|
|
19
|
+
if (match && !sessionId) {
|
|
20
|
+
sessionId = match[1];
|
|
21
|
+
console.log("FOUND SESSION ID:", sessionId);
|
|
22
|
+
// 2. Test POST to /message
|
|
23
|
+
console.log(`2. Testing POST to /message?sessionId=${sessionId}...`);
|
|
24
|
+
const postResponse = await fetch(`http://localhost:3333/message?sessionId=${sessionId}`, {
|
|
25
|
+
method: 'POST',
|
|
26
|
+
headers: {
|
|
27
|
+
'Content-Type': 'application/json'
|
|
28
|
+
},
|
|
29
|
+
body: JSON.stringify({
|
|
30
|
+
jsonrpc: "2.0",
|
|
31
|
+
id: 1,
|
|
32
|
+
method: "initialize",
|
|
33
|
+
params: {
|
|
34
|
+
clientInfo: { name: "test-client", version: "1.0.0" },
|
|
35
|
+
protocolVersion: "2024-11-05",
|
|
36
|
+
capabilities: {}
|
|
37
|
+
}
|
|
38
|
+
})
|
|
39
|
+
});
|
|
40
|
+
console.log("POST Response Status:", postResponse.status);
|
|
41
|
+
const responseText = await postResponse.text();
|
|
42
|
+
console.log("POST Response Body:", responseText);
|
|
43
|
+
if (postResponse.status === 200 || postResponse.status === 202) {
|
|
44
|
+
console.log("SUCCESS: Stream was readable and message was accepted.");
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
console.error("FAILURE: Server returned error status.");
|
|
48
|
+
}
|
|
49
|
+
process.exit(0);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
setTimeout(() => {
|
|
53
|
+
if (!sessionId) {
|
|
54
|
+
console.error("TIMEOUT: Did not receive sessionId from SSE.");
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}, 10000);
|
|
58
|
+
}
|
|
59
|
+
test();
|
package/dist/test_sse.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import fetch from "node-fetch";
|
|
2
|
+
async function test() {
|
|
3
|
+
console.log("Connecting to http://localhost:3333/sse...");
|
|
4
|
+
const response = await fetch("http://localhost:3333/sse?apiKey=test-key");
|
|
5
|
+
if (!response.ok) {
|
|
6
|
+
console.error("Failed to connect:", response.status, await response.text());
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
console.log("Headers:", response.headers.raw());
|
|
10
|
+
const body = response.body;
|
|
11
|
+
body.on("data", (chunk) => {
|
|
12
|
+
console.log("Chunk received:", chunk.toString());
|
|
13
|
+
if (chunk.toString().includes("event: endpoint")) {
|
|
14
|
+
console.log("FOUND ENDPOINT EVENT!");
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
body.on("end", () => console.log("Connection closed"));
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
console.log("Closing test...");
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}, 5000);
|
|
22
|
+
}
|
|
23
|
+
test();
|