@insforge/mcp 1.1.7-dev.3 → 1.1.7-dev.31

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.
@@ -4,6 +4,9 @@
4
4
  import { z as z14 } from "zod";
5
5
  import fetch2 from "node-fetch";
6
6
  import { promises as fs } from "fs";
7
+ import { exec } from "child_process";
8
+ import { promisify } from "util";
9
+ import { tmpdir } from "os";
7
10
 
8
11
  // src/shared/response-handler.ts
9
12
  async function handleApiResponse(response) {
@@ -735,10 +738,77 @@ var functionUpdateRequestSchema = z13.object({
735
738
 
736
739
  // src/shared/tools.ts
737
740
  import FormData from "form-data";
741
+ var execAsync = promisify(exec);
742
+ var TOOL_VERSION_REQUIREMENTS = {
743
+ "upsert-schedule": "1.1.1",
744
+ // 'get-schedules': '1.1.1',
745
+ // 'get-schedule-logs': '1.1.1',
746
+ "delete-schedule": "1.1.1"
747
+ };
738
748
  function registerInsforgeTools(server, config = {}) {
739
749
  const GLOBAL_API_KEY = config.apiKey || process.env.API_KEY || "";
740
750
  const API_BASE_URL = config.apiBaseUrl || process.env.API_BASE_URL || "http://localhost:7130";
741
751
  const usageTracker = new UsageTracker(API_BASE_URL, GLOBAL_API_KEY);
752
+ let versionCache = null;
753
+ const VERSION_CACHE_TTL = 5 * 60 * 1e3;
754
+ async function getBackendVersion() {
755
+ const now = Date.now();
756
+ if (versionCache && now - versionCache.timestamp < VERSION_CACHE_TTL) {
757
+ return versionCache.version;
758
+ }
759
+ try {
760
+ const response = await fetch2(`${API_BASE_URL}/api/health`, {
761
+ method: "GET",
762
+ headers: {
763
+ "Content-Type": "application/json"
764
+ }
765
+ });
766
+ if (!response.ok) {
767
+ throw new Error(`Health check failed with status ${response.status}`);
768
+ }
769
+ const health = await response.json();
770
+ versionCache = {
771
+ version: health.version,
772
+ timestamp: now
773
+ };
774
+ return health.version;
775
+ } catch (error) {
776
+ const errMsg = error instanceof Error ? error.message : "Unknown error";
777
+ throw new Error(`Failed to fetch backend version: ${errMsg}`);
778
+ }
779
+ }
780
+ function compareVersions(v1, v2) {
781
+ const clean1 = v1.replace(/^v/, "");
782
+ const clean2 = v2.replace(/^v/, "");
783
+ const parts1 = clean1.split(".").map(Number);
784
+ const parts2 = clean2.split(".").map(Number);
785
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
786
+ const part1 = parts1[i] || 0;
787
+ const part2 = parts2[i] || 0;
788
+ if (part1 > part2) return 1;
789
+ if (part1 < part2) return -1;
790
+ }
791
+ return 0;
792
+ }
793
+ async function checkToolVersion(toolName) {
794
+ const requiredVersion = TOOL_VERSION_REQUIREMENTS[toolName];
795
+ if (!requiredVersion) {
796
+ return;
797
+ }
798
+ try {
799
+ const currentVersion = await getBackendVersion();
800
+ if (compareVersions(currentVersion, requiredVersion) < 0) {
801
+ throw new Error(
802
+ `Tool '${toolName}' requires backend version ${requiredVersion} or higher, but current version is ${currentVersion}. Please upgrade your Insforge backend server.`
803
+ );
804
+ }
805
+ } catch (error) {
806
+ if (error instanceof Error && error.message.includes("requires backend version")) {
807
+ throw error;
808
+ }
809
+ console.warn(`Warning: Could not verify backend version for tool '${toolName}': ${error instanceof Error ? error.message : "Unknown error"}`);
810
+ }
811
+ }
742
812
  async function trackToolUsage(toolName, success = true) {
743
813
  if (GLOBAL_API_KEY) {
744
814
  await usageTracker.trackUsage(toolName, success);
@@ -770,10 +840,14 @@ function registerInsforgeTools(server, config = {}) {
770
840
  "Content-Type": "application/json"
771
841
  }
772
842
  });
843
+ if (response.status === 404) {
844
+ throw new Error("Documentation not found");
845
+ }
773
846
  const result = await handleApiResponse(response);
774
847
  if (result && typeof result === "object" && "content" in result) {
775
848
  let content = result.content;
776
849
  content = content.replace(/http:\/\/localhost:7130/g, API_BASE_URL);
850
+ content = content.replace(/https:\/\/your-app\.region\.insforge\.app/g, API_BASE_URL);
777
851
  return content;
778
852
  }
779
853
  throw new Error("Invalid response format from documentation endpoint");
@@ -782,25 +856,106 @@ function registerInsforgeTools(server, config = {}) {
782
856
  throw new Error(`Unable to retrieve ${docType} documentation: ${errMsg}`);
783
857
  }
784
858
  };
859
+ const fetchInsforgeInstructionsContext = async () => {
860
+ try {
861
+ return await fetchDocumentation("instructions");
862
+ } catch (error) {
863
+ console.error("Failed to fetch insforge-instructions.md:", error);
864
+ return null;
865
+ }
866
+ };
867
+ const addBackgroundContext = async (response) => {
868
+ try {
869
+ const currentVersion = await getBackendVersion();
870
+ const isLegacyVersion = compareVersions(currentVersion, "1.1.7") < 0;
871
+ if (isLegacyVersion) {
872
+ const context = await fetchInsforgeInstructionsContext();
873
+ if (context && response.content && Array.isArray(response.content)) {
874
+ response.content.push({
875
+ type: "text",
876
+ text: `
877
+
878
+ ---
879
+ \u{1F527} INSFORGE DEVELOPMENT RULES (Auto-loaded):
880
+ ${context}`
881
+ });
882
+ }
883
+ }
884
+ } catch {
885
+ console.warn("Could not determine backend version, skipping background context");
886
+ }
887
+ return response;
888
+ };
785
889
  server.tool(
786
- "get-instructions",
787
- "Instruction Essential backend setup tool. <critical>MANDATORY: You MUST use this tool FIRST before attempting any backend operations. Contains required API endpoints, authentication details, and setup instructions.</critical>",
788
- {},
789
- withUsageTracking("get-instructions", async () => {
890
+ "fetch-docs",
891
+ 'Fetch Insforge documentation. Use "instructions" for essential backend setup (MANDATORY FIRST), or select specific SDK docs for database, auth, storage, functions, or AI integration.',
892
+ {
893
+ docType: z14.enum(["instructions", "db-sdk", "storage-sdk", "functions-sdk", "ai-integration-sdk", "auth-components-react"]).describe(
894
+ 'Documentation type: "instructions" (essential backend setup - use FIRST), "db-sdk" (database operations), "storage-sdk" (file storage), "functions-sdk" (edge functions), "ai-integration-sdk" (AI features), "auth-components-react" (authentication components for React+Vite applications,'
895
+ )
896
+ },
897
+ withUsageTracking("fetch-docs", async ({ docType }) => {
790
898
  try {
791
- const content = await fetchDocumentation("instructions");
792
- return {
899
+ const content = await fetchDocumentation(docType);
900
+ return await addBackgroundContext({
793
901
  content: [
794
902
  {
795
903
  type: "text",
796
904
  text: content
797
905
  }
798
906
  ]
907
+ });
908
+ } catch (error) {
909
+ const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
910
+ if (errMsg.includes("404") || errMsg.toLowerCase().includes("not found")) {
911
+ return {
912
+ content: [{
913
+ type: "text",
914
+ text: `Documentation for "${docType}" is not available. This is likely because your backend version is too old and doesn't support this documentation endpoint yet. This won't affect the functionality of the tools - they will still work correctly.`
915
+ }]
916
+ };
917
+ }
918
+ return {
919
+ content: [{ type: "text", text: `Error fetching ${docType} documentation: ${errMsg}` }]
799
920
  };
921
+ }
922
+ })
923
+ );
924
+ server.tool(
925
+ "get-anon-key",
926
+ "Generate an anonymous JWT token that never expires. Requires admin API key. Use this for client-side applications that need public access.",
927
+ {
928
+ apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)")
929
+ },
930
+ withUsageTracking("get-anon-key", async ({ apiKey }) => {
931
+ try {
932
+ const actualApiKey = getApiKey(apiKey);
933
+ const response = await fetch2(`${API_BASE_URL}/api/auth/tokens/anon`, {
934
+ method: "POST",
935
+ headers: {
936
+ "x-api-key": actualApiKey,
937
+ "Content-Type": "application/json"
938
+ }
939
+ });
940
+ const result = await handleApiResponse(response);
941
+ return await addBackgroundContext({
942
+ content: [
943
+ {
944
+ type: "text",
945
+ text: formatSuccessMessage("Anonymous token generated", result)
946
+ }
947
+ ]
948
+ });
800
949
  } catch (error) {
801
950
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
802
951
  return {
803
- content: [{ type: "text", text: `Error: ${errMsg}` }]
952
+ content: [
953
+ {
954
+ type: "text",
955
+ text: `Error generating anonymous token: ${errMsg}`
956
+ }
957
+ ],
958
+ isError: true
804
959
  };
805
960
  }
806
961
  })
@@ -822,14 +977,14 @@ function registerInsforgeTools(server, config = {}) {
822
977
  }
823
978
  });
824
979
  const result = await handleApiResponse(response);
825
- return {
980
+ return await addBackgroundContext({
826
981
  content: [
827
982
  {
828
983
  type: "text",
829
984
  text: formatSuccessMessage("Schema retrieved", result)
830
985
  }
831
986
  ]
832
- };
987
+ });
833
988
  } catch (error) {
834
989
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
835
990
  return {
@@ -860,7 +1015,7 @@ function registerInsforgeTools(server, config = {}) {
860
1015
  }
861
1016
  });
862
1017
  const metadata = await handleApiResponse(response);
863
- return {
1018
+ return await addBackgroundContext({
864
1019
  content: [
865
1020
  {
866
1021
  type: "text",
@@ -869,7 +1024,7 @@ function registerInsforgeTools(server, config = {}) {
869
1024
  ${JSON.stringify(metadata, null, 2)}`
870
1025
  }
871
1026
  ]
872
- };
1027
+ });
873
1028
  } catch (error) {
874
1029
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
875
1030
  return {
@@ -907,14 +1062,14 @@ ${JSON.stringify(metadata, null, 2)}`
907
1062
  body: JSON.stringify(requestBody)
908
1063
  });
909
1064
  const result = await handleApiResponse(response);
910
- return {
1065
+ return await addBackgroundContext({
911
1066
  content: [
912
1067
  {
913
1068
  type: "text",
914
1069
  text: formatSuccessMessage("SQL query executed", result)
915
1070
  }
916
1071
  ]
917
- };
1072
+ });
918
1073
  } catch (error) {
919
1074
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
920
1075
  return {
@@ -929,9 +1084,85 @@ ${JSON.stringify(metadata, null, 2)}`
929
1084
  }
930
1085
  })
931
1086
  );
1087
+ server.tool(
1088
+ "download-template",
1089
+ "CRITICAL: MANDATORY FIRST STEP for all new InsForge projects. Download pre-configured starter template (React) to a temporary directory. After download, you MUST copy files to current directory using the provided command.",
1090
+ {
1091
+ frame: z14.enum(["react"]).describe("Framework to use for the template (currently only React is supported)"),
1092
+ projectName: z14.string().optional().describe('Name for the project directory (optional, defaults to "insforge-react")')
1093
+ },
1094
+ withUsageTracking("download-template", async ({ frame, projectName }) => {
1095
+ try {
1096
+ const response = await fetch2(`${API_BASE_URL}/api/auth/tokens/anon`, {
1097
+ method: "POST",
1098
+ headers: {
1099
+ "x-api-key": getApiKey(),
1100
+ "Content-Type": "application/json"
1101
+ }
1102
+ });
1103
+ const result = await handleApiResponse(response);
1104
+ const anonKey = result.accessToken;
1105
+ if (!anonKey) {
1106
+ throw new Error("Failed to retrieve anon key from backend");
1107
+ }
1108
+ const tempDir = tmpdir();
1109
+ const targetDir = projectName || `insforge-${frame}`;
1110
+ const templatePath = `${tempDir}/${targetDir}`;
1111
+ console.error(`[download-template] Target path: ${templatePath}`);
1112
+ try {
1113
+ const stats = await fs.stat(templatePath);
1114
+ if (stats.isDirectory()) {
1115
+ console.error(`[download-template] Removing existing template at ${templatePath}`);
1116
+ await fs.rm(templatePath, { recursive: true, force: true });
1117
+ }
1118
+ } catch {
1119
+ }
1120
+ const command = `npx create-insforge-app ${targetDir} --frame ${frame} --base-url ${API_BASE_URL} --anon-key ${anonKey} --skip-install`;
1121
+ const { stdout, stderr } = await execAsync(command, {
1122
+ maxBuffer: 10 * 1024 * 1024,
1123
+ // 10MB buffer
1124
+ cwd: tempDir
1125
+ });
1126
+ const output = stdout || stderr || "";
1127
+ if (output.toLowerCase().includes("error") && !output.includes("successfully")) {
1128
+ throw new Error(`Failed to download template: ${output}`);
1129
+ }
1130
+ return await addBackgroundContext({
1131
+ content: [
1132
+ {
1133
+ type: "text",
1134
+ text: `\u2705 React template downloaded successfully
1135
+
1136
+ \u{1F4C1} Template Location: ${templatePath}
1137
+
1138
+ \u26A0\uFE0F IMPORTANT: The template is in a temporary directory and NOT in your current working directory.
1139
+
1140
+ \u{1F534} CRITICAL NEXT STEP REQUIRED:
1141
+ You MUST copy ALL files (INCLUDING HIDDEN FILES like .env, .gitignore, etc.) from the temporary directory to your current project directory.
1142
+
1143
+ Copy all files from: ${templatePath}
1144
+ To: Your current project directory
1145
+ `
1146
+ }
1147
+ ]
1148
+ });
1149
+ } catch (error) {
1150
+ const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1151
+ return {
1152
+ content: [
1153
+ {
1154
+ type: "text",
1155
+ text: `Error downloading template: ${errMsg}`
1156
+ }
1157
+ ],
1158
+ isError: true
1159
+ };
1160
+ }
1161
+ })
1162
+ );
932
1163
  server.tool(
933
1164
  "bulk-upsert",
934
- "Bulk insert or update data from CSV or JSON file. Supports upsert operations with a unique key.",
1165
+ "Bulk insert or updallet data from CSV or JSON file. Supports upsert operations with a unique key.",
935
1166
  {
936
1167
  apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)"),
937
1168
  ...bulkUpsertRequestSchema.shape,
@@ -958,7 +1189,7 @@ ${JSON.stringify(metadata, null, 2)}`
958
1189
  });
959
1190
  const result = await handleApiResponse(response);
960
1191
  const message = result.success ? `Successfully processed ${result.rowsAffected} of ${result.totalRecords} records into table "${result.table}"` : result.message || "Bulk upsert operation completed";
961
- return {
1192
+ return await addBackgroundContext({
962
1193
  content: [
963
1194
  {
964
1195
  type: "text",
@@ -971,7 +1202,7 @@ ${JSON.stringify(metadata, null, 2)}`
971
1202
  })
972
1203
  }
973
1204
  ]
974
- };
1205
+ });
975
1206
  } catch (error) {
976
1207
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
977
1208
  return {
@@ -1005,14 +1236,14 @@ ${JSON.stringify(metadata, null, 2)}`
1005
1236
  body: JSON.stringify({ bucketName, isPublic })
1006
1237
  });
1007
1238
  const result = await handleApiResponse(response);
1008
- return {
1239
+ return await addBackgroundContext({
1009
1240
  content: [
1010
1241
  {
1011
1242
  type: "text",
1012
1243
  text: formatSuccessMessage("Bucket created", result)
1013
1244
  }
1014
1245
  ]
1015
- };
1246
+ });
1016
1247
  } catch (error) {
1017
1248
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1018
1249
  return {
@@ -1040,14 +1271,14 @@ ${JSON.stringify(metadata, null, 2)}`
1040
1271
  }
1041
1272
  });
1042
1273
  const result = await handleApiResponse(response);
1043
- return {
1274
+ return await addBackgroundContext({
1044
1275
  content: [
1045
1276
  {
1046
1277
  type: "text",
1047
1278
  text: formatSuccessMessage("Buckets retrieved", result)
1048
1279
  }
1049
1280
  ]
1050
- };
1281
+ });
1051
1282
  } catch (error) {
1052
1283
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1053
1284
  return {
@@ -1079,14 +1310,14 @@ ${JSON.stringify(metadata, null, 2)}`
1079
1310
  }
1080
1311
  });
1081
1312
  const result = await handleApiResponse(response);
1082
- return {
1313
+ return await addBackgroundContext({
1083
1314
  content: [
1084
1315
  {
1085
1316
  type: "text",
1086
1317
  text: formatSuccessMessage("Bucket deleted", result)
1087
1318
  }
1088
1319
  ]
1089
- };
1320
+ });
1090
1321
  } catch (error) {
1091
1322
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1092
1323
  return {
@@ -1135,7 +1366,7 @@ ${JSON.stringify(metadata, null, 2)}`
1135
1366
  })
1136
1367
  });
1137
1368
  const result = await handleApiResponse(response);
1138
- return {
1369
+ return await addBackgroundContext({
1139
1370
  content: [
1140
1371
  {
1141
1372
  type: "text",
@@ -1145,7 +1376,7 @@ ${JSON.stringify(metadata, null, 2)}`
1145
1376
  )
1146
1377
  }
1147
1378
  ]
1148
- };
1379
+ });
1149
1380
  } catch (error) {
1150
1381
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1151
1382
  return {
@@ -1175,14 +1406,14 @@ ${JSON.stringify(metadata, null, 2)}`
1175
1406
  }
1176
1407
  });
1177
1408
  const result = await handleApiResponse(response);
1178
- return {
1409
+ return await addBackgroundContext({
1179
1410
  content: [
1180
1411
  {
1181
1412
  type: "text",
1182
1413
  text: formatSuccessMessage(`Edge function '${args.slug}' details`, result)
1183
1414
  }
1184
1415
  ]
1185
- };
1416
+ });
1186
1417
  } catch (error) {
1187
1418
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1188
1419
  return {
@@ -1238,7 +1469,7 @@ ${JSON.stringify(metadata, null, 2)}`
1238
1469
  });
