@insforge/mcp 1.1.7-dev.2 → 1.1.7-dev.20
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/{chunk-74IVXADC.js → chunk-OLIGYXLN.js} +311 -11
- package/dist/http-server.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +5 -3
- package/server.json +17 -0
|
@@ -4,6 +4,8 @@
|
|
|
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";
|
|
7
9
|
|
|
8
10
|
// src/shared/response-handler.ts
|
|
9
11
|
async function handleApiResponse(response) {
|
|
@@ -161,8 +163,8 @@ var deleteTableResponse = z2.object({
|
|
|
161
163
|
});
|
|
162
164
|
var rawSQLRequestSchema = z2.object({
|
|
163
165
|
query: z2.string().min(1, "Query is required"),
|
|
164
|
-
params: z2.array(z2.
|
|
165
|
-
// z.
|
|
166
|
+
params: z2.array(z2.unknown()).optional()
|
|
167
|
+
// z.unknown() generates JSON Schema with items: {}
|
|
166
168
|
});
|
|
167
169
|
var rawSQLResponseSchema = z2.object({
|
|
168
170
|
rows: z2.array(z2.record(z2.string(), z2.unknown())),
|
|
@@ -735,10 +737,75 @@ var functionUpdateRequestSchema = z13.object({
|
|
|
735
737
|
|
|
736
738
|
// src/shared/tools.ts
|
|
737
739
|
import FormData from "form-data";
|
|
740
|
+
var execAsync = promisify(exec);
|
|
741
|
+
var TOOL_VERSION_REQUIREMENTS = {
|
|
742
|
+
"upsert-schedule": "1.1.1",
|
|
743
|
+
// 'get-schedules': '1.1.1',
|
|
744
|
+
// 'get-schedule-logs': '1.1.1',
|
|
745
|
+
"delete-schedule": "1.1.1"
|
|
746
|
+
};
|
|
738
747
|
function registerInsforgeTools(server, config = {}) {
|
|
739
748
|
const GLOBAL_API_KEY = config.apiKey || process.env.API_KEY || "";
|
|
740
749
|
const API_BASE_URL = config.apiBaseUrl || process.env.API_BASE_URL || "http://localhost:7130";
|
|
741
750
|
const usageTracker = new UsageTracker(API_BASE_URL, GLOBAL_API_KEY);
|
|
751
|
+
let versionCache = null;
|
|
752
|
+
const VERSION_CACHE_TTL = 5 * 60 * 1e3;
|
|
753
|
+
async function getBackendVersion() {
|
|
754
|
+
const now = Date.now();
|
|
755
|
+
if (versionCache && now - versionCache.timestamp < VERSION_CACHE_TTL) {
|
|
756
|
+
return versionCache.version;
|
|
757
|
+
}
|
|
758
|
+
try {
|
|
759
|
+
const response = await fetch2(`${API_BASE_URL}/api/health`, {
|
|
760
|
+
method: "GET",
|
|
761
|
+
headers: {
|
|
762
|
+
"Content-Type": "application/json"
|
|
763
|
+
}
|
|
764
|
+
});
|
|
765
|
+
if (!response.ok) {
|
|
766
|
+
throw new Error(`Health check failed with status ${response.status}`);
|
|
767
|
+
}
|
|
768
|
+
const health = await response.json();
|
|
769
|
+
versionCache = {
|
|
770
|
+
version: health.version,
|
|
771
|
+
timestamp: now
|
|
772
|
+
};
|
|
773
|
+
return health.version;
|
|
774
|
+
} catch (error) {
|
|
775
|
+
const errMsg = error instanceof Error ? error.message : "Unknown error";
|
|
776
|
+
throw new Error(`Failed to fetch backend version: ${errMsg}`);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
function compareVersions(v1, v2) {
|
|
780
|
+
const parts1 = v1.split(".").map(Number);
|
|
781
|
+
const parts2 = v2.split(".").map(Number);
|
|
782
|
+
for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
|
|
783
|
+
const part1 = parts1[i] || 0;
|
|
784
|
+
const part2 = parts2[i] || 0;
|
|
785
|
+
if (part1 > part2) return 1;
|
|
786
|
+
if (part1 < part2) return -1;
|
|
787
|
+
}
|
|
788
|
+
return 0;
|
|
789
|
+
}
|
|
790
|
+
async function checkToolVersion(toolName) {
|
|
791
|
+
const requiredVersion = TOOL_VERSION_REQUIREMENTS[toolName];
|
|
792
|
+
if (!requiredVersion) {
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
try {
|
|
796
|
+
const currentVersion = await getBackendVersion();
|
|
797
|
+
if (compareVersions(currentVersion, requiredVersion) < 0) {
|
|
798
|
+
throw new Error(
|
|
799
|
+
`Tool '${toolName}' requires backend version ${requiredVersion} or higher, but current version is ${currentVersion}. Please upgrade your Insforge backend server.`
|
|
800
|
+
);
|
|
801
|
+
}
|
|
802
|
+
} catch (error) {
|
|
803
|
+
if (error instanceof Error && error.message.includes("requires backend version")) {
|
|
804
|
+
throw error;
|
|
805
|
+
}
|
|
806
|
+
console.warn(`Warning: Could not verify backend version for tool '${toolName}': ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
807
|
+
}
|
|
808
|
+
}
|
|
742
809
|
async function trackToolUsage(toolName, success = true) {
|
|
743
810
|
if (GLOBAL_API_KEY) {
|
|
744
811
|
await usageTracker.trackUsage(toolName, success);
|
|
@@ -774,6 +841,7 @@ function registerInsforgeTools(server, config = {}) {
|
|
|
774
841
|
if (result && typeof result === "object" && "content" in result) {
|
|
775
842
|
let content = result.content;
|
|
776
843
|
content = content.replace(/http:\/\/localhost:7130/g, API_BASE_URL);
|
|
844
|
+
content = content.replace(/https:\/\/your-app\.region\.insforge\.app/g, API_BASE_URL);
|
|
777
845
|
return content;
|
|
778
846
|
}
|
|
779
847
|
throw new Error("Invalid response format from documentation endpoint");
|
|
@@ -783,12 +851,16 @@ function registerInsforgeTools(server, config = {}) {
|
|
|
783
851
|
}
|
|
784
852
|
};
|
|
785
853
|
server.tool(
|
|
786
|
-
"
|
|
787
|
-
|
|
788
|
-
{
|
|
789
|
-
|
|
854
|
+
"fetch-docs",
|
|
855
|
+
'Fetch Insforge documentation. Use "instructions" for essential backend setup (MANDATORY FIRST), or select specific SDK docs for database, auth, storage, functions, or AI integration.',
|
|
856
|
+
{
|
|
857
|
+
docType: z14.enum(["instructions", "db-sdk", "storage-sdk", "functions-sdk", "ai-integration-sdk", "auth-components-react", "auth-components-react-router"]).describe(
|
|
858
|
+
'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), "auth-components-react-router" (authentication components for React + React Router applications),'
|
|
859
|
+
)
|
|
860
|
+
},
|
|
861
|
+
withUsageTracking("fetch-docs", async ({ docType }) => {
|
|
790
862
|
try {
|
|
791
|
-
const content = await fetchDocumentation(
|
|
863
|
+
const content = await fetchDocumentation(docType);
|
|
792
864
|
return {
|
|
793
865
|
content: [
|
|
794
866
|
{
|
|
@@ -797,10 +869,62 @@ function registerInsforgeTools(server, config = {}) {
|
|
|
797
869
|
}
|
|
798
870
|
]
|
|
799
871
|
};
|
|
872
|
+
} catch (error) {
|
|
873
|
+
if (error instanceof Error && error.message.includes("404")) {
|
|
874
|
+
try {
|
|
875
|
+
const instructionsContent = await fetchDocumentation("instructions");
|
|
876
|
+
return {
|
|
877
|
+
content: [{ type: "text", text: instructionsContent }]
|
|
878
|
+
};
|
|
879
|
+
} catch (fallbackError) {
|
|
880
|
+
const fallbackErrMsg = fallbackError instanceof Error ? fallbackError.message : "Unknown error occurred";
|
|
881
|
+
return {
|
|
882
|
+
content: [{ type: "text", text: `Error fetching documentation: ${fallbackErrMsg}` }]
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
|
|
887
|
+
return {
|
|
888
|
+
content: [{ type: "text", text: `Error fetching ${docType} documentation: ${errMsg}` }]
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
})
|
|
892
|
+
);
|
|
893
|
+
server.tool(
|
|
894
|
+
"get-anon-key",
|
|
895
|
+
"Generate an anonymous JWT token that never expires. Requires admin API key. Use this for client-side applications that need public access.",
|
|
896
|
+
{
|
|
897
|
+
apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)")
|
|
898
|
+
},
|
|
899
|
+
withUsageTracking("get-anon-key", async ({ apiKey }) => {
|
|
900
|
+
try {
|
|
901
|
+
const actualApiKey = getApiKey(apiKey);
|
|
902
|
+
const response = await fetch2(`${API_BASE_URL}/api/auth/tokens/anon`, {
|
|
903
|
+
method: "POST",
|
|
904
|
+
headers: {
|
|
905
|
+
"x-api-key": actualApiKey,
|
|
906
|
+
"Content-Type": "application/json"
|
|
907
|
+
}
|
|
908
|
+
});
|
|
909
|
+
const result = await handleApiResponse(response);
|
|
910
|
+
return {
|
|
911
|
+
content: [
|
|
912
|
+
{
|
|
913
|
+
type: "text",
|
|
914
|
+
text: formatSuccessMessage("Anonymous token generated", result)
|
|
915
|
+
}
|
|
916
|
+
]
|
|
917
|
+
};
|
|
800
918
|
} catch (error) {
|
|
801
919
|
const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
|
|
802
920
|
return {
|
|
803
|
-
content: [
|
|
921
|
+
content: [
|
|
922
|
+
{
|
|
923
|
+
type: "text",
|
|
924
|
+
text: `Error generating anonymous token: ${errMsg}`
|
|
925
|
+
}
|
|
926
|
+
],
|
|
927
|
+
isError: true
|
|
804
928
|
};
|
|
805
929
|
}
|
|
806
930
|
})
|
|
@@ -929,9 +1053,73 @@ ${JSON.stringify(metadata, null, 2)}`
|
|
|
929
1053
|
}
|
|
930
1054
|
})
|
|
931
1055
|
);
|
|
1056
|
+
server.tool(
|
|
1057
|
+
"download-template",
|
|
1058
|
+
"CRITICAL: MANDATORY FIRST STEP for all new InsForge projects. Download pre-configured starter template (React/Next.js/React Router). ALWAYS use this tool BEFORE any other setup when starting a new project.",
|
|
1059
|
+
{
|
|
1060
|
+
frame: z14.enum(["react"]).describe("Framework to use for the template (currently only React is supported)"),
|
|
1061
|
+
projectName: z14.string().optional().describe('Name for the project directory (optional, defaults to "insforge-react")')
|
|
1062
|
+
},
|
|
1063
|
+
withUsageTracking("download-template", async ({ frame, projectName }) => {
|
|
1064
|
+
try {
|
|
1065
|
+
const response = await fetch2(`${API_BASE_URL}/api/auth/tokens/anon`, {
|
|
1066
|
+
method: "POST",
|
|
1067
|
+
headers: {
|
|
1068
|
+
"x-api-key": getApiKey(),
|
|
1069
|
+
"Content-Type": "application/json"
|
|
1070
|
+
}
|
|
1071
|
+
});
|
|
1072
|
+
const result = await handleApiResponse(response);
|
|
1073
|
+
const anonKey = result.accessToken;
|
|
1074
|
+
if (!anonKey) {
|
|
1075
|
+
throw new Error("Failed to retrieve anon key from backend");
|
|
1076
|
+
}
|
|
1077
|
+
const targetDir = projectName || `insforge-${frame}`;
|
|
1078
|
+
const command = `npx create-insforge-app ${targetDir} --frame ${frame} --base-url ${API_BASE_URL} --anon-key ${anonKey}`;
|
|
1079
|
+
const { stdout, stderr } = await execAsync(command, {
|
|
1080
|
+
maxBuffer: 10 * 1024 * 1024
|
|
1081
|
+
// 10MB buffer
|
|
1082
|
+
});
|
|
1083
|
+
const output = stdout || stderr || "";
|
|
1084
|
+
if (output.toLowerCase().includes("error") && !output.includes("successfully")) {
|
|
1085
|
+
throw new Error(`Failed to download template: ${output}`);
|
|
1086
|
+
}
|
|
1087
|
+
return {
|
|
1088
|
+
content: [
|
|
1089
|
+
{
|
|
1090
|
+
type: "text",
|
|
1091
|
+
text: formatSuccessMessage(
|
|
1092
|
+
`React template downloaded to ${targetDir}`,
|
|
1093
|
+
{
|
|
1094
|
+
targetDir,
|
|
1095
|
+
baseUrl: API_BASE_URL,
|
|
1096
|
+
nextSteps: [
|
|
1097
|
+
`cd ${targetDir}`,
|
|
1098
|
+
`npm install`,
|
|
1099
|
+
`npm run dev`
|
|
1100
|
+
]
|
|
1101
|
+
}
|
|
1102
|
+
)
|
|
1103
|
+
}
|
|
1104
|
+
]
|
|
1105
|
+
};
|
|
1106
|
+
} catch (error) {
|
|
1107
|
+
const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1108
|
+
return {
|
|
1109
|
+
content: [
|
|
1110
|
+
{
|
|
1111
|
+
type: "text",
|
|
1112
|
+
text: `Error downloading template: ${errMsg}`
|
|
1113
|
+
}
|
|
1114
|
+
],
|
|
1115
|
+
isError: true
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
})
|
|
1119
|
+
);
|
|
932
1120
|
server.tool(
|
|
933
1121
|
"bulk-upsert",
|
|
934
|
-
"Bulk insert or
|
|
1122
|
+
"Bulk insert or updallet data from CSV or JSON file. Supports upsert operations with a unique key.",
|
|
935
1123
|
{
|
|
936
1124
|
apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)"),
|
|
937
1125
|
...bulkUpsertRequestSchema.shape,
|
|
@@ -1313,12 +1501,20 @@ ${JSON.stringify(metadata, null, 2)}`
|
|
|
1313
1501
|
const actualApiKey = getApiKey(apiKey);
|
|
1314
1502
|
const queryParams = new URLSearchParams();
|
|
1315
1503
|
if (limit) queryParams.append("limit", limit.toString());
|
|
1316
|
-
|
|
1504
|
+
let response = await fetch2(`${API_BASE_URL}/api/logs/${source}?${queryParams}`, {
|
|
1317
1505
|
method: "GET",
|
|
1318
1506
|
headers: {
|
|
1319
1507
|
"x-api-key": actualApiKey
|
|
1320
1508
|
}
|
|
1321
1509
|
});
|
|
1510
|
+
if (response.status === 404) {
|
|
1511
|
+
response = await fetch2(`${API_BASE_URL}/api/logs/analytics/${source}?${queryParams}`, {
|
|
1512
|
+
method: "GET",
|
|
1513
|
+
headers: {
|
|
1514
|
+
"x-api-key": actualApiKey
|
|
1515
|
+
}
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1322
1518
|
const result = await handleApiResponse(response);
|
|
1323
1519
|
return {
|
|
1324
1520
|
content: [
|
|
@@ -1342,10 +1538,114 @@ ${JSON.stringify(metadata, null, 2)}`
|
|
|
1342
1538
|
}
|
|
1343
1539
|
})
|
|
1344
1540
|
);
|
|
1541
|
+
server.tool(
|
|
1542
|
+
"upsert-schedule",
|
|
1543
|
+
"Create or update a cron job schedule. If id is provided, updates existing schedule; otherwise creates a new one.",
|
|
1544
|
+
{
|
|
1545
|
+
apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)"),
|
|
1546
|
+
id: z14.string().uuid().optional().describe("The UUID of the schedule to update. If omitted, a new schedule will be created."),
|
|
1547
|
+
name: z14.string().min(3).describe("Schedule name (at least 3 characters)"),
|
|
1548
|
+
cronSchedule: z14.string().describe('Cron schedule format (5 or 6 parts, e.g., "0 */2 * * *" for every 2 hours)'),
|
|
1549
|
+
functionUrl: z14.string().url().describe("The URL to call when the schedule triggers"),
|
|
1550
|
+
httpMethod: z14.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]).optional().default("POST").describe("HTTP method to use"),
|
|
1551
|
+
headers: z14.record(z14.string()).optional().describe('HTTP headers. Values starting with "secret:" will be resolved from secrets store.'),
|
|
1552
|
+
body: z14.record(z14.unknown()).optional().describe("JSON body to send with the request")
|
|
1553
|
+
},
|
|
1554
|
+
withUsageTracking("upsert-schedule", async ({ apiKey, id, name, cronSchedule, functionUrl, httpMethod, headers, body }) => {
|
|
1555
|
+
try {
|
|
1556
|
+
await checkToolVersion("upsert-schedule");
|
|
1557
|
+
const actualApiKey = getApiKey(apiKey);
|
|
1558
|
+
const requestBody = {
|
|
1559
|
+
name,
|
|
1560
|
+
cronSchedule,
|
|
1561
|
+
functionUrl,
|
|
1562
|
+
httpMethod: httpMethod || "POST"
|
|
1563
|
+
};
|
|
1564
|
+
if (id) {
|
|
1565
|
+
requestBody.id = id;
|
|
1566
|
+
}
|
|
1567
|
+
if (headers) {
|
|
1568
|
+
requestBody.headers = headers;
|
|
1569
|
+
}
|
|
1570
|
+
if (body) {
|
|
1571
|
+
requestBody.body = body;
|
|
1572
|
+
}
|
|
1573
|
+
const response = await fetch2(`${API_BASE_URL}/api/schedules`, {
|
|
1574
|
+
method: "POST",
|
|
1575
|
+
headers: {
|
|
1576
|
+
"x-api-key": actualApiKey,
|
|
1577
|
+
"Content-Type": "application/json"
|
|
1578
|
+
},
|
|
1579
|
+
body: JSON.stringify(requestBody)
|
|
1580
|
+
});
|
|
1581
|
+
const result = await handleApiResponse(response);
|
|
1582
|
+
const action = id ? "updated" : "created";
|
|
1583
|
+
return {
|
|
1584
|
+
content: [
|
|
1585
|
+
{
|
|
1586
|
+
type: "text",
|
|
1587
|
+
text: formatSuccessMessage(`Schedule '${name}' ${action} successfully`, result)
|
|
1588
|
+
}
|
|
1589
|
+
]
|
|
1590
|
+
};
|
|
1591
|
+
} catch (error) {
|
|
1592
|
+
const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1593
|
+
return {
|
|
1594
|
+
content: [
|
|
1595
|
+
{
|
|
1596
|
+
type: "text",
|
|
1597
|
+
text: `Error upserting schedule: ${errMsg}`
|
|
1598
|
+
}
|
|
1599
|
+
],
|
|
1600
|
+
isError: true
|
|
1601
|
+
};
|
|
1602
|
+
}
|
|
1603
|
+
})
|
|
1604
|
+
);
|
|
1605
|
+
server.tool(
|
|
1606
|
+
"delete-schedule",
|
|
1607
|
+
"Delete a cron job schedule permanently",
|
|
1608
|
+
{
|
|
1609
|
+
apiKey: z14.string().optional().describe("API key for authentication (optional if provided via --api_key)"),
|
|
1610
|
+
scheduleId: z14.string().uuid().describe("The UUID of the schedule to delete")
|
|
1611
|
+
},
|
|
1612
|
+
withUsageTracking("delete-schedule", async ({ apiKey, scheduleId }) => {
|
|
1613
|
+
try {
|
|
1614
|
+
await checkToolVersion("delete-schedule");
|
|
1615
|
+
const actualApiKey = getApiKey(apiKey);
|
|
1616
|
+
const response = await fetch2(`${API_BASE_URL}/api/schedules/${scheduleId}`, {
|
|
1617
|
+
method: "DELETE",
|
|
1618
|
+
headers: {
|
|
1619
|
+
"x-api-key": actualApiKey
|
|
1620
|
+
}
|
|
1621
|
+
});
|
|
1622
|
+
const result = await handleApiResponse(response);
|
|
1623
|
+
return {
|
|
1624
|
+
content: [
|
|
1625
|
+
{
|
|
1626
|
+
type: "text",
|
|
1627
|
+
text: formatSuccessMessage(`Schedule ${scheduleId} deleted successfully`, result)
|
|
1628
|
+
}
|
|
1629
|
+
]
|
|
1630
|
+
};
|
|
1631
|
+
} catch (error) {
|
|
1632
|
+
const errMsg = error instanceof Error ? error.message : "Unknown error occurred";
|
|
1633
|
+
return {
|
|
1634
|
+
content: [
|
|
1635
|
+
{
|
|
1636
|
+
type: "text",
|
|
1637
|
+
text: `Error deleting schedule: ${errMsg}`
|
|
1638
|
+
}
|
|
1639
|
+
],
|
|
1640
|
+
isError: true
|
|
1641
|
+
};
|
|
1642
|
+
}
|
|
1643
|
+
})
|
|
1644
|
+
);
|
|
1345
1645
|
return {
|
|
1346
1646
|
apiKey: GLOBAL_API_KEY,
|
|
1347
1647
|
apiBaseUrl: API_BASE_URL,
|
|
1348
|
-
toolCount:
|
|
1648
|
+
toolCount: 17
|
|
1349
1649
|
};
|
|
1350
1650
|
}
|
|
1351
1651
|
|
package/dist/http-server.js
CHANGED
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@insforge/mcp",
|
|
3
|
-
"version": "1.1.7-dev.
|
|
3
|
+
"version": "1.1.7-dev.20",
|
|
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,10 +32,11 @@
|
|
|
31
32
|
},
|
|
32
33
|
"files": [
|
|
33
34
|
"dist",
|
|
34
|
-
"mcp.json"
|
|
35
|
+
"mcp.json",
|
|
36
|
+
"server.json"
|
|
35
37
|
],
|
|
36
38
|
"dependencies": {
|
|
37
|
-
"@insforge/shared-schemas": "^1.1.
|
|
39
|
+
"@insforge/shared-schemas": "^1.1.7",
|
|
38
40
|
"@modelcontextprotocol/sdk": "^1.15.1",
|
|
39
41
|
"@types/express": "^5.0.3",
|
|
40
42
|
"commander": "^14.0.0",
|
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
|
+
}
|