mcp-caller 0.0.3 → 0.0.4

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.
Files changed (3) hide show
  1. package/README.md +12 -0
  2. package/index.js +84 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -48,6 +48,18 @@ 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
+ List callable tools:
52
+
53
+ ```bash
54
+ npx -y mcp-caller --server-file server.json --list-tools
55
+ ```
56
+
57
+ Inspect tools, prompts, and resources:
58
+
59
+ ```bash
60
+ npx -y mcp-caller --server-file server.json --inspect --pretty
61
+ ```
62
+
51
63
  ## JSON Shapes
52
64
 
53
65
  Server JSON:
package/index.js CHANGED
@@ -7,6 +7,8 @@ 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
10
12
  mcp-caller --server-json <json> --call-json <json>
11
13
  mcp-caller --server-file <path> --call-file <path>
12
14
 
@@ -81,6 +83,14 @@ function parseArgs(argv) {
81
83
  options.callFile = argv[++i];
82
84
  continue;
83
85
  }
86
+ if (token === "--list-tools") {
87
+ options.listTools = true;
88
+ continue;
89
+ }
90
+ if (token === "--inspect") {
91
+ options.inspect = true;
92
+ continue;
93
+ }
84
94
  if (token === "--server-name") {
85
95
  options.serverName = argv[++i];
86
96
  continue;
@@ -153,6 +163,31 @@ function extractText(result) {
153
163
  return pieces.join("\n");
154
164
  }
155
165
 
166
+ function printTools(tools) {
167
+ for (const tool of tools) {
168
+ console.log(`- ${tool.name}${tool.description ? `: ${tool.description}` : ""}`);
169
+ }
170
+ }
171
+
172
+ function formatInspect(serverName, tools, prompts, resources) {
173
+ return {
174
+ server: serverName,
175
+ tools: tools.map((tool) => ({
176
+ name: tool.name,
177
+ description: tool.description ?? ""
178
+ })),
179
+ prompts: prompts.map((prompt) => ({
180
+ name: prompt.name,
181
+ description: prompt.description ?? ""
182
+ })),
183
+ resources: resources.map((resource) => ({
184
+ uri: resource.uri,
185
+ name: resource.name ?? "",
186
+ description: resource.description ?? ""
187
+ }))
188
+ };
189
+ }
190
+
156
191
  async function main() {
157
192
  const options = parseArgs(process.argv.slice(2));
158
193
  if (options.help) {
@@ -161,13 +196,17 @@ async function main() {
161
196
  }
162
197
 
163
198
  const serverSource = readSource(options, "serverJson", "serverFile", "--server-json/--server-file");
164
- const callSource = readSource(options, "callJson", "callFile", "--call-json/--call-file");
199
+ const callSource = options.listTools || options.inspect
200
+ ? null
201
+ : readSource(options, "callJson", "callFile", "--call-json/--call-file");
165
202
 
166
- if (!callSource || typeof callSource !== "object") {
167
- throw new Error("Call JSON must be an object");
168
- }
169
- if (typeof callSource.tool !== "string" || !callSource.tool) {
170
- throw new Error('Call JSON must include a non-empty "tool" string');
203
+ if (callSource) {
204
+ if (typeof callSource !== "object") {
205
+ throw new Error("Call JSON must be an object");
206
+ }
207
+ if (typeof callSource.tool !== "string" || !callSource.tool) {
208
+ throw new Error('Call JSON must include a non-empty "tool" string');
209
+ }
171
210
  }
172
211
 
173
212
  const { server } = resolveServerDefinition(serverSource, options.serverName);
@@ -177,18 +216,49 @@ async function main() {
177
216
  try {
178
217
  await client.connect(transport);
179
218
 
180
- const result = await client.callTool({
181
- name: callSource.tool,
182
- arguments: callSource.params ?? callSource.arguments ?? {}
183
- });
219
+ if (options.listTools || options.inspect) {
220
+ const [toolsResult, promptsResult, resourcesResult] = await Promise.all([
221
+ client.listTools(),
222
+ options.inspect ? client.listPrompts() : Promise.resolve({ prompts: [] }),
223
+ options.inspect ? client.listResources() : Promise.resolve({ resources: [] })
224
+ ]);
184
225
 
185
- const text = extractText(result);
186
- if (text) {
187
- console.log(text);
226
+ if (options.listTools) {
227
+ printTools(toolsResult.tools ?? []);
228
+ return;
229
+ }
230
+
231
+ console.log(JSON.stringify(
232
+ formatInspect(
233
+ options.serverName ?? (serverSource?.mcpServers ? Object.keys(serverSource.mcpServers)[0] : "server"),
234
+ toolsResult.tools ?? [],
235
+ promptsResult.prompts ?? [],
236
+ resourcesResult.resources ?? []
237
+ ),
238
+ null,
239
+ options.pretty ? 2 : 0
240
+ ));
188
241
  return;
189
242
  }
190
243
 
191
- console.log(JSON.stringify(result, null, options.pretty ? 2 : 0));
244
+ if (!options.listTools && !options.inspect && !callSource) {
245
+ throw new Error("Missing --call-json/--call-file, or use --list-tools / --inspect");
246
+ }
247
+
248
+ if (callSource) {
249
+ const result = await client.callTool({
250
+ name: callSource.tool,
251
+ arguments: callSource.params ?? callSource.arguments ?? {}
252
+ });
253
+
254
+ const text = extractText(result);
255
+ if (text) {
256
+ console.log(text);
257
+ return;
258
+ }
259
+
260
+ console.log(JSON.stringify(result, null, options.pretty ? 2 : 0));
261
+ }
192
262
  } finally {
193
263
  await client.close().catch(() => {});
194
264
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-caller",
3
- "version": "0.0.3",
3
+ "version": "0.0.4",
4
4
  "description": "A small MCP client CLI that can start a server and call a tool from JSON input.",
5
5
  "type": "module",
6
6
  "main": "index.js",