mcp-caller 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -0
- package/index.js +120 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,6 +48,24 @@ Read JSON from files instead of inline values:
|
|
|
48
48
|
npx -y mcp-caller --server-file server.json --call-file call.json
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
+
Short call form:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npx -y mcp-caller --server-file server.json --tool say_hello --params-json '{"name":"world"}'
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
List callable tools:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx -y mcp-caller --server-file server.json --list-tools
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Inspect tools, prompts, and resources:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
npx -y mcp-caller --server-file server.json --inspect --pretty
|
|
67
|
+
```
|
|
68
|
+
|
|
51
69
|
## JSON Shapes
|
|
52
70
|
|
|
53
71
|
Server JSON:
|
package/index.js
CHANGED
|
@@ -7,6 +7,9 @@ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/
|
|
|
7
7
|
|
|
8
8
|
function printUsage() {
|
|
9
9
|
console.error(`Usage:
|
|
10
|
+
mcp-caller --server-json <json> --list-tools
|
|
11
|
+
mcp-caller --server-json <json> --inspect
|
|
12
|
+
mcp-caller --server-json <json> --tool <name> [--params-json <json>]
|
|
10
13
|
mcp-caller --server-json <json> --call-json <json>
|
|
11
14
|
mcp-caller --server-file <path> --call-file <path>
|
|
12
15
|
|
|
@@ -57,6 +60,16 @@ function readSource(options, jsonKey, fileKey, label) {
|
|
|
57
60
|
throw new Error(`Missing ${label}`);
|
|
58
61
|
}
|
|
59
62
|
|
|
63
|
+
function readParams(options) {
|
|
64
|
+
if (options.paramsFile) {
|
|
65
|
+
return parseJson(readFileSync(options.paramsFile, "utf8"), "--params-json/--params-file");
|
|
66
|
+
}
|
|
67
|
+
if (options.paramsJson) {
|
|
68
|
+
return parseJson(options.paramsJson, "--params-json/--params-file");
|
|
69
|
+
}
|
|
70
|
+
return {};
|
|
71
|
+
}
|
|
72
|
+
|
|
60
73
|
function parseArgs(argv) {
|
|
61
74
|
const options = {};
|
|
62
75
|
for (let i = 0; i < argv.length; i += 1) {
|
|
@@ -81,6 +94,26 @@ function parseArgs(argv) {
|
|
|
81
94
|
options.callFile = argv[++i];
|
|
82
95
|
continue;
|
|
83
96
|
}
|
|
97
|
+
if (token === "--tool") {
|
|
98
|
+
options.tool = argv[++i];
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (token === "--params-json") {
|
|
102
|
+
options.paramsJson = argv[++i];
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (token === "--params-file") {
|
|
106
|
+
options.paramsFile = argv[++i];
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (token === "--list-tools") {
|
|
110
|
+
options.listTools = true;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (token === "--inspect") {
|
|
114
|
+
options.inspect = true;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
84
117
|
if (token === "--server-name") {
|
|
85
118
|
options.serverName = argv[++i];
|
|
86
119
|
continue;
|
|
@@ -153,6 +186,31 @@ function extractText(result) {
|
|
|
153
186
|
return pieces.join("\n");
|
|
154
187
|
}
|
|
155
188
|
|
|
189
|
+
function printTools(tools) {
|
|
190
|
+
for (const tool of tools) {
|
|
191
|
+
console.log(`- ${tool.name}${tool.description ? `: ${tool.description}` : ""}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function formatInspect(serverName, tools, prompts, resources) {
|
|
196
|
+
return {
|
|
197
|
+
server: serverName,
|
|
198
|
+
tools: tools.map((tool) => ({
|
|
199
|
+
name: tool.name,
|
|
200
|
+
description: tool.description ?? ""
|
|
201
|
+
})),
|
|
202
|
+
prompts: prompts.map((prompt) => ({
|
|
203
|
+
name: prompt.name,
|
|
204
|
+
description: prompt.description ?? ""
|
|
205
|
+
})),
|
|
206
|
+
resources: resources.map((resource) => ({
|
|
207
|
+
uri: resource.uri,
|
|
208
|
+
name: resource.name ?? "",
|
|
209
|
+
description: resource.description ?? ""
|
|
210
|
+
}))
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
156
214
|
async function main() {
|
|
157
215
|
const options = parseArgs(process.argv.slice(2));
|
|
158
216
|
if (options.help) {
|
|
@@ -161,13 +219,30 @@ async function main() {
|
|
|
161
219
|
}
|
|
162
220
|
|
|
163
221
|
const serverSource = readSource(options, "serverJson", "serverFile", "--server-json/--server-file");
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
if (!callSource || typeof callSource !== "object") {
|
|
167
|
-
throw new Error("Call JSON must be an object");
|
|
222
|
+
if (options.tool && (options.callJson || options.callFile)) {
|
|
223
|
+
throw new Error("Use either --tool/--params-json or --call-json/--call-file, not both");
|
|
168
224
|
}
|
|
169
|
-
if (
|
|
170
|
-
throw new Error('
|
|
225
|
+
if (options.tool && options.tool.trim().length === 0) {
|
|
226
|
+
throw new Error('Option "--tool" must be a non-empty string');
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
const shorthandCall = options.tool
|
|
230
|
+
? {
|
|
231
|
+
tool: options.tool,
|
|
232
|
+
params: readParams(options)
|
|
233
|
+
}
|
|
234
|
+
: null;
|
|
235
|
+
const callSource = options.listTools || options.inspect
|
|
236
|
+
? null
|
|
237
|
+
: shorthandCall ?? readSource(options, "callJson", "callFile", "--call-json/--call-file");
|
|
238
|
+
|
|
239
|
+
if (callSource) {
|
|
240
|
+
if (typeof callSource !== "object") {
|
|
241
|
+
throw new Error("Call JSON must be an object");
|
|
242
|
+
}
|
|
243
|
+
if (typeof callSource.tool !== "string" || !callSource.tool) {
|
|
244
|
+
throw new Error('Call JSON must include a non-empty "tool" string');
|
|
245
|
+
}
|
|
171
246
|
}
|
|
172
247
|
|
|
173
248
|
const { server } = resolveServerDefinition(serverSource, options.serverName);
|
|
@@ -177,18 +252,49 @@ async function main() {
|
|
|
177
252
|
try {
|
|
178
253
|
await client.connect(transport);
|
|
179
254
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
255
|
+
if (options.listTools || options.inspect) {
|
|
256
|
+
const [toolsResult, promptsResult, resourcesResult] = await Promise.all([
|
|
257
|
+
client.listTools(),
|
|
258
|
+
options.inspect ? client.listPrompts() : Promise.resolve({ prompts: [] }),
|
|
259
|
+
options.inspect ? client.listResources() : Promise.resolve({ resources: [] })
|
|
260
|
+
]);
|
|
184
261
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
262
|
+
if (options.listTools) {
|
|
263
|
+
printTools(toolsResult.tools ?? []);
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
console.log(JSON.stringify(
|
|
268
|
+
formatInspect(
|
|
269
|
+
options.serverName ?? (serverSource?.mcpServers ? Object.keys(serverSource.mcpServers)[0] : "server"),
|
|
270
|
+
toolsResult.tools ?? [],
|
|
271
|
+
promptsResult.prompts ?? [],
|
|
272
|
+
resourcesResult.resources ?? []
|
|
273
|
+
),
|
|
274
|
+
null,
|
|
275
|
+
options.pretty ? 2 : 0
|
|
276
|
+
));
|
|
188
277
|
return;
|
|
189
278
|
}
|
|
190
279
|
|
|
191
|
-
|
|
280
|
+
if (!options.listTools && !options.inspect && !callSource) {
|
|
281
|
+
throw new Error("Missing --call-json/--call-file, or use --list-tools / --inspect");
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
if (callSource) {
|
|
285
|
+
const result = await client.callTool({
|
|
286
|
+
name: callSource.tool,
|
|
287
|
+
arguments: callSource.params ?? callSource.arguments ?? {}
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const text = extractText(result);
|
|
291
|
+
if (text) {
|
|
292
|
+
console.log(text);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
console.log(JSON.stringify(result, null, options.pretty ? 2 : 0));
|
|
297
|
+
}
|
|
192
298
|
} finally {
|
|
193
299
|
await client.close().catch(() => {});
|
|
194
300
|
}
|