1239
1470
  const result = await handleApiResponse(response);
1240
1471
  const fileInfo = args.codeFile ? ` from ${args.codeFile}` : "";
1241
- return {
1472
+ return await addBackgroundContext({
1242
1473
  content: [
1243
1474
  {
1244
1475
  type: "text",
@@ -1248,7 +1479,7 @@ ${JSON.stringify(metadata, null, 2)}`
1248
1479
  )
1249
1480
  }
1250
1481
  ]
1251
- };
1482
+ });
1252
1483
  } catch (error) {
1253
1484
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1254
1485
  return {
@@ -1278,14 +1509,14 @@ ${JSON.stringify(metadata, null, 2)}`
1278
1509
  }
1279
1510
  });
1280
1511
  const result = await handleApiResponse(response);
1281
- return {
1512
+ return await addBackgroundContext({
1282
1513
  content: [
1283
1514
  {
1284
1515
  type: "text",
1285
1516
  text: formatSuccessMessage(`Edge function '${args.slug}' deleted successfully`, result)
1286
1517
  }
1287
1518
  ]
1288
- };
1519
+ });
1289
1520
  } catch (error) {
1290
1521
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1291
1522
  return {
@@ -1313,21 +1544,29 @@ ${JSON.stringify(metadata, null, 2)}`
1313
1544
  const actualApiKey = getApiKey(apiKey);
1314
1545
  const queryParams = new URLSearchParams();
1315
1546
  if (limit) queryParams.append("limit", limit.toString());
1316
- const response = await fetch2(`${API_BASE_URL}/api/logs/analytics/${source}?${queryParams}`, {
1547
+ let response = await fetch2(`${API_BASE_URL}/api/logs/${source}?${queryParams}`, {
1317
1548
  method: "GET",
1318
1549
  headers: {
1319
1550
  "x-api-key": actualApiKey
1320
1551
  }
1321
1552
  });
1553
+ if (response.status === 404) {
1554
+ response = await fetch2(`${API_BASE_URL}/api/logs/analytics/${source}?${queryParams}`, {
1555
+ method: "GET",
1556
+ headers: {
1557
+ "x-api-key": actualApiKey
1558
+ }
1559
+ });
1560
+ }
1322
1561
  const result = await handleApiResponse(response);
1323
- return {
1562
+ return await addBackgroundContext({
1324
1563
  content: [
1325
1564
  {
1326
1565
  type: "text",
1327
1566
  text: formatSuccessMessage(`Latest logs from ${source}`, result)
1328
1567
  }
1329
1568
  ]
1330
- };
1569
+ });
1331
1570
  } catch (error) {
1332
1571
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1333
1572
  return {
@@ -1345,7 +1584,7 @@ ${JSON.stringify(metadata, null, 2)}`
1345
1584
  return {
1346
1585
  apiKey: GLOBAL_API_KEY,
1347
1586
  apiBaseUrl: API_BASE_URL,
1348
- toolCount: 14
1587
+ toolCount: 15
1349
1588
  };
1350
1589
  }
1351
1590
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  registerInsforgeTools
4
- } from "./chunk-CLLI7UFN.js";
4
+ } from "./chunk-TOH3XKIT.js";
5
5
 
