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

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,75 @@ 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 parts1 = v1.split(".").map(Number);
782
+ const parts2 = v2.split(".").map(Number);
783
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
784
+ const part1 = parts1[i] || 0;
785
+ const part2 = parts2[i] || 0;
786
+ if (part1 > part2) return 1;
787
+ if (part1 < part2) return -1;
788
+ }
789
+ return 0;
790
+ }
791
+ async function checkToolVersion(toolName) {
792
+ const requiredVersion = TOOL_VERSION_REQUIREMENTS[toolName];
793
+ if (!requiredVersion) {
794
+ return;
795
+ }
796
+ try {
797
+ const currentVersion = await getBackendVersion();
798
+ if (compareVersions(currentVersion, requiredVersion) < 0) {
799
+ throw new Error(
800
+ `Tool '${toolName}' requires backend version ${requiredVersion} or higher, but current version is ${currentVersion}. Please upgrade your Insforge backend server.`
801
+ );
802
+ }
803
+ } catch (error) {
804
+ if (error instanceof Error && error.message.includes("requires backend version")) {
805
+ throw error;
806
+ }
807
+ console.warn(`Warning: Could not verify backend version for tool '${toolName}': ${error instanceof Error ? error.message : "Unknown error"}`);
808
+ }
809
+ }
742
810
  async function trackToolUsage(toolName, success = true) {
743
811
  if (GLOBAL_API_KEY) {
744
812
  await usageTracker.trackUsage(toolName, success);
@@ -770,10 +838,14 @@ function registerInsforgeTools(server, config = {}) {
770
838
  "Content-Type": "application/json"
771
839
  }
772
840
  });
841
+ if (response.status === 404) {
842
+ throw new Error("Documentation not found");
843
+ }
773
844
  const result = await handleApiResponse(response);
774
845
  if (result && typeof result === "object" && "content" in result) {
775
846
  let content = result.content;
776
847
  content = content.replace(/http:\/\/localhost:7130/g, API_BASE_URL);
848
+ content = content.replace(/https:\/\/your-app\.region\.insforge\.app/g, API_BASE_URL);
777
849
  return content;
778
850
  }
779
851
  throw new Error("Invalid response format from documentation endpoint");
@@ -782,25 +854,106 @@ function registerInsforgeTools(server, config = {}) {
782
854
  throw new Error(`Unable to retrieve ${docType} documentation: ${errMsg}`);
783
855
  }
784
856
  };
