@evantahler/mcpcli 0.3.0 → 0.3.3

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 CHANGED
@@ -32,7 +32,7 @@ mcpcli -d
32
32
  mcpcli info github
33
33
 
34
34
  # Inspect a specific tool
35
- mcpcli info github/search_repositories
35
+ mcpcli info github search_repositories
36
36
 
37
37
  # Call a tool
38
38
  mcpcli call github search_repositories '{"query": "mcp server"}'
@@ -53,7 +53,7 @@ mcpcli search -q "manage pull requests"
53
53
  | ------------------------------------ | -------------------------------------------- |
54
54
  | `mcpcli` | List all configured servers and tools |
55
55
  | `mcpcli info <server>` | Show tools for a server |
56
- | `mcpcli info <server>/<tool>` | Show tool schema |
56
+ | `mcpcli info <server> <tool>` | Show tool schema |
57
57
  | `mcpcli search <query>` | Search tools (keyword + semantic) |
58
58
  | `mcpcli search -k <pattern>` | Keyword/glob search only |
59
59
  | `mcpcli search -q <query>` | Semantic search only |
@@ -415,7 +415,7 @@ cp skills/mcpcli.md ~/.claude/skills/mcpcli.md
415
415
  Then in any Claude Code session, the agent can use `/mcpcli` or the skill triggers automatically when the agent needs to interact with external services. The skill instructs the agent to:
416
416
 
417
417
  1. **Search first** — `mcpcli search "<intent>"` to find relevant tools
418
- 2. **Inspect** — `mcpcli info <server>/<tool>` to get the schema before calling
418
+ 2. **Inspect** — `mcpcli info <server> <tool>` to get the schema before calling
419
419
  3. **Call** — `mcpcli call <server> <tool> '<json>'` to execute
420
420
 
421
421
  This keeps tool schemas out of the system prompt entirely. The agent discovers what it needs on-demand, saving tokens and context window space.
@@ -430,7 +430,7 @@ You have access to MCP tools via the `mcpcli` CLI.
430
430
  To discover tools:
431
431
  mcpcli search "<what you want to do>" # combined keyword + semantic
432
432
  mcpcli search -k "<pattern>" # keyword/glob only
433
- mcpcli info <server>/<tool> # tool schema
433
+ mcpcli info <server> <tool> # tool schema
434
434
 
435
435
  To call tools:
436
436
  mcpcli call <server> <tool> '<json args>'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evantahler/mcpcli",
3
- "version": "0.3.0",
3
+ "version": "0.3.3",
4
4
  "description": "A command-line interface for MCP servers. curl for MCP.",
5
5
  "type": "module",
