From e2f92529ff990ad384e4f98dbcd166710ece1ab4 Mon Sep 17 00:00:00 2001 From: Rene Leonhardt <65483435+reneleonhardt@users.noreply.github.com> Date: Wed, 22 Jul 2026 11:55:38 +0200 Subject: [PATCH] fix(mcp): unify executable entrypoints Co-Authored-By: GPT-5.6 Sol --- cmd/codemap-mcp/main.go | 9 +++------ cmd/mcp.go | 22 ++++++++++++++++++++++ cmd/mcp_test.go | 17 +++++++++++++++++ main.go | 7 ++----- mcp_fallback_entrypoints_test.go | 6 ++++++ 5 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 cmd/mcp.go create mode 100644 cmd/mcp_test.go diff --git a/cmd/codemap-mcp/main.go b/cmd/codemap-mcp/main.go index db3d5da..73907df 100644 --- a/cmd/codemap-mcp/main.go +++ b/cmd/codemap-mcp/main.go @@ -1,16 +1,13 @@ package main import ( - "context" - "fmt" "os" - codemapmcp "codemap/mcp" + "codemap/cmd" ) func main() { - if err := codemapmcp.Run(context.Background()); err != nil { - fmt.Fprintf(os.Stderr, "MCP server error: %v\n", err) - os.Exit(1) + if code := cmd.RunMCP(); code != 0 { + os.Exit(code) } } diff --git a/cmd/mcp.go b/cmd/mcp.go new file mode 100644 index 0000000..61793f9 --- /dev/null +++ b/cmd/mcp.go @@ -0,0 +1,22 @@ +package cmd + +import ( + "context" + "fmt" + "os" + + codemapmcp "codemap/mcp" +) + +// RunMCP runs the shared stdio server and returns its process exit status. +func RunMCP() int { + return runMCP(codemapmcp.Run) +} + +func runMCP(runner func(context.Context) error) int { + if err := runner(context.Background()); err != nil { + fmt.Fprintf(os.Stderr, "MCP server error: %v\n", err) + return 1 + } + return 0 +} diff --git a/cmd/mcp_test.go b/cmd/mcp_test.go new file mode 100644 index 0000000..2a31c16 --- /dev/null +++ b/cmd/mcp_test.go @@ -0,0 +1,17 @@ +package cmd + +import ( + "context" + "errors" + "testing" +) + +func TestRunMCPReturnsServerStatus(t *testing.T) { + if code := runMCP(func(context.Context) error { return nil }); code != 0 { + t.Fatalf("RunMCP success exit code = %d, want 0", code) + } + + if code := runMCP(func(context.Context) error { return errors.New("boom") }); code != 1 { + t.Fatalf("RunMCP failure exit code = %d, want 1", code) + } +} diff --git a/main.go b/main.go index 62749b9..cbe76f3 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "context" "encoding/json" "errors" "flag" @@ -18,7 +17,6 @@ import ( "codemap/config" "codemap/handoff" "codemap/limits" - codemapmcp "codemap/mcp" "codemap/render" "codemap/scanner" "codemap/watch" @@ -108,9 +106,8 @@ func main() { // Handle "mcp" subcommand before global flag parsing if len(os.Args) >= 2 && os.Args[1] == "mcp" { - if err := codemapmcp.Run(context.Background()); err != nil { - fmt.Fprintf(os.Stderr, "MCP server error: %v\n", err) - os.Exit(1) + if code := cmd.RunMCP(); code != 0 { + os.Exit(code) } return } diff --git a/mcp_fallback_entrypoints_test.go b/mcp_fallback_entrypoints_test.go index 0aa6080..418236d 100644 --- a/mcp_fallback_entrypoints_test.go +++ b/mcp_fallback_entrypoints_test.go @@ -35,6 +35,12 @@ func TestMCPEntrypointsMatchConfigFallback(t *testing.T) { if !strings.Contains(cliResult, "Matches excluded by `only` config:") { t.Fatalf("fallback guidance missing: %s", cliResult) } + + cliResult = probeFallbackTestBinary(t, cli, []string{"mcp", "ignored"}, root) + standaloneResult = probeFallbackTestBinary(t, standalone, []string{"ignored"}, root) + if cliResult != standaloneResult { + t.Fatalf("legacy argument handling differs:\ncodemap mcp: %s\ncodemap-mcp: %s", cliResult, standaloneResult) + } } func buildFallbackTestBinary(t *testing.T, output, pkg string) string {