857
+ const fetchInsforgeInstructionsContext = async () => {
858
+ try {
859
+ return await fetchDocumentation("instructions");
860
+ } catch (error) {
861
+ console.error("Failed to fetch insforge-instructions.md:", error);
862
+ return null;
863
+ }
864
+ };
865
+ const addBackgroundContext = async (response) => {
866
+ try {
867
+ const currentVersion = await getBackendVersion();
868
+ const isLegacyVersion = compareVersions(currentVersion, "1.1.7") < 0;
869
+ if (isLegacyVersion) {
870
+ const context = await fetchInsforgeInstructionsContext();
871
+ if (context && response.content && Array.isArray(response.content)) {
872
+ response.content.push({
873
+ type: "text",
874
+ text: `
875
+
876
+ ---
877
+ \u{1F527} INSFORGE DEVELOPMENT RULES (Auto-loaded):
878
+ ${context}`
879
+ });
880
+ }
881
+ }
882
+ } catch {
883
+ console.warn("Could not determine backend version, skipping background context");
884
+ }
885
+ return response;
886
+ };
785
887
  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 () => {
888
+ "fetch-docs",
889
+ 'Fetch Insforge documentation. Use "instructions" for essential backend setup (MANDATORY FIRST), or select specific SDK docs for database, auth, storage, functions, or AI integration.',
890
+ {
891
+ docType: z14.enum(["instructions", "db-sdk", "storage-sdk", "functions-sdk", "ai-integration-sdk", "auth-components-react"]).describe(
892
+ '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,'
893
+ )
894
+ },
895
+ withUsageTracking("fetch-docs", async ({ docType }) => {
790
896
  try {
791
- const content = await fetchDocumentation("instructions");
792
- return {
897
+ const content = await fetchDocumentation(docType);
898
+ return await addBackgroundContext({
793
899
  content: [
794
900
  {
795
901
  type: "text",
796
902
  text: content
797
903
  }
798
904
  ]
905
+ });
906
+ } catch (error) {
907
+ const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
908
+ if (errMsg.includes("404") || errMsg.toLowerCase().includes("not found")) {
909
+ return {
910
+ content: [{
911
+ type: "text",
912
+ 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.`
913
+ }]
914
+ };
915
+ }
916
+ return {
917
+ content: [{ type: "text", text: `Error fetching ${docType} documentation: ${errMsg}` }]
799
918
  };
919
+ }
920
+ })
921
+ );
922
+ server.tool(
923
+ "get-anon-key",
924
+ "Generate an anonymous JWT token that never expires. Requires admin API key. Use this for client-side applications that need public access.",
925
+ {
926
+ apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)")
927
+ },
928
+ withUsageTracking("get-anon-key", async ({ apiKey }) => {
929
+ try {
930
+ const actualApiKey = getApiKey(apiKey);
931
+ const response = await fetch2(`${API_BASE_URL}/api/auth/tokens/anon`, {
932
+ method: "POST",
933
+ headers: {
934
+ "x-api-key": actualApiKey,
935
+ "Content-Type": "application/json"
936
+ }
937
+ });
938
+ const result = await handleApiResponse(response);
939
+ return await addBackgroundContext({
940
+ content: [
941
+ {
942
+ type: "text",
943
+ text: formatSuccessMessage("Anonymous token generated", result)
944
+ }
945
+ ]
946
+ });
800
947
  } catch (error) {
801
948
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
802
949
  return {
803
- content: [{ type: "text", text: `Error: ${errMsg}` }]
950
+ content: [
951
+ {
952
+ type: "text",
953
+ text: `Error generating anonymous token: ${errMsg}`
954
+ }
955
+ ],
956
+ isError: true
804
957
  };
805
958
  }
806
959
  })
@@ -822,14 +975,14 @@ function registerInsforgeTools(server, config = {}) {
822
975
  }
823
976
  });
824
977
  const result = await handleApiResponse(response);
825
- return {
978
+ return await addBackgroundContext({
826
979
  content: [
827
980
  {
828
981
  type: "text",
829
982
  text: formatSuccessMessage("Schema retrieved", result)
830
983
  }
831
984
  ]
832
- };
985
+ });
833
986
  } catch (error) {
834
987
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
835
988
  return {
@@ -860,7 +1013,7 @@ function registerInsforgeTools(server, config = {}) {
860
1013
  }
861
1014
  });
862
1015
  const metadata = await handleApiResponse(response);
863
- return {
1016
+ return await addBackgroundContext({
864
1017
  content: [
865
1018
  {
866
1019
  type: "text",
@@ -869,7 +1022,7 @@ function registerInsforgeTools(server, config = {}) {
869
1022
  ${JSON.stringify(metadata, null, 2)}`
870
1023
  }
871
1024
  ]
872
- };
1025
+ });
873
1026
  } catch (error) {
874
1027
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
875
1028
  return {
@@ -907,14 +1060,14 @@ ${JSON.stringify(metadata, null, 2)}`
907
1060
  body: JSON.stringify(requestBody)
908
1061
  });
909
1062
  const result = await handleApiResponse(response);
910
- return {
1063
+ return await addBackgroundContext({
911
1064
  content: [
912
1065
  {
913
1066
  type: "text",
914
1067
  text: formatSuccessMessage("SQL query executed", result)
915
1068
  }
916
1069
  ]
917
- };
1070
+ });
918
1071
  } catch (error) {
919
1072
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
920
1073
  return {
@@ -929,9 +1082,85 @@ ${JSON.stringify(metadata, null, 2)}`
929
1082
  }
930
1083
  })
931
1084
  );
1085
+ server.tool(
1086
+ "download-template",
1087
+ "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.",
1088
+ {
1089
+ frame: z14.enum(["react"]).describe("Framework to use for the template (currently only React is supported)"),
1090
+ projectName: z14.string().optional().describe('Name for the project directory (optional, defaults to "insforge-react")')
1091
+ },
1092
+ withUsageTracking("download-template", async ({ frame, projectName }) => {
1093
+ try {
1094
+ const response = await fetch2(`${API_BASE_URL}/api/auth/tokens/anon`, {
1095
+ method: "POST",
1096
+ headers: {
1097
+ "x-api-key": getApiKey(),
1098
+ "Content-Type": "application/json"
1099
+ }
1100
+ });
1101
+ const result = await handleApiResponse(response);
1102
+ const anonKey = result.accessToken;
1103
+ if (!anonKey) {
1104
+ throw new Error("Failed to retrieve anon key from backend");
1105
+ }
1106
+ const tempDir = tmpdir();
1107
+ const targetDir = projectName || `insforge-${frame}`;
1108
+ const templatePath = `${tempDir}/${targetDir}`;
1109
+ console.error(`[download-template] Target path: ${templatePath}`);
1110
+ try {
1111
+ const stats = await fs.stat(templatePath);
1112
+ if (stats.isDirectory()) {
1113
+ console.error(`[download-template] Removing existing template at ${templatePath}`);
1114
+ await fs.rm(templatePath, { recursive: true, force: true });
1115
+ }
1116
+ } catch {
1117
+ }
1118
+ const command = `npx create-insforge-app ${targetDir} --frame ${frame} --base-url ${API_BASE_URL} --anon-key ${anonKey} --skip-install`;
1119
+ const { stdout, stderr } = await execAsync(command, {
1120
+ maxBuffer: 10 * 1024 * 1024,
1121
+ // 10MB buffer
1122
+ cwd: tempDir
1123
+ });
1124
+ const output = stdout || stderr || "";
1125
+ if (output.toLowerCase().includes("error") && !output.includes("successfully")) {
1126
+ throw new Error(`Failed to download template: ${output}`);
1127
+ }
1128
+ return await addBackgroundContext({
1129
+ content: [
1130
+ {
1131
+ type: "text",
1132
+ text: `\u2705 React template downloaded successfully
1133
+
1134
+ \u{1F4C1} Template Location: ${templatePath}
1135
+
1136
+ \u26A0\uFE0F IMPORTANT: The template is in a temporary directory and NOT in your current working directory.
1137
+
1138
+ \u{1F534} CRITICAL NEXT STEP REQUIRED:
1139
+ You MUST copy ALL files (INCLUDING HIDDEN FILES like .env, .gitignore, etc.) from the temporary directory to your current project directory.
1140
+
1141
+ Copy all files from: ${templatePath}
1142
+ To: Your current project directory
1143
+ `
1144
+ }
1145
+ ]
1146
+ });
1147
+ } catch (error) {
1148
+ const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1149
+ return {
1150
+ content: [
1151
+ {
1152
+ type: "text",
1153
+ text: `Error downloading template: ${errMsg}`
1154
+ }
1155
+ ],
1156
+ isError: true
1157
+ };
1158
+ }
1159
+ })
1160
+ );
932
1161
  server.tool(
933
1162
  "bulk-upsert",
934
- "Bulk insert or update data from CSV or JSON file. Supports upsert operations with a unique key.",
1163
+ "Bulk insert or updallet data from CSV or JSON file. Supports upsert operations with a unique key.",
935
1164
  {
936
1165
  apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)"),
937
1166
  ...bulkUpsertRequestSchema.shape,
@@ -958,7 +1187,7 @@ ${JSON.stringify(metadata, null, 2)}`
958
1187
  });
959
1188
  const result = await handleApiResponse(response);
960
1189
  const message = result.success ? `Successfully processed ${result.rowsAffected} of ${result.totalRecords} records into table "${result.table}"` : result.message || "Bulk upsert operation completed";
961
- return {
1190
+ return await addBackgroundContext({
962
1191
  content: [
963
1192
  {
964
1193
  type: "text",
@@ -971,7 +1200,7 @@ ${JSON.stringify(metadata, null, 2)}`
971
1200
  })
