callman-mcp 0.1.0
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/CHANGELOG.md +28 -0
- package/LICENSE +21 -0
- package/README.md +203 -0
- package/dist/client/api.d.ts +109 -0
- package/dist/client/api.d.ts.map +1 -0
- package/dist/client/api.js +180 -0
- package/dist/client/api.js.map +1 -0
- package/dist/client/errors.d.ts +27 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +98 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/http.d.ts +34 -0
- package/dist/client/http.d.ts.map +1 -0
- package/dist/client/http.js +121 -0
- package/dist/client/http.js.map +1 -0
- package/dist/client/types.d.ts +327 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +5 -0
- package/dist/client/types.js.map +1 -0
- package/dist/config.d.ts +20 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +69 -0
- package/dist/config.js.map +1 -0
- package/dist/context.d.ts +35 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +91 -0
- package/dist/context.js.map +1 -0
- package/dist/domain/diagram/build.d.ts +260 -0
- package/dist/domain/diagram/build.d.ts.map +1 -0
- package/dist/domain/diagram/build.js +160 -0
- package/dist/domain/diagram/build.js.map +1 -0
- package/dist/domain/diagram/layout.d.ts +17 -0
- package/dist/domain/diagram/layout.d.ts.map +1 -0
- package/dist/domain/diagram/layout.js +61 -0
- package/dist/domain/diagram/layout.js.map +1 -0
- package/dist/domain/diagram/patch.d.ts +330 -0
- package/dist/domain/diagram/patch.d.ts.map +1 -0
- package/dist/domain/diagram/patch.js +176 -0
- package/dist/domain/diagram/patch.js.map +1 -0
- package/dist/domain/diagram/summarize.d.ts +41 -0
- package/dist/domain/diagram/summarize.d.ts.map +1 -0
- package/dist/domain/diagram/summarize.js +47 -0
- package/dist/domain/diagram/summarize.js.map +1 -0
- package/dist/domain/importDetect.d.ts +6 -0
- package/dist/domain/importDetect.d.ts.map +1 -0
- package/dist/domain/importDetect.js +32 -0
- package/dist/domain/importDetect.js.map +1 -0
- package/dist/domain/requestShape.d.ts +796 -0
- package/dist/domain/requestShape.d.ts.map +1 -0
- package/dist/domain/requestShape.js +250 -0
- package/dist/domain/requestShape.js.map +1 -0
- package/dist/domain/resolve.d.ts +30 -0
- package/dist/domain/resolve.d.ts.map +1 -0
- package/dist/domain/resolve.js +56 -0
- package/dist/domain/resolve.js.map +1 -0
- package/dist/domain/scenario/build.d.ts +270 -0
- package/dist/domain/scenario/build.d.ts.map +1 -0
- package/dist/domain/scenario/build.js +135 -0
- package/dist/domain/scenario/build.js.map +1 -0
- package/dist/domain/scenario/summarize.d.ts +206 -0
- package/dist/domain/scenario/summarize.d.ts.map +1 -0
- package/dist/domain/scenario/summarize.js +138 -0
- package/dist/domain/scenario/summarize.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +142 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cache.d.ts +12 -0
- package/dist/lib/cache.d.ts.map +1 -0
- package/dist/lib/cache.js +40 -0
- package/dist/lib/cache.js.map +1 -0
- package/dist/lib/ids.d.ts +5 -0
- package/dist/lib/ids.d.ts.map +1 -0
- package/dist/lib/ids.js +19 -0
- package/dist/lib/ids.js.map +1 -0
- package/dist/lib/log.d.ts +10 -0
- package/dist/lib/log.d.ts.map +1 -0
- package/dist/lib/log.js +25 -0
- package/dist/lib/log.js.map +1 -0
- package/dist/lib/mask.d.ts +24 -0
- package/dist/lib/mask.d.ts.map +1 -0
- package/dist/lib/mask.js +63 -0
- package/dist/lib/mask.js.map +1 -0
- package/dist/lib/pagination.d.ts +21 -0
- package/dist/lib/pagination.d.ts.map +1 -0
- package/dist/lib/pagination.js +40 -0
- package/dist/lib/pagination.js.map +1 -0
- package/dist/lib/truncate.d.ts +25 -0
- package/dist/lib/truncate.d.ts.map +1 -0
- package/dist/lib/truncate.js +45 -0
- package/dist/lib/truncate.js.map +1 -0
- package/dist/main.d.ts +9 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +12 -0
- package/dist/main.js.map +1 -0
- package/dist/prompts/index.d.ts +4 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +72 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/resources/docs/diagramSchema.d.ts +2 -0
- package/dist/resources/docs/diagramSchema.d.ts.map +1 -0
- package/dist/resources/docs/diagramSchema.js +65 -0
- package/dist/resources/docs/diagramSchema.js.map +1 -0
- package/dist/resources/docs/overview.d.ts +2 -0
- package/dist/resources/docs/overview.d.ts.map +1 -0
- package/dist/resources/docs/overview.js +46 -0
- package/dist/resources/docs/overview.js.map +1 -0
- package/dist/resources/docs/requestSchema.d.ts +2 -0
- package/dist/resources/docs/requestSchema.d.ts.map +1 -0
- package/dist/resources/docs/requestSchema.js +70 -0
- package/dist/resources/docs/requestSchema.js.map +1 -0
- package/dist/resources/generated/aiPacks.d.ts +3 -0
- package/dist/resources/generated/aiPacks.d.ts.map +1 -0
- package/dist/resources/generated/aiPacks.js +11 -0
- package/dist/resources/generated/aiPacks.js.map +1 -0
- package/dist/resources/index.d.ts +4 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +114 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/run/executeCollection.d.ts +19 -0
- package/dist/run/executeCollection.d.ts.map +1 -0
- package/dist/run/executeCollection.js +89 -0
- package/dist/run/executeCollection.js.map +1 -0
- package/dist/run/loadBundle.d.ts +9 -0
- package/dist/run/loadBundle.d.ts.map +1 -0
- package/dist/run/loadBundle.js +242 -0
- package/dist/run/loadBundle.js.map +1 -0
- package/dist/run/resolveTemplate.d.ts +2 -0
- package/dist/run/resolveTemplate.d.ts.map +1 -0
- package/dist/run/resolveTemplate.js +12 -0
- package/dist/run/resolveTemplate.js.map +1 -0
- package/dist/run/summarize.d.ts +73 -0
- package/dist/run/summarize.d.ts.map +1 -0
- package/dist/run/summarize.js +69 -0
- package/dist/run/summarize.js.map +1 -0
- package/dist/run/types.d.ts +46 -0
- package/dist/run/types.d.ts.map +1 -0
- package/dist/run/types.js +2 -0
- package/dist/run/types.js.map +1 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +25 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/catalog.d.ts +18 -0
- package/dist/tools/catalog.d.ts.map +1 -0
- package/dist/tools/catalog.js +66 -0
- package/dist/tools/catalog.js.map +1 -0
- package/dist/tools/collections.d.ts +4 -0
- package/dist/tools/collections.d.ts.map +1 -0
- package/dist/tools/collections.js +201 -0
- package/dist/tools/collections.js.map +1 -0
- package/dist/tools/diagrams.d.ts +4 -0
- package/dist/tools/diagrams.d.ts.map +1 -0
- package/dist/tools/diagrams.js +226 -0
- package/dist/tools/diagrams.js.map +1 -0
- package/dist/tools/environments.d.ts +4 -0
- package/dist/tools/environments.d.ts.map +1 -0
- package/dist/tools/environments.js +150 -0
- package/dist/tools/environments.js.map +1 -0
- package/dist/tools/import.d.ts +6 -0
- package/dist/tools/import.d.ts.map +1 -0
- package/dist/tools/import.js +144 -0
- package/dist/tools/import.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +26 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/lookups.d.ts +33 -0
- package/dist/tools/lookups.d.ts.map +1 -0
- package/dist/tools/lookups.js +132 -0
- package/dist/tools/lookups.js.map +1 -0
- package/dist/tools/meta.d.ts +4 -0
- package/dist/tools/meta.d.ts.map +1 -0
- package/dist/tools/meta.js +78 -0
- package/dist/tools/meta.js.map +1 -0
- package/dist/tools/requests.d.ts +4 -0
- package/dist/tools/requests.d.ts.map +1 -0
- package/dist/tools/requests.js +247 -0
- package/dist/tools/requests.js.map +1 -0
- package/dist/tools/run.d.ts +4 -0
- package/dist/tools/run.d.ts.map +1 -0
- package/dist/tools/run.js +167 -0
- package/dist/tools/run.js.map +1 -0
- package/dist/tools/scenarios.d.ts +4 -0
- package/dist/tools/scenarios.d.ts.map +1 -0
- package/dist/tools/scenarios.js +242 -0
- package/dist/tools/scenarios.js.map +1 -0
- package/dist/tools/shared.d.ts +20 -0
- package/dist/tools/shared.d.ts.map +1 -0
- package/dist/tools/shared.js +74 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/workspaces.d.ts +4 -0
- package/dist/tools/workspaces.d.ts.map +1 -0
- package/dist/tools/workspaces.js +80 -0
- package/dist/tools/workspaces.js.map +1 -0
- package/dist-cjs/client/api.js +183 -0
- package/dist-cjs/client/errors.js +104 -0
- package/dist-cjs/client/http.js +124 -0
- package/dist-cjs/client/types.js +5 -0
- package/dist-cjs/config.js +73 -0
- package/dist-cjs/context.js +94 -0
- package/dist-cjs/domain/diagram/build.js +164 -0
- package/dist-cjs/domain/diagram/layout.js +98 -0
- package/dist-cjs/domain/diagram/patch.js +179 -0
- package/dist-cjs/domain/diagram/summarize.js +52 -0
- package/dist-cjs/domain/importDetect.js +40 -0
- package/dist-cjs/domain/requestShape.js +260 -0
- package/dist-cjs/domain/resolve.js +63 -0
- package/dist-cjs/domain/scenario/build.js +140 -0
- package/dist-cjs/domain/scenario/summarize.js +144 -0
- package/dist-cjs/lib/cache.js +43 -0
- package/dist-cjs/lib/ids.js +24 -0
- package/dist-cjs/lib/log.js +28 -0
- package/dist-cjs/lib/mask.js +72 -0
- package/dist-cjs/lib/pagination.js +48 -0
- package/dist-cjs/lib/truncate.js +52 -0
- package/dist-cjs/main.js +31 -0
- package/dist-cjs/package.json +3 -0
- package/dist-cjs/prompts/index.js +75 -0
- package/dist-cjs/resources/docs/diagramSchema.js +67 -0
- package/dist-cjs/resources/docs/overview.js +48 -0
- package/dist-cjs/resources/docs/requestSchema.js +72 -0
- package/dist-cjs/resources/generated/aiPacks.js +13 -0
- package/dist-cjs/resources/index.js +117 -0
- package/dist-cjs/run/executeCollection.js +93 -0
- package/dist-cjs/run/loadBundle.js +246 -0
- package/dist-cjs/run/resolveTemplate.js +15 -0
- package/dist-cjs/run/summarize.js +73 -0
- package/dist-cjs/run/types.js +2 -0
- package/dist-cjs/server.js +28 -0
- package/dist-cjs/tools/catalog.js +69 -0
- package/dist-cjs/tools/collections.js +204 -0
- package/dist-cjs/tools/diagrams.js +229 -0
- package/dist-cjs/tools/environments.js +153 -0
- package/dist-cjs/tools/import.js +147 -0
- package/dist-cjs/tools/index.js +31 -0
- package/dist-cjs/tools/lookups.js +149 -0
- package/dist-cjs/tools/meta.js +81 -0
- package/dist-cjs/tools/requests.js +250 -0
- package/dist-cjs/tools/run.js +203 -0
- package/dist-cjs/tools/scenarios.js +245 -0
- package/dist-cjs/tools/shared.js +81 -0
- package/dist-cjs/tools/workspaces.js +83 -0
- package/package.json +80 -0
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerScenarioTools = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const errors_js_1 = require("../client/errors.js");
|
|
6
|
+
const resolve_js_1 = require("../domain/resolve.js");
|
|
7
|
+
const build_js_1 = require("../domain/scenario/build.js");
|
|
8
|
+
const summarize_js_1 = require("../domain/scenario/summarize.js");
|
|
9
|
+
const ids_js_1 = require("../lib/ids.js");
|
|
10
|
+
const pagination_js_1 = require("../lib/pagination.js");
|
|
11
|
+
const lookups_js_1 = require("./lookups.js");
|
|
12
|
+
const shared_js_1 = require("./shared.js");
|
|
13
|
+
const TERMINAL_STATUSES = new Set(["success", "failed", "completed_with_failures", "stopped"]);
|
|
14
|
+
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
|
+
const registerScenarioTools = (server, ctx) => {
|
|
16
|
+
server.registerTool("list_scenarios", {
|
|
17
|
+
title: "List scenarios",
|
|
18
|
+
description: "List API test scenarios (multi-step flows) with their folder, review status and version. `query` filters by name. Scenarios are scoped by edition (on-prem: your groups), not strictly by workspace.",
|
|
19
|
+
inputSchema: { workspace: shared_js_1.workspaceArg, query: zod_1.z.string().max(200).optional(), folder: zod_1.z.string().max(200).optional(), ...shared_js_1.cursorArgs },
|
|
20
|
+
annotations: shared_js_1.READ,
|
|
21
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, query, folder, cursor, limit }) => {
|
|
22
|
+
const ws = await ctx.resolveWorkspaceOrNull(workspace);
|
|
23
|
+
const { scenarios, folders } = await (0, lookups_js_1.loadScenarioCatalog)(ctx, ws?.id ?? null);
|
|
24
|
+
const folderName = new Map(folders.map((entry) => [entry.id, entry.name]));
|
|
25
|
+
const scope = folder ? await (0, lookups_js_1.resolveScenarioFolder)(ctx, ws?.id ?? null, folder) : null;
|
|
26
|
+
const needle = query?.trim().toLowerCase();
|
|
27
|
+
const filtered = scenarios
|
|
28
|
+
.filter((scenario) => !scope || scenario.folderId === scope.item.id)
|
|
29
|
+
.filter((scenario) => !needle || scenario.name.toLowerCase().includes(needle));
|
|
30
|
+
const page = (0, pagination_js_1.sliceWithCursor)(filtered, cursor, limit);
|
|
31
|
+
return (0, shared_js_1.ok)({
|
|
32
|
+
...(ws ? { workspace: { id: ws.id, name: ws.name } } : {}),
|
|
33
|
+
folders: folders.map((entry) => ({ id: entry.id, name: entry.name })),
|
|
34
|
+
scenarios: page.items.map((scenario) => (0, summarize_js_1.scenarioSummaryView)(scenario, scenario.folderId ? (folderName.get(scenario.folderId) ?? null) : null)),
|
|
35
|
+
total: page.total,
|
|
36
|
+
nextCursor: page.nextCursor,
|
|
37
|
+
});
|
|
38
|
+
}));
|
|
39
|
+
server.registerTool("get_scenario", {
|
|
40
|
+
title: "Get a scenario",
|
|
41
|
+
description: "Read a scenario: `summary` (metadata), `graph` (nodes with type/label and the edges — enough to understand the flow) or `full` (node configs, secrets masked, clipped at 2 KB per node). Use `graph` before editing with update_scenario.",
|
|
42
|
+
inputSchema: {
|
|
43
|
+
workspace: shared_js_1.workspaceArg,
|
|
44
|
+
scenario: (0, shared_js_1.refArg)("Scenario"),
|
|
45
|
+
view: zod_1.z.enum(["summary", "graph", "full"]).default("graph"),
|
|
46
|
+
reveal: zod_1.z.boolean().optional().describe("full view: return environment values and auth secrets unmasked (needs environments:reveal)"),
|
|
47
|
+
},
|
|
48
|
+
annotations: shared_js_1.READ,
|
|
49
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, scenario, view, reveal }) => {
|
|
50
|
+
const ws = await ctx.resolveWorkspaceOrNull(workspace);
|
|
51
|
+
const resolved = await (0, lookups_js_1.resolveScenario)(ctx, ws?.id ?? null, scenario);
|
|
52
|
+
const fresh = resolved.matched === "id" && !reveal ? resolved.item : await ctx.api.getScenario(ws?.id ?? null, resolved.item.id, reveal ?? false);
|
|
53
|
+
const body = view === "summary" ? (0, summarize_js_1.scenarioSummaryView)(fresh) : view === "graph" ? (0, summarize_js_1.scenarioGraphView)(fresh) : (0, summarize_js_1.scenarioFullView)(fresh, { reveal });
|
|
54
|
+
return (0, shared_js_1.ok)({ scenario: body, ...(resolved.annotation ? { resolved: [(0, resolve_js_1.resolvedSummary)(scenario, resolved)] } : {}) });
|
|
55
|
+
}));
|
|
56
|
+
server.registerTool("get_scenario_report", {
|
|
57
|
+
title: "Get a scenario run report",
|
|
58
|
+
description: "The result of a scenario run: status, summary counts and a per-node timeline (status, duration, HTTP status, failed tests) with the first failed node expanded. Defaults to the latest run.",
|
|
59
|
+
inputSchema: {
|
|
60
|
+
workspace: shared_js_1.workspaceArg,
|
|
61
|
+
scenario: (0, shared_js_1.refArg)("Scenario"),
|
|
62
|
+
report: zod_1.z.string().max(64).optional().describe("Report id; omit for the latest run"),
|
|
63
|
+
},
|
|
64
|
+
annotations: shared_js_1.READ,
|
|
65
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, scenario, report }) => {
|
|
66
|
+
const ws = await ctx.resolveWorkspaceOrNull(workspace);
|
|
67
|
+
const resolved = await (0, lookups_js_1.resolveScenario)(ctx, ws?.id ?? null, scenario);
|
|
68
|
+
let reportId = report;
|
|
69
|
+
if (!reportId) {
|
|
70
|
+
const list = await ctx.api.listScenarioReports(ws?.id ?? null, resolved.item.id, 5);
|
|
71
|
+
const latest = list.items[0];
|
|
72
|
+
if (!latest)
|
|
73
|
+
return (0, shared_js_1.ok)({ scenario: { id: resolved.item.id, name: resolved.item.name }, report: null, note: "This scenario has not been run on the server yet. Use run_scenario." });
|
|
74
|
+
reportId = latest.reportId;
|
|
75
|
+
}
|
|
76
|
+
const detail = await ctx.api.getScenarioReport(ws?.id ?? null, resolved.item.id, reportId);
|
|
77
|
+
return (0, shared_js_1.ok)({ report: (0, summarize_js_1.compactReportView)(detail), ...(resolved.annotation ? { resolved: [(0, resolve_js_1.resolvedSummary)(scenario, resolved)] } : {}) });
|
|
78
|
+
}));
|
|
79
|
+
server.registerTool("create_scenario", {
|
|
80
|
+
title: "Create a scenario",
|
|
81
|
+
description: "Create a multi-step API test scenario from compact nodes and edges. Node configs are merged over the type's defaults, so partial configs are fine (a request node needs at least method + url). Read callman://docs/scenario-nodes for every node type and config field. Positions are laid out automatically. dryRun: true returns the resolved graph without saving. On-prem: new scenarios start as drafts and need approval before scheduled/CI runs.",
|
|
82
|
+
inputSchema: {
|
|
83
|
+
workspace: shared_js_1.workspaceArg,
|
|
84
|
+
folder: zod_1.z.string().max(200).optional().describe("Scenario folder id or name"),
|
|
85
|
+
...build_js_1.scenarioInputSchema.shape,
|
|
86
|
+
dryRun: shared_js_1.dryRunArg,
|
|
87
|
+
},
|
|
88
|
+
annotations: shared_js_1.WRITE,
|
|
89
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, folder, dryRun, ...input }) => {
|
|
90
|
+
const ws = await ctx.resolveWorkspace(workspace);
|
|
91
|
+
const targetFolder = folder ? await (0, lookups_js_1.resolveScenarioFolder)(ctx, ws.id, folder) : null;
|
|
92
|
+
const body = (0, build_js_1.buildScenarioCreateBody)(input, targetFolder?.item.id ?? null);
|
|
93
|
+
if (dryRun) {
|
|
94
|
+
const nodes = body.nodes;
|
|
95
|
+
return (0, shared_js_1.ok)({ dryRun: true, scenario: { name: body.name, nodeCount: nodes.length, edgeCount: body.edges.length, nodes: nodes.map((node) => ({ id: node.id, type: node.type, label: node.data.label ?? null })), edges: body.edges } });
|
|
96
|
+
}
|
|
97
|
+
const created = await ctx.api.createScenario(ws.id, body);
|
|
98
|
+
ctx.invalidate("scenarios:");
|
|
99
|
+
return (0, shared_js_1.ok)({
|
|
100
|
+
scenario: (0, summarize_js_1.scenarioGraphView)(created),
|
|
101
|
+
...(created.graph?.warnings?.length ? { warnings: created.graph.warnings } : {}),
|
|
102
|
+
note: created.reviewStatus === "draft" ? "Created as a draft. Run it with run_scenario; on-prem, submit it for approval in the desktop app before scheduling." : "Created.",
|
|
103
|
+
...(targetFolder ? { resolved: [(0, resolve_js_1.resolvedSummary)(folder, targetFolder)] } : {}),
|
|
104
|
+
});
|
|
105
|
+
}));
|
|
106
|
+
server.registerTool("update_scenario", {
|
|
107
|
+
title: "Update a scenario",
|
|
108
|
+
description: "Update a scenario's name/description/priority/folder and/or replace its graph (send nodes AND edges together; node configs merge over defaults like create_scenario). Version-checked: pass the `version` you read (expectedVersion) or it is fetched first; a 409 conflict comes back structured — re-read and retry. On-prem: editing an approved scenario returns it to draft.",
|
|
109
|
+
inputSchema: {
|
|
110
|
+
workspace: shared_js_1.workspaceArg,
|
|
111
|
+
scenario: (0, shared_js_1.refArg)("Scenario"),
|
|
112
|
+
expectedVersion: zod_1.z.number().int().nonnegative().optional(),
|
|
113
|
+
force: zod_1.z.boolean().optional().describe("Overwrite even if someone changed it since expectedVersion"),
|
|
114
|
+
name: zod_1.z.string().min(1).max(200).optional(),
|
|
115
|
+
description: zod_1.z.string().max(5000).optional(),
|
|
116
|
+
priority: zod_1.z.enum(["critical", "high", "medium", "low"]).optional(),
|
|
117
|
+
folder: zod_1.z.string().max(200).nullable().optional().describe("Scenario folder id or name; null = no folder"),
|
|
118
|
+
nodes: zod_1.z.array(build_js_1.scenarioNodeInputSchema).min(1).max(1000).optional(),
|
|
119
|
+
edges: zod_1.z.array(build_js_1.scenarioEdgeInputSchema).max(2000).optional(),
|
|
120
|
+
environments: zod_1.z.array(build_js_1.scenarioEnvironmentInputSchema).max(20).optional(),
|
|
121
|
+
},
|
|
122
|
+
annotations: shared_js_1.IDEMPOTENT_WRITE,
|
|
123
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, scenario, expectedVersion, force, name, description, priority, folder, nodes, edges, environments }) => {
|
|
124
|
+
if ((nodes === undefined) !== (edges === undefined)) {
|
|
125
|
+
throw new errors_js_1.ToolInputError("GRAPH_INCOMPLETE", "Send nodes and edges together when replacing the graph.");
|
|
126
|
+
}
|
|
127
|
+
const ws = await ctx.resolveWorkspaceOrNull(workspace);
|
|
128
|
+
const resolved = await (0, lookups_js_1.resolveScenario)(ctx, ws?.id ?? null, scenario);
|
|
129
|
+
const current = resolved.item;
|
|
130
|
+
const targetFolder = folder ? await (0, lookups_js_1.resolveScenarioFolder)(ctx, ws?.id ?? null, folder) : null;
|
|
131
|
+
const body = {
|
|
132
|
+
...(name !== undefined ? { name: name.trim() } : {}),
|
|
133
|
+
...(description !== undefined ? { description } : {}),
|
|
134
|
+
...(priority !== undefined ? { priority } : {}),
|
|
135
|
+
...(folder !== undefined ? { folderId: targetFolder?.item.id ?? null } : {}),
|
|
136
|
+
expectedVersion: expectedVersion ?? current.version,
|
|
137
|
+
...(force ? { force: true } : {}),
|
|
138
|
+
};
|
|
139
|
+
if (nodes && edges) {
|
|
140
|
+
const graph = (0, build_js_1.buildScenarioGraph)(nodes, edges);
|
|
141
|
+
body.nodes = graph.nodes;
|
|
142
|
+
body.edges = graph.edges;
|
|
143
|
+
}
|
|
144
|
+
if (environments) {
|
|
145
|
+
const nextEnvId = (0, ids_js_1.sequentialIds)("env", current.environments.map((environment) => environment.id));
|
|
146
|
+
body.environments = environments.map((environment) => {
|
|
147
|
+
const nextVarId = (0, ids_js_1.sequentialIds)("v");
|
|
148
|
+
return {
|
|
149
|
+
id: environment.id ?? nextEnvId(),
|
|
150
|
+
name: environment.name,
|
|
151
|
+
variables: environment.variables.filter((variable) => variable.key.trim()).map((variable) => ({ id: nextVarId(), key: variable.key.trim(), value: variable.value ?? "", enabled: variable.enabled ?? true })),
|
|
152
|
+
};
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
if (Object.keys(body).filter((key) => key !== "expectedVersion" && key !== "force").length === 0) {
|
|
156
|
+
throw new errors_js_1.ToolInputError("NOTHING_TO_UPDATE", "Pass at least one field to change.");
|
|
157
|
+
}
|
|
158
|
+
try {
|
|
159
|
+
const updated = await ctx.api.patchScenario(ws?.id ?? null, current.id, body);
|
|
160
|
+
ctx.invalidate("scenarios:");
|
|
161
|
+
return (0, shared_js_1.ok)({
|
|
162
|
+
scenario: (0, summarize_js_1.scenarioGraphView)(updated),
|
|
163
|
+
previousVersion: current.version,
|
|
164
|
+
...(current.reviewStatus === "approved" && updated.reviewStatus !== "approved" ? { note: "The scenario was approved and is now a draft again; schedules keep using the last approved version until it is re-approved." } : {}),
|
|
165
|
+
...(resolved.annotation ? { resolved: [(0, resolve_js_1.resolvedSummary)(scenario, resolved)] } : {}),
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
if (error instanceof errors_js_1.CallmanApiError && error.code === "SCENARIO_VERSION_CONFLICT") {
|
|
170
|
+
const details = (error.details ?? {});
|
|
171
|
+
return (0, shared_js_1.ok)({
|
|
172
|
+
conflict: true,
|
|
173
|
+
code: error.code,
|
|
174
|
+
message: error.message,
|
|
175
|
+
currentVersion: details.currentScenario?.version ?? null,
|
|
176
|
+
hint: "Re-read the scenario (get_scenario view:graph), reapply your change and call update_scenario with expectedVersion set to currentVersion — or force: true to overwrite.",
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
throw error;
|
|
180
|
+
}
|
|
181
|
+
}));
|
|
182
|
+
server.registerTool("delete_scenario", {
|
|
183
|
+
title: "Delete a scenario",
|
|
184
|
+
description: "Delete a scenario and its run history. Permanent — confirm with the user first.",
|
|
185
|
+
inputSchema: { workspace: shared_js_1.workspaceArg, scenario: (0, shared_js_1.refArg)("Scenario"), confirm: shared_js_1.confirmArg },
|
|
186
|
+
annotations: shared_js_1.DESTRUCTIVE,
|
|
187
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, scenario, confirm }) => {
|
|
188
|
+
(0, shared_js_1.requireConfirm)(confirm, "a scenario");
|
|
189
|
+
const ws = await ctx.resolveWorkspaceOrNull(workspace);
|
|
190
|
+
const resolved = await (0, lookups_js_1.resolveScenario)(ctx, ws?.id ?? null, scenario);
|
|
191
|
+
await ctx.api.deleteScenario(ws?.id ?? null, resolved.item.id);
|
|
192
|
+
ctx.invalidate("scenarios:");
|
|
193
|
+
return (0, shared_js_1.ok)({ deleted: { id: resolved.item.id, name: resolved.item.name }, resolved: [(0, resolve_js_1.resolvedSummary)(scenario, resolved)] });
|
|
194
|
+
}));
|
|
195
|
+
server.registerTool("run_scenario", {
|
|
196
|
+
title: "Run a scenario on the server",
|
|
197
|
+
description: "Start a server-side run of a scenario (with one of its inline environments, by name or id) and wait for the result (default up to 5 minutes, max 30). Returns the compact report; if it times out you get the reportId to check later with get_scenario_report.",
|
|
198
|
+
inputSchema: {
|
|
199
|
+
workspace: shared_js_1.workspaceArg,
|
|
200
|
+
scenario: (0, shared_js_1.refArg)("Scenario"),
|
|
201
|
+
environment: zod_1.z.string().max(200).optional().describe("One of the scenario's own environments (name or id)"),
|
|
202
|
+
wait: zod_1.z.boolean().default(true),
|
|
203
|
+
timeoutSec: zod_1.z.number().int().min(5).max(1800).default(300),
|
|
204
|
+
},
|
|
205
|
+
annotations: shared_js_1.RUN,
|
|
206
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, scenario, environment, wait, timeoutSec }) => {
|
|
207
|
+
const ws = await ctx.resolveWorkspaceOrNull(workspace);
|
|
208
|
+
const resolved = await (0, lookups_js_1.resolveScenario)(ctx, ws?.id ?? null, scenario);
|
|
209
|
+
let environmentId;
|
|
210
|
+
if (environment) {
|
|
211
|
+
const environments = resolved.item.environments ?? [];
|
|
212
|
+
const match = environments.find((entry) => entry.id === environment) ?? environments.filter((entry) => entry.name.trim().toLowerCase() === environment.trim().toLowerCase());
|
|
213
|
+
const picked = Array.isArray(match) ? (match.length === 1 ? match[0] : null) : match;
|
|
214
|
+
if (!picked) {
|
|
215
|
+
throw new errors_js_1.ToolInputError("SCENARIO_ENV_NOT_FOUND", `The scenario has no environment "${environment}".`, { candidates: environments.map((entry) => ({ id: entry.id, name: entry.name })) });
|
|
216
|
+
}
|
|
217
|
+
environmentId = picked.id;
|
|
218
|
+
}
|
|
219
|
+
const trigger = await ctx.api.runScenario(ws?.id ?? null, resolved.item.id, environmentId ? { environmentId } : {});
|
|
220
|
+
if (!wait)
|
|
221
|
+
return (0, shared_js_1.ok)({ scenario: { id: resolved.item.id, name: resolved.item.name }, reportId: trigger.reportId, status: trigger.status, note: "Check with get_scenario_report." });
|
|
222
|
+
const deadline = Date.now() + timeoutSec * 1000;
|
|
223
|
+
let polls = 0;
|
|
224
|
+
let last = null;
|
|
225
|
+
while (Date.now() < deadline) {
|
|
226
|
+
await sleep(polls < 5 ? ctx.pollDelaysMs.fast : ctx.pollDelaysMs.slow);
|
|
227
|
+
polls += 1;
|
|
228
|
+
try {
|
|
229
|
+
last = await ctx.api.getScenarioReport(ws?.id ?? null, resolved.item.id, trigger.reportId);
|
|
230
|
+
}
|
|
231
|
+
catch (error) {
|
|
232
|
+
if (error instanceof errors_js_1.CallmanApiError && error.status === 404)
|
|
233
|
+
continue; // placeholder not yet visible
|
|
234
|
+
throw error;
|
|
235
|
+
}
|
|
236
|
+
if (TERMINAL_STATUSES.has(last.status))
|
|
237
|
+
break;
|
|
238
|
+
}
|
|
239
|
+
if (!last || !TERMINAL_STATUSES.has(last.status)) {
|
|
240
|
+
return (0, shared_js_1.ok)({ scenario: { id: resolved.item.id, name: resolved.item.name }, reportId: trigger.reportId, status: last?.status ?? "running", timedOut: true, note: `Still running after ${timeoutSec}s — call get_scenario_report with this reportId later.` });
|
|
241
|
+
}
|
|
242
|
+
return (0, shared_js_1.ok)({ report: (0, summarize_js_1.compactReportView)(last), ...(resolved.annotation ? { resolved: [(0, resolve_js_1.resolvedSummary)(scenario, resolved)] } : {}) });
|
|
243
|
+
}));
|
|
244
|
+
};
|
|
245
|
+
exports.registerScenarioTools = registerScenarioTools;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requireConfirm = exports.dryRunArg = exports.confirmArg = exports.cursorArgs = exports.refArg = exports.workspaceArg = exports.RUN = exports.DESTRUCTIVE = exports.IDEMPOTENT_WRITE = exports.WRITE = exports.READ = exports.guarded = exports.toolFailure = exports.ok = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const errors_js_1 = require("../client/errors.js");
|
|
6
|
+
const truncate_js_1 = require("../lib/truncate.js");
|
|
7
|
+
// Conventions every tool follows:
|
|
8
|
+
// * `structuredContent` carries the typed result; `content[0].text` is the
|
|
9
|
+
// same JSON (compact) so clients without structured-output support see it.
|
|
10
|
+
// * Errors are never thrown to the client: they come back as
|
|
11
|
+
// `{ isError: true, structuredContent: { error: { code, message, hint, … } } }`
|
|
12
|
+
// with a hint the model can act on (which scope is missing, which
|
|
13
|
+
// candidates exist, what to call next).
|
|
14
|
+
// * Every tool takes an optional `workspace` (name or id) where it matters.
|
|
15
|
+
const ok = (structured, text) => ({
|
|
16
|
+
content: [{ type: "text", text: text ?? (0, truncate_js_1.safeStringify)(structured) }],
|
|
17
|
+
structuredContent: structured,
|
|
18
|
+
});
|
|
19
|
+
exports.ok = ok;
|
|
20
|
+
const toolFailure = (error) => {
|
|
21
|
+
let payload;
|
|
22
|
+
if (error instanceof errors_js_1.CallmanApiError) {
|
|
23
|
+
payload = {
|
|
24
|
+
code: error.code,
|
|
25
|
+
status: error.status,
|
|
26
|
+
message: error.message,
|
|
27
|
+
hint: (0, errors_js_1.hintFor)(error),
|
|
28
|
+
...(error.details !== undefined ? { details: error.details } : {}),
|
|
29
|
+
request: `${error.method} ${error.path}`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
else if (error instanceof errors_js_1.ToolInputError) {
|
|
33
|
+
payload = { code: error.code, message: error.message, ...(error.data ?? {}) };
|
|
34
|
+
}
|
|
35
|
+
else if (error instanceof errors_js_1.CallmanNetworkError) {
|
|
36
|
+
payload = { code: "NETWORK_UNREACHABLE", message: error.message, apiUrl: error.apiUrl };
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
payload = { code: "INTERNAL_ERROR", message: error instanceof Error ? error.message : String(error) };
|
|
40
|
+
}
|
|
41
|
+
const structured = { error: payload };
|
|
42
|
+
return { isError: true, content: [{ type: "text", text: (0, truncate_js_1.safeStringify)(structured) }], structuredContent: structured };
|
|
43
|
+
};
|
|
44
|
+
exports.toolFailure = toolFailure;
|
|
45
|
+
const guarded = (fn) => async (args) => {
|
|
46
|
+
try {
|
|
47
|
+
return await fn(args);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
return (0, exports.toolFailure)(error);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
exports.guarded = guarded;
|
|
54
|
+
// ── annotations ────────────────────────────────────────────────────────
|
|
55
|
+
exports.READ = { readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
56
|
+
exports.WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false };
|
|
57
|
+
exports.IDEMPOTENT_WRITE = { readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false };
|
|
58
|
+
exports.DESTRUCTIVE = { readOnlyHint: false, destructiveHint: true, idempotentHint: true, openWorldHint: false };
|
|
59
|
+
exports.RUN = { readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: true };
|
|
60
|
+
// ── shared argument schemas ────────────────────────────────────────────
|
|
61
|
+
exports.workspaceArg = zod_1.z
|
|
62
|
+
.string()
|
|
63
|
+
.max(200)
|
|
64
|
+
.optional()
|
|
65
|
+
.describe("Workspace id or name. Defaults to CALLMAN_WORKSPACE_ID, or the only workspace you have; call list_workspaces to see them.");
|
|
66
|
+
const refArg = (what, extra = "") => zod_1.z.string().min(1).max(500).describe(`${what} id or name${extra ? ` ${extra}` : ""}`);
|
|
67
|
+
exports.refArg = refArg;
|
|
68
|
+
exports.cursorArgs = {
|
|
69
|
+
cursor: zod_1.z.string().max(200).optional().describe("Pass the previous result's nextCursor to get the next page"),
|
|
70
|
+
limit: zod_1.z.number().int().min(1).max(truncate_js_1.LIMITS.LIST_MAX).optional().describe(`Page size (default ${truncate_js_1.LIMITS.LIST_DEFAULT})`),
|
|
71
|
+
};
|
|
72
|
+
exports.confirmArg = zod_1.z
|
|
73
|
+
.literal(true)
|
|
74
|
+
.describe("Must be exactly true. Confirms a permanent deletion — ask the user first unless they already asked for it explicitly.");
|
|
75
|
+
exports.dryRunArg = zod_1.z.boolean().optional().describe("true = validate and preview only; nothing is written");
|
|
76
|
+
const requireConfirm = (confirm, what) => {
|
|
77
|
+
if (confirm !== true) {
|
|
78
|
+
throw new errors_js_1.ToolInputError("CONFIRM_REQUIRED", `Deleting ${what} is permanent. Call again with confirm: true after the user agrees.`);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
exports.requireConfirm = requireConfirm;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerWorkspaceTools = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const errors_js_1 = require("../client/errors.js");
|
|
6
|
+
const resolve_js_1 = require("../domain/resolve.js");
|
|
7
|
+
const ids_js_1 = require("../lib/ids.js");
|
|
8
|
+
const shared_js_1 = require("./shared.js");
|
|
9
|
+
const registerWorkspaceTools = (server, ctx) => {
|
|
10
|
+
server.registerTool("list_workspaces", {
|
|
11
|
+
title: "List workspaces",
|
|
12
|
+
description: "List the workspaces you belong to, with your role in each (owner / editor / viewer). A token keeps your role: writes are refused where you are a viewer.",
|
|
13
|
+
inputSchema: {},
|
|
14
|
+
annotations: shared_js_1.READ,
|
|
15
|
+
}, (0, shared_js_1.guarded)(async () => {
|
|
16
|
+
const workspaces = await ctx.listWorkspaces();
|
|
17
|
+
return (0, shared_js_1.ok)({
|
|
18
|
+
workspaces: workspaces.map((workspace) => ({
|
|
19
|
+
id: workspace.id,
|
|
20
|
+
name: workspace.name,
|
|
21
|
+
role: workspace.role,
|
|
22
|
+
memberCount: workspace.memberCount ?? null,
|
|
23
|
+
isDefault: workspace.id === ctx.config.defaultWorkspaceId,
|
|
24
|
+
})),
|
|
25
|
+
});
|
|
26
|
+
}));
|
|
27
|
+
server.registerTool("list_workspace_members", {
|
|
28
|
+
title: "List workspace members",
|
|
29
|
+
description: "List the members of a workspace with their role and status (active / invited).",
|
|
30
|
+
inputSchema: { workspace: shared_js_1.workspaceArg },
|
|
31
|
+
annotations: shared_js_1.READ,
|
|
32
|
+
}, (0, shared_js_1.guarded)(async ({ workspace }) => {
|
|
33
|
+
const target = await ctx.resolveWorkspace(workspace);
|
|
34
|
+
const { items } = await ctx.api.listMembers(target.id);
|
|
35
|
+
return (0, shared_js_1.ok)({
|
|
36
|
+
workspace: { id: target.id, name: target.name },
|
|
37
|
+
members: items.map((member) => ({ id: member.id, userId: member.userId, email: member.email, role: member.role, status: member.status })),
|
|
38
|
+
});
|
|
39
|
+
}));
|
|
40
|
+
server.registerTool("add_workspace_member", {
|
|
41
|
+
title: "Add a workspace member",
|
|
42
|
+
description: "Add a person to a workspace by email with a role (editor can write collections/requests/scenarios; viewer is read-only; owner manages the workspace). Requires the owner role in that workspace. The person must already have a Callman account — the server does not send invitations to unknown emails.",
|
|
43
|
+
inputSchema: {
|
|
44
|
+
workspace: shared_js_1.workspaceArg,
|
|
45
|
+
email: zod_1.z.string().email().max(255),
|
|
46
|
+
role: zod_1.z.enum(["owner", "editor", "viewer"]).default("editor"),
|
|
47
|
+
},
|
|
48
|
+
annotations: shared_js_1.WRITE,
|
|
49
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, email, role }) => {
|
|
50
|
+
const target = await ctx.resolveWorkspace(workspace);
|
|
51
|
+
const member = await ctx.api.addMember(target.id, { email: email.trim().toLowerCase(), role });
|
|
52
|
+
ctx.invalidate(`members:${target.id}`);
|
|
53
|
+
return (0, shared_js_1.ok)({
|
|
54
|
+
workspace: { id: target.id, name: target.name },
|
|
55
|
+
member: { id: member.id, email: member.email, role: member.role, status: member.status },
|
|
56
|
+
note: member.status === "invited" ? "Pending — the person gets access when they sign in." : "Added.",
|
|
57
|
+
});
|
|
58
|
+
}));
|
|
59
|
+
server.registerTool("remove_workspace_member", {
|
|
60
|
+
title: "Remove a workspace member",
|
|
61
|
+
description: "Remove a member from a workspace (by email or membership id). Requires the owner role. Permanent — confirm with the user first.",
|
|
62
|
+
inputSchema: {
|
|
63
|
+
workspace: shared_js_1.workspaceArg,
|
|
64
|
+
member: zod_1.z.string().min(1).max(255).describe("Member email or membership id"),
|
|
65
|
+
confirm: shared_js_1.confirmArg,
|
|
66
|
+
},
|
|
67
|
+
annotations: shared_js_1.DESTRUCTIVE,
|
|
68
|
+
}, (0, shared_js_1.guarded)(async ({ workspace, member, confirm }) => {
|
|
69
|
+
(0, shared_js_1.requireConfirm)(confirm, "a workspace member");
|
|
70
|
+
const target = await ctx.resolveWorkspace(workspace);
|
|
71
|
+
const { items } = await ctx.api.listMembers(target.id);
|
|
72
|
+
const needle = (0, ids_js_1.normalizeName)(member);
|
|
73
|
+
const byEmail = items.filter((entry) => (0, ids_js_1.normalizeName)(entry.email) === needle);
|
|
74
|
+
const resolved = byEmail.length === 1
|
|
75
|
+
? byEmail[0]
|
|
76
|
+
: (0, resolve_js_1.resolveRef)("member", member, items.map((entry) => ({ ...entry, name: entry.email }))).item;
|
|
77
|
+
if (!resolved)
|
|
78
|
+
throw new errors_js_1.ToolInputError("REF_NOT_FOUND", `No member matches "${member}".`);
|
|
79
|
+
await ctx.api.removeMember(target.id, resolved.id);
|
|
80
|
+
return (0, shared_js_1.ok)({ workspace: { id: target.id, name: target.name }, removed: { id: resolved.id, email: resolved.email } });
|
|
81
|
+
}));
|
|
82
|
+
};
|
|
83
|
+
exports.registerWorkspaceTools = registerWorkspaceTools;
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "callman-mcp",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for Callman: lets Claude Code, Claude Desktop, Cursor, Codex and Gemini CLI manage collections, requests, environments, test scenarios and system-design diagrams in your Callman workspace — cloud or on-prem.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"callman",
|
|
7
|
+
"mcp",
|
|
8
|
+
"model-context-protocol",
|
|
9
|
+
"api",
|
|
10
|
+
"testing",
|
|
11
|
+
"claude",
|
|
12
|
+
"cursor",
|
|
13
|
+
"codex",
|
|
14
|
+
"gemini",
|
|
15
|
+
"postman"
|
|
16
|
+
],
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/memmedov-karim/callman_mcp.git"
|
|
21
|
+
},
|
|
22
|
+
"homepage": "https://github.com/memmedov-karim/callman_mcp#readme",
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/memmedov-karim/callman_mcp/issues"
|
|
25
|
+
},
|
|
26
|
+
"type": "module",
|
|
27
|
+
"bin": {
|
|
28
|
+
"callman-mcp": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"main": "./dist-cjs/main.js",
|
|
31
|
+
"module": "./dist/main.js",
|
|
32
|
+
"types": "./dist/main.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/main.d.ts",
|
|
36
|
+
"import": "./dist/main.js",
|
|
37
|
+
"require": "./dist-cjs/main.js"
|
|
38
|
+
},
|
|
39
|
+
"./package.json": "./package.json"
|
|
40
|
+
},
|
|
41
|
+
"files": [
|
|
42
|
+
"dist",
|
|
43
|
+
"dist-cjs",
|
|
44
|
+
"README.md",
|
|
45
|
+
"CHANGELOG.md"
|
|
46
|
+
],
|
|
47
|
+
"engines": {
|
|
48
|
+
"node": ">=20"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build:resources": "node scripts/build-static-resources.mjs",
|
|
55
|
+
"build": "npm run build:resources && tsc -p tsconfig.json && tsc -p tsconfig.cjs.json && node scripts/postbuild.mjs",
|
|
56
|
+
"typecheck": "tsc -p tsconfig.test.json",
|
|
57
|
+
"lint": "eslint . && npm run typecheck",
|
|
58
|
+
"test": "vitest run",
|
|
59
|
+
"smoke": "node scripts/smoke.mjs",
|
|
60
|
+
"doctor": "node dist/index.js doctor",
|
|
61
|
+
"prepublishOnly": "npm run lint && npm run build && npm test && npm run smoke"
|
|
62
|
+
},
|
|
63
|
+
"dependencies": {
|
|
64
|
+
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
65
|
+
"callman-core": "^1.28.0",
|
|
66
|
+
"elkjs": "^0.12.0",
|
|
67
|
+
"js-yaml": "^4.1.0",
|
|
68
|
+
"zod": "^3.25.0"
|
|
69
|
+
},
|
|
70
|
+
"devDependencies": {
|
|
71
|
+
"@eslint/js": "^9.39.5",
|
|
72
|
+
"@types/js-yaml": "^4.0.9",
|
|
73
|
+
"@types/node": "^22.10.2",
|
|
74
|
+
"eslint": "^9.39.5",
|
|
75
|
+
"globals": "^16.5.0",
|
|
76
|
+
"typescript": "^5.7.2",
|
|
77
|
+
"typescript-eslint": "^8.70.0",
|
|
78
|
+
"vitest": "^4.1.10"
|
|
79
|
+
}
|
|
80
|
+
}
|