viewgate-mcp 1.0.48 → 1.0.50

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 +31 -13
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -53,6 +53,7 @@ function createMcpServer(apiKey, personalKey) {
53
53
  step: 0,
54
54
  startedAt: Date.now(),
55
55
  lastActivityAt: Date.now(),
56
+ lockTokens: {},
56
57
  };
57
58
  function resetGuard() {
58
59
  guard.flow = "idle";
@@ -60,6 +61,8 @@ function createMcpServer(apiKey, personalKey) {
60
61
  guard.lastTool = undefined;
61
62
  guard.startedAt = Date.now();
62
63
  guard.lastActivityAt = Date.now();
64
+ guard.lockTokens = {};
65
+ guard.backlogVersion = undefined;
63
66
  }
64
67
  function getToolFlow(toolName) {
65
68
  switch (toolName) {
@@ -99,6 +102,7 @@ function createMcpServer(apiKey, personalKey) {
99
102
  // Implicit flow reset if we are starting a new flow with a "start tool"
100
103
  switch (toolName) {
101
104
  case "get_ui_components":
105
+ case "mark_ui_component_generated":
102
106
  guard.flow = "ui_components";
103
107
  guard.step = 1;
104
108
  break;
@@ -139,18 +143,13 @@ function createMcpServer(apiKey, personalKey) {
139
143
  }
140
144
  if (guard.flow === "ui_components") {
141
145
  if (toolName === "get_ui_components") {
142
- if (guard.step > 2)
143
- throw new Error("TOOL_CALL_BLOCKED: cannot restart flow at this step");
144
146
  guard.step = 1;
145
147
  }
146
148
  else if (toolName === "generate_ui_components") {
147
- if (guard.step !== 1)
148
- throw new Error("TOOL_CALL_BLOCKED: unexpected step");
149
149
  guard.step = 2;
150
150
  }
151
151
  else if (toolName === "mark_ui_component_generated") {
152
- if (guard.step !== 2)
153
- throw new Error("TOOL_CALL_BLOCKED: unexpected step");
152
+ // Allow finishing if it was started in this flow
154
153
  resetGuard();
155
154
  }
156
155
  else {
@@ -533,7 +532,13 @@ function createMcpServer(apiKey, personalKey) {
533
532
  if (!Array.isArray(rawAnnotations)) {
534
533
  return { content: [{ type: "text", text: "Error: Invalid format from backend" }], isError: true };
535
534
  }
536
- console.error(`[MCP] Received ${rawAnnotations.length} annotations from backend.`);
535
+ // Point: Lease Collection | Store lockTokens in the session guard
536
+ rawAnnotations.forEach((ann) => {
537
+ if (ann._id && ann.lockToken) {
538
+ guard.lockTokens[ann._id] = ann.lockToken;
539
+ }
540
+ });
541
+ console.error(`[MCP] Received ${rawAnnotations.length} annotations. Tokens stored: ${Object.keys(guard.lockTokens).length}`);
537
542
  // Local filtering fallback (for older backend versions or additional client-side safety)
538
543
  if (search) {
539
544
  const lowSearch = search.toLowerCase();
@@ -617,7 +622,11 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
617
622
  'x-personal-key': personalKey || ''
618
623
  },
619
624
  body: JSON.stringify({
620
- results: results.map((r) => ({ ...r, status: 'applied' }))
625
+ results: results.map((r) => ({
626
+ ...r,
627
+ status: 'applied',
628
+ lockToken: guard.lockTokens[r.id] // Attach the session-locked token
629
+ }))
621
630
  })
622
631
  });
623
632
  if (!response.ok)
@@ -634,11 +643,18 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
634
643
  const response = await fetch(url, {
635
644
  method,
636
645
  headers: { 'Content-Type': 'application/json', 'x-api-key': apiKey, 'x-mcp-tool-name': toolName, ...(personalKey ? { 'x-personal-key': personalKey } : {}) },
637
- body: args.results ? JSON.stringify({ results: args.results, force: args.force }) : undefined
646
+ body: args.results ? JSON.stringify({
647
+ results: args.results,
648
+ force: args.force,
649
+ backlogVersion: guard.backlogVersion
650
+ }) : undefined
638
651
  });
639
652
  if (!response.ok)
640
653
  throw new Error(`Backend responded with ${response.status}`);
641
654
  const data = (await response.json());
655
+ // Point: Version Storing
656
+ if (data.backlogVersion)
657
+ guard.backlogVersion = data.backlogVersion;
642
658
  const langHint = data.preferredLanguage === 'es'
643
659
  ? "\n*** [INSTRUCTION: Project is in SPANISH. Provide all comments, appliedChanges, and aiAnalysis in SPANISH ONLY.] ***\n\n\n\n"
644
660
  : (data.preferredLanguage === 'en' ? "\n*** [INSTRUCTION: Provide all comments and analysis in English.] ***\n\n\n\n" : "");
@@ -667,15 +683,17 @@ Lang: ${rawData.preferredLanguage === 'es' ? 'ES' : 'EN'}
667
683
  ...(personalKey ? { 'x-personal-key': personalKey } : {})
668
684
  }
669
685
  });
670
- if (!response.ok) {
671
- const errorBody = await response.text();
672
- throw new Error(`Backend responded with ${response.status}: ${errorBody}`);
673
- }
674
686
  const rawData = (await response.json());
675
687
  let rawImprovements = Array.isArray(rawData) ? rawData : (rawData?.data || rawData?.improvements || []);
676
688
  if (!Array.isArray(rawImprovements)) {
677
689
  return { content: [{ type: "text", text: "Error: Invalid format from backend" }], isError: true };
678
690
  }
691
+ // Point: Lease Collection UI | Store lockTokens for UI tickets
692
+ rawImprovements.forEach((ann) => {
693
+ if (ann._id && ann.lockToken) {
694
+ guard.lockTokens[ann._id] = ann.lockToken;
695
+ }
696
+ });
679
697
  const improvementsWithTips = rawImprovements.map((ann) => {
680
698
  return {
681
699
  ...ann,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viewgate-mcp",
3
- "version": "1.0.48",
3
+ "version": "1.0.50",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "viewgate-mcp": "./dist/index.js"