972
1201
  }
973
1202
  ]
974
- };
1203
+ });
975
1204
  } catch (error) {
976
1205
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
977
1206
  return {
@@ -1005,14 +1234,14 @@ ${JSON.stringify(metadata, null, 2)}`
1005
1234
  body: JSON.stringify({ bucketName, isPublic })
1006
1235
  });
1007
1236
  const result = await handleApiResponse(response);
1008
- return {
1237
+ return await addBackgroundContext({
1009
1238
  content: [
1010
1239
  {
1011
1240
  type: "text",
1012
1241
  text: formatSuccessMessage("Bucket created", result)
1013
1242
  }
1014
1243
  ]
1015
- };
1244
+ });
1016
1245
  } catch (error) {
1017
1246
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1018
1247
  return {
@@ -1040,14 +1269,14 @@ ${JSON.stringify(metadata, null, 2)}`
1040
1269
  }
1041
1270
  });
1042
1271
  const result = await handleApiResponse(response);
1043
- return {
1272
+ return await addBackgroundContext({
1044
1273
  content: [
1045
1274
  {
1046
1275
  type: "text",
1047
1276
  text: formatSuccessMessage("Buckets retrieved", result)
1048
1277
  }
1049
1278
  ]
1050
- };
1279
+ });
1051
1280
  } catch (error) {
1052
1281
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1053
1282
  return {
@@ -1079,14 +1308,14 @@ ${JSON.stringify(metadata, null, 2)}`
1079
1308
  }
1080
1309
  });
1081
1310
  const result = await handleApiResponse(response);
1082
- return {
1311
+ return await addBackgroundContext({
1083
1312
  content: [
1084
1313
  {
1085
1314
  type: "text",
1086
1315
  text: formatSuccessMessage("Bucket deleted", result)
1087
1316
  }
1088
1317
  ]
1089
- };
1318
+ });
1090
1319
  } catch (error) {
1091
1320
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1092
1321
  return {
@@ -1135,7 +1364,7 @@ ${JSON.stringify(metadata, null, 2)}`
1135
1364
  })
