Skip to content

Commit 24d5345

Browse files
committed
feat(cli): agent-first output — JSON default, compact index, search, human mode
v1.2.2 Changed: - JSON is now the default output for list-tools and bare invocation - Bare 'mcp-cli-ent' outputs compact index: {server: [{name, description}]} - --human flag switches to terminal output (terse by default) - --human --verbose expands to 4-line format (desc, params, call) - All stdout pollution removed in JSON mode (headers, errors → stderr) - Empty results return structured JSON error with error_code Added: - --search <query> filters tools by name/description (case-insensitive) - --verbose in JSON mode includes full inputSchema - Shared JSONTool, indexTool types and encodeErrorJSON helper Fixed: - Dead verbose branch removed (identical if/else output) - Server count after search uses actual matching servers - Deterministic output: server keys sorted alphabetically - jsonServer dead code deleted - desc/description field name consistency across commands
1 parent 4370983 commit 24d5345

4 files changed

Lines changed: 257 additions & 77 deletions

File tree

CHANGELOG.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,29 @@
22

33
All notable changes to MCP CLI-Ent will be documented in this file.
44

5+
<!-- RELEASE:START 1.2.2 -->
6+
## [1.2.2] - 2026-06-08
7+
8+
### Changed
9+
10+
- **JSON is now the default output format** for `list-tools` and bare `mcp-cli-ent` invocation. Agents parse structured JSON natively; `--human` flag switches to terminal-readable output.
11+
- **Terse human output by default**: `--human` output shows one line per tool (`name: description`). Use `--human --verbose` for expanded 4-line format (desc, params, call).
12+
- **Dead verbose branch removed**: The `if verbose`/`else` block in `listToolsFromServer` produced identical output regardless of flag. Deleted.
13+
14+
### Added
15+
16+
- **`--human` flag**: Switches from JSON to human-readable terminal output.
17+
- **`--search <query>` flag**: Filters tools by name or description (case-insensitive substring). Works in both JSON and human modes.
18+
- **`--verbose` now includes full schema**: In JSON mode, `--verbose` adds the complete `inputSchema` for each tool.
19+
20+
### Fixed
21+
22+
- **Server count after search**: `--human --search` now reports the correct number of matching servers instead of total configured servers.
23+
- **Deterministic JSON output**: Server keys are now sorted alphabetically for stable, diff-friendly output.
24+
- **Shared `JSONTool` type**: Extracted from local duplicates in `commands.go` and `root.go` to a single package-level type, preventing silent output contract divergence.
25+
26+
<!-- RELEASE:END 1.2.2 -->
27+
528
<!-- RELEASE:START 1.2.1 -->
629
## [1.2.1] - 2026-06-07
730

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.2.1
1+
1.2.2

internal/cli/commands.go

Lines changed: 43 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -385,11 +385,6 @@ func runListTools(cmd *cobra.Command, args []string) error {
385385
return fmt.Errorf("server '%s' is disabled", serverName)
386386
}
387387

388-
// Display server description if available
389-
if serverConfig.Description != "" {
390-
fmt.Printf("%s - %s\n\n", serverName, serverConfig.Description)
391-
}
392-
393388
return listToolsFromServer(ctx, serverName, serverConfig)
394389
}
395390
}
@@ -452,44 +447,60 @@ func listToolsFromServer(ctx context.Context, serverName string, serverConfig co
452447
}
453448

454449
if len(tools) == 0 {
455-
fmt.Println("No tools found.")
450+
if humanOutput {
451+
fmt.Println("No tools found.")
452+
} else {
453+
return encodeErrorJSON("no_tools", "No tools found on %s", serverName)
454+
}
456455
return nil
457456
}
458457

459-
fmt.Printf("Available tools (%d):\n", len(tools))
460-
for _, tool := range tools {
461-
fmt.Printf(" • %s\n", tool.Name)
462-
if tool.Description != "" {
463-
fmt.Printf(" desc: %s\n", tool.Description)
464-
}
465-
if tool.InputSchema != nil {
466-
if properties, ok := tool.InputSchema["properties"].(map[string]interface{}); ok {
467-
var paramNames []string
468-
for name := range properties {
469-
paramNames = append(paramNames, name)
470-
}
471-
if len(paramNames) > 0 {
472-
fmt.Printf(" params: %s\n", strings.Join(paramNames, ", "))
473-
}
458+
// Filter by search query
459+
if searchQuery != "" {
460+
var filtered []mcp.Tool
461+
for _, tool := range tools {
462+
if toolMatches(tool, searchQuery) {
463+
filtered = append(filtered, tool)
474464
}
475465
}
476-
// Build and display call example
477-
exampleArgs := BuildExampleArgs(&tool)
478-
if verbose {
479-
if exampleArgs == "'{}'" {
480-
fmt.Printf(" call: mcp-cli-ent call %s %s\n\n", serverName, tool.Name)
466+
if len(filtered) == 0 {
467+
if humanOutput {
468+
fmt.Printf("No tools matching '%s' found on %s.\n", searchQuery, serverName)
481469
} else {
482-
fmt.Printf(" call: mcp-cli-ent call %s %s %s\n\n", serverName, tool.Name, exampleArgs)
470+
return encodeErrorJSON("no_match", "No tools matching '%s' found on %s", searchQuery, serverName)
483471
}
484-
} else {
485-
if exampleArgs == "'{}'" {
486-
fmt.Printf(" call: mcp-cli-ent call %s %s\n\n", serverName, tool.Name)
487-
} else {
488-
fmt.Printf(" call: mcp-cli-ent call %s %s %s\n\n", serverName, tool.Name, exampleArgs)
472+
return nil
473+
}
474+
tools = filtered
475+
}
476+
477+
// JSON output by default
478+
if !humanOutput {
479+
result := make([]JSONTool, 0, len(tools))
480+
for _, tool := range tools {
481+
jt := JSONTool{
482+
Name: tool.Name,
483+
Description: tool.Description,
484+
Params: extractParamNames(tool.InputSchema),
485+
Call: buildCallString(serverName, tool.Name, BuildExampleArgs(&tool)),
489486
}
487+
if verbose {
488+
jt.Schema = tool.InputSchema
489+
}
490+
result = append(result, jt)
490491
}
492+
493+
enc := json.NewEncoder(os.Stdout)
494+
enc.SetIndent("", " ")
495+
return enc.Encode(result)
491496
}
492497

498+
// Human-readable output (terse by default, verbose expands)
499+
if serverConfig.Description != "" {
500+
fmt.Printf("%s - %s\n\n", serverName, serverConfig.Description)
501+
}
502+
fmt.Printf("Available tools (%d):\n", len(tools))
503+
printToolsHuman(tools, serverName, verbose)
493504
return nil
494505
}
495506

0 commit comments

Comments
 (0)