From 51b6274270ec6489ae3fb24cc2204dbfa29fcb7e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:35:05 +0000 Subject: [PATCH 1/4] Initial plan From 78fd9181a204e77a50b758dab831cd895c02178a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:41:07 +0000 Subject: [PATCH 2/4] Add workflow name validation to MCP logs tool - Add validateWorkflowName() function in mcp_server.go - Validate workflow name before executing logs command - Return structured MCP error with suggestions on invalid workflow - Add unit test TestMCPValidateWorkflowName - Import sliceutil package for workflow name checking Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/mcp_server.go | 57 +++++++++++++++++++ .../mcp_server_workflow_validation_test.go | 51 +++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 pkg/cli/mcp_server_workflow_validation_test.go diff --git a/pkg/cli/mcp_server.go b/pkg/cli/mcp_server.go index d1760f49e95..5975f32d741 100644 --- a/pkg/cli/mcp_server.go +++ b/pkg/cli/mcp_server.go @@ -14,6 +14,7 @@ import ( "github.com/github/gh-aw/pkg/console" "github.com/github/gh-aw/pkg/logger" + "github.com/github/gh-aw/pkg/sliceutil" "github.com/github/gh-aw/pkg/workflow" "github.com/modelcontextprotocol/go-sdk/jsonrpc" "github.com/modelcontextprotocol/go-sdk/mcp" @@ -162,6 +163,49 @@ func hasWriteAccess(permission string) bool { } } +// validateWorkflowName validates that a workflow name exists. +// Returns nil if the workflow exists, or an error with suggestions if not. +// Empty workflow names are considered valid (means all workflows). +func validateWorkflowName(workflowName string) error { + // Empty workflow name means "all workflows" - this is valid + if workflowName == "" { + return nil + } + + mcpLog.Printf("Validating workflow name: %s", workflowName) + + // Try to resolve as workflow ID first + resolvedName, err := workflow.ResolveWorkflowName(workflowName) + if err == nil { + mcpLog.Printf("Workflow name resolved successfully: %s -> %s", workflowName, resolvedName) + return nil + } + + // Check if it's a valid GitHub Actions workflow name + agenticWorkflowNames, nameErr := getAgenticWorkflowNames(false) + if nameErr == nil && sliceutil.Contains(agenticWorkflowNames, workflowName) { + mcpLog.Printf("Workflow name is valid GitHub Actions workflow name: %s", workflowName) + return nil + } + + // Workflow not found - build error with suggestions + mcpLog.Printf("Workflow name not found: %s", workflowName) + + suggestions := []string{ + "Run 'gh aw status' to see all available workflows", + "Check for typos in the workflow name", + "Use the workflow ID (e.g., 'test-claude') or GitHub Actions workflow name (e.g., 'Test Claude')", + } + + // Add fuzzy match suggestions + similarNames := suggestWorkflowNames(workflowName) + if len(similarNames) > 0 { + suggestions = append([]string{fmt.Sprintf("Did you mean: %s?", strings.Join(similarNames, ", "))}, suggestions...) + } + + return fmt.Errorf("workflow '%s' not found. %s", workflowName, strings.Join(suggestions, " ")) +} + // NewMCPServerCommand creates the mcp-server command func NewMCPServerCommand() *cobra.Command { var port int @@ -718,6 +762,19 @@ return a schema description instead of the full output. Adjust the 'max_tokens' } } + // Validate workflow name before executing command + if err := validateWorkflowName(args.WorkflowName); err != nil { + mcpLog.Printf("Workflow name validation failed: %v", err) + return nil, nil, &jsonrpc.Error{ + Code: jsonrpc.CodeInvalidParams, + Message: err.Error(), + Data: mcpErrorData(map[string]any{ + "workflow_name": args.WorkflowName, + "error_type": "workflow_not_found", + }), + } + } + // Build command arguments // Force output directory to /tmp/gh-aw/aw-mcp/logs for MCP server cmdArgs := []string{"logs", "-o", "/tmp/gh-aw/aw-mcp/logs"} diff --git a/pkg/cli/mcp_server_workflow_validation_test.go b/pkg/cli/mcp_server_workflow_validation_test.go new file mode 100644 index 00000000000..0f6290147d6 --- /dev/null +++ b/pkg/cli/mcp_server_workflow_validation_test.go @@ -0,0 +1,51 @@ +//go:build !integration + +package cli + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestMCPValidateWorkflowName(t *testing.T) { + tests := []struct { + name string + workflowName string + shouldSucceed bool + errorContains string + }{ + { + name: "empty workflow name is valid (all workflows)", + workflowName: "", + shouldSucceed: true, + }, + { + name: "non-existent workflow returns error", + workflowName: "nonexistent-workflow-xyz-12345", + shouldSucceed: false, + errorContains: "workflow 'nonexistent-workflow-xyz-12345' not found", + }, + { + name: "error includes suggestions", + workflowName: "invalid-name", + shouldSucceed: false, + errorContains: "Run 'gh aw status' to see all available workflows", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := validateWorkflowName(tt.workflowName) + + if tt.shouldSucceed { + assert.NoError(t, err, "Validation should succeed for workflow: %s", tt.workflowName) + } else { + assert.Error(t, err, "Validation should fail for workflow: %s", tt.workflowName) + if tt.errorContains != "" { + assert.Contains(t, err.Error(), tt.errorContains, "Error message should contain expected text") + } + } + }) + } +} From d20a5d5a70f8243d15678072609e6b1345c28575 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 18:45:02 +0000 Subject: [PATCH 3/4] Add test case for fuzzy match suggestions in workflow validation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/mcp_server_workflow_validation_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pkg/cli/mcp_server_workflow_validation_test.go b/pkg/cli/mcp_server_workflow_validation_test.go index 0f6290147d6..56932b37af7 100644 --- a/pkg/cli/mcp_server_workflow_validation_test.go +++ b/pkg/cli/mcp_server_workflow_validation_test.go @@ -32,6 +32,12 @@ func TestMCPValidateWorkflowName(t *testing.T) { shouldSucceed: false, errorContains: "Run 'gh aw status' to see all available workflows", }, + { + name: "error includes fuzzy matched suggestions for similar names", + workflowName: "brave-test", // Similar to "brave" workflow + shouldSucceed: false, + errorContains: "workflow 'brave-test' not found", + }, } for _, tt := range tests { From 78ac30b1abf58ef7b3057411db504745e71dbd19 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 12 Feb 2026 19:00:46 +0000 Subject: [PATCH 4/4] Update error message to suggest status tool instead of CLI command Change suggestion from "Run 'gh aw status'" to "Use the 'status' tool" to reference the MCP status tool available in the server. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/cli/mcp_server.go | 2 +- pkg/cli/mcp_server_workflow_validation_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/cli/mcp_server.go b/pkg/cli/mcp_server.go index 5975f32d741..19371793ec3 100644 --- a/pkg/cli/mcp_server.go +++ b/pkg/cli/mcp_server.go @@ -192,7 +192,7 @@ func validateWorkflowName(workflowName string) error { mcpLog.Printf("Workflow name not found: %s", workflowName) suggestions := []string{ - "Run 'gh aw status' to see all available workflows", + "Use the 'status' tool to see all available workflows", "Check for typos in the workflow name", "Use the workflow ID (e.g., 'test-claude') or GitHub Actions workflow name (e.g., 'Test Claude')", } diff --git a/pkg/cli/mcp_server_workflow_validation_test.go b/pkg/cli/mcp_server_workflow_validation_test.go index 56932b37af7..c26051f1324 100644 --- a/pkg/cli/mcp_server_workflow_validation_test.go +++ b/pkg/cli/mcp_server_workflow_validation_test.go @@ -30,7 +30,7 @@ func TestMCPValidateWorkflowName(t *testing.T) { name: "error includes suggestions", workflowName: "invalid-name", shouldSucceed: false, - errorContains: "Run 'gh aw status' to see all available workflows", + errorContains: "Use the 'status' tool to see all available workflows", }, { name: "error includes fuzzy matched suggestions for similar names",