viewgate-mcp 1.0.32 → 1.0.33
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 -28
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ import fetch from "node-fetch";
|
|
|
21
21
|
import cors from "cors";
|
|
22
22
|
import dotenv from "dotenv";
|
|
23
23
|
import path from "path";
|
|
24
|
+
import os from "os";
|
|
24
25
|
import { fileURLToPath } from "url";
|
|
25
26
|
const __filename = fileURLToPath(import.meta.url);
|
|
26
27
|
const __dirname = path.dirname(__filename);
|
|
@@ -29,6 +30,8 @@ const port = process.env.PORT || 3000;
|
|
|
29
30
|
const BACKEND_URL = process.env.BACKEND_URL || "https://view-gate.vercel.app";
|
|
30
31
|
console.error(`[MCP Config] BACKEND_URL: ${BACKEND_URL}`);
|
|
31
32
|
console.error(`[MCP Config] API_KEY Prefix: ${process.env.API_KEY?.substring(0, 5)}...`);
|
|
33
|
+
const agentId = `${os.hostname()}-${process.pid}`;
|
|
34
|
+
console.error(`[MCP Identity] Agent ID: ${agentId}`);
|
|
32
35
|
// Store active sessions for SSE: sessionId -> { server, transport }
|
|
33
36
|
const sessions = new Map();
|
|
34
37
|
/**
|
|
@@ -82,6 +85,21 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
82
85
|
required: ["results"]
|
|
83
86
|
},
|
|
84
87
|
},
|
|
88
|
+
{
|
|
89
|
+
name: "mark_annotations_as_live",
|
|
90
|
+
description: "Transitions annotations from 'applied' (local fix) to 'ready_for_review' (live on server). Call this tool ONLY after you have successfully deployed/uploaded your code changes.",
|
|
91
|
+
inputSchema: {
|
|
92
|
+
type: "object",
|
|
93
|
+
properties: {
|
|
94
|
+
ids: {
|
|
95
|
+
type: "array",
|
|
96
|
+
items: { type: "string" },
|
|
97
|
+
description: "List of internal database IDs to mark as live."
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
required: ["ids"]
|
|
101
|
+
},
|
|
102
|
+
},
|
|
85
103
|
{
|
|
86
104
|
name: "planning",
|
|
87
105
|
description: "Planning tool for backlog tickets. Fetch tickets or submit analysis.",
|
|
@@ -177,23 +195,27 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
177
195
|
let keysToFetch = [];
|
|
178
196
|
if (args.key)
|
|
179
197
|
keysToFetch = keysToFetch.concat(args.key.split(',').map(s => s.trim()));
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
const idsToFetch = args.ids || '';
|
|
198
|
+
const key = args.key;
|
|
199
|
+
const keys = args.keys;
|
|
200
|
+
const ids = args.ids;
|
|
184
201
|
const agentId = personalKey || 'mcp-agent-' + (apiKey?.slice(-6) || 'generic');
|
|
185
|
-
|
|
186
|
-
if (statuses && statuses !== 'all')
|
|
187
|
-
fetchUrl += `&status=${statuses}`;
|
|
202
|
+
const fetchUrl = new URL(`${BACKEND_URL}/api/mcp/annotations`);
|
|
188
203
|
if (limit)
|
|
189
|
-
fetchUrl
|
|
204
|
+
fetchUrl.searchParams.append("limit", limit.toString());
|
|
205
|
+
if (statuses)
|
|
206
|
+
fetchUrl.searchParams.append("status", statuses);
|
|
190
207
|
if (search)
|
|
191
|
-
fetchUrl
|
|
192
|
-
if (
|
|
193
|
-
fetchUrl
|
|
194
|
-
if (
|
|
195
|
-
fetchUrl
|
|
196
|
-
|
|
208
|
+
fetchUrl.searchParams.append("search", search);
|
|
209
|
+
if (key)
|
|
210
|
+
fetchUrl.searchParams.append("key", key);
|
|
211
|
+
if (ids)
|
|
212
|
+
fetchUrl.searchParams.append("ids", ids);
|
|
213
|
+
if (keys && keys.length > 0)
|
|
214
|
+
fetchUrl.searchParams.append("keys", keys.join(","));
|
|
215
|
+
// Add lock and agentId parameters
|
|
216
|
+
fetchUrl.searchParams.append("lock", "true");
|
|
217
|
+
fetchUrl.searchParams.append("agentId", agentId);
|
|
218
|
+
console.error(`[get_annotations] Fetching: ${fetchUrl.toString()}`);
|
|
197
219
|
const response = await fetch(fetchUrl, {
|
|
198
220
|
headers: {
|
|
199
221
|
'x-api-key': apiKey,
|
|
@@ -217,10 +239,11 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
217
239
|
(ann.reference?.source && ann.reference.source.toLowerCase().includes(lowSearch)) ||
|
|
218
240
|
(ann.key && ann.key.toLowerCase().includes(lowSearch)));
|
|
219
241
|
}
|
|
242
|
+
const combinedKey = key || (keys && keys.join(','));
|
|
220
243
|
if (combinedKey) {
|
|
221
244
|
// Normalize keyList for case-insensitive matching and handle VG- prefix
|
|
222
|
-
const keyList = combinedKey.split(',').map(k => k.trim().toUpperCase());
|
|
223
|
-
const baseKeys = keyList.map(k => k.startsWith('VG-') ? k.substring(3) : k);
|
|
245
|
+
const keyList = combinedKey.split(',').map((k) => k.trim().toUpperCase());
|
|
246
|
+
const baseKeys = keyList.map((k) => k.startsWith('VG-') ? k.substring(3) : k);
|
|
224
247
|
rawAnnotations = rawAnnotations.filter((ann) => {
|
|
225
248
|
if (!ann.key)
|
|
226
249
|
return keyList.includes(ann._id);
|
|
@@ -232,8 +255,8 @@ function createMcpServer(apiKey, personalKey) {
|
|
|
232
255
|
});
|
|
233
256
|
console.error(`[MCP] Filtered with keys. Remaining: ${rawAnnotations.length}`);
|
|
234
257
|
}
|
|
235
|
-
if (
|
|
236
|
-
const idList =
|
|
258
|
+
if (ids) {
|
|
259
|
+
const idList = ids.split(',').map((i) => i.trim());
|
|
237
260
|
rawAnnotations = rawAnnotations.filter((ann) => idList.includes(ann._id));
|
|
238
261
|
console.error(`[MCP] Filtered with IDs. Remaining: ${rawAnnotations.length}`);
|
|
239
262
|
}
|
|
@@ -293,19 +316,45 @@ Instruction: ${ann.message}`
|
|
|
293
316
|
}
|
|
294
317
|
case "mark_annotation_ready": {
|
|
295
318
|
const args = request.params.arguments;
|
|
296
|
-
|
|
297
|
-
console.error(`[
|
|
319
|
+
const results = args.results;
|
|
320
|
+
console.error(`[mark_annotation_ready] Submitting results for ${results?.length} items`);
|
|
298
321
|
const response = await fetch(`${BACKEND_URL}/api/mcp/annotations/batch-ready`, {
|
|
299
322
|
method: 'PATCH',
|
|
300
|
-
headers: {
|
|
301
|
-
|
|
323
|
+
headers: {
|
|
324
|
+
'Content-Type': 'application/json',
|
|
325
|
+
'x-api-key': apiKey,
|
|
326
|
+
'x-personal-key': personalKey || ''
|
|
327
|
+
},
|
|
328
|
+
body: JSON.stringify({
|
|
329
|
+
results: results.map((r) => ({ ...r, status: 'applied' }))
|
|
330
|
+
})
|
|
302
331
|
});
|
|
303
|
-
if (!response.ok)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
332
|
+
if (!response.ok)
|
|
333
|
+
throw new Error(`Backend responded with ${response.status}`);
|
|
334
|
+
const data = await response.json();
|
|
335
|
+
return {
|
|
336
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
case "mark_annotations_as_live": {
|
|
340
|
+
const args = request.params.arguments;
|
|
341
|
+
const ids = args.ids;
|
|
342
|
+
console.error(`[mark_annotations_as_live] Marking ${ids?.length} items as live`);
|
|
343
|
+
const response = await fetch(`${BACKEND_URL}/api/mcp/annotations/mark-as-live`, {
|
|
344
|
+
method: 'POST',
|
|
345
|
+
headers: {
|
|
346
|
+
'Content-Type': 'application/json',
|
|
347
|
+
'x-api-key': apiKey,
|
|
348
|
+
'x-personal-key': personalKey || ''
|
|
349
|
+
},
|
|
350
|
+
body: JSON.stringify({ ids })
|
|
351
|
+
});
|
|
352
|
+
if (!response.ok)
|
|
353
|
+
throw new Error(`Backend responded with ${response.status}`);
|
|
354
|
+
const data = await response.json();
|
|
355
|
+
return {
|
|
356
|
+
content: [{ type: "text", text: JSON.stringify(data, null, 2) }],
|
|
357
|
+
};
|
|
309
358
|
}
|
|
310
359
|
case "planning": {
|
|
311
360
|
const args = request.params.arguments;
|