diff --git a/changelog.d/unreleased/1424.fixed.md b/changelog.d/unreleased/1424.fixed.md new file mode 100644 index 0000000000..d32f5e8e9f --- /dev/null +++ b/changelog.d/unreleased/1424.fixed.md @@ -0,0 +1,17 @@ +--- +category: fixed +issues: + - 1424 +affected: + - src/CodeIndex/Cli/ConsoleUi.cs + - src/CodeIndex/Cli/ProgramRunner.cs + - tests/CodeIndex.Tests/ProgramCliTests.cs +--- + +## English + +- **`mcp` and `completions` help now calls out unsupported `--json` usage (#1424)** - subcommand help now documents that `--json` is not supported, and direct `--json` errors explain the command-specific output format. + +## 日本語 + +- **`mcp` / `completions` の help で `--json` 非対応を明示するようになりました (#1424)** - subcommand help に `--json` が非対応であることを記載し、直接 `--json` を指定した場合のエラーも各コマンドの出力形式に合わせて説明します。 diff --git a/src/CodeIndex/Cli/ConsoleUi.cs b/src/CodeIndex/Cli/ConsoleUi.cs index 07c7a835e7..cb879fd597 100644 --- a/src/CodeIndex/Cli/ConsoleUi.cs +++ b/src/CodeIndex/Cli/ConsoleUi.cs @@ -108,7 +108,7 @@ private static readonly (string Command, string Usage)[] CommandUsageLines = ("import", "cdidx import [--db ] [--prune-paths] [--json]"), ("languages", "cdidx languages [--json]"), ("batch", "cdidx batch [--db ] # reads JSON string arrays from stdin, one query command per line"), - ("mcp", "cdidx mcp [--db ]"), + ("mcp", "cdidx mcp [--db ] [--transport stdio|http] [--http-listen ] [--audit-log ] [--audit-log-include-values] [--audit-log-max-bytes ] [--suggestion-dedup-threshold <0..1>]"), ("lsp", "cdidx lsp [--db ]"), ("completions", "cdidx completions "), ("--completions", "cdidx --completions "), @@ -116,6 +116,12 @@ private static readonly (string Command, string Usage)[] CommandUsageLines = ("license", "cdidx license"), ]; + private static readonly (string Command, string Note)[] CommandUsageNotes = + [ + ("mcp", "--json is not supported; MCP requests and responses are JSON-RPC over the selected transport."), + ("completions", "--json is not supported; output is a shell script for the selected shell."), + ]; + public static string FormatSummaryLine(string label, object? value, int labelWidth = SummaryLabelWidth, string indent = "") => $"{indent}{label.PadRight(labelWidth)}: {value}"; @@ -1104,6 +1110,14 @@ public static bool PrintCommandUsage(string command) Console.WriteLine("Usage:"); foreach (var usage in usages) Console.WriteLine($" {usage}"); + var notes = GetCommandUsageNotes(command); + if (notes.Count > 0) + { + Console.WriteLine(); + Console.WriteLine("Notes:"); + foreach (var note in notes) + Console.WriteLine($" {note}"); + } Console.WriteLine(); Console.WriteLine("Run `cdidx --help` to show all commands and shared options."); return true; @@ -1124,6 +1138,18 @@ private static IReadOnlyList GetCommandUsageLines(string command) return usages; } + private static IReadOnlyList GetCommandUsageNotes(string command) + { + var notes = new List(); + foreach (var (name, note) in CommandUsageNotes) + { + if (string.Equals(name, command, StringComparison.Ordinal)) + notes.Add(note); + } + + return notes; + } + // --- Did-you-mean / もしかして --- /// diff --git a/src/CodeIndex/Cli/ProgramRunner.cs b/src/CodeIndex/Cli/ProgramRunner.cs index a871131042..2ca52cd087 100644 --- a/src/CodeIndex/Cli/ProgramRunner.cs +++ b/src/CodeIndex/Cli/ProgramRunner.cs @@ -1610,7 +1610,10 @@ private static int RunMcp(string[] cmdArgs, string appVersion) continue; } - Console.Error.WriteLine($"Error: {residualArgs[i]} is not supported for mcp."); + if (residualArgs[i] == "--json") + Console.Error.WriteLine("Error: --json is not supported for mcp; MCP already speaks JSON-RPC over the selected transport."); + else + Console.Error.WriteLine($"Error: {residualArgs[i]} is not supported for mcp."); Console.Error.WriteLine("Hint: use `--db ` to point at a specific index, `--transport stdio|http` to pick a transport, `--http-listen host:port` for HTTP, or `--audit-log ` to enable per-call auditing."); PrintMcpUsage(); return CommandExitCodes.UsageError; @@ -1805,6 +1808,7 @@ private static string FormatLogValue(string? value) private static void PrintMcpUsage() { Console.Error.WriteLine("Usage: cdidx mcp [--db ] [--transport stdio|http] [--http-listen ] [--audit-log ] [--audit-log-include-values] [--audit-log-max-bytes ] [--suggestion-dedup-threshold <0..1>]"); + Console.Error.WriteLine("Note: --json is not supported; MCP requests and responses are JSON-RPC over the selected transport."); } internal static bool TryConsumeSuggestionDedupThresholdFlag(ref string[] args, out string error) @@ -2268,6 +2272,13 @@ private static int RunCompletions(string[] cmdArgs, string commandName = "--comp "rerun with one of `bash`, `zsh`, `fish`, or `powershell`.", usage); + if (cmdArgs[0] == "--json") + return CommandErrorWriter.Write( + "--json is not supported for completions.", + CommandExitCodes.UsageError, + "rerun with one of `bash`, `zsh`, `fish`, or `powershell`; completions output is already a shell script.", + usage); + if (cmdArgs[0].StartsWith("-", StringComparison.Ordinal)) return CommandErrorWriter.Write( $"{commandName} requires a shell value, got option-like token '{cmdArgs[0]}'.", diff --git a/tests/CodeIndex.Tests/ProgramCliTests.cs b/tests/CodeIndex.Tests/ProgramCliTests.cs index 867497435f..df1d8dfe4d 100644 --- a/tests/CodeIndex.Tests/ProgramCliTests.cs +++ b/tests/CodeIndex.Tests/ProgramCliTests.cs @@ -37,7 +37,7 @@ public void Mcp_UnsupportedOptionReturnUsageError() var (exitCode, _, stderr) = RunCliInSubprocess(["mcp", "--json"]); Assert.Equal(1, exitCode); - Assert.Contains("Error: --json is not supported for mcp.", stderr); + Assert.Contains("Error: --json is not supported for mcp; MCP already speaks JSON-RPC", stderr); Assert.Contains("Usage: cdidx mcp [--db ]", stderr); Assert.DoesNotContain("Warning: unknown option", stderr); } @@ -266,7 +266,7 @@ public void Completions_OptionLikeShellTokenReturnsUsageError() Assert.Equal(1, exitCode); Assert.Equal(string.Empty, stdout); - Assert.Contains("requires a shell value, got option-like token '--json'", stderr); + Assert.Contains("--json is not supported for completions", stderr); Assert.Contains("powershell", stderr); Assert.Contains("Usage: cdidx --completions ", stderr); Assert.DoesNotContain("Unknown shell", stderr); @@ -294,6 +294,7 @@ public void Completions_OptionLikeShellTokenReturnsUsageError() [InlineData("export", "cdidx export ")] [InlineData("import", "cdidx import ")] [InlineData("doctor", "cdidx doctor")] + [InlineData("mcp", "cdidx mcp")] [InlineData("completions", "cdidx completions ")] [InlineData("license", "cdidx license")] public void SubcommandHelp_PrintsCommandSpecificUsage(string command, string expectedUsage) @@ -305,6 +306,15 @@ public void SubcommandHelp_PrintsCommandSpecificUsage(string command, string exp Assert.Contains("Usage:", stdout); Assert.Contains(expectedUsage, stdout); Assert.Contains("Run `cdidx --help`", stdout); + if (command is "mcp" or "completions") + { + Assert.Contains("Notes:", stdout); + Assert.Contains("--json is not supported", stdout); + } + else + { + Assert.DoesNotContain("Notes:", stdout); + } Assert.DoesNotContain("Commands:", stdout); Assert.DoesNotContain("Index and update options:", stdout); Assert.DoesNotContain("██████╗", stdout); @@ -486,6 +496,20 @@ public void CompletionsCommand_ErrorsUseCommandUsage(params string[] args) Assert.Equal(string.Empty, stdout); Assert.Contains("Usage: cdidx completions ", stderr); Assert.DoesNotContain("Usage: cdidx --completions ", stderr); + if (args is ["completions", "--json"]) + Assert.Contains("--json is not supported for completions", stderr); + } + + [Fact] + public void Mcp_JsonFlagReturnsExplicitUnsupportedError() + { + var (exitCode, stdout, stderr) = RunCliInSubprocess(["mcp", "--json"]); + + Assert.Equal(1, exitCode); + Assert.Equal(string.Empty, stdout); + Assert.Contains("--json is not supported for mcp", stderr); + Assert.Contains("Usage: cdidx mcp", stderr); + Assert.Contains("Note: --json is not supported", stderr); } [Fact]