6
6
  // src/http/server.ts
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  registerInsforgeTools
4
- } from "./chunk-CLLI7UFN.js";
4
+ } from "./chunk-TOH3XKIT.js";
5
5
 
6
6
  // src/stdio/index.ts
7
7
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@insforge/mcp",
3
- "version": "1.1.7-dev.3",
3
+ "version": "1.1.7-dev.31",
4
4
  "description": "MCP (Model Context Protocol) server for Insforge backend-as-a-service",
5
+ "mcpName": "io.github.InsForge/insforge-mcp",
5
6
  "type": "module",
6
7
  "main": "dist/index.js",
7
8
  "bin": {
@@ -31,7 +32,8 @@
31
32
  },
32
33
  "files": [
33
34
  "dist",
34
- "mcp.json"
35
+ "mcp.json",
36
+ "server.json"
35
37
  ],
36
38
  "dependencies": {
37
39
  "@insforge/shared-schemas": "^1.1.7",
package/server.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-10-17/server.schema.json",
3
+ "name": "io.github.InsForge/insforge-mcp",
4
+ "title": "Insforge",
5
+ "description": "MCP server for Insforge BaaS - database, auth, storage, edge functions, and container logs",
6
+ "version": "1.1.5",
7
+ "packages": [
8
+ {
9
+ "registryType": "npm",
10
+ "identifier": "@insforge/mcp",
11
+ "version": "1.1.5",
12
+ "transport": {
13
+ "type": "stdio"
14
+ }
15
+ }
16
+ ]
17
+ }