diff --git a/cmd/gh-aw/main.go b/cmd/gh-aw/main.go index 9f9f6e5710..f46a5323d6 100644 --- a/cmd/gh-aw/main.go +++ b/cmd/gh-aw/main.go @@ -373,7 +373,7 @@ func init() { rootCmd.AddCommand(enableCmd) rootCmd.AddCommand(disableCmd) rootCmd.AddCommand(cli.NewLogsCommand()) - rootCmd.AddCommand(cli.NewMCPInspectCommand()) + rootCmd.AddCommand(cli.NewMCPCommand()) rootCmd.AddCommand(versionCmd) } diff --git a/cmd/gh-aw/main_entry_test.go b/cmd/gh-aw/main_entry_test.go index 666a5e6e6d..83177d3379 100644 --- a/cmd/gh-aw/main_entry_test.go +++ b/cmd/gh-aw/main_entry_test.go @@ -309,7 +309,7 @@ func TestCommandLineIntegration(t *testing.T) { t.Run("command structure validation", func(t *testing.T) { // Test that essential commands are present - expectedCommands := []string{"add", "compile", "list", "remove", "status", "run", "version"} + expectedCommands := []string{"add", "compile", "list", "remove", "status", "run", "version", "mcp"} cmdMap := make(map[string]bool) for _, cmd := range rootCmd.Commands() { @@ -341,6 +341,61 @@ func TestCommandLineIntegration(t *testing.T) { }) } +func TestMCPCommand(t *testing.T) { + // Test the new MCP command structure + t.Run("mcp command is available", func(t *testing.T) { + found := false + for _, cmd := range rootCmd.Commands() { + if cmd.Name() == "mcp" { + found = true + break + } + } + if !found { + t.Error("mcp command should be available") + } + }) + + t.Run("mcp command has inspect subcommand", func(t *testing.T) { + mcpCmd, _, _ := rootCmd.Find([]string{"mcp"}) + if mcpCmd == nil { + t.Fatal("mcp command not found") + } + + found := false + for _, subCmd := range mcpCmd.Commands() { + if subCmd.Name() == "inspect" { + found = true + break + } + } + if !found { + t.Error("mcp inspect subcommand should be available") + } + }) + + t.Run("mcp inspect command help", func(t *testing.T) { + // Test help for nested command + mcpCmd, _, _ := rootCmd.Find([]string{"mcp"}) + if mcpCmd == nil { + t.Fatal("mcp command not found") + } + + inspectCmd, _, _ := mcpCmd.Find([]string{"inspect"}) + if inspectCmd == nil { + t.Fatal("mcp inspect command not found") + } + + // Basic validation that command structure is valid + if inspectCmd.Use == "" { + t.Error("mcp inspect command should have usage text") + } + if inspectCmd.Short == "" { + t.Error("mcp inspect command should have short description") + } + }) +} + func TestCommandErrorHandling(t *testing.T) { t.Run("invalid command produces error", func(t *testing.T) { // Capture stderr diff --git a/docs/src/content/docs/guides/mcps.md b/docs/src/content/docs/guides/mcps.md index 56f25026f9..f6ce1be36a 100644 --- a/docs/src/content/docs/guides/mcps.md +++ b/docs/src/content/docs/guides/mcps.md @@ -41,7 +41,7 @@ tools: > [!TIP] > You can inspect test your MCP configuration by running
-> `gh aw mcp-inspect ` +> `gh aw mcp inspect ` ### Engine Compatibility @@ -236,23 +236,23 @@ The compiler enforces these network permission rules: ### MCP Server Inspection -Use the `mcp-inspect` command to analyze and troubleshoot MCP configurations: +Use the `mcp inspect` command to analyze and troubleshoot MCP configurations: ```bash # List all workflows with MCP servers configured -gh aw mcp-inspect +gh aw mcp inspect # Inspect all MCP servers in a specific workflow -gh aw mcp-inspect my-workflow +gh aw mcp inspect my-workflow # Inspect a specific MCP server in a workflow -gh aw mcp-inspect my-workflow --server trello-server +gh aw mcp inspect my-workflow --server trello-server # Enable verbose output for debugging connection issues -gh aw mcp-inspect my-workflow --verbose +gh aw mcp inspect my-workflow --verbose # Launch official MCP inspector web interface -gh aw mcp-inspect my-workflow --inspector +gh aw mcp inspect my-workflow --inspector ### Common Issues and Solutions @@ -278,7 +278,7 @@ Error: Tool 'my_tool' not found **Solutions**: 1. Add tool to `allowed` list -2. Check tool name spelling (use `gh aw mcp-inspect` to see available tools) +2. Check tool name spelling (use `gh aw mcp inspect` to see available tools) 3. Verify MCP server is running correctly ## Related Documentation diff --git a/docs/src/content/docs/tools/cli.md b/docs/src/content/docs/tools/cli.md index 0b6ef763ed..e853f88be2 100644 --- a/docs/src/content/docs/tools/cli.md +++ b/docs/src/content/docs/tools/cli.md @@ -189,28 +189,28 @@ gh aw logs --format json -o ./exports/ ## 🔍 MCP Server Inspection -The `mcp-inspect` command allows you to analyze and troubleshoot Model Context Protocol (MCP) servers configured in your workflows. +The `mcp inspect` command allows you to analyze and troubleshoot Model Context Protocol (MCP) servers configured in your workflows. > **📘 Complete MCP Guide**: For comprehensive MCP setup, configuration examples, and troubleshooting, see the [MCPs](/gh-aw/guides/mcps/). ```bash # List all workflows that contain MCP server configurations -gh aw mcp-inspect +gh aw mcp inspect # Inspect all MCP servers in a specific workflow -gh aw mcp-inspect workflow-name +gh aw mcp inspect workflow-name # Filter inspection to specific servers by name -gh aw mcp-inspect workflow-name --server server-name +gh aw mcp inspect workflow-name --server server-name # Show detailed information about a specific tool (requires --server) -gh aw mcp-inspect workflow-name --server server-name --tool tool-name +gh aw mcp inspect workflow-name --server server-name --tool tool-name # Enable verbose output with connection details -gh aw mcp-inspect workflow-name --verbose +gh aw mcp inspect workflow-name --verbose # Launch the official @modelcontextprotocol/inspector web interface -gh aw mcp-inspect workflow-name --inspector +gh aw mcp inspect workflow-name --inspector ``` **Key Features:** diff --git a/pkg/cli/mcp.go b/pkg/cli/mcp.go new file mode 100644 index 0000000000..e33dfa7233 --- /dev/null +++ b/pkg/cli/mcp.go @@ -0,0 +1,29 @@ +package cli + +import ( + "github.com/spf13/cobra" +) + +// NewMCPCommand creates the main mcp command with subcommands +func NewMCPCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "mcp", + Short: "Model Context Protocol (MCP) server management and inspection", + Long: `Model Context Protocol (MCP) server management and inspection. + +MCP enables AI workflows to connect to external tools and data sources through +standardized servers. This command provides tools for inspecting and managing +MCP server configurations in your agentic workflows. + +Available subcommands: + inspect - Inspect MCP servers and list available tools, resources, and roots`, + Run: func(cmd *cobra.Command, args []string) { + _ = cmd.Help() + }, + } + + // Add subcommands + cmd.AddCommand(NewMCPInspectSubcommand()) + + return cmd +} diff --git a/pkg/cli/mcp_inspect.go b/pkg/cli/mcp_inspect.go index 0471795e92..cedcdfc645 100644 --- a/pkg/cli/mcp_inspect.go +++ b/pkg/cli/mcp_inspect.go @@ -184,7 +184,7 @@ func listWorkflowsWithMCP(workflowsDir string, verbose bool) error { for _, workflow := range workflowsWithMCP { fmt.Printf(" • %s\n", workflow) } - fmt.Printf("\nRun 'gh aw mcp-inspect ' to inspect MCP servers in a specific workflow.\n") + fmt.Printf("\nRun 'gh aw mcp inspect ' to inspect MCP servers in a specific workflow.\n") return nil } @@ -452,3 +452,73 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e return cmd.Run() } + +// NewMCPInspectSubcommand creates the mcp inspect subcommand +// This is the former mcp-inspect command now nested under mcp +func NewMCPInspectSubcommand() *cobra.Command { + var serverFilter string + var toolFilter string + var spawnInspector bool + + cmd := &cobra.Command{ + Use: "inspect [workflow-file]", + Short: "Inspect MCP servers and list available tools, resources, and roots", + Long: `Inspect MCP servers used by a workflow and display available tools, resources, and roots. + +This command starts each MCP server configured in the workflow, queries its capabilities, +and displays the results in a formatted table. It supports stdio, Docker, and HTTP MCP servers. + +Examples: + gh aw mcp inspect # List workflows with MCP servers + gh aw mcp inspect weekly-research # Inspect MCP servers in weekly-research.md + gh aw mcp inspect weekly-research --server github --tool create_issue # Show details for a specific tool + gh aw mcp inspect weekly-research -v # Verbose output with detailed connection info + gh aw mcp inspect weekly-research --inspector # Launch @modelcontextprotocol/inspector + +The command will: +- Parse the workflow file to extract MCP server configurations +- Start each MCP server (stdio, docker, http) +- Query available tools, resources, and roots +- Validate required secrets are available +- Display results in formatted tables with error details`, + Args: cobra.MaximumNArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + var workflowFile string + if len(args) > 0 { + workflowFile = args[0] + } + + verbose, _ := cmd.Flags().GetBool("verbose") + // Check for verbose flag from parent commands (root and mcp) + if cmd.Parent() != nil { + if parentVerbose, _ := cmd.Parent().PersistentFlags().GetBool("verbose"); parentVerbose { + verbose = true + } + if cmd.Parent().Parent() != nil { + if rootVerbose, _ := cmd.Parent().Parent().PersistentFlags().GetBool("verbose"); rootVerbose { + verbose = true + } + } + } + + // Validate that tool flag requires server flag + if toolFilter != "" && serverFilter == "" { + return fmt.Errorf("--tool flag requires --server flag to be specified") + } + + // Handle spawn inspector flag + if spawnInspector { + return spawnMCPInspector(workflowFile, serverFilter, verbose) + } + + return InspectWorkflowMCP(workflowFile, serverFilter, toolFilter, verbose) + }, + } + + cmd.Flags().StringVar(&serverFilter, "server", "", "Filter to inspect only the specified MCP server") + cmd.Flags().StringVar(&toolFilter, "tool", "", "Show detailed information about a specific tool (requires --server)") + cmd.Flags().BoolP("verbose", "v", false, "Enable verbose output with detailed connection information") + cmd.Flags().BoolVar(&spawnInspector, "inspector", false, "Launch the official @modelcontextprotocol/inspector tool") + + return cmd +}