callman-mcp 0.7.0 → 0.7.1
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 +9 -0
- package/README.md +6 -3
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -1
- package/dist/config.js.map +1 -1
- package/dist/index.js +10 -2
- package/dist/index.js.map +1 -1
- package/dist/resources/generated/aiPacks.d.ts +1 -1
- package/dist/resources/generated/aiPacks.js +2 -2
- package/dist/run/executeCollection.d.ts.map +1 -1
- package/dist/run/executeCollection.js +5 -1
- package/dist/run/executeCollection.js.map +1 -1
- package/dist/run/loadBundle.d.ts.map +1 -1
- package/dist/run/loadBundle.js +49 -2
- package/dist/run/loadBundle.js.map +1 -1
- package/dist/run/summarize.d.ts +28 -4
- package/dist/run/summarize.d.ts.map +1 -1
- package/dist/run/summarize.js +19 -1
- package/dist/run/summarize.js.map +1 -1
- package/dist/run/types.d.ts +2 -1
- package/dist/run/types.d.ts.map +1 -1
- package/dist/server.d.ts +1 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +13 -2
- package/dist/server.js.map +1 -1
- package/dist/tools/index.d.ts +9 -2
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +25 -3
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/run.d.ts +0 -1
- package/dist/tools/run.d.ts.map +1 -1
- package/dist/tools/run.js +7 -26
- package/dist/tools/run.js.map +1 -1
- package/dist-cjs/config.js +5 -1
- package/dist-cjs/resources/generated/aiPacks.js +2 -2
- package/dist-cjs/run/executeCollection.js +5 -1
- package/dist-cjs/run/loadBundle.js +49 -2
- package/dist-cjs/run/summarize.js +19 -1
- package/dist-cjs/server.js +13 -2
- package/dist-cjs/tools/index.js +28 -6
- package/dist-cjs/tools/run.js +7 -26
- package/package.json +2 -2
package/dist-cjs/tools/index.js
CHANGED
|
@@ -16,20 +16,25 @@ const uiTestAdmin_js_1 = require("./uiTestAdmin.js");
|
|
|
16
16
|
const uiTestRuns_js_1 = require("./uiTestRuns.js");
|
|
17
17
|
const uiTests_js_1 = require("./uiTests.js");
|
|
18
18
|
const workspaces_js_1 = require("./workspaces.js");
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
Object.defineProperty(exports, "
|
|
19
|
+
const catalog_js_1 = require("./catalog.js");
|
|
20
|
+
var catalog_js_2 = require("./catalog.js");
|
|
21
|
+
Object.defineProperty(exports, "TOOL_CATALOG", { enumerable: true, get: function () { return catalog_js_2.TOOL_CATALOG; } });
|
|
22
|
+
Object.defineProperty(exports, "toolAvailability", { enumerable: true, get: function () { return catalog_js_2.toolAvailability; } });
|
|
22
23
|
// Every tool's arguments are strict: the SDK would otherwise build a
|
|
23
24
|
// strip-mode object from the raw shape, and a misspelled argument
|
|
24
25
|
// (`workspaceId` for `workspace`, `colour` for `color`) would vanish while the
|
|
25
26
|
// tool ran with its default. Runtime only — handler types still come from the
|
|
26
27
|
// raw shapes at each registerTool call.
|
|
27
28
|
const isRawShape = (schema) => typeof schema === "object" && schema !== null && !("_def" in schema) && !("_zod" in schema);
|
|
28
|
-
const withStrictArguments = (server) => new Proxy(server, {
|
|
29
|
+
const withStrictArguments = (server, handles) => new Proxy(server, {
|
|
29
30
|
get(target, property, receiver) {
|
|
30
31
|
if (property !== "registerTool")
|
|
31
32
|
return Reflect.get(target, property, receiver);
|
|
32
|
-
const register = (name, config, callback) =>
|
|
33
|
+
const register = (name, config, callback) => {
|
|
34
|
+
const handle = target.registerTool(name, { ...config, inputSchema: isRawShape(config.inputSchema) ? (0, strict_js_1.strictObject)(config.inputSchema, "argument", name) : config.inputSchema }, callback);
|
|
35
|
+
handles?.set(name, handle);
|
|
36
|
+
return handle;
|
|
37
|
+
};
|
|
33
38
|
return register;
|
|
34
39
|
},
|
|
35
40
|
});
|
|
@@ -38,7 +43,8 @@ exports.withStrictArguments = withStrictArguments;
|
|
|
38
43
|
// registered when local execution is allowed (a backend-hosted server passes
|
|
39
44
|
// allowLocalRun: false and they disappear from tools/list).
|
|
40
45
|
const registerAllTools = (host, ctx) => {
|
|
41
|
-
const
|
|
46
|
+
const handles = new Map();
|
|
47
|
+
const server = (0, exports.withStrictArguments)(host, handles);
|
|
42
48
|
(0, meta_js_1.registerMetaTools)(server, ctx);
|
|
43
49
|
(0, workspaces_js_1.registerWorkspaceTools)(server, ctx);
|
|
44
50
|
(0, collections_js_1.registerCollectionTools)(server, ctx);
|
|
@@ -55,5 +61,21 @@ const registerAllTools = (host, ctx) => {
|
|
|
55
61
|
(0, run_js_1.registerRunTools)(server, ctx);
|
|
56
62
|
(0, loadTest_js_1.registerLoadTestTool)(server, ctx);
|
|
57
63
|
}
|
|
64
|
+
return {
|
|
65
|
+
hideUnavailable: (tokenScopes) => {
|
|
66
|
+
const hidden = [];
|
|
67
|
+
for (const tool of (0, catalog_js_1.toolAvailability)(tokenScopes, ctx.config.allowLocalRun)) {
|
|
68
|
+
// whoami stays: it is how a model learns why the others are missing.
|
|
69
|
+
if (tool.available || tool.name === "whoami")
|
|
70
|
+
continue;
|
|
71
|
+
const handle = handles.get(tool.name);
|
|
72
|
+
if (!handle)
|
|
73
|
+
continue;
|
|
74
|
+
handle.disable();
|
|
75
|
+
hidden.push(tool.name);
|
|
76
|
+
}
|
|
77
|
+
return hidden;
|
|
78
|
+
},
|
|
79
|
+
};
|
|
58
80
|
};
|
|
59
81
|
exports.registerAllTools = registerAllTools;
|
package/dist-cjs/tools/run.js
CHANGED
|
@@ -52,14 +52,12 @@ const shared_js_1 = require("./shared.js");
|
|
|
52
52
|
// {{key}}). One run at a time.
|
|
53
53
|
// What a local run does NOT do, stated up front so a model does not read a
|
|
54
54
|
// missing check as a pass.
|
|
55
|
-
const LOCAL_RUN_LIMITS = "Local-run limits:
|
|
55
|
+
const LOCAL_RUN_LIMITS = "Local-run limits: no cookie jar between requests; no client certificates (mTLS); each request times out after 30 s. Database and Redis steps run when the collection's runnerSettings allow them and the connection is usable from this machine; the request's DB and Redis assertions are then evaluated like the desktop does (one that cannot be checked, e.g. an unreachable connection, FAILS).";
|
|
56
56
|
const maxBodyArg = zod_1.z.number().int().min(256).max(truncate_js_1.LIMITS.RUN_BODY_MAX).optional().describe("Response body preview cap in bytes (default 16 KB)");
|
|
57
|
-
// apiKey auth names its own header / query parameter — mask those too
|
|
58
|
-
// note the steps a local run skips.
|
|
57
|
+
// apiKey auth names its own header / query parameter — mask those too.
|
|
59
58
|
const inspectBundle = (rawCollection) => {
|
|
60
59
|
const secretHeaders = new Set();
|
|
61
60
|
const secretQuery = new Set();
|
|
62
|
-
const skipped = new Map();
|
|
63
61
|
const requests = rawCollection?.requests;
|
|
64
62
|
for (const raw of Array.isArray(requests) ? requests : []) {
|
|
65
63
|
const request = raw;
|
|
@@ -67,13 +65,8 @@ const inspectBundle = (rawCollection) => {
|
|
|
67
65
|
if (auth && (auth.type === "apikey" || auth.type === "apiKey") && typeof auth.apiKeyKey === "string" && auth.apiKeyKey.trim()) {
|
|
68
66
|
(auth.apiKeyLocation === "query" ? secretQuery : secretHeaders).add(auth.apiKeyKey.trim());
|
|
69
67
|
}
|
|
70
|
-
const notes = [];
|
|
71
|
-
if (Array.isArray(request.dbAssertions) && request.dbAssertions.length > 0)
|
|
72
|
-
notes.push("DB assertions (desktop only)");
|
|
73
|
-
if (typeof request.id === "string" && notes.length > 0)
|
|
74
|
-
skipped.set(request.id, notes);
|
|
75
68
|
}
|
|
76
|
-
return { redaction: { secretHeaders, secretQuery }
|
|
69
|
+
return { redaction: { secretHeaders, secretQuery } };
|
|
77
70
|
};
|
|
78
71
|
const prepareRun = async (ctx, ws, collectionId, environmentRef) => {
|
|
79
72
|
const environment = environmentRef ? (await (0, lookups_js_1.resolveEnvironment)(ctx, ws, environmentRef)).item : null;
|
|
@@ -99,7 +92,7 @@ const prepareRun = async (ctx, ws, collectionId, environmentRef) => {
|
|
|
99
92
|
const { map, skipped } = (0, loadBundle_js_1.buildConnectionRuntimeMap)(bundle.connections);
|
|
100
93
|
if (skipped.length > 0)
|
|
101
94
|
warnings.push(`Connections not usable in a local run: ${skipped.join(", ")}`);
|
|
102
|
-
const { redaction
|
|
95
|
+
const { redaction } = inspectBundle(bundle.collection);
|
|
103
96
|
return {
|
|
104
97
|
collection,
|
|
105
98
|
env: { ...(bundle.environment?.variables ?? {}) },
|
|
@@ -108,21 +101,9 @@ const prepareRun = async (ctx, ws, collectionId, environmentRef) => {
|
|
|
108
101
|
environment: bundle.environment ? { id: bundle.environment.id, name: bundle.environment.name } : null,
|
|
109
102
|
warnings,
|
|
110
103
|
redaction,
|
|
111
|
-
skipped: skippedSteps,
|
|
112
104
|
};
|
|
113
105
|
};
|
|
114
106
|
exports.prepareRun = prepareRun;
|
|
115
|
-
// Warnings for the requests actually run.
|
|
116
|
-
const skippedWarnings = (prepared, ids) => {
|
|
117
|
-
const out = [];
|
|
118
|
-
const names = new Map(prepared.collection.requests.map((request) => [request.id, request.name]));
|
|
119
|
-
for (const id of ids) {
|
|
120
|
-
const notes = prepared.skipped.get(id);
|
|
121
|
-
if (notes)
|
|
122
|
-
out.push(`${names.get(id) ?? id}: not run locally — ${notes.join(", ")}.`);
|
|
123
|
-
}
|
|
124
|
-
return out;
|
|
125
|
-
};
|
|
126
107
|
const registerRunTools = (server, ctx) => {
|
|
127
108
|
server.registerTool("run_request", {
|
|
128
109
|
title: "Run a request locally",
|
|
@@ -176,7 +157,7 @@ const registerRunTools = (server, ctx) => {
|
|
|
176
157
|
environment: prepared.environment,
|
|
177
158
|
availableVariableKeys: Object.keys(env),
|
|
178
159
|
unresolvedVariables: unresolved([runnable.url, ...Object.values(runnable.headers ?? {}), ...Object.values(runnable.query ?? {}), (0, truncate_js_1.safeStringify)(runnable.body ?? "")], env),
|
|
179
|
-
warnings:
|
|
160
|
+
warnings: prepared.warnings,
|
|
180
161
|
...(runnable.isEnabledInRunner === false ? { note: "This request is switched off for the collection runner; run_request still runs it." } : {}),
|
|
181
162
|
});
|
|
182
163
|
}
|
|
@@ -193,7 +174,7 @@ const registerRunTools = (server, ctx) => {
|
|
|
193
174
|
collection: { id: found.collectionId },
|
|
194
175
|
workspace: (0, lookups_js_1.workspaceTag)(ws),
|
|
195
176
|
environment: prepared.environment,
|
|
196
|
-
warnings:
|
|
177
|
+
warnings: prepared.warnings,
|
|
197
178
|
...(annotation ? { resolved: [{ input: request, matched: found.name, id: found.id, note: annotation }] } : {}),
|
|
198
179
|
}, prepared.redaction);
|
|
199
180
|
return (0, shared_js_1.ok)({ ...summary, result: summary.results[0] ?? null });
|
|
@@ -243,7 +224,7 @@ const registerRunTools = (server, ctx) => {
|
|
|
243
224
|
collection: { id: resolved.item.id, name: resolved.item.name },
|
|
244
225
|
workspace: (0, lookups_js_1.workspaceTag)(ws),
|
|
245
226
|
environment: prepared.environment,
|
|
246
|
-
warnings:
|
|
227
|
+
warnings: prepared.warnings,
|
|
247
228
|
resolved: [(0, resolve_js_1.resolvedSummary)(collection, resolved)],
|
|
248
229
|
}, prepared.redaction));
|
|
249
230
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "callman-mcp",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"description": "MCP server for Callman: lets Claude Code, Claude Desktop, Cursor, Codex and Gemini CLI manage collections, requests, environments, test scenarios, UI tests (web, Android, iOS) and system-design diagrams in your Callman workspace \u2014 cloud or on-prem.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"callman",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@modelcontextprotocol/sdk": "^1.30.0",
|
|
65
|
-
"callman-core": "^1.
|
|
65
|
+
"callman-core": "^1.38.0",
|
|
66
66
|
"elkjs": "^0.12.0",
|
|
67
67
|
"js-yaml": "^4.1.0",
|
|
68
68
|
"zod": "^3.25.0"
|