1136
1365
  });
1137
1366
  const result = await handleApiResponse(response);
1138
- return {
1367
+ return await addBackgroundContext({
1139
1368
  content: [
1140
1369
  {
1141
1370
  type: "text",
@@ -1145,7 +1374,7 @@ ${JSON.stringify(metadata, null, 2)}`
1145
1374
  )
1146
1375
  }
1147
1376
  ]
1148
- };
1377
+ });
1149
1378
  } catch (error) {
1150
1379
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1151
1380
  return {
@@ -1175,14 +1404,14 @@ ${JSON.stringify(metadata, null, 2)}`
1175
1404
  }
1176
1405
  });
1177
1406
  const result = await handleApiResponse(response);
1178
- return {
1407
+ return await addBackgroundContext({
1179
1408
  content: [
1180
1409
  {
1181
1410
  type: "text",
1182
1411
  text: formatSuccessMessage(`Edge function '${args.slug}' details`, result)
1183
1412
  }
1184
1413
  ]
1185
- };
1414
+ });
1186
1415
  } catch (error) {
1187
1416
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1188
1417
  return {
@@ -1238,7 +1467,7 @@ ${JSON.stringify(metadata, null, 2)}`
1238
1467
  });
1239
1468
  const result = await handleApiResponse(response);
1240
1469
  const fileInfo = args.codeFile ? ` from ${args.codeFile}` : "";
1241
- return {
1470
+ return await addBackgroundContext({
1242
1471
  content: [
1243
1472
  {
1244
1473
  type: "text",
@@ -1248,7 +1477,7 @@ ${JSON.stringify(metadata, null, 2)}`
1248
1477
  )
1249
1478
  }
1250
1479
  ]
1251
- };
1480
+ });
1252
1481
  } catch (error) {
1253
1482
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1254
1483
  return {
@@ -1278,14 +1507,14 @@ ${JSON.stringify(metadata, null, 2)}`
1278
1507
  }
1279
1508
  });
1280
1509
  const result = await handleApiResponse(response);
1281
- return {
1510
+ return await addBackgroundContext({
1282
1511
  content: [
1283
1512
  {
1284
1513
  type: "text",
1285
1514
  text: formatSuccessMessage(`Edge function '${args.slug}' deleted successfully`, result)
1286
1515
  }
1287
1516
  ]
1288
- };
1517
+ });
1289
1518
  } catch (error) {
1290
1519
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1291
1520
  return {
@@ -1313,21 +1542,29 @@ ${JSON.stringify(metadata, null, 2)}`
1313
1542
  const actualApiKey = getApiKey(apiKey);
1314
1543
  const queryParams = new URLSearchParams();
1315
1544
  if (limit) queryParams.append("limit", limit.toString());
1316
- const response = await fetch2(`${API_BASE_URL}/api/logs/analytics/${source}?${queryParams}`, {
1545
+ let response = await fetch2(`${API_BASE_URL}/api/logs/${source}?${queryParams}`, {
1317
1546
  method: "GET",
1318
1547
  headers: {
1319
1548
  "x-api-key": actualApiKey
1320
1549
  }
1321
1550
  });
1551
+ if (response.status === 404) {
1552
+ response = await fetch2(`${API_BASE_URL}/api/logs/analytics/${source}?${queryParams}`, {
1553
+ method: "GET",
1554
+ headers: {
1555
+ "x-api-key": actualApiKey
1556
+ }
1557
+ });
1558
+ }
1322
1559
  const result = await handleApiResponse(response);
1323
- return {
1560
+ return await addBackgroundContext({
1324
1561
  content: [
1325
1562
  {
1326
1563
  type: "text",
1327
1564
  text: formatSuccessMessage(`Latest logs from ${source}`, result)
1328
1565
  }
1329
1566
  ]
1330
- };
1567
+ });
1331
1568
  } catch (error) {
1332
1569
  const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
1333
1570
  return {
@@ -1345,7 +1582,7 @@ ${JSON.stringify(metadata, null, 2)}`
1345
1582
  return {
1346
1583
  apiKey: GLOBAL_API_KEY,
1347
1584
  apiBaseUrl: API_BASE_URL,
1348
- toolCount: 14
1585
+ toolCount: 15
1349
1586
  };
1350
1587
  }
1351
1588
 
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  registerInsforgeTools
4
- } from "./chunk-CLLI7UFN.js";
4
+ } from "./chunk-RCSKABFT.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-RCSKABFT.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.30",
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
+ }