From 83973a8eef2d71caae3c3f70dcfe4a0812282fc6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 15:58:13 +0000 Subject: [PATCH 1/5] Initial plan From 49575c6913504821806d4d05f1a52753300707df Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:11:52 +0000 Subject: [PATCH 2/5] Implement --allowed-rules filtering support for MCP server - Apply global allowedRules setting to MCP server default config - Add allowed_rules parameter to all MCP tool definitions - Update all handler functions to parse and apply allowed_rules parameter - Ensure consistent behavior between CLI and MCP server for rule filtering Co-authored-by: fproulx-boostsecurity <76956526+fproulx-boostsecurity@users.noreply.github.com> --- cmd/mcp_server.go | 73 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/cmd/mcp_server.go b/cmd/mcp_server.go index 46d5be40..41f88936 100644 --- a/cmd/mcp_server.go +++ b/cmd/mcp_server.go @@ -60,6 +60,10 @@ func startMCPServer(ctx context.Context) error { Format = "noop" defaultConfig := *config + // Apply global allowedRules setting to MCP server config + if len(allowedRules) > 0 { + defaultConfig.AllowedRules = allowedRules + } opaClient, err := newOpaWithConfig(ctx, &defaultConfig) if err != nil { log.Error().Err(err).Msg("Failed to create manifest OPA client") @@ -95,6 +99,10 @@ func startMCPServer(ctx context.Context) error { mcp.WithBoolean("ignore_forks", mcp.Description("Ignore forked repositories"), ), + mcp.WithArray("allowed_rules", + mcp.Description("Filter to only run specified rules (optional)"), + mcp.WithStringItems(), + ), mcp.WithTitleAnnotation("CI/CD Pipeline Security Scan - Organization"), mcp.WithReadOnlyHintAnnotation(true), mcp.WithDestructiveHintAnnotation(false), @@ -119,6 +127,10 @@ func startMCPServer(ctx context.Context) error { mcp.WithString("ref", mcp.Description("Commit or branch to analyze"), ), + mcp.WithArray("allowed_rules", + mcp.Description("Filter to only run specified rules (optional)"), + mcp.WithStringItems(), + ), mcp.WithTitleAnnotation("CI/CD Pipeline Security Scan - Repository"), mcp.WithReadOnlyHintAnnotation(true), mcp.WithDestructiveHintAnnotation(false), @@ -149,6 +161,10 @@ func startMCPServer(ctx context.Context) error { mcp.WithString("regex", mcp.Description("Regex to check if the workflow is accessible in stale branches"), ), + mcp.WithArray("allowed_rules", + mcp.Description("Filter to only run specified rules (optional)"), + mcp.WithStringItems(), + ), mcp.WithTitleAnnotation("CI/CD Pipeline Security Scan - Stale Branches"), mcp.WithReadOnlyHintAnnotation(true), mcp.WithDestructiveHintAnnotation(false), @@ -163,6 +179,10 @@ func startMCPServer(ctx context.Context) error { mcp.Required(), mcp.Description("Local file system path to the repository"), ), + mcp.WithArray("allowed_rules", + mcp.Description("Filter to only run specified rules (optional)"), + mcp.WithStringItems(), + ), mcp.WithTitleAnnotation("CI/CD Pipeline Security Scan - Local Repository"), mcp.WithReadOnlyHintAnnotation(true), mcp.WithDestructiveHintAnnotation(false), @@ -244,6 +264,10 @@ Remember: This tool exists to prevent security vulnerabilities in generated code mcp.Description("Type of CI/CD manifest: 'github-actions' for GitHub Actions workflows, 'gitlab-ci' for GitLab CI, 'azure-pipelines' for Azure Pipelines, 'tekton' for Tekton pipelines"), mcp.Enum("github-actions", "gitlab-ci", "azure-pipelines", "tekton"), ), + mcp.WithArray("allowed_rules", + mcp.Description("Filter to only run specified rules (optional)"), + mcp.WithStringItems(), + ), mcp.WithTitleAnnotation("CI/CD Pipeline Security Scan - Manifest"), mcp.WithReadOnlyHintAnnotation(true), mcp.WithDestructiveHintAnnotation(false), @@ -288,9 +312,13 @@ func handleAnalyzeOrg(ctx context.Context, request mcp.CallToolRequest) (*mcp.Ca scmBaseURLStr := request.GetString("scm_base_url", "") threads := int(request.GetFloat("threads", 2)) ignoreForks := request.GetBool("ignore_forks", false) + allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) requestConfig := *config requestConfig.IgnoreForks = ignoreForks + if len(allowedRulesParam) > 0 { + requestConfig.AllowedRules = allowedRulesParam + } analyzer, err := GetAnalyzerWithConfig(ctx, "analyze_org", scmProvider, scmBaseURLStr, token, &requestConfig) if err != nil { @@ -333,8 +361,12 @@ func handleAnalyzeRepo(ctx context.Context, request mcp.CallToolRequest) (*mcp.C scmProvider := request.GetString("scm_provider", "github") scmBaseURLStr := request.GetString("scm_base_url", "") ref := request.GetString("ref", "HEAD") + allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) requestConfig := *config + if len(allowedRulesParam) > 0 { + requestConfig.AllowedRules = allowedRulesParam + } analyzer, err := GetAnalyzerWithConfig(ctx, "analyze_repo", scmProvider, scmBaseURLStr, token, &requestConfig) if err != nil { @@ -366,7 +398,23 @@ func handleAnalyzeLocal(ctx context.Context, request mcp.CallToolRequest, opaCli return mcp.NewToolResultError("path parameter is required"), nil } + allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) + requestConfig := *config + if len(allowedRulesParam) > 0 { + requestConfig.AllowedRules = allowedRulesParam + } + + // Create a new OPA client with the request-specific config if allowed_rules is specified + var requestOpaClient *opa.Opa + if len(allowedRulesParam) > 0 { + requestOpaClient, err = newOpaWithConfig(ctx, &requestConfig) + if err != nil { + return mcp.NewToolResultError(fmt.Sprintf("failed to create OPA client with allowed rules: %v", err)), nil + } + } else { + requestOpaClient = opaClient + } localScmClient, err := local.NewGitSCMClient(ctx, path, nil) if err != nil { @@ -377,7 +425,7 @@ func handleAnalyzeLocal(ctx context.Context, request mcp.CallToolRequest, opaCli formatter := &noop.Format{} - analyzer := analyze.NewAnalyzer(localScmClient, localGitClient, formatter, &requestConfig, opaClient) + analyzer := analyze.NewAnalyzer(localScmClient, localGitClient, formatter, &requestConfig, requestOpaClient) analysisResults, err := analyzer.AnalyzeLocalRepo(ctx, path) if err != nil { @@ -414,6 +462,7 @@ func handleAnalyzeStaleBranches(ctx context.Context, request mcp.CallToolRequest threads := int(request.GetFloat("threads", 5)) expand := request.GetBool("expand", false) regexStr := request.GetString("regex", "pull_request_target") + allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) // Compile the regex reg, err := regexp.Compile(regexStr) @@ -422,6 +471,9 @@ func handleAnalyzeStaleBranches(ctx context.Context, request mcp.CallToolRequest } requestConfig := *config + if len(allowedRulesParam) > 0 { + requestConfig.AllowedRules = allowedRulesParam + } analyzer, err := GetAnalyzerWithConfig(ctx, "analyze_repo_stale_branches", scmProvider, scmBaseURLStr, token, &requestConfig) if err != nil { @@ -454,9 +506,26 @@ func handleAnalyzeManifest(ctx context.Context, request mcp.CallToolRequest, ana } manifestType := request.GetString("manifest_type", "github-actions") + allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) + + // Create a new analyzer with allowed rules if specified + var requestAnalyzer *analyze.Analyzer + if len(allowedRulesParam) > 0 { + requestConfig := *config + requestConfig.AllowedRules = allowedRulesParam + + requestOpaClient, err := newOpaWithConfig(ctx, &requestConfig) + if err != nil { + return mcp.NewToolResultError(fmt.Sprintf("failed to create OPA client with allowed rules: %v", err)), nil + } + + requestAnalyzer = analyze.NewAnalyzer(nil, nil, &noop.Format{}, &requestConfig, requestOpaClient) + } else { + requestAnalyzer = analyzer + } manifestReader := strings.NewReader(content) - analysisResults, err := analyzer.AnalyzeManifest(ctx, manifestReader, manifestType) + analysisResults, err := requestAnalyzer.AnalyzeManifest(ctx, manifestReader, manifestType) if err != nil { return mcp.NewToolResultError(fmt.Sprintf("failed to analyze manifest: %v", err)), nil } From ac6de7b91af7e1dfd6e1dd713879e4a914e9ccff Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:15:07 +0000 Subject: [PATCH 3/5] Add comprehensive tests for --allowed-rules filtering in MCP server - Add test cases for analyze_manifest with allowed_rules parameter - Verify filtering works correctly with single rule, multiple rules, and non-existent rules - Confirm both global flag and per-request parameter functionality - All tests pass demonstrating successful implementation Co-authored-by: fproulx-boostsecurity <76956526+fproulx-boostsecurity@users.noreply.github.com> --- cmd/handle_analyze_manifest_test.go | 123 ++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) diff --git a/cmd/handle_analyze_manifest_test.go b/cmd/handle_analyze_manifest_test.go index 9131d358..e97872f5 100644 --- a/cmd/handle_analyze_manifest_test.go +++ b/cmd/handle_analyze_manifest_test.go @@ -294,3 +294,126 @@ jobs: t.Logf("Successfully analyzed manifest with %d findings", len(insights.Findings)) } + +func TestHandleAnalyzeManifestWithAllowedRules(t *testing.T) { + ctx := context.Background() + + analyzer, err := createTestAnalyzer(ctx) + require.NoError(t, err) + + vulnerableManifest := `name: Test Workflow +on: + pull_request_target: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Run test + run: echo "Testing ${{ github.event.pull_request.head.ref }}"` + + t.Run("without allowed_rules filter", func(t *testing.T) { + request := NewCallToolRequest("analyze_manifest", map[string]interface{}{ + "content": vulnerableManifest, + "manifest_type": "github-actions", + }) + + result, err := handleAnalyzeManifest(ctx, request, analyzer) + require.NoError(t, err) + require.NotNil(t, result) + assert.False(t, result.IsError) + + contentText := extractTextFromContent(t, result.Content[0]) + require.NotEmpty(t, contentText) + + var insights struct { + Findings []results.Finding `json:"findings"` + Rules map[string]results.Rule `json:"rules"` + } + err = json.Unmarshal([]byte(contentText), &insights) + require.NoError(t, err) + + // Should have multiple findings including injection + assert.Greater(t, len(insights.Findings), 1, "Should have multiple findings without filter") + + // Verify injection rule is present + hasInjection := false + for _, finding := range insights.Findings { + if finding.RuleId == "injection" { + hasInjection = true + break + } + } + assert.True(t, hasInjection, "Should have injection finding") + + t.Logf("Found %d findings without filter", len(insights.Findings)) + }) + + t.Run("with allowed_rules filter for injection only", func(t *testing.T) { + request := NewCallToolRequest("analyze_manifest", map[string]interface{}{ + "content": vulnerableManifest, + "manifest_type": "github-actions", + "allowed_rules": []string{"injection"}, + }) + + result, err := handleAnalyzeManifest(ctx, request, analyzer) + require.NoError(t, err) + require.NotNil(t, result) + assert.False(t, result.IsError) + + contentText := extractTextFromContent(t, result.Content[0]) + require.NotEmpty(t, contentText) + + var insights struct { + Findings []results.Finding `json:"findings"` + Rules map[string]results.Rule `json:"rules"` + } + err = json.Unmarshal([]byte(contentText), &insights) + require.NoError(t, err) + + // Should have only injection finding + assert.Len(t, insights.Findings, 1, "Should have only one finding with filter") + assert.Equal(t, "injection", insights.Findings[0].RuleId, "Should only have injection finding") + + // Should have only injection rule + assert.Len(t, insights.Rules, 1, "Should have only one rule with filter") + _, hasInjectionRule := insights.Rules["injection"] + assert.True(t, hasInjectionRule, "Should have injection rule in rules map") + + t.Logf("Found %d findings with allowed_rules filter", len(insights.Findings)) + }) + + t.Run("with allowed_rules filter for non-existent rule", func(t *testing.T) { + request := NewCallToolRequest("analyze_manifest", map[string]interface{}{ + "content": vulnerableManifest, + "manifest_type": "github-actions", + "allowed_rules": []string{"non_existent_rule"}, + }) + + result, err := handleAnalyzeManifest(ctx, request, analyzer) + require.NoError(t, err) + require.NotNil(t, result) + assert.False(t, result.IsError) + + contentText := extractTextFromContent(t, result.Content[0]) + require.NotEmpty(t, contentText) + + var insights struct { + Findings []results.Finding `json:"findings"` + Rules map[string]results.Rule `json:"rules"` + } + err = json.Unmarshal([]byte(contentText), &insights) + require.NoError(t, err) + + // Should have no findings + assert.Len(t, insights.Findings, 0, "Should have no findings with non-existent rule filter") + assert.Len(t, insights.Rules, 0, "Should have no rules with non-existent rule filter") + + t.Logf("Found %d findings with non-existent rule filter", len(insights.Findings)) + }) +} From 59526f74ede33c9d98f2cd8ef4acf380c3718edd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:25:26 +0000 Subject: [PATCH 4/5] Fix linting issues: gofmt formatting and testifylint violations - Remove trailing whitespace in cmd/handle_analyze_manifest_test.go and cmd/mcp_server.go - Replace assert.Len(t, ..., 0, ...) with assert.Empty(t, ...) for testifylint compliance - All tests still pass and functionality remains intact Co-authored-by: fproulx-boostsecurity <76956526+fproulx-boostsecurity@users.noreply.github.com> --- cmd/handle_analyze_manifest_test.go | 8 ++++---- cmd/mcp_server.go | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/handle_analyze_manifest_test.go b/cmd/handle_analyze_manifest_test.go index e97872f5..c39f7127 100644 --- a/cmd/handle_analyze_manifest_test.go +++ b/cmd/handle_analyze_manifest_test.go @@ -340,7 +340,7 @@ jobs: // Should have multiple findings including injection assert.Greater(t, len(insights.Findings), 1, "Should have multiple findings without filter") - + // Verify injection rule is present hasInjection := false for _, finding := range insights.Findings { @@ -379,7 +379,7 @@ jobs: // Should have only injection finding assert.Len(t, insights.Findings, 1, "Should have only one finding with filter") assert.Equal(t, "injection", insights.Findings[0].RuleId, "Should only have injection finding") - + // Should have only injection rule assert.Len(t, insights.Rules, 1, "Should have only one rule with filter") _, hasInjectionRule := insights.Rules["injection"] @@ -411,8 +411,8 @@ jobs: require.NoError(t, err) // Should have no findings - assert.Len(t, insights.Findings, 0, "Should have no findings with non-existent rule filter") - assert.Len(t, insights.Rules, 0, "Should have no rules with non-existent rule filter") + assert.Empty(t, insights.Findings, "Should have no findings with non-existent rule filter") + assert.Empty(t, insights.Rules, "Should have no rules with non-existent rule filter") t.Logf("Found %d findings with non-existent rule filter", len(insights.Findings)) }) diff --git a/cmd/mcp_server.go b/cmd/mcp_server.go index 41f88936..51feabe7 100644 --- a/cmd/mcp_server.go +++ b/cmd/mcp_server.go @@ -513,12 +513,12 @@ func handleAnalyzeManifest(ctx context.Context, request mcp.CallToolRequest, ana if len(allowedRulesParam) > 0 { requestConfig := *config requestConfig.AllowedRules = allowedRulesParam - + requestOpaClient, err := newOpaWithConfig(ctx, &requestConfig) if err != nil { return mcp.NewToolResultError(fmt.Sprintf("failed to create OPA client with allowed rules: %v", err)), nil } - + requestAnalyzer = analyze.NewAnalyzer(nil, nil, &noop.Format{}, &requestConfig, requestOpaClient) } else { requestAnalyzer = analyzer From 08fa4dd3f724047e9aafc204fba3e419484bdb3c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 9 Oct 2025 16:57:05 +0000 Subject: [PATCH 5/5] Fix global --allowed-rules flag not being honored by MCP server handlers - Modify startMCPServer to create mcpDefaultConfig with global allowedRules applied - Update all handler functions to accept and use the mcpDefaultConfig instead of global config - Add comprehensive test to verify global allowed rules are properly inherited - Handlers now properly inherit global --allowed-rules setting when no per-request rules specified - CLI and MCP server behavior now consistent for global rule filtering Co-authored-by: fproulx-boostsecurity <76956526+fproulx-boostsecurity@users.noreply.github.com> --- cmd/handle_analyze_manifest_test.go | 68 +++++++++++++++++++++++++++++ cmd/mcp_server.go | 39 ++++++++++------- 2 files changed, 91 insertions(+), 16 deletions(-) diff --git a/cmd/handle_analyze_manifest_test.go b/cmd/handle_analyze_manifest_test.go index c39f7127..c19fb80f 100644 --- a/cmd/handle_analyze_manifest_test.go +++ b/cmd/handle_analyze_manifest_test.go @@ -417,3 +417,71 @@ jobs: t.Logf("Found %d findings with non-existent rule filter", len(insights.Findings)) }) } + +func TestMCPServerGlobalAllowedRules(t *testing.T) { + ctx := context.Background() + + // Save original state + originalAllowedRules := allowedRules + defer func() { + allowedRules = originalAllowedRules + }() + + // Simulate global --allowed-rules injection flag + allowedRules = []string{"injection"} + + // Create analyzer with global allowed rules (simulating startMCPServer behavior) + testConfig := *config + if len(allowedRules) > 0 { + testConfig.AllowedRules = allowedRules + } + + vulnerableManifest := `name: Test Workflow +on: + pull_request_target: + branches: [main] + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + - name: Run test + run: echo "Testing ${{ github.event.pull_request.head.ref }}"` + + t.Run("handleAnalyzeManifest respects global allowed rules", func(t *testing.T) { + opaClient, err := newOpaWithConfig(ctx, &testConfig) + require.NoError(t, err) + manifestAnalyzer := analyze.NewAnalyzer(nil, nil, &noop.Format{}, &testConfig, opaClient) + + // Call without allowed_rules parameter (should inherit global) + request := NewCallToolRequest("analyze_manifest", map[string]interface{}{ + "content": vulnerableManifest, + "manifest_type": "github-actions", + }) + + result, err := handleAnalyzeManifest(ctx, request, manifestAnalyzer) + require.NoError(t, err) + require.NotNil(t, result) + assert.False(t, result.IsError) + + contentText := extractTextFromContent(t, result.Content[0]) + require.NotEmpty(t, contentText) + + var insights struct { + Findings []results.Finding `json:"findings"` + Rules map[string]results.Rule `json:"rules"` + } + err = json.Unmarshal([]byte(contentText), &insights) + require.NoError(t, err) + + // Should have only injection finding due to global allowed rules + assert.Len(t, insights.Findings, 1, "Should have only injection finding with global allowed rules") + assert.Equal(t, "injection", insights.Findings[0].RuleId, "Should only have injection finding") + + t.Logf("Global allowed rules test: Found %d findings", len(insights.Findings)) + }) +} diff --git a/cmd/mcp_server.go b/cmd/mcp_server.go index 51feabe7..01786e31 100644 --- a/cmd/mcp_server.go +++ b/cmd/mcp_server.go @@ -59,17 +59,18 @@ The SCM access token should be provided via the --token flag or GH_TOKEN/GL_TOKE func startMCPServer(ctx context.Context) error { Format = "noop" - defaultConfig := *config + // Create default config with global allowedRules applied + mcpDefaultConfig := *config // Apply global allowedRules setting to MCP server config if len(allowedRules) > 0 { - defaultConfig.AllowedRules = allowedRules + mcpDefaultConfig.AllowedRules = allowedRules } - opaClient, err := newOpaWithConfig(ctx, &defaultConfig) + opaClient, err := newOpaWithConfig(ctx, &mcpDefaultConfig) if err != nil { log.Error().Err(err).Msg("Failed to create manifest OPA client") return fmt.Errorf("failed to create manifest opa client: %w", err) } - manifestAnalyzer := analyze.NewAnalyzer(nil, nil, &noop.Format{}, &defaultConfig, opaClient) + manifestAnalyzer := analyze.NewAnalyzer(nil, nil, &noop.Format{}, &mcpDefaultConfig, opaClient) // Create MCP server s := server.NewMCPServer( @@ -276,12 +277,18 @@ Remember: This tool exists to prevent security vulnerabilities in generated code ) // Add tool handlers - s.AddTool(analyzeOrgTool, handleAnalyzeOrg) - s.AddTool(analyzeRepoTool, handleAnalyzeRepo) + s.AddTool(analyzeOrgTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return handleAnalyzeOrg(ctx, request, &mcpDefaultConfig) + }) + s.AddTool(analyzeRepoTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return handleAnalyzeRepo(ctx, request, &mcpDefaultConfig) + }) s.AddTool(analyzeLocalTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { - return handleAnalyzeLocal(ctx, request, opaClient) + return handleAnalyzeLocal(ctx, request, opaClient, &mcpDefaultConfig) + }) + s.AddTool(analyzeStaleBranchesTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { + return handleAnalyzeStaleBranches(ctx, request, &mcpDefaultConfig) }) - s.AddTool(analyzeStaleBranchesTool, handleAnalyzeStaleBranches) s.AddTool(analyzeManifestTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { return handleAnalyzeManifest(ctx, request, manifestAnalyzer) }) @@ -297,7 +304,7 @@ Remember: This tool exists to prevent security vulnerabilities in generated code return nil } -func handleAnalyzeOrg(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { +func handleAnalyzeOrg(ctx context.Context, request mcp.CallToolRequest, defaultConfig *models.Config) (*mcp.CallToolResult, error) { token := viper.GetString("token") if token == "" { return mcp.NewToolResultError("SCM access token is required. Please provide it via --token flag or GH_TOKEN/GL_TOKEN environment variable"), nil @@ -314,7 +321,7 @@ func handleAnalyzeOrg(ctx context.Context, request mcp.CallToolRequest) (*mcp.Ca ignoreForks := request.GetBool("ignore_forks", false) allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) - requestConfig := *config + requestConfig := *defaultConfig requestConfig.IgnoreForks = ignoreForks if len(allowedRulesParam) > 0 { requestConfig.AllowedRules = allowedRulesParam @@ -347,7 +354,7 @@ func handleAnalyzeOrg(ctx context.Context, request mcp.CallToolRequest) (*mcp.Ca return mcp.NewToolResultText(string(resultData)), nil } -func handleAnalyzeRepo(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { +func handleAnalyzeRepo(ctx context.Context, request mcp.CallToolRequest, defaultConfig *models.Config) (*mcp.CallToolResult, error) { token := viper.GetString("token") if token == "" { return mcp.NewToolResultError("SCM access token is required. Please provide it via --token flag or GH_TOKEN/GL_TOKEN environment variable"), nil @@ -363,7 +370,7 @@ func handleAnalyzeRepo(ctx context.Context, request mcp.CallToolRequest) (*mcp.C ref := request.GetString("ref", "HEAD") allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) - requestConfig := *config + requestConfig := *defaultConfig if len(allowedRulesParam) > 0 { requestConfig.AllowedRules = allowedRulesParam } @@ -392,7 +399,7 @@ func handleAnalyzeRepo(ctx context.Context, request mcp.CallToolRequest) (*mcp.C return mcp.NewToolResultText(string(resultData)), nil } -func handleAnalyzeLocal(ctx context.Context, request mcp.CallToolRequest, opaClient *opa.Opa) (*mcp.CallToolResult, error) { +func handleAnalyzeLocal(ctx context.Context, request mcp.CallToolRequest, opaClient *opa.Opa, defaultConfig *models.Config) (*mcp.CallToolResult, error) { path, err := request.RequireString("path") if err != nil { return mcp.NewToolResultError("path parameter is required"), nil @@ -400,7 +407,7 @@ func handleAnalyzeLocal(ctx context.Context, request mcp.CallToolRequest, opaCli allowedRulesParam := request.GetStringSlice("allowed_rules", []string{}) - requestConfig := *config + requestConfig := *defaultConfig if len(allowedRulesParam) > 0 { requestConfig.AllowedRules = allowedRulesParam } @@ -446,7 +453,7 @@ func handleAnalyzeLocal(ctx context.Context, request mcp.CallToolRequest, opaCli return mcp.NewToolResultText(string(resultData)), nil } -func handleAnalyzeStaleBranches(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { +func handleAnalyzeStaleBranches(ctx context.Context, request mcp.CallToolRequest, defaultConfig *models.Config) (*mcp.CallToolResult, error) { token := viper.GetString("token") if token == "" { return mcp.NewToolResultError("SCM access token is required. Please provide it via --token flag or GH_TOKEN/GL_TOKEN environment variable"), nil @@ -470,7 +477,7 @@ func handleAnalyzeStaleBranches(ctx context.Context, request mcp.CallToolRequest return mcp.NewToolResultError(fmt.Sprintf("error compiling regex: %v", err)), nil } - requestConfig := *config + requestConfig := *defaultConfig if len(allowedRulesParam) > 0 { requestConfig.AllowedRules = allowedRulesParam }