From 3c5931354db3c1de0cdd3c3769545e0f9e4c638b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 21:53:28 +0000 Subject: [PATCH 1/3] Initial plan From 1adbafa737fb4e6b75e56c159b30559a219d5093 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:25:29 +0000 Subject: [PATCH 2/3] chore: outline plan for resolving type naming conflicts Agent-Logs-Url: https://github.com/github/gh-aw/sessions/4ebefa13-7ba9-44a0-b8b7-7bb6839951e7 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-claude.lock.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index c9cc51bc704..3f9f5675126 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -1066,13 +1066,19 @@ jobs: "maxLength": 256 }, "reviewers": { - "required": true, "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 39 + }, + "team_reviewers": { + "type": "array", + "itemType": "string", + "itemSanitize": true, + "itemMaxLength": 100 } - } + }, + "customValidation": "requiresOneOf:reviewers,team_reviewers" }, "close_pull_request": { "defaultMax": 1, From 65908c75af864d183ca66f60f3747288cdca3825 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:48:39 +0000 Subject: [PATCH 3/3] refactor: resolve critical cross-package type naming conflicts Agent-Logs-Url: https://github.com/github/gh-aw/sessions/4ebefa13-7ba9-44a0-b8b7-7bb6839951e7 Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/smoke-claude.lock.yml | 10 +--- pkg/cli/audit_expanded.go | 10 ++-- pkg/cli/audit_expanded_test.go | 2 +- pkg/cli/audit_report.go | 2 +- pkg/cli/audit_report_render_overview.go | 2 +- pkg/cli/mcp_inspect_headers_test.go | 6 +-- pkg/cli/mcp_inspect_inspector.go | 4 +- pkg/cli/mcp_inspect_list.go | 4 +- pkg/cli/mcp_inspect_mcp.go | 10 ++-- pkg/cli/mcp_inspect_mcp_scripts_server.go | 4 +- pkg/cli/mcp_inspect_test.go | 44 +++++++-------- pkg/cli/mcp_list.go | 4 +- pkg/cli/mcp_list_test.go | 10 ++-- pkg/cli/mcp_list_tools.go | 4 +- pkg/cli/mcp_list_tools_test.go | 8 +-- pkg/cli/mcp_tool_table_test.go | 8 +-- pkg/cli/mcp_validation.go | 2 +- pkg/cli/mcp_workflow_loader.go | 4 +- pkg/cli/mcp_workflow_scanner.go | 2 +- pkg/cli/secrets.go | 2 +- pkg/cli/secrets_test.go | 12 ++--- pkg/cli/trial_command.go | 2 +- pkg/cli/trial_types.go | 6 +-- pkg/parser/README.md | 6 +-- pkg/parser/mcp.go | 36 +++++++------ pkg/parser/mcp_test.go | 66 +++++++++++------------ pkg/workflow/README.md | 2 +- pkg/workflow/compiler_types.go | 8 +-- pkg/workflow/mcp_config_custom.go | 4 +- pkg/workflow/mcp_json_test.go | 8 +-- 30 files changed, 144 insertions(+), 148 deletions(-) diff --git a/.github/workflows/smoke-claude.lock.yml b/.github/workflows/smoke-claude.lock.yml index 3f9f5675126..c9cc51bc704 100644 --- a/.github/workflows/smoke-claude.lock.yml +++ b/.github/workflows/smoke-claude.lock.yml @@ -1066,19 +1066,13 @@ jobs: "maxLength": 256 }, "reviewers": { + "required": true, "type": "array", "itemType": "string", "itemSanitize": true, "itemMaxLength": 39 - }, - "team_reviewers": { - "type": "array", - "itemType": "string", - "itemSanitize": true, - "itemMaxLength": 100 } - }, - "customValidation": "requiresOneOf:reviewers,team_reviewers" + } }, "close_pull_request": { "defaultMax": 1, diff --git a/pkg/cli/audit_expanded.go b/pkg/cli/audit_expanded.go index 1af75754b63..cca6622baaf 100644 --- a/pkg/cli/audit_expanded.go +++ b/pkg/cli/audit_expanded.go @@ -15,8 +15,8 @@ import ( var auditExpandedLog = logger.New("cli:audit_expanded") -// EngineConfig represents the engine configuration extracted from aw_info.json -type EngineConfig struct { +// AuditEngineConfig represents the engine configuration extracted from aw_info.json +type AuditEngineConfig struct { EngineID string `json:"engine_id" console:"header:Engine ID"` EngineName string `json:"engine_name,omitempty" console:"header:Engine Name,omitempty"` Model string `json:"model,omitempty" console:"header:Model,omitempty"` @@ -110,8 +110,8 @@ func findAwInfoPath(logsPath string) string { return "" } -// extractEngineConfig parses aw_info.json and returns an EngineConfig -func extractEngineConfig(logsPath string) *EngineConfig { +// extractEngineConfig parses aw_info.json and returns an AuditEngineConfig +func extractEngineConfig(logsPath string) *AuditEngineConfig { if logsPath == "" { return nil } @@ -127,7 +127,7 @@ func extractEngineConfig(logsPath string) *EngineConfig { return nil } - config := &EngineConfig{ + config := &AuditEngineConfig{ EngineID: awInfo.EngineID, EngineName: awInfo.EngineName, Model: awInfo.Model, diff --git a/pkg/cli/audit_expanded_test.go b/pkg/cli/audit_expanded_test.go index e420ef9cb63..230a3a2c96a 100644 --- a/pkg/cli/audit_expanded_test.go +++ b/pkg/cli/audit_expanded_test.go @@ -557,7 +557,7 @@ func TestBuildAuditDataWithExpandedSections(t *testing.T) { auditData := buildAuditData(processedRun, metrics, mcpToolUsage) // Verify new expanded sections are populated - t.Run("EngineConfig", func(t *testing.T) { + t.Run("AuditEngineConfig", func(t *testing.T) { require.NotNil(t, auditData.EngineConfig, "Engine config should be populated") assert.Equal(t, "copilot", auditData.EngineConfig.EngineID, "Engine ID should match") assert.Equal(t, "gpt-4", auditData.EngineConfig.Model, "Model should match") diff --git a/pkg/cli/audit_report.go b/pkg/cli/audit_report.go index fe6f3760cf7..4b458291b73 100644 --- a/pkg/cli/audit_report.go +++ b/pkg/cli/audit_report.go @@ -30,7 +30,7 @@ type AuditData struct { Recommendations []Recommendation `json:"recommendations,omitempty"` ObservabilityInsights []ObservabilityInsight `json:"observability_insights,omitempty"` PerformanceMetrics *PerformanceMetrics `json:"performance_metrics,omitempty"` - EngineConfig *EngineConfig `json:"engine_config,omitempty"` + EngineConfig *AuditEngineConfig `json:"engine_config,omitempty"` PromptAnalysis *PromptAnalysis `json:"prompt_analysis,omitempty"` SessionAnalysis *SessionAnalysis `json:"session_analysis,omitempty"` SafeOutputSummary *SafeOutputSummary `json:"safe_output_summary,omitempty"` diff --git a/pkg/cli/audit_report_render_overview.go b/pkg/cli/audit_report_render_overview.go index a76078cfe92..07254aedb76 100644 --- a/pkg/cli/audit_report_render_overview.go +++ b/pkg/cli/audit_report_render_overview.go @@ -122,7 +122,7 @@ func renderPerformanceMetrics(metrics *PerformanceMetrics) { } // renderEngineConfig renders engine configuration details -func renderEngineConfig(config *EngineConfig) { +func renderEngineConfig(config *AuditEngineConfig) { if config == nil { return } diff --git a/pkg/cli/mcp_inspect_headers_test.go b/pkg/cli/mcp_inspect_headers_test.go index 72a1e47f1c0..b6aab7be1c7 100644 --- a/pkg/cli/mcp_inspect_headers_test.go +++ b/pkg/cli/mcp_inspect_headers_test.go @@ -129,7 +129,7 @@ func TestConnectHTTPMCPServer_WithHeaders(t *testing.T) { })) defer server.Close() - config := parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config := parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: server.URL, Headers: map[string]string{ "Authorization": "Bearer test-token-123", @@ -199,7 +199,7 @@ func TestConnectHTTPMCPServer_NoHeaders(t *testing.T) { })) defer server.Close() - config := parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config := parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: server.URL, Headers: map[string]string{}}, Name: "test-http-server-no-headers", @@ -238,7 +238,7 @@ func TestConnectHTTPMCPServer_NilHeaders(t *testing.T) { })) defer server.Close() - config := parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config := parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: server.URL, Headers: nil}, Name: "test-http-server-nil-headers", diff --git a/pkg/cli/mcp_inspect_inspector.go b/pkg/cli/mcp_inspect_inspector.go index 406fa03da35..bdc02ff6fd8 100644 --- a/pkg/cli/mcp_inspect_inspector.go +++ b/pkg/cli/mcp_inspect_inspector.go @@ -26,7 +26,7 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e return fmt.Errorf("npx not found. Please install Node.js and npm to use the MCP inspector: %w", err) } - var mcpConfigs []parser.MCPServerConfig + var mcpConfigs []parser.RegistryMCPServerConfig var serverProcesses []*exec.Cmd var wg sync.WaitGroup @@ -78,7 +78,7 @@ func spawnMCPInspector(workflowFile string, serverFilter string, verbose bool) e fmt.Fprintln(os.Stderr) // Start stdio MCP servers in the background - stdioServers := []parser.MCPServerConfig{} + stdioServers := []parser.RegistryMCPServerConfig{} for _, config := range mcpConfigs { if config.Type == "stdio" { stdioServers = append(stdioServers, config) diff --git a/pkg/cli/mcp_inspect_list.go b/pkg/cli/mcp_inspect_list.go index 71eb24c7a9f..102c925dc2e 100644 --- a/pkg/cli/mcp_inspect_list.go +++ b/pkg/cli/mcp_inspect_list.go @@ -15,8 +15,8 @@ var mcpInspectListLog = logger.New("cli:mcp_inspect_list") // filterOutSafeOutputs removes safe-outputs MCP servers from the list since they are // handled by the workflow compiler and not actual MCP servers that can be inspected -func filterOutSafeOutputs(configs []parser.MCPServerConfig) []parser.MCPServerConfig { - var filteredConfigs []parser.MCPServerConfig +func filterOutSafeOutputs(configs []parser.RegistryMCPServerConfig) []parser.RegistryMCPServerConfig { + var filteredConfigs []parser.RegistryMCPServerConfig for _, config := range configs { if config.Name != constants.SafeOutputsMCPServerID.String() { filteredConfigs = append(filteredConfigs, config) diff --git a/pkg/cli/mcp_inspect_mcp.go b/pkg/cli/mcp_inspect_mcp.go index 33f46a61050..ccaa6e41699 100644 --- a/pkg/cli/mcp_inspect_mcp.go +++ b/pkg/cli/mcp_inspect_mcp.go @@ -49,7 +49,7 @@ func (h *headerRoundTripper) RoundTrip(req *http.Request) (*http.Response, error } // inspectMCPServer connects to an MCP server and queries its capabilities -func inspectMCPServer(config parser.MCPServerConfig, toolFilter string, verbose bool, useActionsSecrets bool) error { +func inspectMCPServer(config parser.RegistryMCPServerConfig, toolFilter string, verbose bool, useActionsSecrets bool) error { mcpInspectServerLog.Printf("Inspecting MCP server: name=%s, type=%s", config.Name, config.Type) fmt.Fprintf(os.Stderr, "%s %s (%s)\n", console.FormatCommandMessage(config.Name), @@ -92,7 +92,7 @@ func inspectMCPServer(config parser.MCPServerConfig, toolFilter string, verbose } // buildConnectionString creates a display string for the connection details -func buildConnectionString(config parser.MCPServerConfig) string { +func buildConnectionString(config parser.RegistryMCPServerConfig) string { switch config.Type { case "stdio": if config.Container != "" { @@ -110,7 +110,7 @@ func buildConnectionString(config parser.MCPServerConfig) string { } // connectToMCPServer establishes a connection to the MCP server and queries its capabilities -func connectToMCPServer(config parser.MCPServerConfig, verbose bool) (*parser.MCPServerInfo, error) { +func connectToMCPServer(config parser.RegistryMCPServerConfig, verbose bool) (*parser.MCPServerInfo, error) { mcpInspectServerLog.Printf("Connecting to MCP server: name=%s, type=%s", config.Name, config.Type) ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() @@ -129,7 +129,7 @@ func connectToMCPServer(config parser.MCPServerConfig, verbose bool) (*parser.MC } // connectStdioMCPServer connects to a stdio-based MCP server using the Go SDK -func connectStdioMCPServer(ctx context.Context, config parser.MCPServerConfig, verbose bool) (*parser.MCPServerInfo, error) { +func connectStdioMCPServer(ctx context.Context, config parser.RegistryMCPServerConfig, verbose bool) (*parser.MCPServerInfo, error) { mcpInspectServerLog.Printf("Connecting to stdio MCP server: command=%s, args=%d", config.Command, len(config.Args)) if verbose { fmt.Fprintln(os.Stderr, console.FormatInfoMessage(fmt.Sprintf("Starting stdio MCP server: %s %s", config.Command, strings.Join(config.Args, " ")))) @@ -224,7 +224,7 @@ func connectStdioMCPServer(ctx context.Context, config parser.MCPServerConfig, v } // connectHTTPMCPServer connects to an HTTP-based MCP server using the Go SDK -func connectHTTPMCPServer(ctx context.Context, config parser.MCPServerConfig, verbose bool) (*parser.MCPServerInfo, error) { +func connectHTTPMCPServer(ctx context.Context, config parser.RegistryMCPServerConfig, verbose bool) (*parser.MCPServerInfo, error) { if verbose { fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Connecting to HTTP MCP server: "+config.URL)) } diff --git a/pkg/cli/mcp_inspect_mcp_scripts_server.go b/pkg/cli/mcp_inspect_mcp_scripts_server.go index 7dd31f0b251..d4657cd41d3 100644 --- a/pkg/cli/mcp_inspect_mcp_scripts_server.go +++ b/pkg/cli/mcp_inspect_mcp_scripts_server.go @@ -98,7 +98,7 @@ func startMCPScriptsHTTPServer(dir string, port int, verbose bool) (*exec.Cmd, e } // startMCPScriptsServer starts the mcp-scripts HTTP server and returns the MCP config -func startMCPScriptsServer(mcpScriptsConfig *workflow.MCPScriptsConfig, verbose bool) (*parser.MCPServerConfig, *exec.Cmd, string, error) { +func startMCPScriptsServer(mcpScriptsConfig *workflow.MCPScriptsConfig, verbose bool) (*parser.RegistryMCPServerConfig, *exec.Cmd, string, error) { mcpInspectLog.Printf("Starting mcp-scripts server with %d tools", len(mcpScriptsConfig.Tools)) // Check if node is available @@ -182,7 +182,7 @@ func startMCPScriptsServer(mcpScriptsConfig *workflow.MCPScriptsConfig, verbose } // Create MCP server config for the mcp-scripts server - config := &parser.MCPServerConfig{ + config := &parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "http", URL: fmt.Sprintf("http://localhost:%d", port), diff --git a/pkg/cli/mcp_inspect_test.go b/pkg/cli/mcp_inspect_test.go index b722142326d..1501f49287a 100644 --- a/pkg/cli/mcp_inspect_test.go +++ b/pkg/cli/mcp_inspect_test.go @@ -16,19 +16,19 @@ import ( func TestValidateServerSecrets(t *testing.T) { tests := []struct { name string - config parser.MCPServerConfig + config parser.RegistryMCPServerConfig envVars map[string]string expectError bool errorMsg string }{ { name: "no environment variables", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio"}, Name: "simple-tool"}, + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio"}, Name: "simple-tool"}, expectError: false, }, { name: "valid environment variable", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Env: map[string]string{ "TEST_VAR": "test_value", }}, Name: "env-tool", @@ -40,7 +40,7 @@ func TestValidateServerSecrets(t *testing.T) { }, { name: "missing environment variable", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Env: map[string]string{ "MISSING_VAR": "test_value", }}, Name: "missing-env-tool", @@ -50,7 +50,7 @@ func TestValidateServerSecrets(t *testing.T) { }, { name: "secrets reference (handled gracefully)", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Env: map[string]string{ "API_KEY": "${secrets.API_KEY}", }}, Name: "secrets-tool", @@ -59,7 +59,7 @@ func TestValidateServerSecrets(t *testing.T) { }, { name: "github remote mode requires GH_AW_GITHUB_TOKEN", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: "https://api.githubcopilot.com/mcp/", Env: map[string]string{}}, Name: "github", }, @@ -70,7 +70,7 @@ func TestValidateServerSecrets(t *testing.T) { }, { name: "github remote mode with custom token", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: "https://api.githubcopilot.com/mcp/", Env: map[string]string{ "GITHUB_TOKEN": "${{ secrets.CUSTOM_PAT }}", @@ -80,7 +80,7 @@ func TestValidateServerSecrets(t *testing.T) { }, { name: "github local mode does not require GH_AW_GITHUB_TOKEN", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Env: map[string]string{}}, Name: "github", }, expectError: false, @@ -125,7 +125,7 @@ func TestDisplayToolAllowanceHint(t *testing.T) { { name: "server with blocked tools", serverInfo: &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{ + Config: parser.RegistryMCPServerConfig{ Name: "test-server", Allowed: []string{"tool1", "tool2"}, }, @@ -150,7 +150,7 @@ func TestDisplayToolAllowanceHint(t *testing.T) { { name: "server with no allowed list (all tools allowed)", serverInfo: &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{ + Config: parser.RegistryMCPServerConfig{ Name: "open-server", Allowed: []string{}, // Empty means all allowed }, @@ -171,7 +171,7 @@ func TestDisplayToolAllowanceHint(t *testing.T) { { name: "server with all tools explicitly allowed", serverInfo: &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{ + Config: parser.RegistryMCPServerConfig{ Name: "explicit-server", Allowed: []string{"tool1", "tool2"}, }, @@ -256,7 +256,7 @@ func TestMCPInspectFiltersSafeOutputs(t *testing.T) { } // Test the filtering logic that inspect command uses - var filteredConfigs []parser.MCPServerConfig + var filteredConfigs []parser.RegistryMCPServerConfig for _, config := range configs { if config.Name != constants.SafeOutputsMCPServerID.String() { filteredConfigs = append(filteredConfigs, config) @@ -278,40 +278,40 @@ func TestMCPInspectFiltersSafeOutputs(t *testing.T) { func TestFilterOutSafeOutputs(t *testing.T) { tests := []struct { name string - input []parser.MCPServerConfig - expected []parser.MCPServerConfig + input []parser.RegistryMCPServerConfig + expected []parser.RegistryMCPServerConfig }{ { name: "empty input", - input: []parser.MCPServerConfig{}, - expected: []parser.MCPServerConfig{}, + input: []parser.RegistryMCPServerConfig{}, + expected: []parser.RegistryMCPServerConfig{}, }, { name: "only safe-outputs", - input: []parser.MCPServerConfig{ + input: []parser.RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio"}, Name: constants.SafeOutputsMCPServerID.String()}, }, - expected: []parser.MCPServerConfig{}, + expected: []parser.RegistryMCPServerConfig{}, }, { name: "mixed servers", - input: []parser.MCPServerConfig{ + input: []parser.RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio"}, Name: constants.SafeOutputsMCPServerID.String()}, {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker"}, Name: "github"}, {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker"}, Name: "playwright"}, }, - expected: []parser.MCPServerConfig{ + expected: []parser.RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker"}, Name: "github"}, {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker"}, Name: "playwright"}, }, }, { name: "no safe-outputs", - input: []parser.MCPServerConfig{ + input: []parser.RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker"}, Name: "github"}, {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio"}, Name: "custom-server"}, }, - expected: []parser.MCPServerConfig{ + expected: []parser.RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker"}, Name: "github"}, {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio"}, Name: "custom-server"}, }, diff --git a/pkg/cli/mcp_list.go b/pkg/cli/mcp_list.go index 424cf8356bd..5b9d78003da 100644 --- a/pkg/cli/mcp_list.go +++ b/pkg/cli/mcp_list.go @@ -145,7 +145,7 @@ func listWorkflowsWithMCPServers(workflowsDir string, verbose bool) error { var totalMCPCount int for _, result := range results { - serverNames := sliceutil.Map(result.MCPConfigs, func(config parser.MCPServerConfig) string { return config.Name }) + serverNames := sliceutil.Map(result.MCPConfigs, func(config parser.RegistryMCPServerConfig) string { return config.Name }) workflowData = append(workflowData, struct { name string @@ -258,7 +258,7 @@ func showInteractiveMCPWorkflowSelection(workflows []struct { } // determineConfigStatus checks if an MCP server configuration is valid and ready -func determineConfigStatus(config parser.MCPServerConfig) string { +func determineConfigStatus(config parser.RegistryMCPServerConfig) string { // Check if the configuration has the minimum required fields hasExecutable := config.Command != "" || config.URL != "" || config.Container != "" diff --git a/pkg/cli/mcp_list_test.go b/pkg/cli/mcp_list_test.go index 04cb572f377..f5535490c64 100644 --- a/pkg/cli/mcp_list_test.go +++ b/pkg/cli/mcp_list_test.go @@ -179,12 +179,12 @@ func TestNewMCPListSubcommand(t *testing.T) { func TestDetermineConfigStatus(t *testing.T) { tests := []struct { name string - config parser.MCPServerConfig + config parser.RegistryMCPServerConfig expected string }{ { name: "valid_stdio_config", - config: parser.MCPServerConfig{ + config: parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Command: "npx", }, @@ -193,7 +193,7 @@ func TestDetermineConfigStatus(t *testing.T) { }, { name: "valid_http_config", - config: parser.MCPServerConfig{ + config: parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ URL: "http://localhost:3000", }, @@ -202,7 +202,7 @@ func TestDetermineConfigStatus(t *testing.T) { }, { name: "valid_container_config", - config: parser.MCPServerConfig{ + config: parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Container: "docker", }, @@ -211,7 +211,7 @@ func TestDetermineConfigStatus(t *testing.T) { }, { name: "incomplete_config", - config: parser.MCPServerConfig{}, + config: parser.RegistryMCPServerConfig{}, expected: "⚠ Incomplete", }, } diff --git a/pkg/cli/mcp_list_tools.go b/pkg/cli/mcp_list_tools.go index 06005c2a9f3..57f459496b9 100644 --- a/pkg/cli/mcp_list_tools.go +++ b/pkg/cli/mcp_list_tools.go @@ -59,7 +59,7 @@ func ListToolsForMCP(workflowFile string, mcpServerName string, verbose bool) er mcpListToolsLog.Printf("Found %d MCP configs in workflow, searching for server: %s", len(mcpConfigs), mcpServerName) // Find the specific MCP server - var targetConfig *parser.MCPServerConfig + var targetConfig *parser.RegistryMCPServerConfig for _, config := range mcpConfigs { if strings.EqualFold(config.Name, mcpServerName) { targetConfig = &config @@ -74,7 +74,7 @@ func ListToolsForMCP(workflowFile string, mcpServerName string, verbose bool) er // Show available servers if len(mcpConfigs) > 0 { fmt.Fprintf(os.Stderr, "Available MCP servers: ") - serverNames := sliceutil.Map(mcpConfigs, func(config parser.MCPServerConfig) string { return config.Name }) + serverNames := sliceutil.Map(mcpConfigs, func(config parser.RegistryMCPServerConfig) string { return config.Name }) fmt.Fprintf(os.Stderr, "%s\n", strings.Join(serverNames, ", ")) } return nil diff --git a/pkg/cli/mcp_list_tools_test.go b/pkg/cli/mcp_list_tools_test.go index 55558102bae..286cac86c6b 100644 --- a/pkg/cli/mcp_list_tools_test.go +++ b/pkg/cli/mcp_list_tools_test.go @@ -233,7 +233,7 @@ func TestDisplayToolsList(t *testing.T) { // Create mock data using parser types // Create a mock MCPServerInfo with sample tools mockInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + Config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "test"}, Name: "test-server", Allowed: []string{"tool1", "tool3"}, // Only tool1 and tool3 are allowed @@ -256,7 +256,7 @@ func TestDisplayToolsList(t *testing.T) { t.Run("empty_tools_list", func(t *testing.T) { emptyInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{Name: "empty-server"}, + Config: parser.RegistryMCPServerConfig{Name: "empty-server"}, Tools: []*mcp.Tool{}, } @@ -278,7 +278,7 @@ func TestDisplayToolsList(t *testing.T) { t.Run("no_allowed_tools_means_all_allowed", func(t *testing.T) { noAllowedInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + Config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "test"}, Name: "no-allowed-server", Allowed: []string{}, // Empty allowed list means all tools allowed @@ -296,7 +296,7 @@ func TestDisplayToolsList(t *testing.T) { t.Run("workflow_config_with_wildcard", func(t *testing.T) { wildcardInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + Config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "test"}, Name: "wildcard-server", Allowed: []string{"*"}, // Wildcard in workflow config diff --git a/pkg/cli/mcp_tool_table_test.go b/pkg/cli/mcp_tool_table_test.go index a6a383e7ea0..db64082f76b 100644 --- a/pkg/cli/mcp_tool_table_test.go +++ b/pkg/cli/mcp_tool_table_test.go @@ -15,7 +15,7 @@ import ( func TestRenderMCPToolTable(t *testing.T) { // Create mock data mockInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + Config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "test"}, Name: "test-server", Allowed: []string{"tool1", "tool3"}, // Only tool1 and tool3 are allowed @@ -38,7 +38,7 @@ func TestRenderMCPToolTable(t *testing.T) { t.Run("empty_tools_list_returns_empty_string", func(t *testing.T) { emptyInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{Name: "empty-server"}, + Config: parser.RegistryMCPServerConfig{Name: "empty-server"}, Tools: []*mcp.Tool{}, } @@ -181,7 +181,7 @@ func TestRenderMCPToolTable(t *testing.T) { t.Run("no_allowed_tools_means_all_allowed", func(t *testing.T) { noAllowedInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + Config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "test"}, Name: "no-allowed-server", Allowed: []string{}, // Empty allowed list means all tools allowed @@ -212,7 +212,7 @@ func TestRenderMCPToolTable(t *testing.T) { t.Run("wildcard_allows_all_tools", func(t *testing.T) { wildcardInfo := &parser.MCPServerInfo{ - Config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + Config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "test"}, Name: "wildcard-server", Allowed: []string{"*"}, // Wildcard in workflow config diff --git a/pkg/cli/mcp_validation.go b/pkg/cli/mcp_validation.go index 32948684f3e..780c7750116 100644 --- a/pkg/cli/mcp_validation.go +++ b/pkg/cli/mcp_validation.go @@ -77,7 +77,7 @@ func logAndValidateBinaryPath() (string, error) { } // validateServerSecrets checks if required environment variables/secrets are available -func validateServerSecrets(config parser.MCPServerConfig, verbose bool, useActionsSecrets bool) error { +func validateServerSecrets(config parser.RegistryMCPServerConfig, verbose bool, useActionsSecrets bool) error { mcpValidationLog.Printf("Validating server secrets: server=%s, type=%s, useActionsSecrets=%v", config.Name, config.Type, useActionsSecrets) // Extract secrets from the config diff --git a/pkg/cli/mcp_workflow_loader.go b/pkg/cli/mcp_workflow_loader.go index 7917fa8fb0b..e7b6d303768 100644 --- a/pkg/cli/mcp_workflow_loader.go +++ b/pkg/cli/mcp_workflow_loader.go @@ -19,9 +19,9 @@ var mcpWorkflowLoaderLog = logger.New("cli:mcp_workflow_loader") // // Returns: // - *parser.FrontmatterResult: parsed workflow data containing frontmatter and content -// - []parser.MCPServerConfig: list of MCP server configurations +// - []parser.RegistryMCPServerConfig: list of MCP server configurations // - error: any error that occurred during loading or parsing -func loadWorkflowMCPConfigs(workflowPath string, serverFilter string) (*parser.FrontmatterResult, []parser.MCPServerConfig, error) { +func loadWorkflowMCPConfigs(workflowPath string, serverFilter string) (*parser.FrontmatterResult, []parser.RegistryMCPServerConfig, error) { mcpWorkflowLoaderLog.Printf("Loading MCP configs: path=%s, server_filter=%q", workflowPath, serverFilter) // Read the workflow file diff --git a/pkg/cli/mcp_workflow_scanner.go b/pkg/cli/mcp_workflow_scanner.go index ac9dcab9a0e..bfe51423374 100644 --- a/pkg/cli/mcp_workflow_scanner.go +++ b/pkg/cli/mcp_workflow_scanner.go @@ -17,7 +17,7 @@ type WorkflowMCPMetadata struct { FilePath string FileName string BaseName string - MCPConfigs []parser.MCPServerConfig + MCPConfigs []parser.RegistryMCPServerConfig Frontmatter map[string]any } diff --git a/pkg/cli/secrets.go b/pkg/cli/secrets.go index 080e4ea6cf7..0fa3736a2da 100644 --- a/pkg/cli/secrets.go +++ b/pkg/cli/secrets.go @@ -61,7 +61,7 @@ func checkSecretExists(secretName string) (bool, error) { } // extractSecretsFromConfig extracts all required secrets from an MCP server config -func extractSecretsFromConfig(config parser.MCPServerConfig) []SecretInfo { +func extractSecretsFromConfig(config parser.RegistryMCPServerConfig) []SecretInfo { secretsLog.Printf("Extracting secrets from MCP config: command=%s", config.Command) var secrets []SecretInfo seen := make(map[string]bool) diff --git a/pkg/cli/secrets_test.go b/pkg/cli/secrets_test.go index d1c63999a4a..1295a3564dc 100644 --- a/pkg/cli/secrets_test.go +++ b/pkg/cli/secrets_test.go @@ -61,12 +61,12 @@ func TestExtractSecretName(t *testing.T) { func TestExtractSecretsFromConfig(t *testing.T) { tests := []struct { name string - config parser.MCPServerConfig + config parser.RegistryMCPServerConfig expectedSecrets []string }{ { name: "HTTP headers with secrets", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", Headers: map[string]string{ "DD_API_KEY": "${{ secrets.DD_API_KEY }}", "DD_APPLICATION_KEY": "${{ secrets.DD_APPLICATION_KEY }}", @@ -77,7 +77,7 @@ func TestExtractSecretsFromConfig(t *testing.T) { }, { name: "env vars with secrets", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Env: map[string]string{ "API_KEY": "${{ secrets.API_KEY }}", "TOKEN": "${{ secrets.TOKEN }}", @@ -87,7 +87,7 @@ func TestExtractSecretsFromConfig(t *testing.T) { }, { name: "mixed headers and env", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", Headers: map[string]string{ "Authorization": "Bearer ${{ secrets.AUTH_TOKEN }}", }, @@ -99,7 +99,7 @@ func TestExtractSecretsFromConfig(t *testing.T) { }, { name: "no secrets", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Env: map[string]string{ "SIMPLE_VAR": "plain value", }}, Name: "simple-server", @@ -108,7 +108,7 @@ func TestExtractSecretsFromConfig(t *testing.T) { }, { name: "duplicate secrets (should only appear once)", - config: parser.MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + config: parser.RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", Headers: map[string]string{ "Header1": "${{ secrets.API_KEY }}", "Header2": "${{ secrets.API_KEY }}", diff --git a/pkg/cli/trial_command.go b/pkg/cli/trial_command.go index c79ede9a4c0..9391dfc53e0 100644 --- a/pkg/cli/trial_command.go +++ b/pkg/cli/trial_command.go @@ -90,7 +90,7 @@ Trial results are saved both locally (in trials/ directory) and in the host repo } opts := TrialOptions{ - Repos: RepoConfig{ + Repos: TrialRepoContext{ LogicalRepo: logicalRepoSpec, CloneRepo: cloneRepoSpec, HostRepo: hostRepoSpec, diff --git a/pkg/cli/trial_types.go b/pkg/cli/trial_types.go index a8648a09328..076474a274b 100644 --- a/pkg/cli/trial_types.go +++ b/pkg/cli/trial_types.go @@ -20,8 +20,8 @@ type CombinedTrialResult struct { Timestamp time.Time `json:"timestamp"` } -// RepoConfig groups repository-related configuration for trial execution -type RepoConfig struct { +// TrialRepoContext groups repository-related configuration for trial execution +type TrialRepoContext struct { LogicalRepo string // The repo to simulate execution against CloneRepo string // Alternative to LogicalRepo: clone this repo's contents HostRepo string // The host repository where workflows will be installed @@ -29,7 +29,7 @@ type RepoConfig struct { // TrialOptions contains all configuration options for running workflow trials type TrialOptions struct { - Repos RepoConfig + Repos TrialRepoContext DeleteHostRepo bool ForceDelete bool Quiet bool diff --git a/pkg/parser/README.md b/pkg/parser/README.md index bac319a4940..6fbf065e24e 100644 --- a/pkg/parser/README.md +++ b/pkg/parser/README.md @@ -31,7 +31,7 @@ The package is designed for use both in the main CLI binary and in WebAssembly c | `JSONPathInfo` | struct | JSON path with human-readable description | | `NestedSection` | struct | Locates nested YAML sections for error reporting | | `PathSegment` | struct | A single segment in a resolved JSON path | -| `MCPServerConfig` | struct | Parsed MCP server configuration (type, command, URL, env, etc.) | +| `RegistryMCPServerConfig` | struct | Parsed MCP server configuration (type, command, URL, env, etc.) | | `MCPServerInfo` | struct | Metadata about an MCP server entry | | `ScheduleParser` | struct | Converts natural-language schedules to cron expressions | | `DeprecatedField` | struct | A deprecated frontmatter field with migration guidance | @@ -88,8 +88,8 @@ The package is designed for use both in the main CLI binary and in WebAssembly c | Function | Signature | Description | |----------|-----------|-------------| -| `ExtractMCPConfigurations` | `func(frontmatter map[string]any, serverFilter string) ([]MCPServerConfig, error)` | Extracts all MCP server configurations from frontmatter | -| `ParseMCPConfig` | `func(toolName string, mcpSection any, toolConfig map[string]any) (MCPServerConfig, error)` | Parses a single MCP server entry | +| `ExtractMCPConfigurations` | `func(frontmatter map[string]any, serverFilter string) ([]RegistryMCPServerConfig, error)` | Extracts all MCP server configurations from frontmatter | +| `ParseMCPConfig` | `func(toolName string, mcpSection any, toolConfig map[string]any) (RegistryMCPServerConfig, error)` | Parses a single MCP server entry | | `IsMCPType` | `func(typeStr string) bool` | Validates an MCP transport type string | #### Schedule Parsing diff --git a/pkg/parser/mcp.go b/pkg/parser/mcp.go index fe560bc4d13..56d30d44a9c 100644 --- a/pkg/parser/mcp.go +++ b/pkg/parser/mcp.go @@ -30,9 +30,11 @@ func IsMCPType(typeStr string) bool { } } -// MCPServerConfig represents a parsed MCP server configuration. +// RegistryMCPServerConfig represents a parser-layer MCP server configuration. +// It is intentionally distinct from workflow.MCPServerConfig, which models +// workflow-facing YAML tool configuration. // It embeds BaseMCPServerConfig for common fields and adds parser-specific fields. -type MCPServerConfig struct { +type RegistryMCPServerConfig struct { types.BaseMCPServerConfig // Parser-specific fields @@ -44,7 +46,7 @@ type MCPServerConfig struct { // MCPServerInfo contains the inspection results for an MCP server type MCPServerInfo struct { - Config MCPServerConfig + Config RegistryMCPServerConfig Connected bool Error error Tools []*mcp.Tool @@ -53,16 +55,16 @@ type MCPServerInfo struct { } // ExtractMCPConfigurations extracts MCP server configurations from workflow frontmatter -func ExtractMCPConfigurations(frontmatter map[string]any, serverFilter string) ([]MCPServerConfig, error) { +func ExtractMCPConfigurations(frontmatter map[string]any, serverFilter string) ([]RegistryMCPServerConfig, error) { mcpLog.Printf("Extracting MCP configurations with filter: %s", serverFilter) - var configs []MCPServerConfig + var configs []RegistryMCPServerConfig // Check for safe-outputs configuration first (built-in MCP) if safeOutputsSection, hasSafeOutputs := frontmatter["safe-outputs"]; hasSafeOutputs { mcpLog.Print("Found safe-outputs configuration") // Apply server filter if specified if serverFilter == "" || strings.Contains(constants.SafeOutputsMCPServerID.String(), strings.ToLower(serverFilter)) { - config := MCPServerConfig{ + config := RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "stdio", Command: "node", @@ -112,7 +114,7 @@ func ExtractMCPConfigurations(frontmatter map[string]any, serverFilter string) ( // Apply server filter if specified if serverFilter == "" || strings.Contains(constants.SafeOutputsMCPServerID.String(), strings.ToLower(serverFilter)) { // Find existing safe-outputs config or create new one - var config *MCPServerConfig + var config *RegistryMCPServerConfig for i := range configs { if configs[i].Name == constants.SafeOutputsMCPServerID.String() { config = &configs[i] @@ -121,7 +123,7 @@ func ExtractMCPConfigurations(frontmatter map[string]any, serverFilter string) ( } if config == nil { - newConfig := MCPServerConfig{ + newConfig := RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "stdio", Command: "node", @@ -147,7 +149,7 @@ func ExtractMCPConfigurations(frontmatter map[string]any, serverFilter string) ( mcpLog.Print("Found mcp-scripts configuration") // Apply server filter if specified if serverFilter == "" || strings.Contains(constants.MCPScriptsMCPServerID.String(), strings.ToLower(serverFilter)) { - config := MCPServerConfig{ + config := RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "http", Command: "", @@ -250,7 +252,7 @@ func ExtractMCPConfigurations(frontmatter map[string]any, serverFilter string) ( } // processBuiltinMCPTool handles built-in MCP tools (github, playwright, and serena) -func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) (*MCPServerConfig, error) { +func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) (*RegistryMCPServerConfig, error) { // Apply server filter if specified if serverFilter != "" && !strings.Contains(strings.ToLower(toolName), strings.ToLower(serverFilter)) { return nil, nil @@ -277,11 +279,11 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) } } - var config MCPServerConfig + var config RegistryMCPServerConfig if useRemote { // Handle GitHub MCP server in remote mode (hosted) - config = MCPServerConfig{ + config = RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "http", URL: "https://api.githubcopilot.com/mcp/", @@ -300,7 +302,7 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) config.Headers["X-MCP-Readonly"] = "true" } else { // Handle GitHub MCP server - use local/Docker by default - config = MCPServerConfig{ + config = RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "docker", // GitHub defaults to Docker (local containerized) Command: "docker", @@ -372,7 +374,7 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) return &config, nil } else if toolName == "playwright" { // Handle Playwright MCP server - always use Docker by default - config := MCPServerConfig{ + config := RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "docker", // Playwright defaults to Docker (containerized) Command: "docker", @@ -422,7 +424,7 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) return &config, nil } else if toolName == "serena" { // Handle Serena MCP server - uses uvx to install and run from GitHub - config := MCPServerConfig{ + config := RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "stdio", Command: "uvx", @@ -479,9 +481,9 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) } // ParseMCPConfig parses MCP configuration from various formats (map or JSON string) -func ParseMCPConfig(toolName string, mcpSection any, toolConfig map[string]any) (MCPServerConfig, error) { +func ParseMCPConfig(toolName string, mcpSection any, toolConfig map[string]any) (RegistryMCPServerConfig, error) { mcpLog.Printf("Parsing MCP configuration for tool: %s", toolName) - config := MCPServerConfig{ + config := RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Env: make(map[string]string), Headers: make(map[string]string), diff --git a/pkg/parser/mcp_test.go b/pkg/parser/mcp_test.go index 06bbe5c1cad..5744c7b746d 100644 --- a/pkg/parser/mcp_test.go +++ b/pkg/parser/mcp_test.go @@ -19,7 +19,7 @@ func TestExtractMCPConfigurations(t *testing.T) { name string frontmatter map[string]any serverFilter string - expected []MCPServerConfig + expected []RegistryMCPServerConfig expectError bool }{ { @@ -31,7 +31,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -56,7 +56,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -79,7 +79,7 @@ func TestExtractMCPConfigurations(t *testing.T) { "github": true, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -100,7 +100,7 @@ func TestExtractMCPConfigurations(t *testing.T) { "github": map[string]any{}, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -120,7 +120,7 @@ func TestExtractMCPConfigurations(t *testing.T) { { name: "Empty frontmatter", frontmatter: map[string]any{}, - expected: []MCPServerConfig{}, + expected: []RegistryMCPServerConfig{}, }, { name: "No tools section", @@ -128,7 +128,7 @@ func TestExtractMCPConfigurations(t *testing.T) { "name": "test-workflow", "on": "push", }, - expected: []MCPServerConfig{}, + expected: []RegistryMCPServerConfig{}, }, { name: "GitHub tool default configuration", @@ -137,7 +137,7 @@ func TestExtractMCPConfigurations(t *testing.T) { "github": map[string]any{}, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -161,7 +161,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -184,7 +184,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -207,7 +207,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -228,7 +228,7 @@ func TestExtractMCPConfigurations(t *testing.T) { "playwright": map[string]any{}, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -249,7 +249,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -270,7 +270,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -291,7 +291,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -312,7 +312,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -339,7 +339,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, serverFilter: "github", - expected: []MCPServerConfig{ + expected: []RegistryMCPServerConfig{ {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", Command: "docker", Args: []string{ @@ -367,7 +367,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, serverFilter: "nomatch", - expected: []MCPServerConfig{}, + expected: []RegistryMCPServerConfig{}, }, } @@ -445,7 +445,7 @@ func TestParseMCPConfig(t *testing.T) { toolName string mcpSection any toolConfig map[string]any - expected MCPServerConfig + expected RegistryMCPServerConfig expectError bool }{ { @@ -457,7 +457,7 @@ func TestParseMCPConfig(t *testing.T) { "args": []any{"--verbose", "--config=/etc/config.yml"}, }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "/usr/bin/server", Args: []string{"--verbose", "--config=/etc/config.yml"}, Env: map[string]string{}, @@ -478,7 +478,7 @@ func TestParseMCPConfig(t *testing.T) { }, }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Container: "myregistry/server:latest", Command: "docker", Args: []string{"run", "--rm", "-i", "-e", "DEBUG", "-e", "API_URL", "myregistry/server:latest"}, @@ -503,7 +503,7 @@ func TestParseMCPConfig(t *testing.T) { }, }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: "https://mcp.example.com/api", Headers: map[string]string{ "Authorization": "Bearer token123", @@ -527,7 +527,7 @@ func TestParseMCPConfig(t *testing.T) { }, }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: "https://mcp.datadoghq.com/api/unstable/mcp-server/mcp", Headers: map[string]string{ "DD_API_KEY": "test-api-key", @@ -549,7 +549,7 @@ func TestParseMCPConfig(t *testing.T) { toolConfig: map[string]any{ "allowed": []any{"tool1", "tool2", "tool3"}, }, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "server", Env: map[string]string{}, Headers: map[string]string{}}, Name: "server-with-allowed", @@ -569,7 +569,7 @@ func TestParseMCPConfig(t *testing.T) { } }`, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "python", Args: []string{"-m", "mcp_server"}, Env: map[string]string{ @@ -592,7 +592,7 @@ func TestParseMCPConfig(t *testing.T) { }, }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "server", Env: map[string]string{ "LOG_LEVEL": "debug", @@ -609,7 +609,7 @@ func TestParseMCPConfig(t *testing.T) { toolName: "inferred-stdio", mcpSection: map[string]any{"command": "server"}, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "server", Args: nil, Env: map[string]string{}, @@ -632,7 +632,7 @@ func TestParseMCPConfig(t *testing.T) { }, }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "docker", Args: []string{"run", "myserver"}, @@ -653,7 +653,7 @@ func TestParseMCPConfig(t *testing.T) { "args": []any{"--local-mode"}, }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", // normalized to stdio + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", // normalized to stdio Command: "local-mcp-server", Args: []string{"--local-mode"}, Env: map[string]string{}, @@ -671,7 +671,7 @@ func TestParseMCPConfig(t *testing.T) { "registry": "https://registry.example.com/servers/mcp-server", }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "registry-server", Env: map[string]string{}, @@ -691,7 +691,7 @@ func TestParseMCPConfig(t *testing.T) { "registry": "https://registry.example.com/servers/http-mcp", }, toolConfig: map[string]any{}, - expected: MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", + expected: RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "http", URL: "https://api.example.com/mcp", Headers: map[string]string{}, @@ -861,7 +861,7 @@ func TestParseMCPConfig(t *testing.T) { // TestMCPConfigTypes tests the struct types for proper JSON serialization func TestMCPConfigTypes(t *testing.T) { // Test that our structs can be properly marshaled/unmarshaled - config := MCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", + config := RegistryMCPServerConfig{BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "stdio", Command: "test-command", Args: []string{"arg1", "arg2"}, @@ -880,7 +880,7 @@ func TestMCPConfigTypes(t *testing.T) { } // Unmarshal from JSON - var decoded MCPServerConfig + var decoded RegistryMCPServerConfig if err := json.Unmarshal(jsonData, &decoded); err != nil { t.Errorf("Failed to unmarshal config: %v", err) } diff --git a/pkg/workflow/README.md b/pkg/workflow/README.md index 5bf86141749..2f63e4b830e 100644 --- a/pkg/workflow/README.md +++ b/pkg/workflow/README.md @@ -25,7 +25,7 @@ The package is intentionally large (~320 source files) because it encodes all Gi | `Compiler` | struct | Main compilation engine; use `NewCompiler(opts...)` | | `CompilerOption` | func type | Functional option for configuring a `Compiler` | | `WorkflowData` | struct | Complete in-memory representation of a compiled workflow | -| `FileTracker` | interface | Abstraction for tracking written files | +| `FileCreationTracker` | interface | Abstraction for tracking written files | #### `Compiler` Methods diff --git a/pkg/workflow/compiler_types.go b/pkg/workflow/compiler_types.go index 1bf0bfa7296..579552333fe 100644 --- a/pkg/workflow/compiler_types.go +++ b/pkg/workflow/compiler_types.go @@ -48,8 +48,8 @@ func WithVersion(version string) CompilerOption { return func(c *Compiler) { c.version = version } } -// FileTracker interface for tracking files created during compilation -type FileTracker interface { +// FileCreationTracker interface for tracking files created during compilation +type FileCreationTracker interface { TrackCreated(filePath string) } @@ -77,7 +77,7 @@ type Compiler struct { jobManager *JobManager // Manages jobs and dependencies engineRegistry *EngineRegistry // Registry of available agentic engines engineCatalog *EngineCatalog // Catalog of engine definitions backed by the registry - fileTracker FileTracker // Optional file tracker for tracking created files + fileTracker FileCreationTracker // Optional file tracker for tracking created files warningCount int // Number of warnings encountered during compilation stepOrderTracker *StepOrderTracker // Tracks step ordering for validation actionCache *ActionCache // Shared cache for action pin resolutions across all workflows @@ -170,7 +170,7 @@ func (c *Compiler) SetApprove(approve bool) { } // SetFileTracker sets the file tracker for tracking created files -func (c *Compiler) SetFileTracker(tracker FileTracker) { +func (c *Compiler) SetFileTracker(tracker FileCreationTracker) { c.fileTracker = tracker } diff --git a/pkg/workflow/mcp_config_custom.go b/pkg/workflow/mcp_config_custom.go index 89825a0c741..0f69eecb7c6 100644 --- a/pkg/workflow/mcp_config_custom.go +++ b/pkg/workflow/mcp_config_custom.go @@ -565,11 +565,11 @@ func collectHTTPMCPHeaderSecrets(tools map[string]any) map[string]string { } // getMCPConfig extracts MCP configuration from a tool config and returns a structured MCPServerConfig -func getMCPConfig(toolConfig map[string]any, toolName string) (*parser.MCPServerConfig, error) { +func getMCPConfig(toolConfig map[string]any, toolName string) (*parser.RegistryMCPServerConfig, error) { mcpCustomLog.Printf("Extracting MCP config for tool: %s", toolName) config := MapToolConfig(toolConfig) - result := &parser.MCPServerConfig{ + result := &parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Env: make(map[string]string), Headers: make(map[string]string), diff --git a/pkg/workflow/mcp_json_test.go b/pkg/workflow/mcp_json_test.go index 018dd166078..ff3d6dd5e42 100644 --- a/pkg/workflow/mcp_json_test.go +++ b/pkg/workflow/mcp_json_test.go @@ -14,7 +14,7 @@ func TestGetMCPConfig(t *testing.T) { tests := []struct { name string toolConfig map[string]any - expected *parser.MCPServerConfig + expected *parser.RegistryMCPServerConfig wantErr bool }{ { @@ -24,7 +24,7 @@ func TestGetMCPConfig(t *testing.T) { "command": "python", "args": []any{"-m", "test"}, }, - expected: &parser.MCPServerConfig{ + expected: &parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "stdio", Command: "python", @@ -42,7 +42,7 @@ func TestGetMCPConfig(t *testing.T) { "command": "python", "args": []any{"-m", "test"}, }, - expected: &parser.MCPServerConfig{ + expected: &parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "stdio", Command: "python", @@ -59,7 +59,7 @@ func TestGetMCPConfig(t *testing.T) { toolConfig: map[string]any{ "url": "https://example.com", }, - expected: &parser.MCPServerConfig{ + expected: &parser.RegistryMCPServerConfig{ BaseMCPServerConfig: types.BaseMCPServerConfig{ Type: "http", URL: "https://example.com",