@apicircle/mcp-server 1.0.6 → 1.0.8
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/README.md +14 -13
- package/dist/bin/mcp-server.cjs +528 -299
- package/dist/bin/mcp-server.cjs.map +1 -1
- package/dist/index.cjs +513 -291
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -6
- package/dist/index.d.ts +20 -6
- package/dist/index.js +515 -287
- package/dist/index.js.map +1 -1
- package/package.json +28 -4
package/dist/bin/mcp-server.cjs
CHANGED
|
@@ -36,10 +36,34 @@ var init_package = __esm({
|
|
|
36
36
|
"package.json"() {
|
|
37
37
|
package_default = {
|
|
38
38
|
name: "@apicircle/mcp-server",
|
|
39
|
-
version: "1.0.
|
|
39
|
+
version: "1.0.8",
|
|
40
40
|
private: false,
|
|
41
41
|
type: "module",
|
|
42
42
|
description: "Model Context Protocol server exposing API Circle Studio's workspace as a tool catalog. Used by Claude Desktop, ChatGPT, Cursor, GitHub Copilot, and any other MCP-compatible AI client.",
|
|
43
|
+
keywords: [
|
|
44
|
+
"apicircle",
|
|
45
|
+
"api",
|
|
46
|
+
"api-circle",
|
|
47
|
+
"mcp",
|
|
48
|
+
"mcp-server",
|
|
49
|
+
"model-context-protocol",
|
|
50
|
+
"ai",
|
|
51
|
+
"llm",
|
|
52
|
+
"agent",
|
|
53
|
+
"tool-catalog",
|
|
54
|
+
"claude",
|
|
55
|
+
"claude-desktop",
|
|
56
|
+
"chatgpt",
|
|
57
|
+
"cursor",
|
|
58
|
+
"copilot",
|
|
59
|
+
"continue",
|
|
60
|
+
"cline",
|
|
61
|
+
"zed",
|
|
62
|
+
"windsurf",
|
|
63
|
+
"openapi",
|
|
64
|
+
"postman",
|
|
65
|
+
"api-tools"
|
|
66
|
+
],
|
|
43
67
|
license: "SEE LICENSE IN LICENSE",
|
|
44
68
|
repository: {
|
|
45
69
|
type: "git",
|
|
@@ -595,12 +619,13 @@ var init_workspaceList = __esm({
|
|
|
595
619
|
});
|
|
596
620
|
|
|
597
621
|
// src/tools/crud.ts
|
|
598
|
-
var import_zod5, import_shared2, HTTP_METHOD, requestCreateTool, requestReadTool, requestUpdateTool, requestDeleteTool, folderCreateTool, folderReadTool, folderUpdateTool, folderDeleteTool, VARIABLE, environmentCreateTool, environmentReadTool, environmentUpdateTool, environmentDeleteTool, environmentSetActiveTool, environmentSetPriorityTool, environmentExportTool, environmentImportTool, PLAN_STEP, planCreateTool, planReadTool, planUpdateTool, planDeleteTool, planAddStepTool, planRemoveStepTool, planReorderStepsTool, PLAN_VARIABLE, planSetVariablesTool, planRunTool, ASSERTION, assertionCreateTool, assertionReadTool, assertionUpdateTool, assertionDeleteTool, workspaceReadTool, workspaceWriteTool;
|
|
622
|
+
var import_zod5, import_shared2, import_core2, HTTP_METHOD, requestCreateTool, requestReadTool, requestUpdateTool, requestDeleteTool, folderCreateTool, folderReadTool, folderUpdateTool, folderDeleteTool, VARIABLE, environmentCreateTool, environmentReadTool, environmentUpdateTool, environmentDeleteTool, environmentSetActiveTool, environmentSetPriorityTool, environmentExportTool, environmentImportTool, PLAN_STEP, planCreateTool, planReadTool, planUpdateTool, planDeleteTool, planAddStepTool, planRemoveStepTool, planReorderStepsTool, PLAN_VARIABLE, planSetVariablesTool, planRunTool, ASSERTION, assertionCreateTool, assertionReadTool, assertionUpdateTool, assertionDeleteTool, workspaceReadTool, workspaceWriteTool;
|
|
599
623
|
var init_crud = __esm({
|
|
600
624
|
"src/tools/crud.ts"() {
|
|
601
625
|
"use strict";
|
|
602
626
|
import_zod5 = require("zod");
|
|
603
627
|
import_shared2 = require("@apicircle/shared");
|
|
628
|
+
import_core2 = require("@apicircle/core");
|
|
604
629
|
HTTP_METHOD = import_zod5.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
605
630
|
requestCreateTool = {
|
|
606
631
|
name: "request.create",
|
|
@@ -845,55 +870,136 @@ var init_crud = __esm({
|
|
|
845
870
|
};
|
|
846
871
|
environmentExportTool = {
|
|
847
872
|
name: "environment.export",
|
|
848
|
-
description: "Serialize an environment to a portable JSON string. Encrypted variables
|
|
873
|
+
description: "Serialize an environment to a portable JSON string (envelope v2). Encrypted variables now carry their ciphertext, slot label, and per-slot salt \u2014 the destination decrypts with its local slot value at request-execute time, matching the Git push/pull contract. The plaintext slot value never leaves the device, but the ciphertext does. v1 envelopes (no ciphertext) still parse on import for back-compat.",
|
|
849
874
|
inputSchema: import_zod5.z.object({ name: import_zod5.z.string() }),
|
|
850
875
|
async handler(input, ctx) {
|
|
851
876
|
const state = await ctx.workspace.read();
|
|
852
877
|
const env = state.synced.environments.items[input.name];
|
|
853
878
|
if (!env) return { ok: false, error: "environment not found" };
|
|
854
879
|
const payload = {
|
|
855
|
-
apicircleEnvironment:
|
|
880
|
+
apicircleEnvironment: 2,
|
|
856
881
|
name: env.name,
|
|
857
|
-
variables: env.variables.map(
|
|
858
|
-
(v
|
|
859
|
-
|
|
882
|
+
variables: env.variables.map((v) => {
|
|
883
|
+
if (v.encrypted && v.secretKeyId) {
|
|
884
|
+
const slot = state.synced.secretKeys?.[v.secretKeyId];
|
|
885
|
+
const label = slot?.label ?? v.key;
|
|
886
|
+
const value = typeof v.value === "string" && v.value.startsWith("enc:") ? v.value : "";
|
|
887
|
+
return {
|
|
888
|
+
key: v.key,
|
|
889
|
+
encrypted: true,
|
|
890
|
+
value,
|
|
891
|
+
secretKeyId: v.secretKeyId,
|
|
892
|
+
secret: { label, salt: slot?.salt ?? null }
|
|
893
|
+
};
|
|
894
|
+
}
|
|
895
|
+
return { key: v.key, value: v.value, encrypted: false };
|
|
896
|
+
})
|
|
860
897
|
};
|
|
861
898
|
return { ok: true, json: JSON.stringify(payload, null, 2) };
|
|
862
899
|
}
|
|
863
900
|
};
|
|
864
901
|
environmentImportTool = {
|
|
865
902
|
name: "environment.import",
|
|
866
|
-
description: "Import an environment from the JSON shape produced by `environment.export`.
|
|
903
|
+
description: "Import an environment from the JSON shape produced by `environment.export`. v2 envelopes carry the row ciphertext + per-slot salt, so the destination decrypts at request-execute time with its local slot value (same model as Git push/pull); when no destination slot matches the source's salt, a new slot is minted via `secretKey.upsert` and surfaced in `mintedSlots` so the caller can provide values via `secret.addLocal`. v1 envelopes carry only metadata, so unmatched rows come back as `pendingBindings` for the caller to prompt-and-bind via `secret.addLocal` + `environment.bindSecret`. Pass `overwrite: true` to replace a same-name destination env.",
|
|
867
904
|
inputSchema: import_zod5.z.object({
|
|
868
905
|
json: import_zod5.z.string().min(1),
|
|
869
906
|
overwrite: import_zod5.z.boolean().default(false)
|
|
870
907
|
}),
|
|
871
908
|
async handler(input, ctx) {
|
|
872
|
-
let
|
|
909
|
+
let raw;
|
|
873
910
|
try {
|
|
874
|
-
|
|
911
|
+
raw = JSON.parse(input.json);
|
|
875
912
|
} catch {
|
|
876
913
|
return { ok: false, error: "invalid JSON" };
|
|
877
914
|
}
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
915
|
+
let parsed;
|
|
916
|
+
try {
|
|
917
|
+
parsed = (0, import_core2.parseApicircleEnvironmentDoc)(raw);
|
|
918
|
+
} catch (err) {
|
|
919
|
+
return {
|
|
920
|
+
ok: false,
|
|
921
|
+
error: err instanceof Error ? err.message : "unsupported export shape"
|
|
922
|
+
};
|
|
881
923
|
}
|
|
882
924
|
const state = await ctx.workspace.read();
|
|
883
|
-
if (state.synced.environments.items[
|
|
925
|
+
if (state.synced.environments.items[parsed.name] && !input.overwrite) {
|
|
884
926
|
return {
|
|
885
927
|
ok: false,
|
|
886
928
|
error: "environment already exists; pass overwrite:true"
|
|
887
929
|
};
|
|
888
930
|
}
|
|
889
|
-
const
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
931
|
+
const destSlots = state.synced.secretKeys ?? {};
|
|
932
|
+
const labelToSlotId = /* @__PURE__ */ new Map();
|
|
933
|
+
for (const slot of Object.values(destSlots)) {
|
|
934
|
+
if (!labelToSlotId.has(slot.label)) labelToSlotId.set(slot.label, slot.id);
|
|
935
|
+
}
|
|
936
|
+
const resolvedVariables = [];
|
|
937
|
+
const pendingBindings = [];
|
|
938
|
+
const mintedSlots = [];
|
|
939
|
+
const knownDestIds = new Set(Object.keys(destSlots));
|
|
940
|
+
let hintCursor = 0;
|
|
941
|
+
for (const v of parsed.variables) {
|
|
942
|
+
if (!v.encrypted) {
|
|
943
|
+
resolvedVariables.push(v);
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
const hint = parsed.encryptedBindingHints[hintCursor];
|
|
947
|
+
hintCursor += 1;
|
|
948
|
+
if (hint && hint.ciphertext && hint.salt) {
|
|
949
|
+
if (hint.originSecretKeyId && destSlots[hint.originSecretKeyId]?.salt === hint.salt) {
|
|
950
|
+
resolvedVariables.push({ ...v, secretKeyId: hint.originSecretKeyId });
|
|
951
|
+
continue;
|
|
952
|
+
}
|
|
953
|
+
const labelMatch = labelToSlotId.get(hint.label);
|
|
954
|
+
if (labelMatch && destSlots[labelMatch]?.salt === hint.salt) {
|
|
955
|
+
resolvedVariables.push({ ...v, secretKeyId: labelMatch });
|
|
956
|
+
continue;
|
|
957
|
+
}
|
|
958
|
+
const mintedId = hint.originSecretKeyId && !knownDestIds.has(hint.originSecretKeyId) ? hint.originSecretKeyId : (0, import_shared2.generateId)();
|
|
959
|
+
knownDestIds.add(mintedId);
|
|
960
|
+
if (!labelToSlotId.has(hint.label)) labelToSlotId.set(hint.label, mintedId);
|
|
961
|
+
mintedSlots.push({
|
|
962
|
+
id: mintedId,
|
|
963
|
+
label: hint.label,
|
|
964
|
+
salt: hint.salt,
|
|
965
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
966
|
+
});
|
|
967
|
+
resolvedVariables.push({ ...v, secretKeyId: mintedId });
|
|
968
|
+
continue;
|
|
969
|
+
}
|
|
970
|
+
if (hint?.originSecretKeyId && destSlots[hint.originSecretKeyId]) {
|
|
971
|
+
resolvedVariables.push({ ...v, secretKeyId: hint.originSecretKeyId });
|
|
972
|
+
continue;
|
|
973
|
+
}
|
|
974
|
+
if (hint?.label) {
|
|
975
|
+
const matchId = labelToSlotId.get(hint.label);
|
|
976
|
+
if (matchId) {
|
|
977
|
+
resolvedVariables.push({ ...v, secretKeyId: matchId });
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
resolvedVariables.push(v);
|
|
982
|
+
if (hint) {
|
|
983
|
+
pendingBindings.push({
|
|
984
|
+
varKey: hint.varKey,
|
|
985
|
+
label: hint.label,
|
|
986
|
+
labelFromFallback: hint.labelFromFallback
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
for (const meta of mintedSlots) {
|
|
991
|
+
await ctx.workspace.apply({ kind: "secretKey.upsert", meta });
|
|
992
|
+
}
|
|
993
|
+
const env = { name: parsed.name, variables: resolvedVariables };
|
|
895
994
|
const out = await ctx.workspace.apply({ kind: "environment.upsert", environment: env });
|
|
896
|
-
return {
|
|
995
|
+
return {
|
|
996
|
+
ok: true,
|
|
997
|
+
name: env.name,
|
|
998
|
+
changedIds: out.changedIds,
|
|
999
|
+
pendingBindings,
|
|
1000
|
+
mintedSlots: mintedSlots.map((s) => ({ id: s.id, label: s.label })),
|
|
1001
|
+
warnings: parsed.warnings
|
|
1002
|
+
};
|
|
897
1003
|
}
|
|
898
1004
|
};
|
|
899
1005
|
PLAN_STEP = import_zod5.z.object({
|
|
@@ -1226,21 +1332,110 @@ var init_crud = __esm({
|
|
|
1226
1332
|
}
|
|
1227
1333
|
});
|
|
1228
1334
|
|
|
1335
|
+
// src/tools/folderExchange.ts
|
|
1336
|
+
var import_zod6, import_core3, folderExportJsonTool, folderImportJsonTool;
|
|
1337
|
+
var init_folderExchange = __esm({
|
|
1338
|
+
"src/tools/folderExchange.ts"() {
|
|
1339
|
+
"use strict";
|
|
1340
|
+
import_zod6 = require("zod");
|
|
1341
|
+
import_core3 = require("@apicircle/core");
|
|
1342
|
+
folderExportJsonTool = {
|
|
1343
|
+
name: "folder.export_json",
|
|
1344
|
+
description: "Export an existing folder (and its subtree) to the API Circle exchange JSON format. Embeds JSON Schema + GraphQL dependencies inline. Auth credentials are redacted by default \u2014 pass `includeCredentialIds` to keep specific fields verbatim (the report from `collectFolderExport` enumerates the available ids).",
|
|
1345
|
+
inputSchema: import_zod6.z.object({
|
|
1346
|
+
folderId: import_zod6.z.string().min(1, "folderId is required"),
|
|
1347
|
+
/**
|
|
1348
|
+
* Subset of credential ids to KEEP in the output. Anything not in
|
|
1349
|
+
* this list (and every detected credential when this is empty)
|
|
1350
|
+
* gets blanked. Use the report-side ids surfaced by the export
|
|
1351
|
+
* report (`<scope>:<ownerId>.<authType>.<field>`).
|
|
1352
|
+
*/
|
|
1353
|
+
includeCredentialIds: import_zod6.z.array(import_zod6.z.string()).optional()
|
|
1354
|
+
}),
|
|
1355
|
+
async handler(input, ctx) {
|
|
1356
|
+
const state = await ctx.workspace.read();
|
|
1357
|
+
const collected = (0, import_core3.collectFolderExport)({
|
|
1358
|
+
synced: state.synced,
|
|
1359
|
+
folderId: input.folderId
|
|
1360
|
+
});
|
|
1361
|
+
if (!collected) {
|
|
1362
|
+
return {
|
|
1363
|
+
error: "folder_not_found",
|
|
1364
|
+
message: `No folder with id "${input.folderId}" exists in the active workspace.`
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
const includeIds = new Set(input.includeCredentialIds ?? []);
|
|
1368
|
+
const redacted = (0, import_core3.redactFolderExportCredentials)(collected.envelope, includeIds);
|
|
1369
|
+
return {
|
|
1370
|
+
envelope: redacted,
|
|
1371
|
+
json: (0, import_core3.serializeFolderExport)(redacted),
|
|
1372
|
+
filename: (0, import_core3.suggestFolderExportFilename)(redacted),
|
|
1373
|
+
report: collected.report
|
|
1374
|
+
};
|
|
1375
|
+
}
|
|
1376
|
+
};
|
|
1377
|
+
folderImportJsonTool = {
|
|
1378
|
+
name: "folder.import_json",
|
|
1379
|
+
description: "Import an `apicircle.folder/v1` envelope into the active workspace. Folder + request ids are reminted, dependency references are remapped, and JSON Schema / GraphQL definitions that match an existing global asset (by name + content) are reused.",
|
|
1380
|
+
inputSchema: import_zod6.z.object({
|
|
1381
|
+
/** Either a JSON string or the already-parsed envelope object. */
|
|
1382
|
+
json: import_zod6.z.string().min(1).optional(),
|
|
1383
|
+
envelope: import_zod6.z.record(import_zod6.z.unknown()).optional(),
|
|
1384
|
+
parentFolderId: import_zod6.z.string().nullable().optional()
|
|
1385
|
+
}),
|
|
1386
|
+
async handler(input, ctx) {
|
|
1387
|
+
if (!input.json && !input.envelope) {
|
|
1388
|
+
return {
|
|
1389
|
+
error: "invalid_input",
|
|
1390
|
+
message: "Pass either `json` (string) or `envelope` (object)."
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1393
|
+
const text = input.json !== void 0 ? input.json : JSON.stringify(input.envelope);
|
|
1394
|
+
let parsed;
|
|
1395
|
+
try {
|
|
1396
|
+
parsed = (0, import_core3.parseApicircleFolderExport)(text);
|
|
1397
|
+
} catch (err) {
|
|
1398
|
+
return {
|
|
1399
|
+
error: "invalid_envelope",
|
|
1400
|
+
message: err instanceof Error ? err.message : String(err)
|
|
1401
|
+
};
|
|
1402
|
+
}
|
|
1403
|
+
const out = await ctx.workspace.apply({
|
|
1404
|
+
kind: "folder.import_apicircle",
|
|
1405
|
+
parsed,
|
|
1406
|
+
parentFolderId: input.parentFolderId ?? null
|
|
1407
|
+
});
|
|
1408
|
+
return {
|
|
1409
|
+
rootFolderId: parsed.rootFolder.id,
|
|
1410
|
+
rootFolderName: parsed.rootFolder.name,
|
|
1411
|
+
counts: {
|
|
1412
|
+
folders: parsed.subfolders.length + 1,
|
|
1413
|
+
requests: parsed.requests.length
|
|
1414
|
+
},
|
|
1415
|
+
filesRequiringReattachment: parsed.dependencies.files.map((f) => f.id),
|
|
1416
|
+
warnings: parsed.warnings,
|
|
1417
|
+
changedIds: out.changedIds
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
};
|
|
1421
|
+
}
|
|
1422
|
+
});
|
|
1423
|
+
|
|
1229
1424
|
// src/tools/history.ts
|
|
1230
|
-
var
|
|
1425
|
+
var import_zod7, historyListRunsTool, historyGetRunTool, historyDeleteRunTool, historyPurgeTool;
|
|
1231
1426
|
var init_history = __esm({
|
|
1232
1427
|
"src/tools/history.ts"() {
|
|
1233
1428
|
"use strict";
|
|
1234
|
-
|
|
1429
|
+
import_zod7 = require("zod");
|
|
1235
1430
|
historyListRunsTool = {
|
|
1236
1431
|
name: "history.list_runs",
|
|
1237
1432
|
description: "List request-run history rows in reverse-chronological order. Filter by `requestId`, `ok` (success/failure), or `since`/`until` ISO timestamps. `limit` caps the result set; default 100.",
|
|
1238
|
-
inputSchema:
|
|
1239
|
-
requestId:
|
|
1240
|
-
ok:
|
|
1241
|
-
since:
|
|
1242
|
-
until:
|
|
1243
|
-
limit:
|
|
1433
|
+
inputSchema: import_zod7.z.object({
|
|
1434
|
+
requestId: import_zod7.z.string().optional(),
|
|
1435
|
+
ok: import_zod7.z.boolean().optional(),
|
|
1436
|
+
since: import_zod7.z.string().optional(),
|
|
1437
|
+
until: import_zod7.z.string().optional(),
|
|
1438
|
+
limit: import_zod7.z.number().int().positive().max(500).default(100)
|
|
1244
1439
|
}),
|
|
1245
1440
|
async handler(input, ctx) {
|
|
1246
1441
|
const state = await ctx.workspace.read();
|
|
@@ -1274,7 +1469,7 @@ var init_history = __esm({
|
|
|
1274
1469
|
historyGetRunTool = {
|
|
1275
1470
|
name: "history.get_run",
|
|
1276
1471
|
description: "Fetch a single history row in full (headers, body preview, assertion results).",
|
|
1277
|
-
inputSchema:
|
|
1472
|
+
inputSchema: import_zod7.z.object({ id: import_zod7.z.string() }),
|
|
1278
1473
|
async handler(input, ctx) {
|
|
1279
1474
|
const state = await ctx.workspace.read();
|
|
1280
1475
|
const run = state.local.history.requestRuns.find((r) => r.id === input.id);
|
|
@@ -1285,7 +1480,7 @@ var init_history = __esm({
|
|
|
1285
1480
|
historyDeleteRunTool = {
|
|
1286
1481
|
name: "history.delete_run",
|
|
1287
1482
|
description: "Delete a single request-run row by id.",
|
|
1288
|
-
inputSchema:
|
|
1483
|
+
inputSchema: import_zod7.z.object({ id: import_zod7.z.string() }),
|
|
1289
1484
|
async handler(input, ctx) {
|
|
1290
1485
|
const out = await ctx.workspace.apply({ kind: "history.delete_run", runId: input.id });
|
|
1291
1486
|
return { deleted: out.changedIds.length, changedIds: out.changedIds };
|
|
@@ -1294,8 +1489,8 @@ var init_history = __esm({
|
|
|
1294
1489
|
historyPurgeTool = {
|
|
1295
1490
|
name: "history.purge_by_age",
|
|
1296
1491
|
description: "Drop every request-run + plan-run older than `olderThanDays` days. Pass 0 to clear all history.",
|
|
1297
|
-
inputSchema:
|
|
1298
|
-
olderThanDays:
|
|
1492
|
+
inputSchema: import_zod7.z.object({
|
|
1493
|
+
olderThanDays: import_zod7.z.number().nonnegative()
|
|
1299
1494
|
}),
|
|
1300
1495
|
async handler(input, ctx) {
|
|
1301
1496
|
const olderThanMs = input.olderThanDays * 24 * 60 * 60 * 1e3;
|
|
@@ -1307,19 +1502,19 @@ var init_history = __esm({
|
|
|
1307
1502
|
});
|
|
1308
1503
|
|
|
1309
1504
|
// src/tools/codebase.ts
|
|
1310
|
-
var
|
|
1505
|
+
var import_zod8, HTTP_METHODS, codebaseExtractCollectionTool;
|
|
1311
1506
|
var init_codebase = __esm({
|
|
1312
1507
|
"src/tools/codebase.ts"() {
|
|
1313
1508
|
"use strict";
|
|
1314
|
-
|
|
1509
|
+
import_zod8 = require("zod");
|
|
1315
1510
|
HTTP_METHODS = ["get", "post", "put", "patch", "delete", "options", "head"];
|
|
1316
1511
|
codebaseExtractCollectionTool = {
|
|
1317
1512
|
name: "codebase.extract_collection",
|
|
1318
1513
|
description: "Scan source code for HTTP route definitions (Express, FastAPI, NestJS, Spring) and return candidate requests for the user to confirm before import.",
|
|
1319
|
-
inputSchema:
|
|
1320
|
-
source:
|
|
1514
|
+
inputSchema: import_zod8.z.object({
|
|
1515
|
+
source: import_zod8.z.string().min(1),
|
|
1321
1516
|
/** Hint to limit which framework patterns to apply. Empty = try all. */
|
|
1322
|
-
frameworks:
|
|
1517
|
+
frameworks: import_zod8.z.array(import_zod8.z.enum(["express", "fastapi", "nest", "spring"])).default([])
|
|
1323
1518
|
}),
|
|
1324
1519
|
async handler(input) {
|
|
1325
1520
|
const enabled = new Set(
|
|
@@ -1490,22 +1685,22 @@ function patchEndpoint(mock, endpointId, patcher) {
|
|
|
1490
1685
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1491
1686
|
};
|
|
1492
1687
|
}
|
|
1493
|
-
var
|
|
1688
|
+
var import_zod9, import_shared3, promptCreateEnvironmentTool, promptCreateAssertionTool, promptCreatePlanTool, HTTP_METHOD2, HEADER_OR_QUERY, REQUEST_BODY, PROMPT_AUTH, PROMPT_ASSERTION, ENDPOINT_RESPONSE, VALIDATION_RULE_NL, CONDITION_CLAUSE_NL, RESPONSE_RULE_NL, MULTIPLIER_NL, ENDPOINT_INPUT, promptCreateRequestTool, promptUpdateRequestTool, FOLDER_TREE_NODE, promptCreateFolderTreeTool, promptAddPlanStepsTool, promptSetPlanVariablesTool, promptCreateMockServerTool, promptAddMockEndpointTool, promptSetEndpointValidationRulesTool, promptSetEndpointResponseRulesTool, promptSetEndpointMultipliersTool;
|
|
1494
1689
|
var init_prompt = __esm({
|
|
1495
1690
|
"src/tools/prompt.ts"() {
|
|
1496
1691
|
"use strict";
|
|
1497
|
-
|
|
1692
|
+
import_zod9 = require("zod");
|
|
1498
1693
|
import_shared3 = require("@apicircle/shared");
|
|
1499
1694
|
promptCreateEnvironmentTool = {
|
|
1500
1695
|
name: "prompt.create_environment",
|
|
1501
1696
|
description: "Create a new environment from an LLM-shaped JSON envelope. The model produces { name, variables: [{ key, value, encrypted }] }; this tool validates and persists it.",
|
|
1502
|
-
inputSchema:
|
|
1503
|
-
name:
|
|
1504
|
-
variables:
|
|
1505
|
-
|
|
1506
|
-
key:
|
|
1507
|
-
value:
|
|
1508
|
-
encrypted:
|
|
1697
|
+
inputSchema: import_zod9.z.object({
|
|
1698
|
+
name: import_zod9.z.string(),
|
|
1699
|
+
variables: import_zod9.z.array(
|
|
1700
|
+
import_zod9.z.object({
|
|
1701
|
+
key: import_zod9.z.string(),
|
|
1702
|
+
value: import_zod9.z.string(),
|
|
1703
|
+
encrypted: import_zod9.z.boolean().default(false)
|
|
1509
1704
|
})
|
|
1510
1705
|
)
|
|
1511
1706
|
}),
|
|
@@ -1518,13 +1713,13 @@ var init_prompt = __esm({
|
|
|
1518
1713
|
promptCreateAssertionTool = {
|
|
1519
1714
|
name: "prompt.create_assertion",
|
|
1520
1715
|
description: 'Add an assertion to a request from an LLM-shaped JSON envelope. Useful when the user asks "assert that the response status is 200 and body.id matches".',
|
|
1521
|
-
inputSchema:
|
|
1522
|
-
requestId:
|
|
1523
|
-
assertion:
|
|
1524
|
-
kind:
|
|
1525
|
-
op:
|
|
1526
|
-
target:
|
|
1527
|
-
expected:
|
|
1716
|
+
inputSchema: import_zod9.z.object({
|
|
1717
|
+
requestId: import_zod9.z.string(),
|
|
1718
|
+
assertion: import_zod9.z.object({
|
|
1719
|
+
kind: import_zod9.z.enum(["status", "header", "json-path", "duration"]),
|
|
1720
|
+
op: import_zod9.z.enum(["equals", "not-equals", "contains", "lt", "gt", "matches"]),
|
|
1721
|
+
target: import_zod9.z.string().optional(),
|
|
1722
|
+
expected: import_zod9.z.union([import_zod9.z.string(), import_zod9.z.number()])
|
|
1528
1723
|
})
|
|
1529
1724
|
}),
|
|
1530
1725
|
async handler(input, ctx) {
|
|
@@ -1543,10 +1738,10 @@ var init_prompt = __esm({
|
|
|
1543
1738
|
promptCreatePlanTool = {
|
|
1544
1739
|
name: "prompt.create_plan",
|
|
1545
1740
|
description: "Create an execution plan from an LLM-shaped JSON envelope. The model produces { name, stepRequestIds: [...] } and the tool validates that each id exists in the workspace before persisting.",
|
|
1546
|
-
inputSchema:
|
|
1547
|
-
name:
|
|
1548
|
-
stepRequestIds:
|
|
1549
|
-
envPriorityOrder:
|
|
1741
|
+
inputSchema: import_zod9.z.object({
|
|
1742
|
+
name: import_zod9.z.string(),
|
|
1743
|
+
stepRequestIds: import_zod9.z.array(import_zod9.z.string()).default([]),
|
|
1744
|
+
envPriorityOrder: import_zod9.z.array(import_zod9.z.string()).default([])
|
|
1550
1745
|
}),
|
|
1551
1746
|
async handler(input, ctx) {
|
|
1552
1747
|
const state = await ctx.workspace.read();
|
|
@@ -1575,51 +1770,51 @@ var init_prompt = __esm({
|
|
|
1575
1770
|
return { ok: true, id, changedIds: out.changedIds };
|
|
1576
1771
|
}
|
|
1577
1772
|
};
|
|
1578
|
-
HTTP_METHOD2 =
|
|
1579
|
-
HEADER_OR_QUERY =
|
|
1580
|
-
key:
|
|
1581
|
-
value:
|
|
1582
|
-
enabled:
|
|
1773
|
+
HTTP_METHOD2 = import_zod9.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
1774
|
+
HEADER_OR_QUERY = import_zod9.z.object({
|
|
1775
|
+
key: import_zod9.z.string(),
|
|
1776
|
+
value: import_zod9.z.string(),
|
|
1777
|
+
enabled: import_zod9.z.boolean().default(true)
|
|
1583
1778
|
});
|
|
1584
|
-
REQUEST_BODY =
|
|
1585
|
-
type:
|
|
1586
|
-
content:
|
|
1587
|
-
variables:
|
|
1779
|
+
REQUEST_BODY = import_zod9.z.object({
|
|
1780
|
+
type: import_zod9.z.enum(["none", "json", "text", "xml", "graphql", "urlencoded"]).default("none"),
|
|
1781
|
+
content: import_zod9.z.string().default(""),
|
|
1782
|
+
variables: import_zod9.z.string().optional()
|
|
1588
1783
|
});
|
|
1589
|
-
PROMPT_AUTH =
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
type:
|
|
1595
|
-
username:
|
|
1596
|
-
password:
|
|
1784
|
+
PROMPT_AUTH = import_zod9.z.discriminatedUnion("type", [
|
|
1785
|
+
import_zod9.z.object({ type: import_zod9.z.literal("none") }),
|
|
1786
|
+
import_zod9.z.object({ type: import_zod9.z.literal("inherit") }),
|
|
1787
|
+
import_zod9.z.object({ type: import_zod9.z.literal("bearer"), token: import_zod9.z.string().default("") }),
|
|
1788
|
+
import_zod9.z.object({
|
|
1789
|
+
type: import_zod9.z.literal("basic"),
|
|
1790
|
+
username: import_zod9.z.string().default(""),
|
|
1791
|
+
password: import_zod9.z.string().default("")
|
|
1597
1792
|
}),
|
|
1598
|
-
|
|
1599
|
-
type:
|
|
1600
|
-
key:
|
|
1601
|
-
value:
|
|
1602
|
-
addTo:
|
|
1793
|
+
import_zod9.z.object({
|
|
1794
|
+
type: import_zod9.z.literal("api-key"),
|
|
1795
|
+
key: import_zod9.z.string().default(""),
|
|
1796
|
+
value: import_zod9.z.string().default(""),
|
|
1797
|
+
addTo: import_zod9.z.enum(["header", "query", "cookie"]).default("header")
|
|
1603
1798
|
}),
|
|
1604
|
-
|
|
1605
|
-
type:
|
|
1606
|
-
key:
|
|
1607
|
-
value:
|
|
1799
|
+
import_zod9.z.object({
|
|
1800
|
+
type: import_zod9.z.literal("custom-header"),
|
|
1801
|
+
key: import_zod9.z.string().default(""),
|
|
1802
|
+
value: import_zod9.z.string().default("")
|
|
1608
1803
|
})
|
|
1609
1804
|
]);
|
|
1610
|
-
PROMPT_ASSERTION =
|
|
1611
|
-
kind:
|
|
1612
|
-
op:
|
|
1613
|
-
target:
|
|
1614
|
-
expected:
|
|
1805
|
+
PROMPT_ASSERTION = import_zod9.z.object({
|
|
1806
|
+
kind: import_zod9.z.enum(["status", "header", "json-path", "duration"]),
|
|
1807
|
+
op: import_zod9.z.enum(["equals", "not-equals", "contains", "lt", "gt", "matches"]),
|
|
1808
|
+
target: import_zod9.z.string().optional(),
|
|
1809
|
+
expected: import_zod9.z.union([import_zod9.z.string(), import_zod9.z.number()])
|
|
1615
1810
|
});
|
|
1616
|
-
ENDPOINT_RESPONSE =
|
|
1617
|
-
status:
|
|
1618
|
-
jsonBody:
|
|
1619
|
-
contentType:
|
|
1811
|
+
ENDPOINT_RESPONSE = import_zod9.z.object({
|
|
1812
|
+
status: import_zod9.z.number().int().min(100).max(599).default(200),
|
|
1813
|
+
jsonBody: import_zod9.z.string().default("{}"),
|
|
1814
|
+
contentType: import_zod9.z.string().default("application/json")
|
|
1620
1815
|
});
|
|
1621
|
-
VALIDATION_RULE_NL =
|
|
1622
|
-
kind:
|
|
1816
|
+
VALIDATION_RULE_NL = import_zod9.z.object({
|
|
1817
|
+
kind: import_zod9.z.enum([
|
|
1623
1818
|
"header-required",
|
|
1624
1819
|
"header-equals",
|
|
1625
1820
|
"header-matches",
|
|
@@ -1630,65 +1825,65 @@ var init_prompt = __esm({
|
|
|
1630
1825
|
"body-required",
|
|
1631
1826
|
"content-type-equals"
|
|
1632
1827
|
]),
|
|
1633
|
-
target:
|
|
1634
|
-
expected:
|
|
1635
|
-
message:
|
|
1636
|
-
enabled:
|
|
1637
|
-
failResponse:
|
|
1638
|
-
status:
|
|
1639
|
-
jsonBody:
|
|
1828
|
+
target: import_zod9.z.string().default(""),
|
|
1829
|
+
expected: import_zod9.z.string().optional(),
|
|
1830
|
+
message: import_zod9.z.string().optional(),
|
|
1831
|
+
enabled: import_zod9.z.boolean().default(true),
|
|
1832
|
+
failResponse: import_zod9.z.object({
|
|
1833
|
+
status: import_zod9.z.number().int().min(100).max(599).default(400),
|
|
1834
|
+
jsonBody: import_zod9.z.string().default('{"error":"validation failed"}')
|
|
1640
1835
|
}).default({})
|
|
1641
1836
|
});
|
|
1642
|
-
CONDITION_CLAUSE_NL =
|
|
1643
|
-
scope:
|
|
1644
|
-
target:
|
|
1645
|
-
op:
|
|
1646
|
-
value:
|
|
1837
|
+
CONDITION_CLAUSE_NL = import_zod9.z.object({
|
|
1838
|
+
scope: import_zod9.z.enum(["query", "pathParam", "header", "cookie", "body-json-path"]),
|
|
1839
|
+
target: import_zod9.z.string(),
|
|
1840
|
+
op: import_zod9.z.enum(["equals", "not-equals", "matches", "gt", "lt", "gte", "lte", "present", "absent"]),
|
|
1841
|
+
value: import_zod9.z.string().optional()
|
|
1647
1842
|
});
|
|
1648
|
-
RESPONSE_RULE_NL =
|
|
1649
|
-
name:
|
|
1650
|
-
enabled:
|
|
1651
|
-
when:
|
|
1652
|
-
response:
|
|
1653
|
-
status:
|
|
1654
|
-
jsonBody:
|
|
1843
|
+
RESPONSE_RULE_NL = import_zod9.z.object({
|
|
1844
|
+
name: import_zod9.z.string(),
|
|
1845
|
+
enabled: import_zod9.z.boolean().default(true),
|
|
1846
|
+
when: import_zod9.z.array(CONDITION_CLAUSE_NL).default([]),
|
|
1847
|
+
response: import_zod9.z.object({
|
|
1848
|
+
status: import_zod9.z.number().int().min(100).max(599).default(200),
|
|
1849
|
+
jsonBody: import_zod9.z.string().default("{}")
|
|
1655
1850
|
}).default({})
|
|
1656
1851
|
});
|
|
1657
|
-
MULTIPLIER_NL =
|
|
1658
|
-
name:
|
|
1659
|
-
source:
|
|
1660
|
-
kind:
|
|
1661
|
-
key:
|
|
1852
|
+
MULTIPLIER_NL = import_zod9.z.object({
|
|
1853
|
+
name: import_zod9.z.string().optional(),
|
|
1854
|
+
source: import_zod9.z.object({
|
|
1855
|
+
kind: import_zod9.z.enum(["query", "pathParam", "header", "body-json-path"]),
|
|
1856
|
+
key: import_zod9.z.string()
|
|
1662
1857
|
}),
|
|
1663
|
-
targetJsonPath:
|
|
1664
|
-
defaultCount:
|
|
1665
|
-
min:
|
|
1666
|
-
max:
|
|
1858
|
+
targetJsonPath: import_zod9.z.string(),
|
|
1859
|
+
defaultCount: import_zod9.z.number().int().nonnegative().default(0),
|
|
1860
|
+
min: import_zod9.z.number().int().nonnegative().optional(),
|
|
1861
|
+
max: import_zod9.z.number().int().nonnegative().optional()
|
|
1667
1862
|
});
|
|
1668
|
-
ENDPOINT_INPUT =
|
|
1863
|
+
ENDPOINT_INPUT = import_zod9.z.object({
|
|
1669
1864
|
method: HTTP_METHOD2,
|
|
1670
|
-
pathPattern:
|
|
1671
|
-
name:
|
|
1672
|
-
description:
|
|
1865
|
+
pathPattern: import_zod9.z.string().min(1),
|
|
1866
|
+
name: import_zod9.z.string().optional(),
|
|
1867
|
+
description: import_zod9.z.string().optional(),
|
|
1673
1868
|
response: ENDPOINT_RESPONSE.optional(),
|
|
1674
|
-
validationRules:
|
|
1675
|
-
responseRules:
|
|
1676
|
-
multipliers:
|
|
1869
|
+
validationRules: import_zod9.z.array(VALIDATION_RULE_NL).default([]),
|
|
1870
|
+
responseRules: import_zod9.z.array(RESPONSE_RULE_NL).default([]),
|
|
1871
|
+
multipliers: import_zod9.z.array(MULTIPLIER_NL).default([])
|
|
1677
1872
|
});
|
|
1678
1873
|
promptCreateRequestTool = {
|
|
1679
1874
|
name: "prompt.create_request",
|
|
1680
1875
|
description: "Create a fully-shaped request from an LLM-shaped JSON envelope: method, url, headers, query params, body, auth, and inline assertions. The model produces a flat object; this tool generates the request id, normalizes auth (defaults to `inherit` so folder auth wins), and persists.",
|
|
1681
|
-
inputSchema:
|
|
1682
|
-
name:
|
|
1876
|
+
inputSchema: import_zod9.z.object({
|
|
1877
|
+
name: import_zod9.z.string().default("New request"),
|
|
1683
1878
|
method: HTTP_METHOD2.default("GET"),
|
|
1684
|
-
url:
|
|
1685
|
-
folderId:
|
|
1686
|
-
headers:
|
|
1687
|
-
queryParams:
|
|
1688
|
-
pathParams:
|
|
1879
|
+
url: import_zod9.z.string().default(""),
|
|
1880
|
+
folderId: import_zod9.z.string().nullable().optional(),
|
|
1881
|
+
headers: import_zod9.z.array(HEADER_OR_QUERY).default([]),
|
|
1882
|
+
queryParams: import_zod9.z.array(HEADER_OR_QUERY).default([]),
|
|
1883
|
+
pathParams: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.string()).optional(),
|
|
1689
1884
|
body: REQUEST_BODY.optional(),
|
|
1690
1885
|
auth: PROMPT_AUTH.optional(),
|
|
1691
|
-
assertions:
|
|
1886
|
+
assertions: import_zod9.z.array(PROMPT_ASSERTION).default([])
|
|
1692
1887
|
}),
|
|
1693
1888
|
async handler(input, ctx) {
|
|
1694
1889
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1718,19 +1913,19 @@ var init_prompt = __esm({
|
|
|
1718
1913
|
promptUpdateRequestTool = {
|
|
1719
1914
|
name: "prompt.update_request",
|
|
1720
1915
|
description: "Patch an existing request from an LLM-shaped JSON envelope. Provided fields replace the existing values; omitted fields are left untouched. Arrays (headers, queryParams, assertions) are full replacements when supplied. Returns `{ ok: false, error }` when the id does not resolve.",
|
|
1721
|
-
inputSchema:
|
|
1722
|
-
id:
|
|
1723
|
-
patch:
|
|
1724
|
-
name:
|
|
1916
|
+
inputSchema: import_zod9.z.object({
|
|
1917
|
+
id: import_zod9.z.string(),
|
|
1918
|
+
patch: import_zod9.z.object({
|
|
1919
|
+
name: import_zod9.z.string().optional(),
|
|
1725
1920
|
method: HTTP_METHOD2.optional(),
|
|
1726
|
-
url:
|
|
1727
|
-
folderId:
|
|
1728
|
-
headers:
|
|
1729
|
-
queryParams:
|
|
1730
|
-
pathParams:
|
|
1921
|
+
url: import_zod9.z.string().optional(),
|
|
1922
|
+
folderId: import_zod9.z.string().nullable().optional(),
|
|
1923
|
+
headers: import_zod9.z.array(HEADER_OR_QUERY).optional(),
|
|
1924
|
+
queryParams: import_zod9.z.array(HEADER_OR_QUERY).optional(),
|
|
1925
|
+
pathParams: import_zod9.z.record(import_zod9.z.string(), import_zod9.z.string()).optional(),
|
|
1731
1926
|
body: REQUEST_BODY.optional(),
|
|
1732
1927
|
auth: PROMPT_AUTH.optional(),
|
|
1733
|
-
assertions:
|
|
1928
|
+
assertions: import_zod9.z.array(PROMPT_ASSERTION).optional()
|
|
1734
1929
|
}).strict()
|
|
1735
1930
|
}),
|
|
1736
1931
|
async handler(input, ctx) {
|
|
@@ -1758,17 +1953,17 @@ var init_prompt = __esm({
|
|
|
1758
1953
|
return { ok: true, changedIds: out.changedIds };
|
|
1759
1954
|
}
|
|
1760
1955
|
};
|
|
1761
|
-
FOLDER_TREE_NODE =
|
|
1762
|
-
() =>
|
|
1763
|
-
name:
|
|
1764
|
-
children:
|
|
1956
|
+
FOLDER_TREE_NODE = import_zod9.z.lazy(
|
|
1957
|
+
() => import_zod9.z.object({
|
|
1958
|
+
name: import_zod9.z.string(),
|
|
1959
|
+
children: import_zod9.z.array(FOLDER_TREE_NODE).optional()
|
|
1765
1960
|
})
|
|
1766
1961
|
);
|
|
1767
1962
|
promptCreateFolderTreeTool = {
|
|
1768
1963
|
name: "prompt.create_folder_tree",
|
|
1769
1964
|
description: "Create a recursive folder hierarchy from an LLM-shaped JSON envelope. The model produces `{ parentId?, tree: { name, children?: [...] } }` and this tool walks the tree, generating ids and persisting one folder per node. Returns the list of created ids in pre-order.",
|
|
1770
|
-
inputSchema:
|
|
1771
|
-
parentId:
|
|
1965
|
+
inputSchema: import_zod9.z.object({
|
|
1966
|
+
parentId: import_zod9.z.string().nullable().optional(),
|
|
1772
1967
|
tree: FOLDER_TREE_NODE
|
|
1773
1968
|
}),
|
|
1774
1969
|
async handler(input, ctx) {
|
|
@@ -1794,9 +1989,9 @@ var init_prompt = __esm({
|
|
|
1794
1989
|
promptAddPlanStepsTool = {
|
|
1795
1990
|
name: "prompt.add_plan_steps",
|
|
1796
1991
|
description: "Append one or more steps to an existing execution plan from an LLM-shaped JSON envelope. The model produces `{ planId, requestIds: [...] }`; each id is validated against the workspace before any step is appended. Order in the input list is preserved.",
|
|
1797
|
-
inputSchema:
|
|
1798
|
-
planId:
|
|
1799
|
-
requestIds:
|
|
1992
|
+
inputSchema: import_zod9.z.object({
|
|
1993
|
+
planId: import_zod9.z.string(),
|
|
1994
|
+
requestIds: import_zod9.z.array(import_zod9.z.string()).min(1)
|
|
1800
1995
|
}),
|
|
1801
1996
|
async handler(input, ctx) {
|
|
1802
1997
|
const state = await ctx.workspace.read();
|
|
@@ -1826,9 +2021,9 @@ var init_prompt = __esm({
|
|
|
1826
2021
|
promptSetPlanVariablesTool = {
|
|
1827
2022
|
name: "prompt.set_plan_variables",
|
|
1828
2023
|
description: "Replace the plan-scoped variables on an execution plan from an LLM-shaped JSON envelope. The model produces `{ planId, variables: [{ key, value }] }`. Empty array clears all plan variables.",
|
|
1829
|
-
inputSchema:
|
|
1830
|
-
planId:
|
|
1831
|
-
variables:
|
|
2024
|
+
inputSchema: import_zod9.z.object({
|
|
2025
|
+
planId: import_zod9.z.string(),
|
|
2026
|
+
variables: import_zod9.z.array(import_zod9.z.object({ key: import_zod9.z.string(), value: import_zod9.z.string() }))
|
|
1832
2027
|
}),
|
|
1833
2028
|
async handler(input, ctx) {
|
|
1834
2029
|
const state = await ctx.workspace.read();
|
|
@@ -1844,10 +2039,10 @@ var init_prompt = __esm({
|
|
|
1844
2039
|
promptCreateMockServerTool = {
|
|
1845
2040
|
name: "prompt.create_mock_server",
|
|
1846
2041
|
description: "Create a manual-mode mock server with optional inline endpoints from an LLM-shaped JSON envelope. The model produces `{ name, defaultPort?, endpoints: [{ method, pathPattern, name?, response?, validationRules?, responseRules?, multipliers? }] }`; this tool generates ids for the server and every endpoint / rule, then persists in one shot.",
|
|
1847
|
-
inputSchema:
|
|
1848
|
-
name:
|
|
1849
|
-
defaultPort:
|
|
1850
|
-
endpoints:
|
|
2042
|
+
inputSchema: import_zod9.z.object({
|
|
2043
|
+
name: import_zod9.z.string().min(1),
|
|
2044
|
+
defaultPort: import_zod9.z.number().int().positive().nullable().optional(),
|
|
2045
|
+
endpoints: import_zod9.z.array(ENDPOINT_INPUT).default([])
|
|
1851
2046
|
}),
|
|
1852
2047
|
async handler(input, ctx) {
|
|
1853
2048
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1874,16 +2069,16 @@ var init_prompt = __esm({
|
|
|
1874
2069
|
promptAddMockEndpointTool = {
|
|
1875
2070
|
name: "prompt.add_mock_endpoint",
|
|
1876
2071
|
description: "Append a new endpoint (with optional inline validation rules, response rules, and multipliers) to an existing mock server from an LLM-shaped JSON envelope. All ids are auto-generated; the existing endpoints stay in place.",
|
|
1877
|
-
inputSchema:
|
|
1878
|
-
mockId:
|
|
2072
|
+
inputSchema: import_zod9.z.object({
|
|
2073
|
+
mockId: import_zod9.z.string(),
|
|
1879
2074
|
method: HTTP_METHOD2,
|
|
1880
|
-
pathPattern:
|
|
1881
|
-
name:
|
|
1882
|
-
description:
|
|
2075
|
+
pathPattern: import_zod9.z.string().min(1),
|
|
2076
|
+
name: import_zod9.z.string().optional(),
|
|
2077
|
+
description: import_zod9.z.string().optional(),
|
|
1883
2078
|
response: ENDPOINT_RESPONSE.optional(),
|
|
1884
|
-
validationRules:
|
|
1885
|
-
responseRules:
|
|
1886
|
-
multipliers:
|
|
2079
|
+
validationRules: import_zod9.z.array(VALIDATION_RULE_NL).default([]),
|
|
2080
|
+
responseRules: import_zod9.z.array(RESPONSE_RULE_NL).default([]),
|
|
2081
|
+
multipliers: import_zod9.z.array(MULTIPLIER_NL).default([])
|
|
1887
2082
|
}),
|
|
1888
2083
|
async handler(input, ctx) {
|
|
1889
2084
|
const state = await ctx.workspace.read();
|
|
@@ -1905,10 +2100,10 @@ var init_prompt = __esm({
|
|
|
1905
2100
|
promptSetEndpointValidationRulesTool = {
|
|
1906
2101
|
name: "prompt.set_endpoint_validation_rules",
|
|
1907
2102
|
description: "Replace an endpoint's validation rules with an LLM-shaped list. Every rule gets a fresh id; the existing rules are dropped. Empty array clears all validation rules.",
|
|
1908
|
-
inputSchema:
|
|
1909
|
-
mockId:
|
|
1910
|
-
endpointId:
|
|
1911
|
-
rules:
|
|
2103
|
+
inputSchema: import_zod9.z.object({
|
|
2104
|
+
mockId: import_zod9.z.string(),
|
|
2105
|
+
endpointId: import_zod9.z.string(),
|
|
2106
|
+
rules: import_zod9.z.array(VALIDATION_RULE_NL)
|
|
1912
2107
|
}),
|
|
1913
2108
|
async handler(input, ctx) {
|
|
1914
2109
|
const state = await ctx.workspace.read();
|
|
@@ -1939,10 +2134,10 @@ var init_prompt = __esm({
|
|
|
1939
2134
|
promptSetEndpointResponseRulesTool = {
|
|
1940
2135
|
name: "prompt.set_endpoint_response_rules",
|
|
1941
2136
|
description: "Replace an endpoint's conditional response rules with an LLM-shaped list. Rules fire in order, first match wins. Every rule + clause gets a fresh id. Empty array falls back to defaultResponse.",
|
|
1942
|
-
inputSchema:
|
|
1943
|
-
mockId:
|
|
1944
|
-
endpointId:
|
|
1945
|
-
rules:
|
|
2137
|
+
inputSchema: import_zod9.z.object({
|
|
2138
|
+
mockId: import_zod9.z.string(),
|
|
2139
|
+
endpointId: import_zod9.z.string(),
|
|
2140
|
+
rules: import_zod9.z.array(RESPONSE_RULE_NL)
|
|
1946
2141
|
}),
|
|
1947
2142
|
async handler(input, ctx) {
|
|
1948
2143
|
const state = await ctx.workspace.read();
|
|
@@ -1977,10 +2172,10 @@ var init_prompt = __esm({
|
|
|
1977
2172
|
promptSetEndpointMultipliersTool = {
|
|
1978
2173
|
name: "prompt.set_endpoint_multipliers",
|
|
1979
2174
|
description: "Replace the response multipliers on an endpoint's defaultResponse with an LLM-shaped list. Multipliers expand an array at `targetJsonPath` to a count derived from a request value. Every multiplier gets a fresh id. Empty array clears all multipliers.",
|
|
1980
|
-
inputSchema:
|
|
1981
|
-
mockId:
|
|
1982
|
-
endpointId:
|
|
1983
|
-
multipliers:
|
|
2175
|
+
inputSchema: import_zod9.z.object({
|
|
2176
|
+
mockId: import_zod9.z.string(),
|
|
2177
|
+
endpointId: import_zod9.z.string(),
|
|
2178
|
+
multipliers: import_zod9.z.array(MULTIPLIER_NL)
|
|
1984
2179
|
}),
|
|
1985
2180
|
async handler(input, ctx) {
|
|
1986
2181
|
const state = await ctx.workspace.read();
|
|
@@ -2072,20 +2267,20 @@ function patchEndpoint2(mock, endpointId, patcher) {
|
|
|
2072
2267
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2073
2268
|
};
|
|
2074
2269
|
}
|
|
2075
|
-
var
|
|
2270
|
+
var import_zod10, import_shared4, import_mock_server_core2, mockCreateFromOpenApiTool, mockCreateFromPostmanTool, mockCreateFromInsomniaTool, mockImportPostmanMockCollectionTool, mockListTool, mockStartTool, mockStopTool, mockDeleteTool, HTTP_METHOD3, mockCreateManualTool, mockListEndpointsTool, ENDPOINT_RESPONSE2, mockAddEndpointTool, mockUpdateEndpointTool, mockDeleteEndpointTool, VALIDATION_RULE, CONDITION_CLAUSE, RESPONSE_RULE, MULTIPLIER, mockSetValidationRulesTool, mockSetResponseRulesTool, mockSetMultipliersTool;
|
|
2076
2271
|
var init_mocks = __esm({
|
|
2077
2272
|
"src/tools/mocks.ts"() {
|
|
2078
2273
|
"use strict";
|
|
2079
|
-
|
|
2274
|
+
import_zod10 = require("zod");
|
|
2080
2275
|
import_shared4 = require("@apicircle/shared");
|
|
2081
2276
|
import_mock_server_core2 = require("@apicircle/mock-server-core");
|
|
2082
2277
|
mockCreateFromOpenApiTool = {
|
|
2083
2278
|
name: "mock.create_from_openapi",
|
|
2084
2279
|
description: "Create a mock server from an OpenAPI / Swagger spec (YAML or JSON).",
|
|
2085
|
-
inputSchema:
|
|
2086
|
-
name:
|
|
2087
|
-
spec:
|
|
2088
|
-
format:
|
|
2280
|
+
inputSchema: import_zod10.z.object({
|
|
2281
|
+
name: import_zod10.z.string(),
|
|
2282
|
+
spec: import_zod10.z.string().min(1),
|
|
2283
|
+
format: import_zod10.z.enum(["json", "yaml"]).default("json")
|
|
2089
2284
|
}),
|
|
2090
2285
|
async handler(input, ctx) {
|
|
2091
2286
|
const { mock, warnings } = await ingestSource(
|
|
@@ -2104,7 +2299,7 @@ var init_mocks = __esm({
|
|
|
2104
2299
|
mockCreateFromPostmanTool = {
|
|
2105
2300
|
name: "mock.create_from_postman",
|
|
2106
2301
|
description: "Create a mock server from a Postman v2/v2.1 collection.",
|
|
2107
|
-
inputSchema:
|
|
2302
|
+
inputSchema: import_zod10.z.object({ name: import_zod10.z.string(), collection: import_zod10.z.string().min(1) }),
|
|
2108
2303
|
async handler(input, ctx) {
|
|
2109
2304
|
const { mock, warnings } = await ingestSource(
|
|
2110
2305
|
{ kind: "postman", collection: input.collection },
|
|
@@ -2122,7 +2317,7 @@ var init_mocks = __esm({
|
|
|
2122
2317
|
mockCreateFromInsomniaTool = {
|
|
2123
2318
|
name: "mock.create_from_insomnia",
|
|
2124
2319
|
description: "Create a mock server from an Insomnia v4 export.",
|
|
2125
|
-
inputSchema:
|
|
2320
|
+
inputSchema: import_zod10.z.object({ name: import_zod10.z.string(), export: import_zod10.z.string().min(1) }),
|
|
2126
2321
|
async handler(input, ctx) {
|
|
2127
2322
|
const { mock, warnings } = await ingestSource(
|
|
2128
2323
|
{ kind: "insomnia", export: input.export },
|
|
@@ -2140,7 +2335,7 @@ var init_mocks = __esm({
|
|
|
2140
2335
|
mockImportPostmanMockCollectionTool = {
|
|
2141
2336
|
name: "mock.import_postman_mock_collection",
|
|
2142
2337
|
description: "Import a Postman Mock Collection (collections previously hosted on Postman's mock service). Same parser as a regular Postman collection but marked as a mock import.",
|
|
2143
|
-
inputSchema:
|
|
2338
|
+
inputSchema: import_zod10.z.object({ name: import_zod10.z.string(), collection: import_zod10.z.string().min(1) }),
|
|
2144
2339
|
async handler(input, ctx) {
|
|
2145
2340
|
const { mock, warnings } = await ingestSource(
|
|
2146
2341
|
{ kind: "postman", collection: input.collection },
|
|
@@ -2158,7 +2353,7 @@ var init_mocks = __esm({
|
|
|
2158
2353
|
mockListTool = {
|
|
2159
2354
|
name: "mock.list",
|
|
2160
2355
|
description: "List all mock servers in the workspace plus their runtime status (running / stopped, port).",
|
|
2161
|
-
inputSchema:
|
|
2356
|
+
inputSchema: import_zod10.z.object({}),
|
|
2162
2357
|
async handler(_input, ctx) {
|
|
2163
2358
|
const state = await ctx.workspace.read();
|
|
2164
2359
|
const running = await ctx.mock.list();
|
|
@@ -2180,9 +2375,9 @@ var init_mocks = __esm({
|
|
|
2180
2375
|
mockStartTool = {
|
|
2181
2376
|
name: "mock.start",
|
|
2182
2377
|
description: "Start a mock server by id. Returns the bound port. Errors if the mock is already running or the requested port is in use.",
|
|
2183
|
-
inputSchema:
|
|
2184
|
-
id:
|
|
2185
|
-
port:
|
|
2378
|
+
inputSchema: import_zod10.z.object({
|
|
2379
|
+
id: import_zod10.z.string(),
|
|
2380
|
+
port: import_zod10.z.number().int().positive().optional()
|
|
2186
2381
|
}),
|
|
2187
2382
|
async handler(input, ctx) {
|
|
2188
2383
|
const state = await ctx.workspace.read();
|
|
@@ -2199,7 +2394,7 @@ var init_mocks = __esm({
|
|
|
2199
2394
|
mockStopTool = {
|
|
2200
2395
|
name: "mock.stop",
|
|
2201
2396
|
description: "Stop a running mock server by id (no-op if not running).",
|
|
2202
|
-
inputSchema:
|
|
2397
|
+
inputSchema: import_zod10.z.object({ id: import_zod10.z.string() }),
|
|
2203
2398
|
async handler(input, ctx) {
|
|
2204
2399
|
try {
|
|
2205
2400
|
await ctx.mock.stop(input.id);
|
|
@@ -2212,7 +2407,7 @@ var init_mocks = __esm({
|
|
|
2212
2407
|
mockDeleteTool = {
|
|
2213
2408
|
name: "mock.delete",
|
|
2214
2409
|
description: "Delete a mock server definition. Stops it first if it's running.",
|
|
2215
|
-
inputSchema:
|
|
2410
|
+
inputSchema: import_zod10.z.object({ id: import_zod10.z.string() }),
|
|
2216
2411
|
async handler(input, ctx) {
|
|
2217
2412
|
try {
|
|
2218
2413
|
await ctx.mock.stop(input.id);
|
|
@@ -2222,13 +2417,13 @@ var init_mocks = __esm({
|
|
|
2222
2417
|
return { ok: true, changedIds: out.changedIds };
|
|
2223
2418
|
}
|
|
2224
2419
|
};
|
|
2225
|
-
HTTP_METHOD3 =
|
|
2420
|
+
HTTP_METHOD3 = import_zod10.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
2226
2421
|
mockCreateManualTool = {
|
|
2227
2422
|
name: "mock.create_manual",
|
|
2228
2423
|
description: "Create an empty manual-mode mock server. Use `mock.add_endpoint` afterward to populate it. CORS defaults to off (same-origin only); enable + list explicit origins via `mock.update_cors` if cross-origin access is needed.",
|
|
2229
|
-
inputSchema:
|
|
2230
|
-
name:
|
|
2231
|
-
defaultPort:
|
|
2424
|
+
inputSchema: import_zod10.z.object({
|
|
2425
|
+
name: import_zod10.z.string().min(1),
|
|
2426
|
+
defaultPort: import_zod10.z.number().int().positive().nullable().optional()
|
|
2232
2427
|
}),
|
|
2233
2428
|
async handler(input, ctx) {
|
|
2234
2429
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2251,7 +2446,7 @@ var init_mocks = __esm({
|
|
|
2251
2446
|
mockListEndpointsTool = {
|
|
2252
2447
|
name: "mock.list_endpoints",
|
|
2253
2448
|
description: "List endpoints for a mock server (id, method, path, name).",
|
|
2254
|
-
inputSchema:
|
|
2449
|
+
inputSchema: import_zod10.z.object({ mockId: import_zod10.z.string() }),
|
|
2255
2450
|
async handler(input, ctx) {
|
|
2256
2451
|
const state = await ctx.workspace.read();
|
|
2257
2452
|
const mock = state.synced.mockServers[input.mockId];
|
|
@@ -2270,20 +2465,20 @@ var init_mocks = __esm({
|
|
|
2270
2465
|
};
|
|
2271
2466
|
}
|
|
2272
2467
|
};
|
|
2273
|
-
ENDPOINT_RESPONSE2 =
|
|
2274
|
-
status:
|
|
2275
|
-
jsonBody:
|
|
2276
|
-
contentType:
|
|
2468
|
+
ENDPOINT_RESPONSE2 = import_zod10.z.object({
|
|
2469
|
+
status: import_zod10.z.number().int().min(100).max(599).default(200),
|
|
2470
|
+
jsonBody: import_zod10.z.string().default("{}"),
|
|
2471
|
+
contentType: import_zod10.z.string().default("application/json")
|
|
2277
2472
|
});
|
|
2278
2473
|
mockAddEndpointTool = {
|
|
2279
2474
|
name: "mock.add_endpoint",
|
|
2280
2475
|
description: "Append a new endpoint to a mock server. Defaults to a 200 JSON response of `{}`. Returns the new endpoint id.",
|
|
2281
|
-
inputSchema:
|
|
2282
|
-
mockId:
|
|
2476
|
+
inputSchema: import_zod10.z.object({
|
|
2477
|
+
mockId: import_zod10.z.string(),
|
|
2283
2478
|
method: HTTP_METHOD3,
|
|
2284
|
-
pathPattern:
|
|
2285
|
-
name:
|
|
2286
|
-
description:
|
|
2479
|
+
pathPattern: import_zod10.z.string().min(1),
|
|
2480
|
+
name: import_zod10.z.string().optional(),
|
|
2481
|
+
description: import_zod10.z.string().optional(),
|
|
2287
2482
|
response: ENDPOINT_RESPONSE2.optional()
|
|
2288
2483
|
}),
|
|
2289
2484
|
async handler(input, ctx) {
|
|
@@ -2306,13 +2501,13 @@ var init_mocks = __esm({
|
|
|
2306
2501
|
mockUpdateEndpointTool = {
|
|
2307
2502
|
name: "mock.update_endpoint",
|
|
2308
2503
|
description: "Patch fields on a single mock endpoint (method, pathPattern, name, description, defaultResponse status / contentType / json body). Pass only the fields you want to change.",
|
|
2309
|
-
inputSchema:
|
|
2310
|
-
mockId:
|
|
2311
|
-
endpointId:
|
|
2504
|
+
inputSchema: import_zod10.z.object({
|
|
2505
|
+
mockId: import_zod10.z.string(),
|
|
2506
|
+
endpointId: import_zod10.z.string(),
|
|
2312
2507
|
method: HTTP_METHOD3.optional(),
|
|
2313
|
-
pathPattern:
|
|
2314
|
-
name:
|
|
2315
|
-
description:
|
|
2508
|
+
pathPattern: import_zod10.z.string().optional(),
|
|
2509
|
+
name: import_zod10.z.string().optional(),
|
|
2510
|
+
description: import_zod10.z.string().optional(),
|
|
2316
2511
|
response: ENDPOINT_RESPONSE2.partial().optional()
|
|
2317
2512
|
}),
|
|
2318
2513
|
async handler(input, ctx) {
|
|
@@ -2353,7 +2548,7 @@ var init_mocks = __esm({
|
|
|
2353
2548
|
mockDeleteEndpointTool = {
|
|
2354
2549
|
name: "mock.delete_endpoint",
|
|
2355
2550
|
description: "Remove an endpoint from a mock server.",
|
|
2356
|
-
inputSchema:
|
|
2551
|
+
inputSchema: import_zod10.z.object({ mockId: import_zod10.z.string(), endpointId: import_zod10.z.string() }),
|
|
2357
2552
|
async handler(input, ctx) {
|
|
2358
2553
|
const state = await ctx.workspace.read();
|
|
2359
2554
|
const mock = state.synced.mockServers[input.mockId];
|
|
@@ -2373,9 +2568,9 @@ var init_mocks = __esm({
|
|
|
2373
2568
|
return { ok: true, changedIds: out.changedIds };
|
|
2374
2569
|
}
|
|
2375
2570
|
};
|
|
2376
|
-
VALIDATION_RULE =
|
|
2377
|
-
id:
|
|
2378
|
-
kind:
|
|
2571
|
+
VALIDATION_RULE = import_zod10.z.object({
|
|
2572
|
+
id: import_zod10.z.string().optional(),
|
|
2573
|
+
kind: import_zod10.z.enum([
|
|
2379
2574
|
"header-required",
|
|
2380
2575
|
"header-equals",
|
|
2381
2576
|
"header-matches",
|
|
@@ -2386,51 +2581,51 @@ var init_mocks = __esm({
|
|
|
2386
2581
|
"body-required",
|
|
2387
2582
|
"content-type-equals"
|
|
2388
2583
|
]),
|
|
2389
|
-
target:
|
|
2390
|
-
expected:
|
|
2391
|
-
message:
|
|
2392
|
-
enabled:
|
|
2393
|
-
failResponse:
|
|
2394
|
-
status:
|
|
2395
|
-
jsonBody:
|
|
2584
|
+
target: import_zod10.z.string().default(""),
|
|
2585
|
+
expected: import_zod10.z.string().optional(),
|
|
2586
|
+
message: import_zod10.z.string().optional(),
|
|
2587
|
+
enabled: import_zod10.z.boolean().default(true),
|
|
2588
|
+
failResponse: import_zod10.z.object({
|
|
2589
|
+
status: import_zod10.z.number().int().min(100).max(599).default(400),
|
|
2590
|
+
jsonBody: import_zod10.z.string().default('{"error":"validation failed"}')
|
|
2396
2591
|
}).default({})
|
|
2397
2592
|
});
|
|
2398
|
-
CONDITION_CLAUSE =
|
|
2399
|
-
id:
|
|
2400
|
-
scope:
|
|
2401
|
-
target:
|
|
2402
|
-
op:
|
|
2403
|
-
value:
|
|
2593
|
+
CONDITION_CLAUSE = import_zod10.z.object({
|
|
2594
|
+
id: import_zod10.z.string().optional(),
|
|
2595
|
+
scope: import_zod10.z.enum(["query", "pathParam", "header", "cookie", "body-json-path"]),
|
|
2596
|
+
target: import_zod10.z.string(),
|
|
2597
|
+
op: import_zod10.z.enum(["equals", "not-equals", "matches", "gt", "lt", "gte", "lte", "present", "absent"]),
|
|
2598
|
+
value: import_zod10.z.string().optional()
|
|
2404
2599
|
});
|
|
2405
|
-
RESPONSE_RULE =
|
|
2406
|
-
id:
|
|
2407
|
-
name:
|
|
2408
|
-
enabled:
|
|
2409
|
-
when:
|
|
2410
|
-
response:
|
|
2411
|
-
status:
|
|
2412
|
-
jsonBody:
|
|
2600
|
+
RESPONSE_RULE = import_zod10.z.object({
|
|
2601
|
+
id: import_zod10.z.string().optional(),
|
|
2602
|
+
name: import_zod10.z.string(),
|
|
2603
|
+
enabled: import_zod10.z.boolean().default(true),
|
|
2604
|
+
when: import_zod10.z.array(CONDITION_CLAUSE).default([]),
|
|
2605
|
+
response: import_zod10.z.object({
|
|
2606
|
+
status: import_zod10.z.number().int().min(100).max(599).default(200),
|
|
2607
|
+
jsonBody: import_zod10.z.string().default("{}")
|
|
2413
2608
|
}).default({})
|
|
2414
2609
|
});
|
|
2415
|
-
MULTIPLIER =
|
|
2416
|
-
id:
|
|
2417
|
-
name:
|
|
2418
|
-
source:
|
|
2419
|
-
kind:
|
|
2420
|
-
key:
|
|
2610
|
+
MULTIPLIER = import_zod10.z.object({
|
|
2611
|
+
id: import_zod10.z.string().optional(),
|
|
2612
|
+
name: import_zod10.z.string().optional(),
|
|
2613
|
+
source: import_zod10.z.object({
|
|
2614
|
+
kind: import_zod10.z.enum(["query", "pathParam", "header", "body-json-path"]),
|
|
2615
|
+
key: import_zod10.z.string()
|
|
2421
2616
|
}),
|
|
2422
|
-
targetJsonPath:
|
|
2423
|
-
defaultCount:
|
|
2424
|
-
min:
|
|
2425
|
-
max:
|
|
2617
|
+
targetJsonPath: import_zod10.z.string(),
|
|
2618
|
+
defaultCount: import_zod10.z.number().int().nonnegative().default(0),
|
|
2619
|
+
min: import_zod10.z.number().int().nonnegative().optional(),
|
|
2620
|
+
max: import_zod10.z.number().int().nonnegative().optional()
|
|
2426
2621
|
});
|
|
2427
2622
|
mockSetValidationRulesTool = {
|
|
2428
2623
|
name: "mock.set_validation_rules",
|
|
2429
2624
|
description: "Replace an endpoint's validation rules. Rules without an `id` get a fresh one; existing rules can keep theirs to preserve client-side selection state. Empty array clears all rules.",
|
|
2430
|
-
inputSchema:
|
|
2431
|
-
mockId:
|
|
2432
|
-
endpointId:
|
|
2433
|
-
rules:
|
|
2625
|
+
inputSchema: import_zod10.z.object({
|
|
2626
|
+
mockId: import_zod10.z.string(),
|
|
2627
|
+
endpointId: import_zod10.z.string(),
|
|
2628
|
+
rules: import_zod10.z.array(VALIDATION_RULE)
|
|
2434
2629
|
}),
|
|
2435
2630
|
async handler(input, ctx) {
|
|
2436
2631
|
const state = await ctx.workspace.read();
|
|
@@ -2457,10 +2652,10 @@ var init_mocks = __esm({
|
|
|
2457
2652
|
mockSetResponseRulesTool = {
|
|
2458
2653
|
name: "mock.set_response_rules",
|
|
2459
2654
|
description: "Replace an endpoint's conditional response rules. Rules fire in order; the first whose every clause matches wins. Disabled rules are skipped. Empty array falls back to defaultResponse.",
|
|
2460
|
-
inputSchema:
|
|
2461
|
-
mockId:
|
|
2462
|
-
endpointId:
|
|
2463
|
-
rules:
|
|
2655
|
+
inputSchema: import_zod10.z.object({
|
|
2656
|
+
mockId: import_zod10.z.string(),
|
|
2657
|
+
endpointId: import_zod10.z.string(),
|
|
2658
|
+
rules: import_zod10.z.array(RESPONSE_RULE)
|
|
2464
2659
|
}),
|
|
2465
2660
|
async handler(input, ctx) {
|
|
2466
2661
|
const state = await ctx.workspace.read();
|
|
@@ -2491,10 +2686,10 @@ var init_mocks = __esm({
|
|
|
2491
2686
|
mockSetMultipliersTool = {
|
|
2492
2687
|
name: "mock.set_multipliers",
|
|
2493
2688
|
description: "Replace the response multipliers on an endpoint's defaultResponse. Multipliers expand an array at `targetJsonPath` to a count derived from a request value. Empty array clears all multipliers.",
|
|
2494
|
-
inputSchema:
|
|
2495
|
-
mockId:
|
|
2496
|
-
endpointId:
|
|
2497
|
-
multipliers:
|
|
2689
|
+
inputSchema: import_zod10.z.object({
|
|
2690
|
+
mockId: import_zod10.z.string(),
|
|
2691
|
+
endpointId: import_zod10.z.string(),
|
|
2692
|
+
multipliers: import_zod10.z.array(MULTIPLIER)
|
|
2498
2693
|
}),
|
|
2499
2694
|
async handler(input, ctx) {
|
|
2500
2695
|
const state = await ctx.workspace.read();
|
|
@@ -2536,6 +2731,7 @@ var init_registry = __esm({
|
|
|
2536
2731
|
init_codegen();
|
|
2537
2732
|
init_workspaceList();
|
|
2538
2733
|
init_crud();
|
|
2734
|
+
init_folderExchange();
|
|
2539
2735
|
init_history();
|
|
2540
2736
|
init_codebase();
|
|
2541
2737
|
init_prompt();
|
|
@@ -2558,6 +2754,8 @@ var init_registry = __esm({
|
|
|
2558
2754
|
folderReadTool,
|
|
2559
2755
|
folderUpdateTool,
|
|
2560
2756
|
folderDeleteTool,
|
|
2757
|
+
folderExportJsonTool,
|
|
2758
|
+
folderImportJsonTool,
|
|
2561
2759
|
environmentCreateTool,
|
|
2562
2760
|
environmentReadTool,
|
|
2563
2761
|
environmentUpdateTool,
|
|
@@ -2686,11 +2884,11 @@ var init_Workspaces = __esm({
|
|
|
2686
2884
|
});
|
|
2687
2885
|
|
|
2688
2886
|
// src/providers/InMemoryWorkspaceProvider.ts
|
|
2689
|
-
var
|
|
2887
|
+
var import_core4, InMemoryWorkspaceProvider;
|
|
2690
2888
|
var init_InMemoryWorkspaceProvider = __esm({
|
|
2691
2889
|
"src/providers/InMemoryWorkspaceProvider.ts"() {
|
|
2692
2890
|
"use strict";
|
|
2693
|
-
|
|
2891
|
+
import_core4 = require("@apicircle/core");
|
|
2694
2892
|
InMemoryWorkspaceProvider = class {
|
|
2695
2893
|
state;
|
|
2696
2894
|
constructor(initial) {
|
|
@@ -2700,7 +2898,7 @@ var init_InMemoryWorkspaceProvider = __esm({
|
|
|
2700
2898
|
return this.state;
|
|
2701
2899
|
}
|
|
2702
2900
|
async apply(patch) {
|
|
2703
|
-
const out = (0,
|
|
2901
|
+
const out = (0, import_core4.applyMutation)(this.state, patch);
|
|
2704
2902
|
this.state = out.next;
|
|
2705
2903
|
return { state: this.state, changedIds: out.changedIds };
|
|
2706
2904
|
}
|
|
@@ -2720,11 +2918,11 @@ var FileBackedWorkspaceProvider_exports = {};
|
|
|
2720
2918
|
__export(FileBackedWorkspaceProvider_exports, {
|
|
2721
2919
|
FileBackedWorkspaceProvider: () => FileBackedWorkspaceProvider
|
|
2722
2920
|
});
|
|
2723
|
-
var
|
|
2921
|
+
var import_core5, import_file_backed, FileBackedWorkspaceProvider;
|
|
2724
2922
|
var init_FileBackedWorkspaceProvider = __esm({
|
|
2725
2923
|
"src/providers/FileBackedWorkspaceProvider.ts"() {
|
|
2726
2924
|
"use strict";
|
|
2727
|
-
|
|
2925
|
+
import_core5 = require("@apicircle/core");
|
|
2728
2926
|
import_file_backed = require("@apicircle/core/workspace/file-backed");
|
|
2729
2927
|
FileBackedWorkspaceProvider = class {
|
|
2730
2928
|
constructor(dir) {
|
|
@@ -2741,7 +2939,7 @@ var init_FileBackedWorkspaceProvider = __esm({
|
|
|
2741
2939
|
async apply(patch) {
|
|
2742
2940
|
let captured = null;
|
|
2743
2941
|
await (0, import_file_backed.withWorkspace)(this.dir, async (state) => {
|
|
2744
|
-
const result = (0,
|
|
2942
|
+
const result = (0, import_core5.applyMutation)(state, patch);
|
|
2745
2943
|
captured = { state: result.next, changedIds: result.changedIds };
|
|
2746
2944
|
return { next: result.next };
|
|
2747
2945
|
});
|
|
@@ -2766,24 +2964,65 @@ var MultiWorkspaceProvider_exports = {};
|
|
|
2766
2964
|
__export(MultiWorkspaceProvider_exports, {
|
|
2767
2965
|
MultiWorkspaceProvider: () => MultiWorkspaceProvider
|
|
2768
2966
|
});
|
|
2769
|
-
var import_registry, MultiWorkspaceProvider;
|
|
2967
|
+
var import_registry, LazyActiveWorkspaceProvider, MultiWorkspaceProvider;
|
|
2770
2968
|
var init_MultiWorkspaceProvider = __esm({
|
|
2771
2969
|
"src/providers/MultiWorkspaceProvider.ts"() {
|
|
2772
2970
|
"use strict";
|
|
2773
2971
|
import_registry = require("@apicircle/core/workspace/registry");
|
|
2774
2972
|
init_FileBackedWorkspaceProvider();
|
|
2775
2973
|
init_Workspaces();
|
|
2974
|
+
LazyActiveWorkspaceProvider = class {
|
|
2975
|
+
constructor(registryRoot, onActiveResolved) {
|
|
2976
|
+
this.registryRoot = registryRoot;
|
|
2977
|
+
this.onActiveResolved = onActiveResolved;
|
|
2978
|
+
}
|
|
2979
|
+
registryRoot;
|
|
2980
|
+
onActiveResolved;
|
|
2981
|
+
async resolveActive() {
|
|
2982
|
+
const registry = await (0, import_registry.loadRegistry)(this.registryRoot);
|
|
2983
|
+
const activeId = registry?.activeWorkspaceId ?? null;
|
|
2984
|
+
if (!activeId) {
|
|
2985
|
+
throw new Error(
|
|
2986
|
+
"No active workspace. Open the desktop app at least once, or run `apicircle workspaces create <name>`."
|
|
2987
|
+
);
|
|
2988
|
+
}
|
|
2989
|
+
this.onActiveResolved(activeId);
|
|
2990
|
+
return new FileBackedWorkspaceProvider((0, import_registry.workspaceDirFor)(this.registryRoot, activeId));
|
|
2991
|
+
}
|
|
2992
|
+
async read() {
|
|
2993
|
+
const provider = await this.resolveActive();
|
|
2994
|
+
return provider.read();
|
|
2995
|
+
}
|
|
2996
|
+
async apply(patch) {
|
|
2997
|
+
const provider = await this.resolveActive();
|
|
2998
|
+
return provider.apply(patch);
|
|
2999
|
+
}
|
|
3000
|
+
async write(next) {
|
|
3001
|
+
const provider = await this.resolveActive();
|
|
3002
|
+
return provider.write(next);
|
|
3003
|
+
}
|
|
3004
|
+
};
|
|
2776
3005
|
MultiWorkspaceProvider = class {
|
|
2777
3006
|
constructor(registryRoot) {
|
|
2778
3007
|
this.registryRoot = registryRoot;
|
|
3008
|
+
this.lazyProvider = new LazyActiveWorkspaceProvider(this.registryRoot, (id) => {
|
|
3009
|
+
this.activeWorkspaceId = id;
|
|
3010
|
+
});
|
|
2779
3011
|
}
|
|
2780
3012
|
registryRoot;
|
|
2781
|
-
active
|
|
3013
|
+
/** Last-known active workspace id. Refreshed every time the lazy
|
|
3014
|
+
* provider resolves; reflects what the most recent operation saw on
|
|
3015
|
+
* disk, not a stale boot-time snapshot. */
|
|
2782
3016
|
activeWorkspaceId = null;
|
|
3017
|
+
/** The lazy provider tool handlers consume as `ctx.workspace`. Holds a
|
|
3018
|
+
* reference back to this instance so each call updates
|
|
3019
|
+
* `activeWorkspaceId` for `activeId()` callers + diagnostic logs. */
|
|
3020
|
+
lazyProvider;
|
|
2783
3021
|
/**
|
|
2784
|
-
*
|
|
2785
|
-
*
|
|
2786
|
-
* registry
|
|
3022
|
+
* Read the registry from disk so the host can log a boot banner. Does
|
|
3023
|
+
* NOT cache a per-id provider — each `activeProvider()` call re-reads
|
|
3024
|
+
* the registry, so a workspace switch in the desktop is picked up by
|
|
3025
|
+
* the next tool call without restarting the MCP server.
|
|
2787
3026
|
*/
|
|
2788
3027
|
async init() {
|
|
2789
3028
|
const registry = await (0, import_registry.loadRegistry)(this.registryRoot) ?? {
|
|
@@ -2791,22 +3030,18 @@ var init_MultiWorkspaceProvider = __esm({
|
|
|
2791
3030
|
activeWorkspaceId: null,
|
|
2792
3031
|
workspaces: []
|
|
2793
3032
|
};
|
|
2794
|
-
|
|
2795
|
-
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2796
|
-
this.active = new FileBackedWorkspaceProvider(
|
|
2797
|
-
(0, import_registry.workspaceDirFor)(this.registryRoot, registry.activeWorkspaceId)
|
|
2798
|
-
);
|
|
2799
|
-
}
|
|
3033
|
+
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2800
3034
|
return registry;
|
|
2801
3035
|
}
|
|
2802
|
-
/**
|
|
3036
|
+
/**
|
|
3037
|
+
* The provider tool handlers see as `ctx.workspace`. Returns a lazy
|
|
3038
|
+
* provider whose `read` / `apply` / `write` calls re-read
|
|
3039
|
+
* `registry.json` so the right active workspace is always targeted
|
|
3040
|
+
* even if the desktop switched workspaces since this MCP process
|
|
3041
|
+
* started.
|
|
3042
|
+
*/
|
|
2803
3043
|
activeProvider() {
|
|
2804
|
-
|
|
2805
|
-
throw new Error(
|
|
2806
|
-
"No active workspace. Open the desktop app at least once, or run `apicircle workspaces create <name>`."
|
|
2807
|
-
);
|
|
2808
|
-
}
|
|
2809
|
-
return this.active;
|
|
3044
|
+
return this.lazyProvider;
|
|
2810
3045
|
}
|
|
2811
3046
|
// ─── Workspaces interface ──────────────────────────────────────────────────
|
|
2812
3047
|
async list() {
|
|
@@ -2854,23 +3089,17 @@ var init_MultiWorkspaceProvider = __esm({
|
|
|
2854
3089
|
if (!registry || !registry.workspaces.some((w) => w.id === workspaceId)) {
|
|
2855
3090
|
throw new WorkspaceNotFoundError(workspaceId);
|
|
2856
3091
|
}
|
|
2857
|
-
|
|
2858
|
-
void next;
|
|
3092
|
+
await (0, import_registry.setActiveWorkspace)(this.registryRoot, workspaceId);
|
|
2859
3093
|
this.activeWorkspaceId = workspaceId;
|
|
2860
|
-
this.active = new FileBackedWorkspaceProvider((0, import_registry.workspaceDirFor)(this.registryRoot, workspaceId));
|
|
2861
3094
|
}
|
|
2862
3095
|
/**
|
|
2863
3096
|
* Idempotent registry write — used by tests / tools that need to
|
|
2864
|
-
* persist registry updates that didn't go through `setActive`.
|
|
3097
|
+
* persist registry updates that didn't go through `setActive`. The
|
|
3098
|
+
* lazy active provider picks the new id up on its next operation.
|
|
2865
3099
|
*/
|
|
2866
3100
|
async writeRegistry(registry) {
|
|
2867
3101
|
await (0, import_registry.saveRegistry)(this.registryRoot, registry);
|
|
2868
3102
|
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2869
|
-
if (registry.activeWorkspaceId) {
|
|
2870
|
-
this.active = new FileBackedWorkspaceProvider(
|
|
2871
|
-
(0, import_registry.workspaceDirFor)(this.registryRoot, registry.activeWorkspaceId)
|
|
2872
|
-
);
|
|
2873
|
-
}
|
|
2874
3103
|
}
|
|
2875
3104
|
};
|
|
2876
3105
|
}
|