@apicircle/mcp-server 1.0.0 → 1.0.2
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/LICENSE +110 -110
- package/README.md +197 -25
- package/dist/bin/mcp-server.cjs +606 -352
- package/dist/bin/mcp-server.cjs.map +1 -1
- package/dist/index.cjs +577 -350
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -1
- package/dist/index.d.ts +88 -1
- package/dist/index.js +580 -350
- package/dist/index.js.map +1 -1
- package/package.json +33 -26
package/dist/bin/mcp-server.cjs
CHANGED
|
@@ -25,6 +25,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/bin/mcp-server.ts
|
|
27
27
|
var path = __toESM(require("path"), 1);
|
|
28
|
+
var import_node_fs = require("fs");
|
|
28
29
|
|
|
29
30
|
// src/host/McpHost.ts
|
|
30
31
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
@@ -458,18 +459,37 @@ function renderRust(req) {
|
|
|
458
459
|
return lines.join("\n");
|
|
459
460
|
}
|
|
460
461
|
|
|
461
|
-
// src/tools/
|
|
462
|
+
// src/tools/workspaceList.ts
|
|
462
463
|
var import_zod4 = require("zod");
|
|
464
|
+
var workspaceListTool = {
|
|
465
|
+
name: "workspace.list",
|
|
466
|
+
description: "List every workspace registered with this server, including which one is currently active. Returns id, display name, last-opened timestamp, and a per-workspace summary (request count, environment count, mock-server count, plan count). Use this BEFORE drilling into a specific workspace via other tools \u2014 pass the resulting `id` as `workspaceId` to `workspace.read` or related reads when you want to scope to a non-active workspace.",
|
|
467
|
+
inputSchema: import_zod4.z.object({}),
|
|
468
|
+
async handler(_input, ctx) {
|
|
469
|
+
const summaries = await ctx.workspaces.list();
|
|
470
|
+
return {
|
|
471
|
+
activeWorkspaceId: ctx.workspaces.activeId(),
|
|
472
|
+
workspaceCount: summaries.length,
|
|
473
|
+
workspaces: summaries,
|
|
474
|
+
// Plain-text hint the AI surfaces when telling the user. Cheap to
|
|
475
|
+
// generate here and saves round-trips on disambiguation prompts.
|
|
476
|
+
hint: summaries.length === 0 ? "No workspaces are registered yet. The user should open the desktop app once or run `apicircle workspaces create <name>` from the terminal." : summaries.length === 1 ? `Only one workspace ("${summaries[0].name}") is registered \u2014 most tools will default to it without a workspaceId.` : `Multiple workspaces are registered. Pass the desired \`id\` as \`workspaceId\` to other tools to scope reads/writes to that workspace; the active one ("${summaries.find((w) => w.isActive)?.name ?? "(none)"}") is used by default.`
|
|
477
|
+
};
|
|
478
|
+
}
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// src/tools/crud.ts
|
|
482
|
+
var import_zod5 = require("zod");
|
|
463
483
|
var import_shared2 = require("@apicircle/shared");
|
|
464
|
-
var HTTP_METHOD =
|
|
484
|
+
var HTTP_METHOD = import_zod5.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
465
485
|
var requestCreateTool = {
|
|
466
486
|
name: "request.create",
|
|
467
487
|
description: "Create a new request from explicit fields and persist it.",
|
|
468
|
-
inputSchema:
|
|
469
|
-
name:
|
|
488
|
+
inputSchema: import_zod5.z.object({
|
|
489
|
+
name: import_zod5.z.string().default("New request"),
|
|
470
490
|
method: HTTP_METHOD.default("GET"),
|
|
471
|
-
url:
|
|
472
|
-
folderId:
|
|
491
|
+
url: import_zod5.z.string().default(""),
|
|
492
|
+
folderId: import_zod5.z.string().nullable().optional()
|
|
473
493
|
}),
|
|
474
494
|
async handler(input, ctx) {
|
|
475
495
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -498,7 +518,7 @@ var requestCreateTool = {
|
|
|
498
518
|
var requestReadTool = {
|
|
499
519
|
name: "request.read",
|
|
500
520
|
description: "Read a request by id, or list summaries (id, name, method, url) when no id is provided.",
|
|
501
|
-
inputSchema:
|
|
521
|
+
inputSchema: import_zod5.z.object({ id: import_zod5.z.string().optional() }),
|
|
502
522
|
async handler(input, ctx) {
|
|
503
523
|
const state = await ctx.workspace.read();
|
|
504
524
|
if (input.id) {
|
|
@@ -519,13 +539,13 @@ var requestReadTool = {
|
|
|
519
539
|
var requestUpdateTool = {
|
|
520
540
|
name: "request.update",
|
|
521
541
|
description: "Patch fields on an existing request.",
|
|
522
|
-
inputSchema:
|
|
523
|
-
id:
|
|
524
|
-
patch:
|
|
525
|
-
name:
|
|
542
|
+
inputSchema: import_zod5.z.object({
|
|
543
|
+
id: import_zod5.z.string(),
|
|
544
|
+
patch: import_zod5.z.object({
|
|
545
|
+
name: import_zod5.z.string().optional(),
|
|
526
546
|
method: HTTP_METHOD.optional(),
|
|
527
|
-
url:
|
|
528
|
-
folderId:
|
|
547
|
+
url: import_zod5.z.string().optional(),
|
|
548
|
+
folderId: import_zod5.z.string().nullable().optional()
|
|
529
549
|
}).strict()
|
|
530
550
|
}),
|
|
531
551
|
async handler(input, ctx) {
|
|
@@ -540,7 +560,7 @@ var requestUpdateTool = {
|
|
|
540
560
|
var requestDeleteTool = {
|
|
541
561
|
name: "request.delete",
|
|
542
562
|
description: "Delete a request by id.",
|
|
543
|
-
inputSchema:
|
|
563
|
+
inputSchema: import_zod5.z.object({ id: import_zod5.z.string() }),
|
|
544
564
|
async handler(input, ctx) {
|
|
545
565
|
const out = await ctx.workspace.apply({ kind: "request.delete", id: input.id });
|
|
546
566
|
return { changedIds: out.changedIds };
|
|
@@ -549,9 +569,9 @@ var requestDeleteTool = {
|
|
|
549
569
|
var folderCreateTool = {
|
|
550
570
|
name: "folder.create",
|
|
551
571
|
description: "Create a folder under an optional parent folder.",
|
|
552
|
-
inputSchema:
|
|
553
|
-
name:
|
|
554
|
-
parentId:
|
|
572
|
+
inputSchema: import_zod5.z.object({
|
|
573
|
+
name: import_zod5.z.string().default("New folder"),
|
|
574
|
+
parentId: import_zod5.z.string().nullable().optional()
|
|
555
575
|
}),
|
|
556
576
|
async handler(input, ctx) {
|
|
557
577
|
const folder = {
|
|
@@ -566,7 +586,7 @@ var folderCreateTool = {
|
|
|
566
586
|
var folderReadTool = {
|
|
567
587
|
name: "folder.read",
|
|
568
588
|
description: "Read a folder by id, or list all folders when no id is provided.",
|
|
569
|
-
inputSchema:
|
|
589
|
+
inputSchema: import_zod5.z.object({ id: import_zod5.z.string().optional() }),
|
|
570
590
|
async handler(input, ctx) {
|
|
571
591
|
const state = await ctx.workspace.read();
|
|
572
592
|
if (input.id) {
|
|
@@ -582,9 +602,9 @@ var folderReadTool = {
|
|
|
582
602
|
var folderUpdateTool = {
|
|
583
603
|
name: "folder.update",
|
|
584
604
|
description: "Move a folder to a new parent (or to root with parentId: null).",
|
|
585
|
-
inputSchema:
|
|
586
|
-
id:
|
|
587
|
-
parentId:
|
|
605
|
+
inputSchema: import_zod5.z.object({
|
|
606
|
+
id: import_zod5.z.string(),
|
|
607
|
+
parentId: import_zod5.z.string().nullable()
|
|
588
608
|
}),
|
|
589
609
|
async handler(input, ctx) {
|
|
590
610
|
const out = await ctx.workspace.apply({
|
|
@@ -598,23 +618,23 @@ var folderUpdateTool = {
|
|
|
598
618
|
var folderDeleteTool = {
|
|
599
619
|
name: "folder.delete",
|
|
600
620
|
description: "Delete a folder. Direct children (sub-folders + requests) are reparented to the deleted folder's parent.",
|
|
601
|
-
inputSchema:
|
|
621
|
+
inputSchema: import_zod5.z.object({ id: import_zod5.z.string() }),
|
|
602
622
|
async handler(input, ctx) {
|
|
603
623
|
const out = await ctx.workspace.apply({ kind: "folder.delete", id: input.id });
|
|
604
624
|
return { changedIds: out.changedIds };
|
|
605
625
|
}
|
|
606
626
|
};
|
|
607
|
-
var VARIABLE =
|
|
608
|
-
key:
|
|
609
|
-
value:
|
|
610
|
-
encrypted:
|
|
627
|
+
var VARIABLE = import_zod5.z.object({
|
|
628
|
+
key: import_zod5.z.string(),
|
|
629
|
+
value: import_zod5.z.string(),
|
|
630
|
+
encrypted: import_zod5.z.boolean().default(false)
|
|
611
631
|
});
|
|
612
632
|
var environmentCreateTool = {
|
|
613
633
|
name: "environment.create",
|
|
614
634
|
description: "Create a new environment (or upsert one with the same name).",
|
|
615
|
-
inputSchema:
|
|
616
|
-
name:
|
|
617
|
-
variables:
|
|
635
|
+
inputSchema: import_zod5.z.object({
|
|
636
|
+
name: import_zod5.z.string(),
|
|
637
|
+
variables: import_zod5.z.array(VARIABLE).default([])
|
|
618
638
|
}),
|
|
619
639
|
async handler(input, ctx) {
|
|
620
640
|
const env = { name: input.name, variables: input.variables };
|
|
@@ -625,7 +645,7 @@ var environmentCreateTool = {
|
|
|
625
645
|
var environmentReadTool = {
|
|
626
646
|
name: "environment.read",
|
|
627
647
|
description: "Read environments \u2014 pass `name` for one, or omit for the full list.",
|
|
628
|
-
inputSchema:
|
|
648
|
+
inputSchema: import_zod5.z.object({ name: import_zod5.z.string().optional() }),
|
|
629
649
|
async handler(input, ctx) {
|
|
630
650
|
const state = await ctx.workspace.read();
|
|
631
651
|
if (input.name) {
|
|
@@ -642,9 +662,9 @@ var environmentReadTool = {
|
|
|
642
662
|
var environmentUpdateTool = {
|
|
643
663
|
name: "environment.update",
|
|
644
664
|
description: "Replace the variables list of an environment.",
|
|
645
|
-
inputSchema:
|
|
646
|
-
name:
|
|
647
|
-
variables:
|
|
665
|
+
inputSchema: import_zod5.z.object({
|
|
666
|
+
name: import_zod5.z.string(),
|
|
667
|
+
variables: import_zod5.z.array(VARIABLE)
|
|
648
668
|
}),
|
|
649
669
|
async handler(input, ctx) {
|
|
650
670
|
const out = await ctx.workspace.apply({
|
|
@@ -657,7 +677,7 @@ var environmentUpdateTool = {
|
|
|
657
677
|
var environmentDeleteTool = {
|
|
658
678
|
name: "environment.delete",
|
|
659
679
|
description: "Delete an environment by name.",
|
|
660
|
-
inputSchema:
|
|
680
|
+
inputSchema: import_zod5.z.object({ name: import_zod5.z.string() }),
|
|
661
681
|
async handler(input, ctx) {
|
|
662
682
|
const out = await ctx.workspace.apply({ kind: "environment.delete", name: input.name });
|
|
663
683
|
return { changedIds: out.changedIds };
|
|
@@ -666,7 +686,7 @@ var environmentDeleteTool = {
|
|
|
666
686
|
var environmentSetActiveTool = {
|
|
667
687
|
name: "environment.set_active",
|
|
668
688
|
description: "Set (or clear) the active environment. Pass `name: null` to deactivate the current environment.",
|
|
669
|
-
inputSchema:
|
|
689
|
+
inputSchema: import_zod5.z.object({ name: import_zod5.z.string().nullable() }),
|
|
670
690
|
async handler(input, ctx) {
|
|
671
691
|
const out = await ctx.workspace.apply({
|
|
672
692
|
kind: "environment.setActive",
|
|
@@ -678,18 +698,18 @@ var environmentSetActiveTool = {
|
|
|
678
698
|
var environmentSetPriorityTool = {
|
|
679
699
|
name: "environment.set_priority",
|
|
680
700
|
description: 'Replace the global environment priority order (highest priority first). Strings are interpreted as local env names. To target a linked env, pass `{ kind: "linked", linkedWorkspaceId, envName }` instead.',
|
|
681
|
-
inputSchema:
|
|
682
|
-
order:
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
kind:
|
|
687
|
-
name:
|
|
701
|
+
inputSchema: import_zod5.z.object({
|
|
702
|
+
order: import_zod5.z.array(
|
|
703
|
+
import_zod5.z.union([
|
|
704
|
+
import_zod5.z.string(),
|
|
705
|
+
import_zod5.z.object({
|
|
706
|
+
kind: import_zod5.z.literal("local"),
|
|
707
|
+
name: import_zod5.z.string()
|
|
688
708
|
}),
|
|
689
|
-
|
|
690
|
-
kind:
|
|
691
|
-
linkedWorkspaceId:
|
|
692
|
-
envName:
|
|
709
|
+
import_zod5.z.object({
|
|
710
|
+
kind: import_zod5.z.literal("linked"),
|
|
711
|
+
linkedWorkspaceId: import_zod5.z.string(),
|
|
712
|
+
envName: import_zod5.z.string()
|
|
693
713
|
})
|
|
694
714
|
])
|
|
695
715
|
)
|
|
@@ -706,7 +726,7 @@ var environmentSetPriorityTool = {
|
|
|
706
726
|
var environmentExportTool = {
|
|
707
727
|
name: "environment.export",
|
|
708
728
|
description: "Serialize an environment to a portable JSON string. Encrypted variables drop their value (only `secretKeyId` survives) so the export can be safely pasted elsewhere \u2014 re-attach secrets locally on the receiving side.",
|
|
709
|
-
inputSchema:
|
|
729
|
+
inputSchema: import_zod5.z.object({ name: import_zod5.z.string() }),
|
|
710
730
|
async handler(input, ctx) {
|
|
711
731
|
const state = await ctx.workspace.read();
|
|
712
732
|
const env = state.synced.environments.items[input.name];
|
|
@@ -724,9 +744,9 @@ var environmentExportTool = {
|
|
|
724
744
|
var environmentImportTool = {
|
|
725
745
|
name: "environment.import",
|
|
726
746
|
description: "Import an environment from the JSON shape produced by `environment.export`. When a target with the same name exists, pass `overwrite: true` to replace it, otherwise the import is rejected.",
|
|
727
|
-
inputSchema:
|
|
728
|
-
json:
|
|
729
|
-
overwrite:
|
|
747
|
+
inputSchema: import_zod5.z.object({
|
|
748
|
+
json: import_zod5.z.string().min(1),
|
|
749
|
+
overwrite: import_zod5.z.boolean().default(false)
|
|
730
750
|
}),
|
|
731
751
|
async handler(input, ctx) {
|
|
732
752
|
let parsed;
|
|
@@ -756,17 +776,17 @@ var environmentImportTool = {
|
|
|
756
776
|
return { ok: true, name: env.name, changedIds: out.changedIds };
|
|
757
777
|
}
|
|
758
778
|
};
|
|
759
|
-
var PLAN_STEP =
|
|
760
|
-
requestId:
|
|
761
|
-
linkedWorkspaceId:
|
|
779
|
+
var PLAN_STEP = import_zod5.z.object({
|
|
780
|
+
requestId: import_zod5.z.string(),
|
|
781
|
+
linkedWorkspaceId: import_zod5.z.string().optional()
|
|
762
782
|
});
|
|
763
783
|
var planCreateTool = {
|
|
764
784
|
name: "plan.create",
|
|
765
785
|
description: "Create a new execution plan (sequence of request steps).",
|
|
766
|
-
inputSchema:
|
|
767
|
-
name:
|
|
768
|
-
steps:
|
|
769
|
-
envPriorityOrder:
|
|
786
|
+
inputSchema: import_zod5.z.object({
|
|
787
|
+
name: import_zod5.z.string().default("New plan"),
|
|
788
|
+
steps: import_zod5.z.array(PLAN_STEP).default([]),
|
|
789
|
+
envPriorityOrder: import_zod5.z.array(import_zod5.z.string()).default([])
|
|
770
790
|
}),
|
|
771
791
|
async handler(input, ctx) {
|
|
772
792
|
const id = (0, import_shared2.generateId)();
|
|
@@ -786,7 +806,7 @@ var planCreateTool = {
|
|
|
786
806
|
var planReadTool = {
|
|
787
807
|
name: "plan.read",
|
|
788
808
|
description: "Read a plan by id, or list all plans when no id is provided.",
|
|
789
|
-
inputSchema:
|
|
809
|
+
inputSchema: import_zod5.z.object({ id: import_zod5.z.string().optional() }),
|
|
790
810
|
async handler(input, ctx) {
|
|
791
811
|
const state = await ctx.workspace.read();
|
|
792
812
|
if (input.id) {
|
|
@@ -802,12 +822,12 @@ var planReadTool = {
|
|
|
802
822
|
var planUpdateTool = {
|
|
803
823
|
name: "plan.update",
|
|
804
824
|
description: "Patch fields on an existing plan.",
|
|
805
|
-
inputSchema:
|
|
806
|
-
id:
|
|
807
|
-
patch:
|
|
808
|
-
name:
|
|
809
|
-
steps:
|
|
810
|
-
envPriorityOrder:
|
|
825
|
+
inputSchema: import_zod5.z.object({
|
|
826
|
+
id: import_zod5.z.string(),
|
|
827
|
+
patch: import_zod5.z.object({
|
|
828
|
+
name: import_zod5.z.string().optional(),
|
|
829
|
+
steps: import_zod5.z.array(PLAN_STEP).optional(),
|
|
830
|
+
envPriorityOrder: import_zod5.z.array(import_zod5.z.string()).optional()
|
|
811
831
|
}).strict()
|
|
812
832
|
}),
|
|
813
833
|
async handler(input, ctx) {
|
|
@@ -828,7 +848,7 @@ var planUpdateTool = {
|
|
|
828
848
|
var planDeleteTool = {
|
|
829
849
|
name: "plan.delete",
|
|
830
850
|
description: "Delete a plan by id. Drops history rows referencing this plan.",
|
|
831
|
-
inputSchema:
|
|
851
|
+
inputSchema: import_zod5.z.object({ id: import_zod5.z.string() }),
|
|
832
852
|
async handler(input, ctx) {
|
|
833
853
|
const out = await ctx.workspace.apply({ kind: "plan.delete", id: input.id });
|
|
834
854
|
return { changedIds: out.changedIds };
|
|
@@ -837,11 +857,11 @@ var planDeleteTool = {
|
|
|
837
857
|
var planAddStepTool = {
|
|
838
858
|
name: "plan.add_step",
|
|
839
859
|
description: "Append a step to an execution plan. Optional `position` (0-based) inserts at that index instead.",
|
|
840
|
-
inputSchema:
|
|
841
|
-
planId:
|
|
842
|
-
requestId:
|
|
843
|
-
linkedWorkspaceId:
|
|
844
|
-
position:
|
|
860
|
+
inputSchema: import_zod5.z.object({
|
|
861
|
+
planId: import_zod5.z.string(),
|
|
862
|
+
requestId: import_zod5.z.string(),
|
|
863
|
+
linkedWorkspaceId: import_zod5.z.string().optional(),
|
|
864
|
+
position: import_zod5.z.number().int().nonnegative().optional()
|
|
845
865
|
}),
|
|
846
866
|
async handler(input, ctx) {
|
|
847
867
|
const state = await ctx.workspace.read();
|
|
@@ -867,9 +887,9 @@ var planAddStepTool = {
|
|
|
867
887
|
var planRemoveStepTool = {
|
|
868
888
|
name: "plan.remove_step",
|
|
869
889
|
description: "Remove a step from a plan by 0-based index.",
|
|
870
|
-
inputSchema:
|
|
871
|
-
planId:
|
|
872
|
-
index:
|
|
890
|
+
inputSchema: import_zod5.z.object({
|
|
891
|
+
planId: import_zod5.z.string(),
|
|
892
|
+
index: import_zod5.z.number().int().nonnegative()
|
|
873
893
|
}),
|
|
874
894
|
async handler(input, ctx) {
|
|
875
895
|
const state = await ctx.workspace.read();
|
|
@@ -889,9 +909,9 @@ var planRemoveStepTool = {
|
|
|
889
909
|
var planReorderStepsTool = {
|
|
890
910
|
name: "plan.reorder_steps",
|
|
891
911
|
description: "Replace the plan steps with a new permutation. The supplied indices must reference valid current step indices.",
|
|
892
|
-
inputSchema:
|
|
893
|
-
planId:
|
|
894
|
-
order:
|
|
912
|
+
inputSchema: import_zod5.z.object({
|
|
913
|
+
planId: import_zod5.z.string(),
|
|
914
|
+
order: import_zod5.z.array(import_zod5.z.number().int().nonnegative())
|
|
895
915
|
}),
|
|
896
916
|
async handler(input, ctx) {
|
|
897
917
|
const state = await ctx.workspace.read();
|
|
@@ -913,13 +933,13 @@ var planReorderStepsTool = {
|
|
|
913
933
|
return { ok: true, changedIds: out.changedIds };
|
|
914
934
|
}
|
|
915
935
|
};
|
|
916
|
-
var PLAN_VARIABLE =
|
|
936
|
+
var PLAN_VARIABLE = import_zod5.z.object({ key: import_zod5.z.string(), value: import_zod5.z.string() });
|
|
917
937
|
var planSetVariablesTool = {
|
|
918
938
|
name: "plan.set_variables",
|
|
919
939
|
description: "Replace the plan-scoped variables. These live highest-priority during plan runs (above environment vars, below context vars).",
|
|
920
|
-
inputSchema:
|
|
921
|
-
planId:
|
|
922
|
-
variables:
|
|
940
|
+
inputSchema: import_zod5.z.object({
|
|
941
|
+
planId: import_zod5.z.string(),
|
|
942
|
+
variables: import_zod5.z.array(PLAN_VARIABLE)
|
|
923
943
|
}),
|
|
924
944
|
async handler(input, ctx) {
|
|
925
945
|
const state = await ctx.workspace.read();
|
|
@@ -935,9 +955,9 @@ var planSetVariablesTool = {
|
|
|
935
955
|
var planRunTool = {
|
|
936
956
|
name: "plan.run",
|
|
937
957
|
description: "Run a plan headlessly (server-side). Currently returns a not-implemented marker \u2014 full execution requires the Desktop or browser runtime which the MCP host does not own. The Desktop integration overrides this tool with a real runner.",
|
|
938
|
-
inputSchema:
|
|
939
|
-
id:
|
|
940
|
-
withAssertions:
|
|
958
|
+
inputSchema: import_zod5.z.object({
|
|
959
|
+
id: import_zod5.z.string(),
|
|
960
|
+
withAssertions: import_zod5.z.boolean().default(true)
|
|
941
961
|
}),
|
|
942
962
|
async handler(input, ctx) {
|
|
943
963
|
const state = await ctx.workspace.read();
|
|
@@ -951,18 +971,18 @@ var planRunTool = {
|
|
|
951
971
|
};
|
|
952
972
|
}
|
|
953
973
|
};
|
|
954
|
-
var ASSERTION =
|
|
955
|
-
id:
|
|
956
|
-
kind:
|
|
957
|
-
op:
|
|
958
|
-
target:
|
|
959
|
-
expected:
|
|
974
|
+
var ASSERTION = import_zod5.z.object({
|
|
975
|
+
id: import_zod5.z.string().optional(),
|
|
976
|
+
kind: import_zod5.z.enum(["status", "header", "json-path", "duration"]),
|
|
977
|
+
op: import_zod5.z.enum(["equals", "not-equals", "contains", "lt", "gt", "matches"]),
|
|
978
|
+
target: import_zod5.z.string().optional(),
|
|
979
|
+
expected: import_zod5.z.union([import_zod5.z.string(), import_zod5.z.number()])
|
|
960
980
|
});
|
|
961
981
|
var assertionCreateTool = {
|
|
962
982
|
name: "assertion.create",
|
|
963
983
|
description: "Add an assertion to a request.",
|
|
964
|
-
inputSchema:
|
|
965
|
-
requestId:
|
|
984
|
+
inputSchema: import_zod5.z.object({
|
|
985
|
+
requestId: import_zod5.z.string(),
|
|
966
986
|
assertion: ASSERTION
|
|
967
987
|
}),
|
|
968
988
|
async handler(input, ctx) {
|
|
@@ -981,9 +1001,9 @@ var assertionCreateTool = {
|
|
|
981
1001
|
var assertionReadTool = {
|
|
982
1002
|
name: "assertion.read",
|
|
983
1003
|
description: "List assertions for a request, or fetch a single assertion by id.",
|
|
984
|
-
inputSchema:
|
|
985
|
-
requestId:
|
|
986
|
-
assertionId:
|
|
1004
|
+
inputSchema: import_zod5.z.object({
|
|
1005
|
+
requestId: import_zod5.z.string(),
|
|
1006
|
+
assertionId: import_zod5.z.string().optional()
|
|
987
1007
|
}),
|
|
988
1008
|
async handler(input, ctx) {
|
|
989
1009
|
const state = await ctx.workspace.read();
|
|
@@ -999,8 +1019,8 @@ var assertionReadTool = {
|
|
|
999
1019
|
var assertionUpdateTool = {
|
|
1000
1020
|
name: "assertion.update",
|
|
1001
1021
|
description: "Replace an existing assertion (matched by `assertion.id`).",
|
|
1002
|
-
inputSchema:
|
|
1003
|
-
requestId:
|
|
1022
|
+
inputSchema: import_zod5.z.object({
|
|
1023
|
+
requestId: import_zod5.z.string(),
|
|
1004
1024
|
assertion: ASSERTION.required({ id: true })
|
|
1005
1025
|
}),
|
|
1006
1026
|
async handler(input, ctx) {
|
|
@@ -1015,9 +1035,9 @@ var assertionUpdateTool = {
|
|
|
1015
1035
|
var assertionDeleteTool = {
|
|
1016
1036
|
name: "assertion.delete",
|
|
1017
1037
|
description: "Remove an assertion from a request.",
|
|
1018
|
-
inputSchema:
|
|
1019
|
-
requestId:
|
|
1020
|
-
assertionId:
|
|
1038
|
+
inputSchema: import_zod5.z.object({
|
|
1039
|
+
requestId: import_zod5.z.string(),
|
|
1040
|
+
assertionId: import_zod5.z.string()
|
|
1021
1041
|
}),
|
|
1022
1042
|
async handler(input, ctx) {
|
|
1023
1043
|
const out = await ctx.workspace.apply({
|
|
@@ -1030,21 +1050,53 @@ var assertionDeleteTool = {
|
|
|
1030
1050
|
};
|
|
1031
1051
|
var workspaceReadTool = {
|
|
1032
1052
|
name: "workspace.read",
|
|
1033
|
-
description:
|
|
1034
|
-
inputSchema:
|
|
1035
|
-
|
|
1036
|
-
|
|
1053
|
+
description: 'Return the full `{ synced, local }` workspace pair. Pass `workspaceId` to scope to a specific workspace when multiple are registered (call `workspace.list` first to discover ids). When omitted and multiple workspaces exist, the response is a structured "multiple workspaces found" envelope listing each summary so the AI can clarify before drilling in. Use sparingly \u2014 entity-specific tools are more efficient for small reads.',
|
|
1054
|
+
inputSchema: import_zod5.z.object({
|
|
1055
|
+
workspaceId: import_zod5.z.string().min(1).max(256).optional().describe(
|
|
1056
|
+
'Optional workspace id (from `workspace.list`). Omit to read the active workspace; the tool will switch to the "multiple workspaces" envelope when ambiguous.'
|
|
1057
|
+
)
|
|
1058
|
+
}),
|
|
1059
|
+
async handler(input, ctx) {
|
|
1060
|
+
if (input.workspaceId) {
|
|
1061
|
+
const provider = ctx.workspaces.for(input.workspaceId);
|
|
1062
|
+
const state2 = await provider.read();
|
|
1063
|
+
return {
|
|
1064
|
+
kind: "single",
|
|
1065
|
+
workspaceId: state2.synced.workspaceId,
|
|
1066
|
+
synced: state2.synced,
|
|
1067
|
+
local: state2.local
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
const summaries = await ctx.workspaces.list();
|
|
1071
|
+
if (summaries.length > 1) {
|
|
1072
|
+
return {
|
|
1073
|
+
kind: "multiple-workspaces",
|
|
1074
|
+
activeWorkspaceId: ctx.workspaces.activeId(),
|
|
1075
|
+
workspaceCount: summaries.length,
|
|
1076
|
+
workspaces: summaries,
|
|
1077
|
+
hint: `Found ${summaries.length} workspaces. Re-call \`workspace.read\` with \`workspaceId\` set to the desired entry, or call entity-specific tools (which default to the active workspace) when scoping to one workspace is acceptable.`
|
|
1078
|
+
};
|
|
1079
|
+
}
|
|
1080
|
+
const state = await ctx.workspace.read();
|
|
1081
|
+
return {
|
|
1082
|
+
kind: "single",
|
|
1083
|
+
workspaceId: state.synced.workspaceId,
|
|
1084
|
+
synced: state.synced,
|
|
1085
|
+
local: state.local
|
|
1086
|
+
};
|
|
1037
1087
|
}
|
|
1038
1088
|
};
|
|
1039
1089
|
var workspaceWriteTool = {
|
|
1040
1090
|
name: "workspace.write",
|
|
1041
|
-
description: "Bulk-replace the workspace. Pass `synced` and/or `local` to overwrite either side. Mutating tools are preferred \u2014 this is for full-doc imports/exports.",
|
|
1042
|
-
inputSchema:
|
|
1043
|
-
|
|
1044
|
-
|
|
1091
|
+
description: "Bulk-replace the workspace. Pass `synced` and/or `local` to overwrite either side. Use `workspaceId` to target a non-active workspace (omit to write the active one). Mutating tools are preferred \u2014 this is for full-doc imports/exports.",
|
|
1092
|
+
inputSchema: import_zod5.z.object({
|
|
1093
|
+
workspaceId: import_zod5.z.string().min(1).max(256).optional().describe("Optional workspace id; omit to write the active workspace."),
|
|
1094
|
+
synced: import_zod5.z.unknown().optional(),
|
|
1095
|
+
local: import_zod5.z.unknown().optional()
|
|
1045
1096
|
}),
|
|
1046
1097
|
async handler(input, ctx) {
|
|
1047
|
-
const
|
|
1098
|
+
const provider = input.workspaceId ? ctx.workspaces.for(input.workspaceId) : ctx.workspace;
|
|
1099
|
+
const next = await provider.write({
|
|
1048
1100
|
synced: input.synced,
|
|
1049
1101
|
local: input.local
|
|
1050
1102
|
});
|
|
@@ -1053,16 +1105,16 @@ var workspaceWriteTool = {
|
|
|
1053
1105
|
};
|
|
1054
1106
|
|
|
1055
1107
|
// src/tools/history.ts
|
|
1056
|
-
var
|
|
1108
|
+
var import_zod6 = require("zod");
|
|
1057
1109
|
var historyListRunsTool = {
|
|
1058
1110
|
name: "history.list_runs",
|
|
1059
1111
|
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.",
|
|
1060
|
-
inputSchema:
|
|
1061
|
-
requestId:
|
|
1062
|
-
ok:
|
|
1063
|
-
since:
|
|
1064
|
-
until:
|
|
1065
|
-
limit:
|
|
1112
|
+
inputSchema: import_zod6.z.object({
|
|
1113
|
+
requestId: import_zod6.z.string().optional(),
|
|
1114
|
+
ok: import_zod6.z.boolean().optional(),
|
|
1115
|
+
since: import_zod6.z.string().optional(),
|
|
1116
|
+
until: import_zod6.z.string().optional(),
|
|
1117
|
+
limit: import_zod6.z.number().int().positive().max(500).default(100)
|
|
1066
1118
|
}),
|
|
1067
1119
|
async handler(input, ctx) {
|
|
1068
1120
|
const state = await ctx.workspace.read();
|
|
@@ -1096,7 +1148,7 @@ var historyListRunsTool = {
|
|
|
1096
1148
|
var historyGetRunTool = {
|
|
1097
1149
|
name: "history.get_run",
|
|
1098
1150
|
description: "Fetch a single history row in full (headers, body preview, assertion results).",
|
|
1099
|
-
inputSchema:
|
|
1151
|
+
inputSchema: import_zod6.z.object({ id: import_zod6.z.string() }),
|
|
1100
1152
|
async handler(input, ctx) {
|
|
1101
1153
|
const state = await ctx.workspace.read();
|
|
1102
1154
|
const run = state.local.history.requestRuns.find((r) => r.id === input.id);
|
|
@@ -1107,7 +1159,7 @@ var historyGetRunTool = {
|
|
|
1107
1159
|
var historyDeleteRunTool = {
|
|
1108
1160
|
name: "history.delete_run",
|
|
1109
1161
|
description: "Delete a single request-run row by id.",
|
|
1110
|
-
inputSchema:
|
|
1162
|
+
inputSchema: import_zod6.z.object({ id: import_zod6.z.string() }),
|
|
1111
1163
|
async handler(input, ctx) {
|
|
1112
1164
|
const out = await ctx.workspace.apply({ kind: "history.delete_run", runId: input.id });
|
|
1113
1165
|
return { deleted: out.changedIds.length, changedIds: out.changedIds };
|
|
@@ -1116,8 +1168,8 @@ var historyDeleteRunTool = {
|
|
|
1116
1168
|
var historyPurgeTool = {
|
|
1117
1169
|
name: "history.purge_by_age",
|
|
1118
1170
|
description: "Drop every request-run + plan-run older than `olderThanDays` days. Pass 0 to clear all history.",
|
|
1119
|
-
inputSchema:
|
|
1120
|
-
olderThanDays:
|
|
1171
|
+
inputSchema: import_zod6.z.object({
|
|
1172
|
+
olderThanDays: import_zod6.z.number().nonnegative()
|
|
1121
1173
|
}),
|
|
1122
1174
|
async handler(input, ctx) {
|
|
1123
1175
|
const olderThanMs = input.olderThanDays * 24 * 60 * 60 * 1e3;
|
|
@@ -1127,15 +1179,15 @@ var historyPurgeTool = {
|
|
|
1127
1179
|
};
|
|
1128
1180
|
|
|
1129
1181
|
// src/tools/codebase.ts
|
|
1130
|
-
var
|
|
1182
|
+
var import_zod7 = require("zod");
|
|
1131
1183
|
var HTTP_METHODS = ["get", "post", "put", "patch", "delete", "options", "head"];
|
|
1132
1184
|
var codebaseExtractCollectionTool = {
|
|
1133
1185
|
name: "codebase.extract_collection",
|
|
1134
1186
|
description: "Scan source code for HTTP route definitions (Express, FastAPI, NestJS, Spring) and return candidate requests for the user to confirm before import.",
|
|
1135
|
-
inputSchema:
|
|
1136
|
-
source:
|
|
1187
|
+
inputSchema: import_zod7.z.object({
|
|
1188
|
+
source: import_zod7.z.string().min(1),
|
|
1137
1189
|
/** Hint to limit which framework patterns to apply. Empty = try all. */
|
|
1138
|
-
frameworks:
|
|
1190
|
+
frameworks: import_zod7.z.array(import_zod7.z.enum(["express", "fastapi", "nest", "spring"])).default([])
|
|
1139
1191
|
}),
|
|
1140
1192
|
async handler(input) {
|
|
1141
1193
|
const enabled = new Set(
|
|
@@ -1216,18 +1268,18 @@ var codebaseExtractCollectionTool = {
|
|
|
1216
1268
|
};
|
|
1217
1269
|
|
|
1218
1270
|
// src/tools/prompt.ts
|
|
1219
|
-
var
|
|
1271
|
+
var import_zod8 = require("zod");
|
|
1220
1272
|
var import_shared3 = require("@apicircle/shared");
|
|
1221
1273
|
var promptCreateEnvironmentTool = {
|
|
1222
1274
|
name: "prompt.create_environment",
|
|
1223
1275
|
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.",
|
|
1224
|
-
inputSchema:
|
|
1225
|
-
name:
|
|
1226
|
-
variables:
|
|
1227
|
-
|
|
1228
|
-
key:
|
|
1229
|
-
value:
|
|
1230
|
-
encrypted:
|
|
1276
|
+
inputSchema: import_zod8.z.object({
|
|
1277
|
+
name: import_zod8.z.string(),
|
|
1278
|
+
variables: import_zod8.z.array(
|
|
1279
|
+
import_zod8.z.object({
|
|
1280
|
+
key: import_zod8.z.string(),
|
|
1281
|
+
value: import_zod8.z.string(),
|
|
1282
|
+
encrypted: import_zod8.z.boolean().default(false)
|
|
1231
1283
|
})
|
|
1232
1284
|
)
|
|
1233
1285
|
}),
|
|
@@ -1240,13 +1292,13 @@ var promptCreateEnvironmentTool = {
|
|
|
1240
1292
|
var promptCreateAssertionTool = {
|
|
1241
1293
|
name: "prompt.create_assertion",
|
|
1242
1294
|
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".',
|
|
1243
|
-
inputSchema:
|
|
1244
|
-
requestId:
|
|
1245
|
-
assertion:
|
|
1246
|
-
kind:
|
|
1247
|
-
op:
|
|
1248
|
-
target:
|
|
1249
|
-
expected:
|
|
1295
|
+
inputSchema: import_zod8.z.object({
|
|
1296
|
+
requestId: import_zod8.z.string(),
|
|
1297
|
+
assertion: import_zod8.z.object({
|
|
1298
|
+
kind: import_zod8.z.enum(["status", "header", "json-path", "duration"]),
|
|
1299
|
+
op: import_zod8.z.enum(["equals", "not-equals", "contains", "lt", "gt", "matches"]),
|
|
1300
|
+
target: import_zod8.z.string().optional(),
|
|
1301
|
+
expected: import_zod8.z.union([import_zod8.z.string(), import_zod8.z.number()])
|
|
1250
1302
|
})
|
|
1251
1303
|
}),
|
|
1252
1304
|
async handler(input, ctx) {
|
|
@@ -1265,10 +1317,10 @@ var promptCreateAssertionTool = {
|
|
|
1265
1317
|
var promptCreatePlanTool = {
|
|
1266
1318
|
name: "prompt.create_plan",
|
|
1267
1319
|
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.",
|
|
1268
|
-
inputSchema:
|
|
1269
|
-
name:
|
|
1270
|
-
stepRequestIds:
|
|
1271
|
-
envPriorityOrder:
|
|
1320
|
+
inputSchema: import_zod8.z.object({
|
|
1321
|
+
name: import_zod8.z.string(),
|
|
1322
|
+
stepRequestIds: import_zod8.z.array(import_zod8.z.string()).default([]),
|
|
1323
|
+
envPriorityOrder: import_zod8.z.array(import_zod8.z.string()).default([])
|
|
1272
1324
|
}),
|
|
1273
1325
|
async handler(input, ctx) {
|
|
1274
1326
|
const state = await ctx.workspace.read();
|
|
@@ -1297,51 +1349,51 @@ var promptCreatePlanTool = {
|
|
|
1297
1349
|
return { ok: true, id, changedIds: out.changedIds };
|
|
1298
1350
|
}
|
|
1299
1351
|
};
|
|
1300
|
-
var HTTP_METHOD2 =
|
|
1301
|
-
var HEADER_OR_QUERY =
|
|
1302
|
-
key:
|
|
1303
|
-
value:
|
|
1304
|
-
enabled:
|
|
1352
|
+
var HTTP_METHOD2 = import_zod8.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
1353
|
+
var HEADER_OR_QUERY = import_zod8.z.object({
|
|
1354
|
+
key: import_zod8.z.string(),
|
|
1355
|
+
value: import_zod8.z.string(),
|
|
1356
|
+
enabled: import_zod8.z.boolean().default(true)
|
|
1305
1357
|
});
|
|
1306
|
-
var REQUEST_BODY =
|
|
1307
|
-
type:
|
|
1308
|
-
content:
|
|
1309
|
-
variables:
|
|
1358
|
+
var REQUEST_BODY = import_zod8.z.object({
|
|
1359
|
+
type: import_zod8.z.enum(["none", "json", "text", "xml", "graphql", "urlencoded"]).default("none"),
|
|
1360
|
+
content: import_zod8.z.string().default(""),
|
|
1361
|
+
variables: import_zod8.z.string().optional()
|
|
1310
1362
|
});
|
|
1311
|
-
var PROMPT_AUTH =
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
type:
|
|
1317
|
-
username:
|
|
1318
|
-
password:
|
|
1363
|
+
var PROMPT_AUTH = import_zod8.z.discriminatedUnion("type", [
|
|
1364
|
+
import_zod8.z.object({ type: import_zod8.z.literal("none") }),
|
|
1365
|
+
import_zod8.z.object({ type: import_zod8.z.literal("inherit") }),
|
|
1366
|
+
import_zod8.z.object({ type: import_zod8.z.literal("bearer"), token: import_zod8.z.string().default("") }),
|
|
1367
|
+
import_zod8.z.object({
|
|
1368
|
+
type: import_zod8.z.literal("basic"),
|
|
1369
|
+
username: import_zod8.z.string().default(""),
|
|
1370
|
+
password: import_zod8.z.string().default("")
|
|
1319
1371
|
}),
|
|
1320
|
-
|
|
1321
|
-
type:
|
|
1322
|
-
key:
|
|
1323
|
-
value:
|
|
1324
|
-
addTo:
|
|
1372
|
+
import_zod8.z.object({
|
|
1373
|
+
type: import_zod8.z.literal("api-key"),
|
|
1374
|
+
key: import_zod8.z.string().default(""),
|
|
1375
|
+
value: import_zod8.z.string().default(""),
|
|
1376
|
+
addTo: import_zod8.z.enum(["header", "query", "cookie"]).default("header")
|
|
1325
1377
|
}),
|
|
1326
|
-
|
|
1327
|
-
type:
|
|
1328
|
-
key:
|
|
1329
|
-
value:
|
|
1378
|
+
import_zod8.z.object({
|
|
1379
|
+
type: import_zod8.z.literal("custom-header"),
|
|
1380
|
+
key: import_zod8.z.string().default(""),
|
|
1381
|
+
value: import_zod8.z.string().default("")
|
|
1330
1382
|
})
|
|
1331
1383
|
]);
|
|
1332
|
-
var PROMPT_ASSERTION =
|
|
1333
|
-
kind:
|
|
1334
|
-
op:
|
|
1335
|
-
target:
|
|
1336
|
-
expected:
|
|
1384
|
+
var PROMPT_ASSERTION = import_zod8.z.object({
|
|
1385
|
+
kind: import_zod8.z.enum(["status", "header", "json-path", "duration"]),
|
|
1386
|
+
op: import_zod8.z.enum(["equals", "not-equals", "contains", "lt", "gt", "matches"]),
|
|
1387
|
+
target: import_zod8.z.string().optional(),
|
|
1388
|
+
expected: import_zod8.z.union([import_zod8.z.string(), import_zod8.z.number()])
|
|
1337
1389
|
});
|
|
1338
|
-
var ENDPOINT_RESPONSE =
|
|
1339
|
-
status:
|
|
1340
|
-
jsonBody:
|
|
1341
|
-
contentType:
|
|
1390
|
+
var ENDPOINT_RESPONSE = import_zod8.z.object({
|
|
1391
|
+
status: import_zod8.z.number().int().min(100).max(599).default(200),
|
|
1392
|
+
jsonBody: import_zod8.z.string().default("{}"),
|
|
1393
|
+
contentType: import_zod8.z.string().default("application/json")
|
|
1342
1394
|
});
|
|
1343
|
-
var VALIDATION_RULE_NL =
|
|
1344
|
-
kind:
|
|
1395
|
+
var VALIDATION_RULE_NL = import_zod8.z.object({
|
|
1396
|
+
kind: import_zod8.z.enum([
|
|
1345
1397
|
"header-required",
|
|
1346
1398
|
"header-equals",
|
|
1347
1399
|
"header-matches",
|
|
@@ -1352,50 +1404,50 @@ var VALIDATION_RULE_NL = import_zod7.z.object({
|
|
|
1352
1404
|
"body-required",
|
|
1353
1405
|
"content-type-equals"
|
|
1354
1406
|
]),
|
|
1355
|
-
target:
|
|
1356
|
-
expected:
|
|
1357
|
-
message:
|
|
1358
|
-
enabled:
|
|
1359
|
-
failResponse:
|
|
1360
|
-
status:
|
|
1361
|
-
jsonBody:
|
|
1407
|
+
target: import_zod8.z.string().default(""),
|
|
1408
|
+
expected: import_zod8.z.string().optional(),
|
|
1409
|
+
message: import_zod8.z.string().optional(),
|
|
1410
|
+
enabled: import_zod8.z.boolean().default(true),
|
|
1411
|
+
failResponse: import_zod8.z.object({
|
|
1412
|
+
status: import_zod8.z.number().int().min(100).max(599).default(400),
|
|
1413
|
+
jsonBody: import_zod8.z.string().default('{"error":"validation failed"}')
|
|
1362
1414
|
}).default({})
|
|
1363
1415
|
});
|
|
1364
|
-
var CONDITION_CLAUSE_NL =
|
|
1365
|
-
scope:
|
|
1366
|
-
target:
|
|
1367
|
-
op:
|
|
1368
|
-
value:
|
|
1416
|
+
var CONDITION_CLAUSE_NL = import_zod8.z.object({
|
|
1417
|
+
scope: import_zod8.z.enum(["query", "pathParam", "header", "cookie", "body-json-path"]),
|
|
1418
|
+
target: import_zod8.z.string(),
|
|
1419
|
+
op: import_zod8.z.enum(["equals", "not-equals", "matches", "gt", "lt", "gte", "lte", "present", "absent"]),
|
|
1420
|
+
value: import_zod8.z.string().optional()
|
|
1369
1421
|
});
|
|
1370
|
-
var RESPONSE_RULE_NL =
|
|
1371
|
-
name:
|
|
1372
|
-
enabled:
|
|
1373
|
-
when:
|
|
1374
|
-
response:
|
|
1375
|
-
status:
|
|
1376
|
-
jsonBody:
|
|
1422
|
+
var RESPONSE_RULE_NL = import_zod8.z.object({
|
|
1423
|
+
name: import_zod8.z.string(),
|
|
1424
|
+
enabled: import_zod8.z.boolean().default(true),
|
|
1425
|
+
when: import_zod8.z.array(CONDITION_CLAUSE_NL).default([]),
|
|
1426
|
+
response: import_zod8.z.object({
|
|
1427
|
+
status: import_zod8.z.number().int().min(100).max(599).default(200),
|
|
1428
|
+
jsonBody: import_zod8.z.string().default("{}")
|
|
1377
1429
|
}).default({})
|
|
1378
1430
|
});
|
|
1379
|
-
var MULTIPLIER_NL =
|
|
1380
|
-
name:
|
|
1381
|
-
source:
|
|
1382
|
-
kind:
|
|
1383
|
-
key:
|
|
1431
|
+
var MULTIPLIER_NL = import_zod8.z.object({
|
|
1432
|
+
name: import_zod8.z.string().optional(),
|
|
1433
|
+
source: import_zod8.z.object({
|
|
1434
|
+
kind: import_zod8.z.enum(["query", "pathParam", "header", "body-json-path"]),
|
|
1435
|
+
key: import_zod8.z.string()
|
|
1384
1436
|
}),
|
|
1385
|
-
targetJsonPath:
|
|
1386
|
-
defaultCount:
|
|
1387
|
-
min:
|
|
1388
|
-
max:
|
|
1437
|
+
targetJsonPath: import_zod8.z.string(),
|
|
1438
|
+
defaultCount: import_zod8.z.number().int().nonnegative().default(0),
|
|
1439
|
+
min: import_zod8.z.number().int().nonnegative().optional(),
|
|
1440
|
+
max: import_zod8.z.number().int().nonnegative().optional()
|
|
1389
1441
|
});
|
|
1390
|
-
var ENDPOINT_INPUT =
|
|
1442
|
+
var ENDPOINT_INPUT = import_zod8.z.object({
|
|
1391
1443
|
method: HTTP_METHOD2,
|
|
1392
|
-
pathPattern:
|
|
1393
|
-
name:
|
|
1394
|
-
description:
|
|
1444
|
+
pathPattern: import_zod8.z.string().min(1),
|
|
1445
|
+
name: import_zod8.z.string().optional(),
|
|
1446
|
+
description: import_zod8.z.string().optional(),
|
|
1395
1447
|
response: ENDPOINT_RESPONSE.optional(),
|
|
1396
|
-
validationRules:
|
|
1397
|
-
responseRules:
|
|
1398
|
-
multipliers:
|
|
1448
|
+
validationRules: import_zod8.z.array(VALIDATION_RULE_NL).default([]),
|
|
1449
|
+
responseRules: import_zod8.z.array(RESPONSE_RULE_NL).default([]),
|
|
1450
|
+
multipliers: import_zod8.z.array(MULTIPLIER_NL).default([])
|
|
1399
1451
|
});
|
|
1400
1452
|
function buildRequestBody(input) {
|
|
1401
1453
|
if (!input) return { type: "none", content: "" };
|
|
@@ -1488,17 +1540,17 @@ function patchEndpoint(mock, endpointId, patcher) {
|
|
|
1488
1540
|
var promptCreateRequestTool = {
|
|
1489
1541
|
name: "prompt.create_request",
|
|
1490
1542
|
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.",
|
|
1491
|
-
inputSchema:
|
|
1492
|
-
name:
|
|
1543
|
+
inputSchema: import_zod8.z.object({
|
|
1544
|
+
name: import_zod8.z.string().default("New request"),
|
|
1493
1545
|
method: HTTP_METHOD2.default("GET"),
|
|
1494
|
-
url:
|
|
1495
|
-
folderId:
|
|
1496
|
-
headers:
|
|
1497
|
-
queryParams:
|
|
1498
|
-
pathParams:
|
|
1546
|
+
url: import_zod8.z.string().default(""),
|
|
1547
|
+
folderId: import_zod8.z.string().nullable().optional(),
|
|
1548
|
+
headers: import_zod8.z.array(HEADER_OR_QUERY).default([]),
|
|
1549
|
+
queryParams: import_zod8.z.array(HEADER_OR_QUERY).default([]),
|
|
1550
|
+
pathParams: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.string()).optional(),
|
|
1499
1551
|
body: REQUEST_BODY.optional(),
|
|
1500
1552
|
auth: PROMPT_AUTH.optional(),
|
|
1501
|
-
assertions:
|
|
1553
|
+
assertions: import_zod8.z.array(PROMPT_ASSERTION).default([])
|
|
1502
1554
|
}),
|
|
1503
1555
|
async handler(input, ctx) {
|
|
1504
1556
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1528,19 +1580,19 @@ var promptCreateRequestTool = {
|
|
|
1528
1580
|
var promptUpdateRequestTool = {
|
|
1529
1581
|
name: "prompt.update_request",
|
|
1530
1582
|
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.",
|
|
1531
|
-
inputSchema:
|
|
1532
|
-
id:
|
|
1533
|
-
patch:
|
|
1534
|
-
name:
|
|
1583
|
+
inputSchema: import_zod8.z.object({
|
|
1584
|
+
id: import_zod8.z.string(),
|
|
1585
|
+
patch: import_zod8.z.object({
|
|
1586
|
+
name: import_zod8.z.string().optional(),
|
|
1535
1587
|
method: HTTP_METHOD2.optional(),
|
|
1536
|
-
url:
|
|
1537
|
-
folderId:
|
|
1538
|
-
headers:
|
|
1539
|
-
queryParams:
|
|
1540
|
-
pathParams:
|
|
1588
|
+
url: import_zod8.z.string().optional(),
|
|
1589
|
+
folderId: import_zod8.z.string().nullable().optional(),
|
|
1590
|
+
headers: import_zod8.z.array(HEADER_OR_QUERY).optional(),
|
|
1591
|
+
queryParams: import_zod8.z.array(HEADER_OR_QUERY).optional(),
|
|
1592
|
+
pathParams: import_zod8.z.record(import_zod8.z.string(), import_zod8.z.string()).optional(),
|
|
1541
1593
|
body: REQUEST_BODY.optional(),
|
|
1542
1594
|
auth: PROMPT_AUTH.optional(),
|
|
1543
|
-
assertions:
|
|
1595
|
+
assertions: import_zod8.z.array(PROMPT_ASSERTION).optional()
|
|
1544
1596
|
}).strict()
|
|
1545
1597
|
}),
|
|
1546
1598
|
async handler(input, ctx) {
|
|
@@ -1568,17 +1620,17 @@ var promptUpdateRequestTool = {
|
|
|
1568
1620
|
return { ok: true, changedIds: out.changedIds };
|
|
1569
1621
|
}
|
|
1570
1622
|
};
|
|
1571
|
-
var FOLDER_TREE_NODE =
|
|
1572
|
-
() =>
|
|
1573
|
-
name:
|
|
1574
|
-
children:
|
|
1623
|
+
var FOLDER_TREE_NODE = import_zod8.z.lazy(
|
|
1624
|
+
() => import_zod8.z.object({
|
|
1625
|
+
name: import_zod8.z.string(),
|
|
1626
|
+
children: import_zod8.z.array(FOLDER_TREE_NODE).optional()
|
|
1575
1627
|
})
|
|
1576
1628
|
);
|
|
1577
1629
|
var promptCreateFolderTreeTool = {
|
|
1578
1630
|
name: "prompt.create_folder_tree",
|
|
1579
1631
|
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.",
|
|
1580
|
-
inputSchema:
|
|
1581
|
-
parentId:
|
|
1632
|
+
inputSchema: import_zod8.z.object({
|
|
1633
|
+
parentId: import_zod8.z.string().nullable().optional(),
|
|
1582
1634
|
tree: FOLDER_TREE_NODE
|
|
1583
1635
|
}),
|
|
1584
1636
|
async handler(input, ctx) {
|
|
@@ -1604,9 +1656,9 @@ var promptCreateFolderTreeTool = {
|
|
|
1604
1656
|
var promptAddPlanStepsTool = {
|
|
1605
1657
|
name: "prompt.add_plan_steps",
|
|
1606
1658
|
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.",
|
|
1607
|
-
inputSchema:
|
|
1608
|
-
planId:
|
|
1609
|
-
requestIds:
|
|
1659
|
+
inputSchema: import_zod8.z.object({
|
|
1660
|
+
planId: import_zod8.z.string(),
|
|
1661
|
+
requestIds: import_zod8.z.array(import_zod8.z.string()).min(1)
|
|
1610
1662
|
}),
|
|
1611
1663
|
async handler(input, ctx) {
|
|
1612
1664
|
const state = await ctx.workspace.read();
|
|
@@ -1636,9 +1688,9 @@ var promptAddPlanStepsTool = {
|
|
|
1636
1688
|
var promptSetPlanVariablesTool = {
|
|
1637
1689
|
name: "prompt.set_plan_variables",
|
|
1638
1690
|
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.",
|
|
1639
|
-
inputSchema:
|
|
1640
|
-
planId:
|
|
1641
|
-
variables:
|
|
1691
|
+
inputSchema: import_zod8.z.object({
|
|
1692
|
+
planId: import_zod8.z.string(),
|
|
1693
|
+
variables: import_zod8.z.array(import_zod8.z.object({ key: import_zod8.z.string(), value: import_zod8.z.string() }))
|
|
1642
1694
|
}),
|
|
1643
1695
|
async handler(input, ctx) {
|
|
1644
1696
|
const state = await ctx.workspace.read();
|
|
@@ -1654,10 +1706,10 @@ var promptSetPlanVariablesTool = {
|
|
|
1654
1706
|
var promptCreateMockServerTool = {
|
|
1655
1707
|
name: "prompt.create_mock_server",
|
|
1656
1708
|
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.",
|
|
1657
|
-
inputSchema:
|
|
1658
|
-
name:
|
|
1659
|
-
defaultPort:
|
|
1660
|
-
endpoints:
|
|
1709
|
+
inputSchema: import_zod8.z.object({
|
|
1710
|
+
name: import_zod8.z.string().min(1),
|
|
1711
|
+
defaultPort: import_zod8.z.number().int().positive().nullable().optional(),
|
|
1712
|
+
endpoints: import_zod8.z.array(ENDPOINT_INPUT).default([])
|
|
1661
1713
|
}),
|
|
1662
1714
|
async handler(input, ctx) {
|
|
1663
1715
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -1684,16 +1736,16 @@ var promptCreateMockServerTool = {
|
|
|
1684
1736
|
var promptAddMockEndpointTool = {
|
|
1685
1737
|
name: "prompt.add_mock_endpoint",
|
|
1686
1738
|
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.",
|
|
1687
|
-
inputSchema:
|
|
1688
|
-
mockId:
|
|
1739
|
+
inputSchema: import_zod8.z.object({
|
|
1740
|
+
mockId: import_zod8.z.string(),
|
|
1689
1741
|
method: HTTP_METHOD2,
|
|
1690
|
-
pathPattern:
|
|
1691
|
-
name:
|
|
1692
|
-
description:
|
|
1742
|
+
pathPattern: import_zod8.z.string().min(1),
|
|
1743
|
+
name: import_zod8.z.string().optional(),
|
|
1744
|
+
description: import_zod8.z.string().optional(),
|
|
1693
1745
|
response: ENDPOINT_RESPONSE.optional(),
|
|
1694
|
-
validationRules:
|
|
1695
|
-
responseRules:
|
|
1696
|
-
multipliers:
|
|
1746
|
+
validationRules: import_zod8.z.array(VALIDATION_RULE_NL).default([]),
|
|
1747
|
+
responseRules: import_zod8.z.array(RESPONSE_RULE_NL).default([]),
|
|
1748
|
+
multipliers: import_zod8.z.array(MULTIPLIER_NL).default([])
|
|
1697
1749
|
}),
|
|
1698
1750
|
async handler(input, ctx) {
|
|
1699
1751
|
const state = await ctx.workspace.read();
|
|
@@ -1715,10 +1767,10 @@ var promptAddMockEndpointTool = {
|
|
|
1715
1767
|
var promptSetEndpointValidationRulesTool = {
|
|
1716
1768
|
name: "prompt.set_endpoint_validation_rules",
|
|
1717
1769
|
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.",
|
|
1718
|
-
inputSchema:
|
|
1719
|
-
mockId:
|
|
1720
|
-
endpointId:
|
|
1721
|
-
rules:
|
|
1770
|
+
inputSchema: import_zod8.z.object({
|
|
1771
|
+
mockId: import_zod8.z.string(),
|
|
1772
|
+
endpointId: import_zod8.z.string(),
|
|
1773
|
+
rules: import_zod8.z.array(VALIDATION_RULE_NL)
|
|
1722
1774
|
}),
|
|
1723
1775
|
async handler(input, ctx) {
|
|
1724
1776
|
const state = await ctx.workspace.read();
|
|
@@ -1749,10 +1801,10 @@ var promptSetEndpointValidationRulesTool = {
|
|
|
1749
1801
|
var promptSetEndpointResponseRulesTool = {
|
|
1750
1802
|
name: "prompt.set_endpoint_response_rules",
|
|
1751
1803
|
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.",
|
|
1752
|
-
inputSchema:
|
|
1753
|
-
mockId:
|
|
1754
|
-
endpointId:
|
|
1755
|
-
rules:
|
|
1804
|
+
inputSchema: import_zod8.z.object({
|
|
1805
|
+
mockId: import_zod8.z.string(),
|
|
1806
|
+
endpointId: import_zod8.z.string(),
|
|
1807
|
+
rules: import_zod8.z.array(RESPONSE_RULE_NL)
|
|
1756
1808
|
}),
|
|
1757
1809
|
async handler(input, ctx) {
|
|
1758
1810
|
const state = await ctx.workspace.read();
|
|
@@ -1787,10 +1839,10 @@ var promptSetEndpointResponseRulesTool = {
|
|
|
1787
1839
|
var promptSetEndpointMultipliersTool = {
|
|
1788
1840
|
name: "prompt.set_endpoint_multipliers",
|
|
1789
1841
|
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.",
|
|
1790
|
-
inputSchema:
|
|
1791
|
-
mockId:
|
|
1792
|
-
endpointId:
|
|
1793
|
-
multipliers:
|
|
1842
|
+
inputSchema: import_zod8.z.object({
|
|
1843
|
+
mockId: import_zod8.z.string(),
|
|
1844
|
+
endpointId: import_zod8.z.string(),
|
|
1845
|
+
multipliers: import_zod8.z.array(MULTIPLIER_NL)
|
|
1794
1846
|
}),
|
|
1795
1847
|
async handler(input, ctx) {
|
|
1796
1848
|
const state = await ctx.workspace.read();
|
|
@@ -1819,7 +1871,7 @@ var promptSetEndpointMultipliersTool = {
|
|
|
1819
1871
|
};
|
|
1820
1872
|
|
|
1821
1873
|
// src/tools/mocks.ts
|
|
1822
|
-
var
|
|
1874
|
+
var import_zod9 = require("zod");
|
|
1823
1875
|
var import_shared4 = require("@apicircle/shared");
|
|
1824
1876
|
var import_mock_server_core2 = require("@apicircle/mock-server-core");
|
|
1825
1877
|
async function ingestSource(source, name) {
|
|
@@ -1842,10 +1894,10 @@ async function ingestSource(source, name) {
|
|
|
1842
1894
|
var mockCreateFromOpenApiTool = {
|
|
1843
1895
|
name: "mock.create_from_openapi",
|
|
1844
1896
|
description: "Create a mock server from an OpenAPI / Swagger spec (YAML or JSON).",
|
|
1845
|
-
inputSchema:
|
|
1846
|
-
name:
|
|
1847
|
-
spec:
|
|
1848
|
-
format:
|
|
1897
|
+
inputSchema: import_zod9.z.object({
|
|
1898
|
+
name: import_zod9.z.string(),
|
|
1899
|
+
spec: import_zod9.z.string().min(1),
|
|
1900
|
+
format: import_zod9.z.enum(["json", "yaml"]).default("json")
|
|
1849
1901
|
}),
|
|
1850
1902
|
async handler(input, ctx) {
|
|
1851
1903
|
const { mock, warnings } = await ingestSource(
|
|
@@ -1864,7 +1916,7 @@ var mockCreateFromOpenApiTool = {
|
|
|
1864
1916
|
var mockCreateFromPostmanTool = {
|
|
1865
1917
|
name: "mock.create_from_postman",
|
|
1866
1918
|
description: "Create a mock server from a Postman v2/v2.1 collection.",
|
|
1867
|
-
inputSchema:
|
|
1919
|
+
inputSchema: import_zod9.z.object({ name: import_zod9.z.string(), collection: import_zod9.z.string().min(1) }),
|
|
1868
1920
|
async handler(input, ctx) {
|
|
1869
1921
|
const { mock, warnings } = await ingestSource(
|
|
1870
1922
|
{ kind: "postman", collection: input.collection },
|
|
@@ -1882,7 +1934,7 @@ var mockCreateFromPostmanTool = {
|
|
|
1882
1934
|
var mockCreateFromInsomniaTool = {
|
|
1883
1935
|
name: "mock.create_from_insomnia",
|
|
1884
1936
|
description: "Create a mock server from an Insomnia v4 export.",
|
|
1885
|
-
inputSchema:
|
|
1937
|
+
inputSchema: import_zod9.z.object({ name: import_zod9.z.string(), export: import_zod9.z.string().min(1) }),
|
|
1886
1938
|
async handler(input, ctx) {
|
|
1887
1939
|
const { mock, warnings } = await ingestSource(
|
|
1888
1940
|
{ kind: "insomnia", export: input.export },
|
|
@@ -1900,7 +1952,7 @@ var mockCreateFromInsomniaTool = {
|
|
|
1900
1952
|
var mockImportPostmanMockCollectionTool = {
|
|
1901
1953
|
name: "mock.import_postman_mock_collection",
|
|
1902
1954
|
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.",
|
|
1903
|
-
inputSchema:
|
|
1955
|
+
inputSchema: import_zod9.z.object({ name: import_zod9.z.string(), collection: import_zod9.z.string().min(1) }),
|
|
1904
1956
|
async handler(input, ctx) {
|
|
1905
1957
|
const { mock, warnings } = await ingestSource(
|
|
1906
1958
|
{ kind: "postman", collection: input.collection },
|
|
@@ -1918,7 +1970,7 @@ var mockImportPostmanMockCollectionTool = {
|
|
|
1918
1970
|
var mockListTool = {
|
|
1919
1971
|
name: "mock.list",
|
|
1920
1972
|
description: "List all mock servers in the workspace plus their runtime status (running / stopped, port).",
|
|
1921
|
-
inputSchema:
|
|
1973
|
+
inputSchema: import_zod9.z.object({}),
|
|
1922
1974
|
async handler(_input, ctx) {
|
|
1923
1975
|
const state = await ctx.workspace.read();
|
|
1924
1976
|
const running = await ctx.mock.list();
|
|
@@ -1940,9 +1992,9 @@ var mockListTool = {
|
|
|
1940
1992
|
var mockStartTool = {
|
|
1941
1993
|
name: "mock.start",
|
|
1942
1994
|
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.",
|
|
1943
|
-
inputSchema:
|
|
1944
|
-
id:
|
|
1945
|
-
port:
|
|
1995
|
+
inputSchema: import_zod9.z.object({
|
|
1996
|
+
id: import_zod9.z.string(),
|
|
1997
|
+
port: import_zod9.z.number().int().positive().optional()
|
|
1946
1998
|
}),
|
|
1947
1999
|
async handler(input, ctx) {
|
|
1948
2000
|
const state = await ctx.workspace.read();
|
|
@@ -1959,7 +2011,7 @@ var mockStartTool = {
|
|
|
1959
2011
|
var mockStopTool = {
|
|
1960
2012
|
name: "mock.stop",
|
|
1961
2013
|
description: "Stop a running mock server by id (no-op if not running).",
|
|
1962
|
-
inputSchema:
|
|
2014
|
+
inputSchema: import_zod9.z.object({ id: import_zod9.z.string() }),
|
|
1963
2015
|
async handler(input, ctx) {
|
|
1964
2016
|
try {
|
|
1965
2017
|
await ctx.mock.stop(input.id);
|
|
@@ -1972,7 +2024,7 @@ var mockStopTool = {
|
|
|
1972
2024
|
var mockDeleteTool = {
|
|
1973
2025
|
name: "mock.delete",
|
|
1974
2026
|
description: "Delete a mock server definition. Stops it first if it's running.",
|
|
1975
|
-
inputSchema:
|
|
2027
|
+
inputSchema: import_zod9.z.object({ id: import_zod9.z.string() }),
|
|
1976
2028
|
async handler(input, ctx) {
|
|
1977
2029
|
try {
|
|
1978
2030
|
await ctx.mock.stop(input.id);
|
|
@@ -1982,13 +2034,13 @@ var mockDeleteTool = {
|
|
|
1982
2034
|
return { ok: true, changedIds: out.changedIds };
|
|
1983
2035
|
}
|
|
1984
2036
|
};
|
|
1985
|
-
var HTTP_METHOD3 =
|
|
2037
|
+
var HTTP_METHOD3 = import_zod9.z.enum(["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"]);
|
|
1986
2038
|
var mockCreateManualTool = {
|
|
1987
2039
|
name: "mock.create_manual",
|
|
1988
2040
|
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.",
|
|
1989
|
-
inputSchema:
|
|
1990
|
-
name:
|
|
1991
|
-
defaultPort:
|
|
2041
|
+
inputSchema: import_zod9.z.object({
|
|
2042
|
+
name: import_zod9.z.string().min(1),
|
|
2043
|
+
defaultPort: import_zod9.z.number().int().positive().nullable().optional()
|
|
1992
2044
|
}),
|
|
1993
2045
|
async handler(input, ctx) {
|
|
1994
2046
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2011,7 +2063,7 @@ var mockCreateManualTool = {
|
|
|
2011
2063
|
var mockListEndpointsTool = {
|
|
2012
2064
|
name: "mock.list_endpoints",
|
|
2013
2065
|
description: "List endpoints for a mock server (id, method, path, name).",
|
|
2014
|
-
inputSchema:
|
|
2066
|
+
inputSchema: import_zod9.z.object({ mockId: import_zod9.z.string() }),
|
|
2015
2067
|
async handler(input, ctx) {
|
|
2016
2068
|
const state = await ctx.workspace.read();
|
|
2017
2069
|
const mock = state.synced.mockServers[input.mockId];
|
|
@@ -2030,10 +2082,10 @@ var mockListEndpointsTool = {
|
|
|
2030
2082
|
};
|
|
2031
2083
|
}
|
|
2032
2084
|
};
|
|
2033
|
-
var ENDPOINT_RESPONSE2 =
|
|
2034
|
-
status:
|
|
2035
|
-
jsonBody:
|
|
2036
|
-
contentType:
|
|
2085
|
+
var ENDPOINT_RESPONSE2 = import_zod9.z.object({
|
|
2086
|
+
status: import_zod9.z.number().int().min(100).max(599).default(200),
|
|
2087
|
+
jsonBody: import_zod9.z.string().default("{}"),
|
|
2088
|
+
contentType: import_zod9.z.string().default("application/json")
|
|
2037
2089
|
});
|
|
2038
2090
|
function buildDefaultEndpoint(args) {
|
|
2039
2091
|
const response = args.response ?? {
|
|
@@ -2062,12 +2114,12 @@ function buildDefaultEndpoint(args) {
|
|
|
2062
2114
|
var mockAddEndpointTool = {
|
|
2063
2115
|
name: "mock.add_endpoint",
|
|
2064
2116
|
description: "Append a new endpoint to a mock server. Defaults to a 200 JSON response of `{}`. Returns the new endpoint id.",
|
|
2065
|
-
inputSchema:
|
|
2066
|
-
mockId:
|
|
2117
|
+
inputSchema: import_zod9.z.object({
|
|
2118
|
+
mockId: import_zod9.z.string(),
|
|
2067
2119
|
method: HTTP_METHOD3,
|
|
2068
|
-
pathPattern:
|
|
2069
|
-
name:
|
|
2070
|
-
description:
|
|
2120
|
+
pathPattern: import_zod9.z.string().min(1),
|
|
2121
|
+
name: import_zod9.z.string().optional(),
|
|
2122
|
+
description: import_zod9.z.string().optional(),
|
|
2071
2123
|
response: ENDPOINT_RESPONSE2.optional()
|
|
2072
2124
|
}),
|
|
2073
2125
|
async handler(input, ctx) {
|
|
@@ -2090,13 +2142,13 @@ var mockAddEndpointTool = {
|
|
|
2090
2142
|
var mockUpdateEndpointTool = {
|
|
2091
2143
|
name: "mock.update_endpoint",
|
|
2092
2144
|
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.",
|
|
2093
|
-
inputSchema:
|
|
2094
|
-
mockId:
|
|
2095
|
-
endpointId:
|
|
2145
|
+
inputSchema: import_zod9.z.object({
|
|
2146
|
+
mockId: import_zod9.z.string(),
|
|
2147
|
+
endpointId: import_zod9.z.string(),
|
|
2096
2148
|
method: HTTP_METHOD3.optional(),
|
|
2097
|
-
pathPattern:
|
|
2098
|
-
name:
|
|
2099
|
-
description:
|
|
2149
|
+
pathPattern: import_zod9.z.string().optional(),
|
|
2150
|
+
name: import_zod9.z.string().optional(),
|
|
2151
|
+
description: import_zod9.z.string().optional(),
|
|
2100
2152
|
response: ENDPOINT_RESPONSE2.partial().optional()
|
|
2101
2153
|
}),
|
|
2102
2154
|
async handler(input, ctx) {
|
|
@@ -2137,7 +2189,7 @@ var mockUpdateEndpointTool = {
|
|
|
2137
2189
|
var mockDeleteEndpointTool = {
|
|
2138
2190
|
name: "mock.delete_endpoint",
|
|
2139
2191
|
description: "Remove an endpoint from a mock server.",
|
|
2140
|
-
inputSchema:
|
|
2192
|
+
inputSchema: import_zod9.z.object({ mockId: import_zod9.z.string(), endpointId: import_zod9.z.string() }),
|
|
2141
2193
|
async handler(input, ctx) {
|
|
2142
2194
|
const state = await ctx.workspace.read();
|
|
2143
2195
|
const mock = state.synced.mockServers[input.mockId];
|
|
@@ -2157,9 +2209,9 @@ var mockDeleteEndpointTool = {
|
|
|
2157
2209
|
return { ok: true, changedIds: out.changedIds };
|
|
2158
2210
|
}
|
|
2159
2211
|
};
|
|
2160
|
-
var VALIDATION_RULE =
|
|
2161
|
-
id:
|
|
2162
|
-
kind:
|
|
2212
|
+
var VALIDATION_RULE = import_zod9.z.object({
|
|
2213
|
+
id: import_zod9.z.string().optional(),
|
|
2214
|
+
kind: import_zod9.z.enum([
|
|
2163
2215
|
"header-required",
|
|
2164
2216
|
"header-equals",
|
|
2165
2217
|
"header-matches",
|
|
@@ -2170,43 +2222,43 @@ var VALIDATION_RULE = import_zod8.z.object({
|
|
|
2170
2222
|
"body-required",
|
|
2171
2223
|
"content-type-equals"
|
|
2172
2224
|
]),
|
|
2173
|
-
target:
|
|
2174
|
-
expected:
|
|
2175
|
-
message:
|
|
2176
|
-
enabled:
|
|
2177
|
-
failResponse:
|
|
2178
|
-
status:
|
|
2179
|
-
jsonBody:
|
|
2225
|
+
target: import_zod9.z.string().default(""),
|
|
2226
|
+
expected: import_zod9.z.string().optional(),
|
|
2227
|
+
message: import_zod9.z.string().optional(),
|
|
2228
|
+
enabled: import_zod9.z.boolean().default(true),
|
|
2229
|
+
failResponse: import_zod9.z.object({
|
|
2230
|
+
status: import_zod9.z.number().int().min(100).max(599).default(400),
|
|
2231
|
+
jsonBody: import_zod9.z.string().default('{"error":"validation failed"}')
|
|
2180
2232
|
}).default({})
|
|
2181
2233
|
});
|
|
2182
|
-
var CONDITION_CLAUSE =
|
|
2183
|
-
id:
|
|
2184
|
-
scope:
|
|
2185
|
-
target:
|
|
2186
|
-
op:
|
|
2187
|
-
value:
|
|
2234
|
+
var CONDITION_CLAUSE = import_zod9.z.object({
|
|
2235
|
+
id: import_zod9.z.string().optional(),
|
|
2236
|
+
scope: import_zod9.z.enum(["query", "pathParam", "header", "cookie", "body-json-path"]),
|
|
2237
|
+
target: import_zod9.z.string(),
|
|
2238
|
+
op: import_zod9.z.enum(["equals", "not-equals", "matches", "gt", "lt", "gte", "lte", "present", "absent"]),
|
|
2239
|
+
value: import_zod9.z.string().optional()
|
|
2188
2240
|
});
|
|
2189
|
-
var RESPONSE_RULE =
|
|
2190
|
-
id:
|
|
2191
|
-
name:
|
|
2192
|
-
enabled:
|
|
2193
|
-
when:
|
|
2194
|
-
response:
|
|
2195
|
-
status:
|
|
2196
|
-
jsonBody:
|
|
2241
|
+
var RESPONSE_RULE = import_zod9.z.object({
|
|
2242
|
+
id: import_zod9.z.string().optional(),
|
|
2243
|
+
name: import_zod9.z.string(),
|
|
2244
|
+
enabled: import_zod9.z.boolean().default(true),
|
|
2245
|
+
when: import_zod9.z.array(CONDITION_CLAUSE).default([]),
|
|
2246
|
+
response: import_zod9.z.object({
|
|
2247
|
+
status: import_zod9.z.number().int().min(100).max(599).default(200),
|
|
2248
|
+
jsonBody: import_zod9.z.string().default("{}")
|
|
2197
2249
|
}).default({})
|
|
2198
2250
|
});
|
|
2199
|
-
var MULTIPLIER =
|
|
2200
|
-
id:
|
|
2201
|
-
name:
|
|
2202
|
-
source:
|
|
2203
|
-
kind:
|
|
2204
|
-
key:
|
|
2251
|
+
var MULTIPLIER = import_zod9.z.object({
|
|
2252
|
+
id: import_zod9.z.string().optional(),
|
|
2253
|
+
name: import_zod9.z.string().optional(),
|
|
2254
|
+
source: import_zod9.z.object({
|
|
2255
|
+
kind: import_zod9.z.enum(["query", "pathParam", "header", "body-json-path"]),
|
|
2256
|
+
key: import_zod9.z.string()
|
|
2205
2257
|
}),
|
|
2206
|
-
targetJsonPath:
|
|
2207
|
-
defaultCount:
|
|
2208
|
-
min:
|
|
2209
|
-
max:
|
|
2258
|
+
targetJsonPath: import_zod9.z.string(),
|
|
2259
|
+
defaultCount: import_zod9.z.number().int().nonnegative().default(0),
|
|
2260
|
+
min: import_zod9.z.number().int().nonnegative().optional(),
|
|
2261
|
+
max: import_zod9.z.number().int().nonnegative().optional()
|
|
2210
2262
|
});
|
|
2211
2263
|
function defaultJsonResponseConfig(args) {
|
|
2212
2264
|
return {
|
|
@@ -2231,10 +2283,10 @@ function patchEndpoint2(mock, endpointId, patcher) {
|
|
|
2231
2283
|
var mockSetValidationRulesTool = {
|
|
2232
2284
|
name: "mock.set_validation_rules",
|
|
2233
2285
|
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.",
|
|
2234
|
-
inputSchema:
|
|
2235
|
-
mockId:
|
|
2236
|
-
endpointId:
|
|
2237
|
-
rules:
|
|
2286
|
+
inputSchema: import_zod9.z.object({
|
|
2287
|
+
mockId: import_zod9.z.string(),
|
|
2288
|
+
endpointId: import_zod9.z.string(),
|
|
2289
|
+
rules: import_zod9.z.array(VALIDATION_RULE)
|
|
2238
2290
|
}),
|
|
2239
2291
|
async handler(input, ctx) {
|
|
2240
2292
|
const state = await ctx.workspace.read();
|
|
@@ -2261,10 +2313,10 @@ var mockSetValidationRulesTool = {
|
|
|
2261
2313
|
var mockSetResponseRulesTool = {
|
|
2262
2314
|
name: "mock.set_response_rules",
|
|
2263
2315
|
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.",
|
|
2264
|
-
inputSchema:
|
|
2265
|
-
mockId:
|
|
2266
|
-
endpointId:
|
|
2267
|
-
rules:
|
|
2316
|
+
inputSchema: import_zod9.z.object({
|
|
2317
|
+
mockId: import_zod9.z.string(),
|
|
2318
|
+
endpointId: import_zod9.z.string(),
|
|
2319
|
+
rules: import_zod9.z.array(RESPONSE_RULE)
|
|
2268
2320
|
}),
|
|
2269
2321
|
async handler(input, ctx) {
|
|
2270
2322
|
const state = await ctx.workspace.read();
|
|
@@ -2295,10 +2347,10 @@ var mockSetResponseRulesTool = {
|
|
|
2295
2347
|
var mockSetMultipliersTool = {
|
|
2296
2348
|
name: "mock.set_multipliers",
|
|
2297
2349
|
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.",
|
|
2298
|
-
inputSchema:
|
|
2299
|
-
mockId:
|
|
2300
|
-
endpointId:
|
|
2301
|
-
multipliers:
|
|
2350
|
+
inputSchema: import_zod9.z.object({
|
|
2351
|
+
mockId: import_zod9.z.string(),
|
|
2352
|
+
endpointId: import_zod9.z.string(),
|
|
2353
|
+
multipliers: import_zod9.z.array(MULTIPLIER)
|
|
2302
2354
|
}),
|
|
2303
2355
|
async handler(input, ctx) {
|
|
2304
2356
|
const state = await ctx.workspace.read();
|
|
@@ -2334,6 +2386,7 @@ var TOOL_REGISTRY = [
|
|
|
2334
2386
|
importInsomniaTool,
|
|
2335
2387
|
importHarTool,
|
|
2336
2388
|
generateCodeTool,
|
|
2389
|
+
workspaceListTool,
|
|
2337
2390
|
workspaceReadTool,
|
|
2338
2391
|
workspaceWriteTool,
|
|
2339
2392
|
requestCreateTool,
|
|
@@ -2401,6 +2454,63 @@ var TOOL_REGISTRY = [
|
|
|
2401
2454
|
mockImportPostmanMockCollectionTool
|
|
2402
2455
|
];
|
|
2403
2456
|
|
|
2457
|
+
// src/providers/Workspaces.ts
|
|
2458
|
+
var SingleWorkspaceAdapter = class {
|
|
2459
|
+
constructor(provider, workspaceId, displayName = "Workspace") {
|
|
2460
|
+
this.provider = provider;
|
|
2461
|
+
this.workspaceId = workspaceId;
|
|
2462
|
+
this.displayName = displayName;
|
|
2463
|
+
}
|
|
2464
|
+
provider;
|
|
2465
|
+
workspaceId;
|
|
2466
|
+
displayName;
|
|
2467
|
+
async list() {
|
|
2468
|
+
const state = await this.provider.read();
|
|
2469
|
+
const id = state.synced.workspaceId;
|
|
2470
|
+
this.workspaceId = id;
|
|
2471
|
+
return [
|
|
2472
|
+
{
|
|
2473
|
+
id,
|
|
2474
|
+
name: this.displayName,
|
|
2475
|
+
isActive: true,
|
|
2476
|
+
createdAt: state.synced.meta.createdAt,
|
|
2477
|
+
lastOpenedAt: state.synced.meta.updatedAt,
|
|
2478
|
+
counts: {
|
|
2479
|
+
requests: Object.keys(state.synced.collections.requests).length,
|
|
2480
|
+
folders: Object.keys(state.synced.collections.folders).length,
|
|
2481
|
+
environments: Object.keys(state.synced.environments.items).length,
|
|
2482
|
+
mockServers: Object.keys(state.synced.mockServers ?? {}).length,
|
|
2483
|
+
plans: Object.keys(state.synced.executionPlans ?? {}).length
|
|
2484
|
+
}
|
|
2485
|
+
}
|
|
2486
|
+
];
|
|
2487
|
+
}
|
|
2488
|
+
for(workspaceId) {
|
|
2489
|
+
if (this.workspaceId && workspaceId !== this.workspaceId) {
|
|
2490
|
+
throw new WorkspaceNotFoundError(workspaceId);
|
|
2491
|
+
}
|
|
2492
|
+
return this.provider;
|
|
2493
|
+
}
|
|
2494
|
+
activeId() {
|
|
2495
|
+
return this.workspaceId;
|
|
2496
|
+
}
|
|
2497
|
+
setActive(workspaceId) {
|
|
2498
|
+
if (this.workspaceId && workspaceId !== this.workspaceId) {
|
|
2499
|
+
throw new WorkspaceNotFoundError(workspaceId);
|
|
2500
|
+
}
|
|
2501
|
+
return Promise.resolve();
|
|
2502
|
+
}
|
|
2503
|
+
};
|
|
2504
|
+
var WorkspaceNotFoundError = class extends Error {
|
|
2505
|
+
code = "workspace-not-found";
|
|
2506
|
+
workspaceId;
|
|
2507
|
+
constructor(workspaceId) {
|
|
2508
|
+
super(`No workspace with id "${workspaceId}" is available on this server.`);
|
|
2509
|
+
this.name = "WorkspaceNotFoundError";
|
|
2510
|
+
this.workspaceId = workspaceId;
|
|
2511
|
+
}
|
|
2512
|
+
};
|
|
2513
|
+
|
|
2404
2514
|
// src/providers/InMemoryWorkspaceProvider.ts
|
|
2405
2515
|
var import_core2 = require("@apicircle/core");
|
|
2406
2516
|
|
|
@@ -2440,6 +2550,109 @@ var FileBackedWorkspaceProvider = class {
|
|
|
2440
2550
|
}
|
|
2441
2551
|
};
|
|
2442
2552
|
|
|
2553
|
+
// src/providers/MultiWorkspaceProvider.ts
|
|
2554
|
+
var import_registry = require("@apicircle/core/workspace/registry");
|
|
2555
|
+
var MultiWorkspaceProvider = class {
|
|
2556
|
+
constructor(registryRoot) {
|
|
2557
|
+
this.registryRoot = registryRoot;
|
|
2558
|
+
}
|
|
2559
|
+
registryRoot;
|
|
2560
|
+
active = null;
|
|
2561
|
+
activeWorkspaceId = null;
|
|
2562
|
+
/**
|
|
2563
|
+
* Hydrate the active provider from disk. Must be called once before the
|
|
2564
|
+
* MCP host boots so `ctx.workspace.read()` doesn't race the first
|
|
2565
|
+
* registry-load. Returns the registry the boot can log.
|
|
2566
|
+
*/
|
|
2567
|
+
async init() {
|
|
2568
|
+
const registry = await (0, import_registry.loadRegistry)(this.registryRoot) ?? {
|
|
2569
|
+
schemaVersion: 1,
|
|
2570
|
+
activeWorkspaceId: null,
|
|
2571
|
+
workspaces: []
|
|
2572
|
+
};
|
|
2573
|
+
if (registry.activeWorkspaceId) {
|
|
2574
|
+
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2575
|
+
this.active = new FileBackedWorkspaceProvider(
|
|
2576
|
+
(0, import_registry.workspaceDirFor)(this.registryRoot, registry.activeWorkspaceId)
|
|
2577
|
+
);
|
|
2578
|
+
}
|
|
2579
|
+
return registry;
|
|
2580
|
+
}
|
|
2581
|
+
/** The provider tool handlers see as `ctx.workspace`. */
|
|
2582
|
+
activeProvider() {
|
|
2583
|
+
if (!this.active) {
|
|
2584
|
+
throw new Error(
|
|
2585
|
+
"No active workspace. Open the desktop app at least once, or run `apicircle workspaces create <name>`."
|
|
2586
|
+
);
|
|
2587
|
+
}
|
|
2588
|
+
return this.active;
|
|
2589
|
+
}
|
|
2590
|
+
// ─── Workspaces interface ──────────────────────────────────────────────────
|
|
2591
|
+
async list() {
|
|
2592
|
+
const registry = await (0, import_registry.loadRegistry)(this.registryRoot) ?? {
|
|
2593
|
+
schemaVersion: 1,
|
|
2594
|
+
activeWorkspaceId: null,
|
|
2595
|
+
workspaces: []
|
|
2596
|
+
};
|
|
2597
|
+
const out = [];
|
|
2598
|
+
for (const entry of registry.workspaces) {
|
|
2599
|
+
let counts = null;
|
|
2600
|
+
try {
|
|
2601
|
+
const state = await (0, import_registry.loadWorkspaceById)(this.registryRoot, entry.id);
|
|
2602
|
+
if (state) {
|
|
2603
|
+
counts = {
|
|
2604
|
+
requests: Object.keys(state.synced.collections.requests).length,
|
|
2605
|
+
folders: Object.keys(state.synced.collections.folders).length,
|
|
2606
|
+
environments: Object.keys(state.synced.environments.items).length,
|
|
2607
|
+
mockServers: Object.keys(state.synced.mockServers ?? {}).length,
|
|
2608
|
+
plans: Object.keys(state.synced.executionPlans ?? {}).length
|
|
2609
|
+
};
|
|
2610
|
+
}
|
|
2611
|
+
} catch {
|
|
2612
|
+
counts = null;
|
|
2613
|
+
}
|
|
2614
|
+
out.push({
|
|
2615
|
+
id: entry.id,
|
|
2616
|
+
name: entry.name,
|
|
2617
|
+
isActive: entry.id === registry.activeWorkspaceId,
|
|
2618
|
+
createdAt: entry.createdAt,
|
|
2619
|
+
lastOpenedAt: entry.lastOpenedAt,
|
|
2620
|
+
counts
|
|
2621
|
+
});
|
|
2622
|
+
}
|
|
2623
|
+
return out;
|
|
2624
|
+
}
|
|
2625
|
+
for(workspaceId) {
|
|
2626
|
+
return new FileBackedWorkspaceProvider((0, import_registry.workspaceDirFor)(this.registryRoot, workspaceId));
|
|
2627
|
+
}
|
|
2628
|
+
activeId() {
|
|
2629
|
+
return this.activeWorkspaceId;
|
|
2630
|
+
}
|
|
2631
|
+
async setActive(workspaceId) {
|
|
2632
|
+
const registry = await (0, import_registry.loadRegistry)(this.registryRoot);
|
|
2633
|
+
if (!registry || !registry.workspaces.some((w) => w.id === workspaceId)) {
|
|
2634
|
+
throw new WorkspaceNotFoundError(workspaceId);
|
|
2635
|
+
}
|
|
2636
|
+
const next = await (0, import_registry.setActiveWorkspace)(this.registryRoot, workspaceId);
|
|
2637
|
+
void next;
|
|
2638
|
+
this.activeWorkspaceId = workspaceId;
|
|
2639
|
+
this.active = new FileBackedWorkspaceProvider((0, import_registry.workspaceDirFor)(this.registryRoot, workspaceId));
|
|
2640
|
+
}
|
|
2641
|
+
/**
|
|
2642
|
+
* Idempotent registry write — used by tests / tools that need to
|
|
2643
|
+
* persist registry updates that didn't go through `setActive`.
|
|
2644
|
+
*/
|
|
2645
|
+
async writeRegistry(registry) {
|
|
2646
|
+
await (0, import_registry.saveRegistry)(this.registryRoot, registry);
|
|
2647
|
+
this.activeWorkspaceId = registry.activeWorkspaceId;
|
|
2648
|
+
if (registry.activeWorkspaceId) {
|
|
2649
|
+
this.active = new FileBackedWorkspaceProvider(
|
|
2650
|
+
(0, import_registry.workspaceDirFor)(this.registryRoot, registry.activeWorkspaceId)
|
|
2651
|
+
);
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
};
|
|
2655
|
+
|
|
2443
2656
|
// src/providers/InProcessMockController.ts
|
|
2444
2657
|
var import_mock_server_core3 = require("@apicircle/mock-server-core");
|
|
2445
2658
|
var InProcessMockController = class {
|
|
@@ -2480,10 +2693,19 @@ var InProcessMockController = class {
|
|
|
2480
2693
|
|
|
2481
2694
|
// src/index.ts
|
|
2482
2695
|
function createMcpServer(options) {
|
|
2696
|
+
const workspaces = options.workspaces ?? new SingleWorkspaceAdapter(
|
|
2697
|
+
options.workspace,
|
|
2698
|
+
null
|
|
2699
|
+
/* discovered on first list() */
|
|
2700
|
+
);
|
|
2483
2701
|
return new McpHost({
|
|
2484
2702
|
serverInfo: options.serverInfo,
|
|
2485
2703
|
tools: options.tools ?? TOOL_REGISTRY,
|
|
2486
|
-
context: {
|
|
2704
|
+
context: {
|
|
2705
|
+
workspace: options.workspace,
|
|
2706
|
+
workspaces,
|
|
2707
|
+
mock: options.mock
|
|
2708
|
+
}
|
|
2487
2709
|
});
|
|
2488
2710
|
}
|
|
2489
2711
|
|
|
@@ -2497,11 +2719,43 @@ function getWorkspaceDir() {
|
|
|
2497
2719
|
if (env) return path.resolve(env);
|
|
2498
2720
|
return path.resolve(process.cwd());
|
|
2499
2721
|
}
|
|
2722
|
+
async function fileExists(p) {
|
|
2723
|
+
try {
|
|
2724
|
+
await import_node_fs.promises.access(p);
|
|
2725
|
+
return true;
|
|
2726
|
+
} catch {
|
|
2727
|
+
return false;
|
|
2728
|
+
}
|
|
2729
|
+
}
|
|
2500
2730
|
async function main() {
|
|
2501
2731
|
const dir = getWorkspaceDir();
|
|
2502
|
-
const
|
|
2732
|
+
const registryPath = path.join(dir, "registry.json");
|
|
2733
|
+
const isRegistryRoot = await fileExists(registryPath);
|
|
2503
2734
|
const mock = new InProcessMockController();
|
|
2504
|
-
|
|
2735
|
+
if (isRegistryRoot) {
|
|
2736
|
+
const workspaces2 = new MultiWorkspaceProvider(dir);
|
|
2737
|
+
const registry = await workspaces2.init();
|
|
2738
|
+
if (!registry.activeWorkspaceId) {
|
|
2739
|
+
process.stderr.write(
|
|
2740
|
+
`apicircle-mcp: registry at ${dir} has no active workspace. Open the desktop app once, or run \`apicircle workspaces create <name>\`.
|
|
2741
|
+
`
|
|
2742
|
+
);
|
|
2743
|
+
process.exit(1);
|
|
2744
|
+
}
|
|
2745
|
+
const workspace2 = workspaces2.activeProvider();
|
|
2746
|
+
const host2 = createMcpServer({ workspace: workspace2, workspaces: workspaces2, mock });
|
|
2747
|
+
process.stderr.write(
|
|
2748
|
+
`apicircle-mcp: multi-workspace mode \xB7 ${registry.workspaces.length} workspace(s) \xB7 active=${registry.activeWorkspaceId}
|
|
2749
|
+
`
|
|
2750
|
+
);
|
|
2751
|
+
await host2.connect();
|
|
2752
|
+
return;
|
|
2753
|
+
}
|
|
2754
|
+
const workspace = new FileBackedWorkspaceProvider(dir);
|
|
2755
|
+
const workspaces = new SingleWorkspaceAdapter(workspace, null);
|
|
2756
|
+
const host = createMcpServer({ workspace, workspaces, mock });
|
|
2757
|
+
process.stderr.write(`apicircle-mcp: single-workspace mode \xB7 ${dir}
|
|
2758
|
+
`);
|
|
2505
2759
|
await host.connect();
|
|
2506
2760
|
}
|
|
2507
2761
|
main().catch((err) => {
|