6
6
  "bin": {
package/skills/mcpcli.md CHANGED
@@ -17,10 +17,10 @@ mcpcli search "<what you want to do>"
17
17
  ## 2. Inspect the tool schema
18
18
 
19
19
  ```bash
20
- mcpcli call <server> <tool>
20
+ mcpcli info <server> <tool>
21
21
  ```
22
22
 
23
- This shows parameters, types, required fields, and an example payload.
23
+ This shows parameters, types, required fields, and the full JSON Schema.
24
24
 
25
25
  ## 3. Call the tool
26
26
 
@@ -34,7 +34,6 @@ mcpcli call <server> <tool> '<json args>'
34
34
  - Always inspect the schema before calling — validate you have the right arguments
35
35
  - Use `mcpcli search -k` for exact name matching
36
36
  - Pipe results through `jq` when you need to extract specific fields
37
- - Tool call results are always JSON with nested JSON strings auto-parsed
38
37
  - Use `-v` for verbose HTTP debugging if a call fails unexpectedly
39
38
 
40
39
  ## Examples
@@ -44,14 +43,14 @@ mcpcli call <server> <tool> '<json args>'
44
43
  mcpcli search "send a message"
45
44
 
46
45
  # See what parameters Slack_SendMessage needs
47
- mcpcli call arcade Slack_SendMessage
46
+ mcpcli info arcade Slack_SendMessage
48
47
 
49
48
  # Send a message
50
49
  mcpcli call arcade Slack_SendMessage '{"channel":"#general","message":"hello"}'
51
50
 
52
51
  # Chain commands — search repos and read the first result
53
52
  mcpcli call github search_repositories '{"query":"mcp"}' \
54
- | jq -r '.content[0].text.items[0].full_name' \
53
+ | jq -r '.content[0].text | fromjson | .items[0].full_name' \
55
54
  | xargs -I {} mcpcli call github get_file_contents '{"owner":"{}","path":"README.md"}'
56
55
 
57
56
  # Read args from stdin
@@ -64,22 +63,30 @@ Some HTTP servers require OAuth. If you see an "Not authenticated" error:
64
63
 
65
64
  ```bash
66
65
  mcpcli auth <server> # authenticate via browser
67
- mcpcli auth <server> -s # check token status
66
+ mcpcli auth <server> -s # check token status and TTL
67
+ mcpcli auth <server> -r # force token refresh
68
68
  mcpcli deauth <server> # remove stored auth
69
69
  ```
70
70
 
71
71
  ## Available commands
72
72
 
73
- | Command | Purpose |
74
- | -------------------------------------- | ---------------------------------- |
75
- | `mcpcli` | List all servers and tools |
76
- | `mcpcli -d` | List with descriptions |
77
- | `mcpcli call <server>` | List tools for a server |
78
- | `mcpcli call <server> <tool>` | Show tool help and example payload |
79
- | `mcpcli call <server> <tool> '<json>'` | Execute a tool |
80
- | `mcpcli info <server>/<tool>` | Show tool schema |
81
- | `mcpcli search "<query>"` | Search tools |
82
- | `mcpcli search -k "<pattern>"` | Keyword/glob search only |
83
- | `mcpcli search -q "<query>"` | Semantic search only |
84
- | `mcpcli index` | Build/rebuild search index |
85
- | `mcpcli auth <server>` | Authenticate with OAuth |
73
+ | Command | Purpose |
74
+ | -------------------------------------- | --------------------------------- |
75
+ | `mcpcli` | List all servers and tools |
76
+ | `mcpcli -d` | List with descriptions |
77
+ | `mcpcli info <server>` | Show tools for a server |
78
+ | `mcpcli info <server> <tool>` | Show tool schema |
79
+ | `mcpcli call <server>` | List tools for a server |
80
+ | `mcpcli call <server> <tool> '<json>'` | Execute a tool |
81
+ | `mcpcli search "<query>"` | Search tools (keyword + semantic) |
82
+ | `mcpcli search -k "<pattern>"` | Keyword/glob search only |
83
+ | `mcpcli search -q "<query>"` | Semantic search only |
84
+ | `mcpcli index` | Build/rebuild search index |
85
+ | `mcpcli index -i` | Show index status |
86
+ | `mcpcli auth <server>` | Authenticate with OAuth |
87
+ | `mcpcli auth <server> -s` | Check token status and TTL |
88
+ | `mcpcli auth <server> -r` | Force token refresh |
89
+ | `mcpcli deauth <server>` | Remove stored authentication |
90
+ | `mcpcli add <name> --command <cmd>` | Add a stdio MCP server |
91
+ | `mcpcli add <name> --url <url>` | Add an HTTP MCP server |
92
+ | `mcpcli remove <name>` | Remove an MCP server |
@@ -4,7 +4,6 @@ import {
4
4
  formatCallResult,
5
5
  formatError,
6
6
  formatServerTools,
7
- formatToolHelp,
8
7
  formatValidationErrors,
9
8
  } from "../output/formatter.ts";
10
9
  import { startSpinner } from "../output/spinner.ts";
@@ -30,18 +29,6 @@ export function registerCallCommand(program: Command) {
30
29
  return;
31
30
  }
32
31
  try {
33
- // No args + interactive terminal → show tool help with example payload
34
- const hasArgs = !!argsStr;
35
- const hasStdin = !process.stdin.isTTY;
36
- if (!hasArgs && !hasStdin) {
37
- const toolSchema = await manager.getToolSchema(server, tool);
38
- if (toolSchema) {
39
- console.log(formatToolHelp(server, toolSchema, formatOptions));
40
- await manager.close();
41
- return;
42
- }
43
- }
44
-
45
32
  // Parse args from argument, stdin, or empty
46
33
  let args: Record<string, unknown> = {};
47
34
 
@@ -5,31 +5,27 @@ import { startSpinner } from "../output/spinner.ts";
5
5
 
6
6
  export function registerInfoCommand(program: Command) {
7
7
  program
8
- .command("info <target>")
8
+ .command("info <server> [tool]")
9
9
  .description("show tools for a server, or schema for a specific tool")
10
- .action(async (target: string) => {
10
+ .action(async (server: string, tool: string | undefined) => {
11
11
  const { manager, formatOptions } = await getContext(program);
12
+ const target = tool ? `${server}/${tool}` : server;
12
13
  const spinner = startSpinner(`Connecting to ${target}...`, formatOptions);
13
14
  try {
14
- // Parse "server/tool" or "server tool" format
15
- const slashIndex = target.indexOf("/");
16
- if (slashIndex !== -1) {
17
- const serverName = target.slice(0, slashIndex);
18
- const toolName = target.slice(slashIndex + 1);
19
- const tool = await manager.getToolSchema(serverName, toolName);
15
+ if (tool) {
16
+ const toolSchema = await manager.getToolSchema(server, tool);
20
17
  spinner.stop();
21
- if (!tool) {
18
+ if (!toolSchema) {
22
19
  console.error(
23
- formatError(`Tool "${toolName}" not found on server "${serverName}"`, formatOptions),
20
+ formatError(`Tool "${tool}" not found on server "${server}"`, formatOptions),
24
21
  );
25
22
  process.exit(1);
26
23
  }
27
- console.log(formatToolSchema(serverName, tool, formatOptions));
24
+ console.log(formatToolSchema(server, toolSchema, formatOptions));
28
25
  } else {
29
- // Just a server name — list its tools
30
- const tools = await manager.listTools(target);
26
+ const tools = await manager.listTools(server);
31
27
  spinner.stop();
32
- console.log(formatServerTools(target, tools, formatOptions));
28
+ console.log(formatServerTools(server, tools, formatOptions));
33
29
  }
34
30
  } catch (err) {
35
31
  spinner.error(`Failed to connect to ${target}`);